Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions net/mwan3/test-version.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/bin/sh

exit 0
45 changes: 43 additions & 2 deletions utils/prometheus-node-exporter-lua/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
include $(TOPDIR)/rules.mk

PKG_NAME:=prometheus-node-exporter-lua
PKG_VERSION:=2025.11.22
PKG_VERSION:=2026.06.05
PKG_RELEASE:=1

PKG_MAINTAINER:=Etienne CHAMPETIER <champetier.etienne@gmail.com>
Expand Down Expand Up @@ -54,7 +54,7 @@ endef
define Package/prometheus-node-exporter-lua/description
Provides node metrics as Prometheus scraping endpoint.

This service is a lightweight rewrite in LUA of the offical Prometheus node_exporter.
This service is a lightweight rewrite in LUA of the official Prometheus node_exporter.
endef

# Additional optional exporters:
Expand All @@ -81,6 +81,17 @@ define Package/prometheus-node-exporter-lua-dawn/install
$(INSTALL_DATA) ./files/usr/lib/lua/prometheus-collectors/dawn.lua $(1)/usr/lib/lua/prometheus-collectors/
endef

define Package/prometheus-node-exporter-lua-filesystem
$(call Package/prometheus-node-exporter-lua/Default)
TITLE+= (filesystem collector)
DEPENDS:=prometheus-node-exporter-lua +luci-lib-nixio
endef

define Package/prometheus-node-exporter-lua-filesystem/install
$(INSTALL_DIR) $(1)/usr/lib/lua/prometheus-collectors
$(INSTALL_BIN) ./files/usr/lib/lua/prometheus-collectors/filesystem.lua $(1)/usr/lib/lua/prometheus-collectors/
endef

define Package/prometheus-node-exporter-lua-hostapd_stations
$(call Package/prometheus-node-exporter-lua/Default)
TITLE+= (hostapd_stations collector) - Requires a full hostapd / wpad build
Expand Down Expand Up @@ -279,9 +290,37 @@ define Package/prometheus-node-exporter-lua-nft-counters/install
$(INSTALL_DATA) ./files/usr/lib/lua/prometheus-collectors/nft_counters.lua $(1)/usr/lib/lua/prometheus-collectors/
endef

define Package/prometheus-node-exporter-lua-modemmanager
$(call Package/prometheus-node-exporter-lua/Default)
TITLE+= (modemmanager collector)
DEPENDS:=prometheus-node-exporter-lua +modemmanager +lua-cjson
endef

define Package/prometheus-node-exporter-lua-modemmanager/install
$(INSTALL_DIR) $(1)/usr/lib/lua/prometheus-collectors
$(INSTALL_DATA) ./files/usr/lib/lua/prometheus-collectors/modemmanager.lua $(1)/usr/lib/lua/prometheus-collectors/
endef

define Package/prometheus-node-exporter-lua-unbound
$(call Package/prometheus-node-exporter-lua/Default)
TITLE+= (unbound stats collector)
DEPENDS:=prometheus-node-exporter-lua +unbound-daemon
endef

define Package/prometheus-node-exporter-lua-unbound/description
Adds a Unbound stats collector to the Prometheus node exporter.
Refer to https://github.com/marinierb/prometheus-node-exporter-lua-unbound for configuration details.
endef

define Package/prometheus-node-exporter-lua-unbound/install
$(INSTALL_DIR) $(1)/usr/lib/lua/prometheus-collectors
$(INSTALL_DATA) ./files/usr/lib/lua/prometheus-collectors/unbound.lua $(1)/usr/lib/lua/prometheus-collectors/
endef

$(eval $(call BuildPackage,prometheus-node-exporter-lua))
$(eval $(call BuildPackage,prometheus-node-exporter-lua-bmx7))
$(eval $(call BuildPackage,prometheus-node-exporter-lua-dawn))
$(eval $(call BuildPackage,prometheus-node-exporter-lua-filesystem))
$(eval $(call BuildPackage,prometheus-node-exporter-lua-hostapd_stations))
$(eval $(call BuildPackage,prometheus-node-exporter-lua-hostapd_ubus_stations))
$(eval $(call BuildPackage,prometheus-node-exporter-lua-hwmon))
Expand All @@ -300,3 +339,5 @@ $(eval $(call BuildPackage,prometheus-node-exporter-lua-realtek-poe))
$(eval $(call BuildPackage,prometheus-node-exporter-lua-mwan3))
$(eval $(call BuildPackage,prometheus-node-exporter-lua-ethtool))
$(eval $(call BuildPackage,prometheus-node-exporter-lua-nft-counters))
$(eval $(call BuildPackage,prometheus-node-exporter-lua-modemmanager))
$(eval $(call BuildPackage,prometheus-node-exporter-lua-unbound))

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
-- depends on luci-lib-nixio
local nix = require "nixio"

local function scrape()
-- node exporter description - Filesystem size in bytes
local metric_size_bytes = metric("node_filesystem_size_bytes", "gauge")
-- node exporter description - Filesystem free space in bytes
local metric_free_bytes = metric("node_filesystem_free_bytes", "gauge")
-- node exporter description - Filesystem space available to non-root users in bytes
local metric_avail_bytes = metric("node_filesystem_avail_bytes", "gauge")
-- node exporter description - Filesystem total file nodes
local metric_files = metric("node_filesystem_files", "gauge")
-- node exporter description - Filesystem total free file nodes
local metric_files_free = metric("node_filesystem_files_free", "gauge")
-- node exporter description - Filesystem read-only status
local metric_readonly = metric("node_filesystem_readonly", "gauge")

for e in io.lines("/proc/self/mounts") do
local fields = space_split(e)

local device = fields[1]
local mount_point = fields[2]
local fs_type = fields[3]

-- Filter list from node exporter:
-- https://github.com/prometheus/node_exporter/blob/b9d0932179a0c5b3a8863f3d6cdafe8584cedc8e/collector/filesystem_linux.go#L36-L37
if mount_point:find("/dev/?", 1) ~= 1
and mount_point:find("/proc/?", 1) ~= 1
and mount_point:find("/run/credentials/?", 1) ~= 1
and mount_point:find("/sys/?", 1) ~= 1
and mount_point:find("/var/lib/docker/?", 1) ~= 1
and mount_point:find("/var/lib/containers/storage/?", 1) ~= 1
and fs_type ~= "autofs"
and fs_type ~= "binfmt_misc"
and fs_type ~= "bpf"
and fs_type ~= "cgroup"
and fs_type ~= "cgroup2"
and fs_type ~= "configfs"
and fs_type ~= "debugfs"
and fs_type ~= "devpts"
and fs_type ~= "devtmpfs"
and fs_type ~= "fusectl"
and fs_type ~= "hugetlbfs"
and fs_type ~= "iso9660"
and fs_type ~= "mqueue"
and fs_type ~= "nsfs"
and fs_type ~= "overlay"
and fs_type ~= "proc"
and fs_type ~= "procfs"
and fs_type ~= "pstore"
and fs_type ~= "rpc_pipefs"
and fs_type ~= "securityfs"
and fs_type ~= "selinuxfs"
and fs_type ~= "squashfs"
and fs_type ~= "sysfs"
and fs_type ~= "tracefs" then
-- note that this excludes / as it's an overlay filesystem

local stat = nix.fs.statvfs(mount_point)

-- https://github.com/torvalds/linux/blob/e5fa841af679cb830da6c609c740a37bdc0b8b35/include/linux/statfs.h#L31
local ST_RDONLY = 0x001

local labels = {
device = device,
fstype = fs_type,
mountpoint = mount_point,
}

local ro = 0
if (nix.bit.band(stat.flag, ST_RDONLY)) == 1 then
ro = 1
end

metric_size_bytes(labels, stat.blocks * stat.bsize)
metric_free_bytes(labels, stat.bfree * stat.bsize)
metric_avail_bytes(labels, stat.bavail * stat.bsize)
metric_files(labels, stat.files)
metric_files_free(labels, stat.ffree)
metric_readonly(labels, ro)
end
end
end

return { scrape = scrape }
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
local cjson = require "cjson"

local function scrape()
local file, output, data

file = io.popen("mmcli -L -J", 'r')
if not file then return end
output = file:read('*all')
file:close()

local ok, modem_list = pcall(cjson.decode, output)
if not ok or not modem_list["modem-list"] then return end

for _, modem in ipairs(modem_list["modem-list"]) do

file = io.popen("mmcli -m " .. modem .. " -J", 'r')
if file then
output = file:read('*all')
file:close()

ok, data = pcall(cjson.decode, output)
if ok and data["modem"] then
local quality = data["modem"]["generic"]["signal-quality"]["value"]
metric("modemmanager_signal_quality", "gauge", {modem=modem}, tonumber(quality))
end
end

file = io.popen("mmcli -m " .. modem .. " --signal-get -J", 'r')
if file then
output = file:read('*all')
file:close()

ok, data = pcall(cjson.decode, output)
if ok and data["modem"] and data["modem"]["signal"] then
for tech, values in pairs(data["modem"]["signal"]) do
for metric_name, value in pairs(values) do
local num = tonumber(value)
if num then
metric("modemmanager_signal_" .. tech .. "_" .. metric_name, "gauge", {modem=modem}, num)
end
end
end
end
end
end
end

return { scrape = scrape }
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,22 @@ local labels = {
target = b.release.target
}

local os_info = {
id = string.lower(b.release.distribution),
name = b.release.distribution,
pretty_name = b.release.distribution .. " " .. b.release.version,
version = b.release.version,
version_id = b.release.version,
build_id = b.release.revision,
}

local b = nil
local u = nil
local ubus = nil

local function scrape()
metric("node_openwrt_info", "gauge", labels, 1)
metric("node_os_info", "gauge", os_info, 1)
end

return { scrape = scrape }

Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,16 @@ local function scrape()
local metric_uci_host = metric("uci_dhcp_host", "gauge")

curs:foreach("dhcp", "host", function(s)
if s[".type"] == "host" then
labels = {name=s["name"], mac=string.upper(s["mac"]), dns=s["dns"], ip=s["ip"]}
local labels = {name=s["name"], dns=s["dns"], ip=s["ip"], duid=s["duid"]}

if s["mac"] == nil then
metric_uci_host(labels, 1)
return
end

local macs = type(s["mac"]) == "table" and s["mac"] or {s["mac"]}
for _, mac in ipairs(macs) do
labels["mac"] = string.upper(mac)
metric_uci_host(labels, 1)
end
end)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
-- Unbound stats exporter

local socket = require("socket")
local unix = require("socket.unix")

local function scrape()
local metrics = {
["total.num.queries" ] = metric("unbound_num_queries_total", "counter"),
["total.num.queries_ip_ratelimited" ] = metric("unbound_num_queries_ip_ratelimited_total", "counter"),
["total.num.queries_cookie_valid" ] = metric("unbound_num_queries_cookie_valid_total", "counter"),
["total.num.queries_cookie_client" ] = metric("unbound_num_queries_cookie_client_total", "counter"),
["total.num.queries_cookie_invalid" ] = metric("unbound_num_queries_cookie_invalid_total", "counter"),
["total.num.queries_discard_timeout"] = metric("unbound_num_queries_discard_timeout_total","counter"),
["total.num.queries_wait_limit" ] = metric("unbound_num_queries_wait_limit_total", "counter"),
["total.num.cachehits" ] = metric("unbound_cachehits_total", "counter"),
["total.num.cachemiss" ] = metric("unbound_cachemiss_total", "counter"),
["total.num.prefetch" ] = metric("unbound_prefetch_total", "counter"),
["total.num.queries_timed_out" ] = metric("unbound_num_queries_timed_out_total", "counter"),
["total.query.queue_time_us.max" ] = metric("unbound_query_queue_time_us_max", "gauge"),
["total.num.expired" ] = metric("unbound_num_expired_total", "counter"),
["total.num.recursivereplies" ] = metric("unbound_num_recursivereplies_total", "counter"),
["total.num.dns_error_reports" ] = metric("unbound_num_dns_error_reports_total", "counter"),
["total.requestlist.avg" ] = metric("unbound_requestlist_avg", "gauge"),
["total.requestlist.max" ] = metric("unbound_requestlist_max", "gauge"),
["total.requestlist.overwritten" ] = metric("unbound_requestlist_overwritten_total", "counter"),
["total.requestlist.exceeded" ] = metric("unbound_requestlist_exceeded_total", "counter"),
["total.requestlist.current.all" ] = metric("unbound_requestlist_current_all", "gauge"),
["total.requestlist.current.user" ] = metric("unbound_requestlist_current_user", "gauge"),
["total.recursion.time.avg" ] = metric("unbound_recursion_time_avg", "gauge"),
["total.recursion.time.median" ] = metric("unbound_recursion_time_median", "gauge"),
}

local sock = unix()
local ok, err = sock:connect("/run/unbound.ctl")
if not ok then
return nil, "failed to connect to unbound socket: " .. (err or "unknown")
end

sock:settimeout(1)
sock:send("UBCT1 stats_noreset\n")
local out = sock:receive("*a")

sock:close()

for line in out:gmatch("[^\r\n]+") do
local key, val = line:match("^([^=]+)=(.+)$")
if key and val then
local n = tonumber(val)
if metrics[key] then
metrics[key]({}, n)
end
end
end
end

return { scrape = scrape }
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ local function scrape()
local u = ubus.connect()
local status = u:call("network.wireless", "status", {})

if not status then
return
end

for dev, dev_table in pairs(status) do
for _, intf in ipairs(dev_table['interfaces']) do
local ifname = intf['ifname']
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ local function scrape()
local u = ubus.connect()
local status = u:call("network.wireless", "status", {})

if not status then
return
end

for dev, dev_table in pairs(status) do
for _, intf in ipairs(dev_table['interfaces']) do
local ifname = intf['ifname']
Expand Down
3 changes: 3 additions & 0 deletions utils/prometheus-node-exporter-lua/test-version.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/bin/sh

exit 0
14 changes: 14 additions & 0 deletions utils/prometheus-node-exporter-lua/test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#!/bin/sh

# shellcheck shell=busybox

case "$PKG_NAME" in
prometheus-node-exporter-lua-openwrt)
# call ubus outside scape, so skip the check
exit 0
;;

*)
prometheus-node-exporter-lua | grep node_scrape_collector_success
;;
esac
Loading
Loading