diff --git a/utils/prometheus-node-exporter-lua/Makefile b/utils/prometheus-node-exporter-lua/Makefile index 6662eb060..8f9e3ccad 100644 --- a/utils/prometheus-node-exporter-lua/Makefile +++ b/utils/prometheus-node-exporter-lua/Makefile @@ -4,7 +4,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=prometheus-node-exporter-lua -PKG_VERSION:=2017.05.07 +PKG_VERSION:=2017.12.08 PKG_RELEASE:=1 PKG_MAINTAINER:=Christian Simon @@ -12,15 +12,18 @@ PKG_LICENSE:=Apache-2.0 include $(INCLUDE_DIR)/package.mk -define Package/prometheus-node-exporter-lua +define Package/prometheus-node-exporter-lua/Default SECTION:=utils CATEGORY:=Utilities - TITLE:=Provides system statistics as Prometheus scraping endpoint - DEPENDS:=+luasocket - URL:=https://github.com/rbo/openwrt_exporter + TITLE:=Prometheus node exporter PKGARCH:=all endef +define Package/prometheus-node-exporter-lua + $(call Package/prometheus-node-exporter-lua/Default) + DEPENDS:=+luasocket +lua +endef + define Package/prometheus-node-exporter-lua/conffiles /etc/config/prometheus-node-exporter-lua endef @@ -31,6 +34,30 @@ define Package/prometheus-node-exporter-lua/description This service is a lightweight rewrite in LUA of the offical Prometheus node_exporter. endef +define Package/prometheus-node-exporter-lua-nat_traffic + $(call Package/prometheus-node-exporter-lua/Default) + TITLE+= (nat_traffic collector) + DEPENDS:=prometheus-node-exporter-lua +endef + +define Package/prometheus-node-exporter-lua-netstat + $(call Package/prometheus-node-exporter-lua/Default) + TITLE+= (netstat collector) + DEPENDS:=prometheus-node-exporter-lua +endef + +define Package/prometheus-node-exporter-lua-wifi + $(call Package/prometheus-node-exporter-lua/Default) + TITLE+= (wifi collector) + DEPENDS:=prometheus-node-exporter-lua +libiwinfo-lua +libubus-lua +endef + +define Package/prometheus-node-exporter-lua-wifi_stations + $(call Package/prometheus-node-exporter-lua/Default) + TITLE+= (wifi_stations collector) + DEPENDS:=prometheus-node-exporter-lua +libiwinfo-lua +libubus-lua +endef + Build/Compile= define Package/prometheus-node-exporter-lua/install @@ -40,6 +67,38 @@ define Package/prometheus-node-exporter-lua/install $(INSTALL_BIN) ./files/etc/init.d/prometheus-node-exporter-lua $(1)/etc/init.d/prometheus-node-exporter-lua $(INSTALL_DIR) $(1)/usr/bin $(INSTALL_BIN) ./files/usr/bin/prometheus-node-exporter-lua $(1)/usr/bin/prometheus-node-exporter-lua + $(INSTALL_DIR) $(1)/usr/lib/lua/prometheus-collectors + $(INSTALL_BIN) ./files/usr/lib/lua/prometheus-collectors/cpu.lua $(1)/usr/lib/lua/prometheus-collectors/ + $(INSTALL_BIN) ./files/usr/lib/lua/prometheus-collectors/filefd.lua $(1)/usr/lib/lua/prometheus-collectors/ + $(INSTALL_BIN) ./files/usr/lib/lua/prometheus-collectors/loadavg.lua $(1)/usr/lib/lua/prometheus-collectors/ + $(INSTALL_BIN) ./files/usr/lib/lua/prometheus-collectors/meminfo.lua $(1)/usr/lib/lua/prometheus-collectors/ + $(INSTALL_BIN) ./files/usr/lib/lua/prometheus-collectors/netdev.lua $(1)/usr/lib/lua/prometheus-collectors/ + $(INSTALL_BIN) ./files/usr/lib/lua/prometheus-collectors/time.lua $(1)/usr/lib/lua/prometheus-collectors/ + $(INSTALL_BIN) ./files/usr/lib/lua/prometheus-collectors/uname.lua $(1)/usr/lib/lua/prometheus-collectors/ +endef + +define Package/prometheus-node-exporter-lua-nat_traffic/install + $(INSTALL_DIR) $(1)/usr/lib/lua/prometheus-collectors + $(INSTALL_BIN) ./files/usr/lib/lua/prometheus-collectors/nat_traffic.lua $(1)/usr/lib/lua/prometheus-collectors/ +endef + +define Package/prometheus-node-exporter-lua-netstat/install + $(INSTALL_DIR) $(1)/usr/lib/lua/prometheus-collectors + $(INSTALL_BIN) ./files/usr/lib/lua/prometheus-collectors/netstat.lua $(1)/usr/lib/lua/prometheus-collectors/ +endef + +define Package/prometheus-node-exporter-lua-wifi/install + $(INSTALL_DIR) $(1)/usr/lib/lua/prometheus-collectors + $(INSTALL_BIN) ./files/usr/lib/lua/prometheus-collectors/wifi.lua $(1)/usr/lib/lua/prometheus-collectors/ +endef + +define Package/prometheus-node-exporter-lua-wifi_stations/install + $(INSTALL_DIR) $(1)/usr/lib/lua/prometheus-collectors + $(INSTALL_BIN) ./files/usr/lib/lua/prometheus-collectors/wifi_stations.lua $(1)/usr/lib/lua/prometheus-collectors/ endef $(eval $(call BuildPackage,prometheus-node-exporter-lua)) +$(eval $(call BuildPackage,prometheus-node-exporter-lua-nat_traffic)) +$(eval $(call BuildPackage,prometheus-node-exporter-lua-netstat)) +$(eval $(call BuildPackage,prometheus-node-exporter-lua-wifi)) +$(eval $(call BuildPackage,prometheus-node-exporter-lua-wifi_stations)) diff --git a/utils/prometheus-node-exporter-lua/files/etc/init.d/prometheus-node-exporter-lua b/utils/prometheus-node-exporter-lua/files/etc/init.d/prometheus-node-exporter-lua index fc8a0b2e6..a1a47079c 100644 --- a/utils/prometheus-node-exporter-lua/files/etc/init.d/prometheus-node-exporter-lua +++ b/utils/prometheus-node-exporter-lua/files/etc/init.d/prometheus-node-exporter-lua @@ -15,5 +15,8 @@ start_service() { procd_append_param command --port ${port} procd_append_param command --bind ${bind} + procd_set_param stdout 1 + procd_set_param stderr 1 + procd_close_instance } diff --git a/utils/prometheus-node-exporter-lua/files/usr/bin/prometheus-node-exporter-lua b/utils/prometheus-node-exporter-lua/files/usr/bin/prometheus-node-exporter-lua index fea846926..62e402280 100755 --- a/utils/prometheus-node-exporter-lua/files/usr/bin/prometheus-node-exporter-lua +++ b/utils/prometheus-node-exporter-lua/files/usr/bin/prometheus-node-exporter-lua @@ -8,32 +8,16 @@ socket = require("socket") --- Allow us to call unpack under both lua5.1 and lua5.2+ -local unpack = unpack or table.unpack - --- This table defines the scrapers to run. --- Each corresponds directly to a scraper_ function. -scrapers = { "cpu", "load_averages", "memory", "file_handles", "network", - "network_devices", "time", "uname", "nat", "wifi"} - -- Parsing function space_split(s) - elements = {} + local elements = {} for element in s:gmatch("%S+") do table.insert(elements, element) end return elements end -function line_split(s) - elements = {} - for element in s:gmatch("[^\n]+") do - table.insert(elements, element) - end - return elements -end - function get_contents(filename) local f = io.open(filename, "rb") local contents = "" @@ -69,284 +53,54 @@ function metric(name, mtype, labels, value) return outputter end -function scraper_wifi() - local rv = { } - local ntm = require "luci.model.network".init() - - local metric_wifi_network_up = metric("wifi_network_up","gauge") - local metric_wifi_network_quality = metric("wifi_network_quality","gauge") - local metric_wifi_network_bitrate = metric("wifi_network_bitrate","gauge") - local metric_wifi_network_noise = metric("wifi_network_noise","gauge") - local metric_wifi_network_signal = metric("wifi_network_signal","gauge") - - local metric_wifi_station_signal = metric("wifi_station_signal","gauge") - local metric_wifi_station_tx_packets = metric("wifi_station_tx_packets","gauge") - local metric_wifi_station_rx_packets = metric("wifi_station_rx_packets","gauge") - - local dev - for _, dev in ipairs(ntm:get_wifidevs()) do - local rd = { - up = dev:is_up(), - device = dev:name(), - name = dev:get_i18n(), - networks = { } - } - - local net - for _, net in ipairs(dev:get_wifinets()) do - local labels = { - channel = net:channel(), - ssid = net:active_ssid(), - bssid = net:active_bssid(), - mode = net:active_mode(), - ifname = net:ifname(), - country = net:country(), - frequency = net:frequency(), - } - if net:is_up() then - metric_wifi_network_up(labels, 1) - local signal = net:signal_percent() - if signal ~= 0 then - metric_wifi_network_quality(labels, net:signal_percent()) - end - metric_wifi_network_noise(labels, net:noise()) - local bitrate = net:bitrate() - if bitrate then - metric_wifi_network_bitrate(labels, bitrate) - end - - local assoclist = net:assoclist() - for mac, station in pairs(assoclist) do - local labels = { - ifname = net:ifname(), - mac = mac, - } - metric_wifi_station_signal(labels, station.signal) - metric_wifi_station_tx_packets(labels, station.tx_packets) - metric_wifi_station_rx_packets(labels, station.rx_packets) - end - else - metric_wifi_network_up(labels, 0) - end - end - rv[#rv+1] = rd - end -end - -function scraper_cpu() - local stat = get_contents("/proc/stat") - - -- system boot time, seconds since epoch - metric("node_boot_time", "gauge", nil, string.match(stat, "btime ([0-9]+)")) - - -- context switches since boot (all CPUs) - metric("node_context_switches", "counter", nil, string.match(stat, "ctxt ([0-9]+)")) - - -- cpu times, per CPU, per mode - local cpu_mode = {"user", "nice", "system", "idle", "iowait", "irq", - "softirq", "steal", "guest", "guest_nice"} - local i = 0 - local cpu_metric = metric("node_cpu", "counter") - while string.match(stat, string.format("cpu%d ", i)) do - local cpu = space_split(string.match(stat, string.format("cpu%d ([0-9 ]+)", i))) - local labels = {cpu = "cpu" .. i} - for ii, mode in ipairs(cpu_mode) do - labels['mode'] = mode - cpu_metric(labels, cpu[ii] / 100) - end - i = i + 1 - end - - -- interrupts served - metric("node_intr", "counter", nil, string.match(stat, "intr ([0-9]+)")) - - -- processes forked - metric("node_forks", "counter", nil, string.match(stat, "processes ([0-9]+)")) - - -- processes running - metric("node_procs_running", "gauge", nil, string.match(stat, "procs_running ([0-9]+)")) - - -- processes blocked for I/O - metric("node_procs_blocked", "gauge", nil, string.match(stat, "procs_blocked ([0-9]+)")) -end - -function scraper_load_averages() - local loadavg = space_split(get_contents("/proc/loadavg")) - - metric("node_load1", "gauge", nil, loadavg[1]) - metric("node_load5", "gauge", nil, loadavg[2]) - metric("node_load15", "gauge", nil, loadavg[3]) -end - -function scraper_memory() - local meminfo = line_split(get_contents("/proc/meminfo"):gsub("[):]", ""):gsub("[(]", "_")) - - for i, mi in ipairs(meminfo) do - local name, size, unit = unpack(space_split(mi)) - if unit == 'kB' then - size = size * 1024 - end - metric("node_memory_" .. name, "gauge", nil, size) - end -end - -function scraper_file_handles() - local file_nr = space_split(get_contents("/proc/sys/fs/file-nr")) - - metric("node_filefd_allocated", "gauge", nil, file_nr[1]) - metric("node_filefd_maximum", "gauge", nil, file_nr[3]) -end - -function scraper_network() - -- NOTE: Both of these are missing in OpenWRT kernels. - -- See: https://dev.openwrt.org/ticket/15781 - local netstat = get_contents("/proc/net/netstat") .. get_contents("/proc/net/snmp") - - -- all devices - local netsubstat = {"IcmpMsg", "Icmp", "IpExt", "Ip", "TcpExt", "Tcp", "UdpLite", "Udp"} - for i, nss in ipairs(netsubstat) do - local substat_s = string.match(netstat, nss .. ": ([A-Z][A-Za-z0-9 ]+)") - if substat_s then - local substat = space_split(substat_s) - local substatv = space_split(string.match(netstat, nss .. ": ([0-9 -]+)")) - for ii, ss in ipairs(substat) do - metric("node_netstat_" .. nss .. "_" .. ss, "gauge", nil, substatv[ii]) - end - end - end -end - -function scraper_network_devices() - local netdevstat = line_split(get_contents("/proc/net/dev")) - local netdevsubstat = {"receive_bytes", "receive_packets", "receive_errs", - "receive_drop", "receive_fifo", "receive_frame", "receive_compressed", - "receive_multicast", "transmit_bytes", "transmit_packets", - "transmit_errs", "transmit_drop", "transmit_fifo", "transmit_colls", - "transmit_carrier", "transmit_compressed"} - for i, line in ipairs(netdevstat) do - netdevstat[i] = string.match(netdevstat[i], "%S.*") - end - local nds_table = {} - local devs = {} - for i, nds in ipairs(netdevstat) do - local dev, stat_s = string.match(netdevstat[i], "([^:]+): (.*)") - if dev then - nds_table[dev] = space_split(stat_s) - table.insert(devs, dev) - end - end - for i, ndss in ipairs(netdevsubstat) do - netdev_metric = metric("node_network_" .. ndss, "gauge") - for ii, d in ipairs(devs) do - netdev_metric({device=d}, nds_table[d][i]) - end - end -end - -function scraper_time() - -- current time - metric("node_time", "counter", nil, os.time()) -end - -function scraper_uname() - -- version can have spaces, so grab it directly - local version = string.sub(io.popen("uname -v"):read("*a"), 1, -2) - -- avoid individual popen calls for the rest of the values - local uname_string = io.popen("uname -a"):read("*a") - local sysname, nodename, release = unpack(space_split(uname_string)) - local labels = {domainname = "(none)", nodename = nodename, release = release, - sysname = sysname, version = version} - - -- The machine hardware name is immediately after the version string, so add - -- up the values we know and add in the 4 spaces to find the offset... - machine_offset = string.len(sysname .. nodename .. release .. version) + 4 - labels['machine'] = string.match(string.sub(uname_string, machine_offset), "(%S+)" ) - metric("node_uname_info", "gauge", labels, 1) -end - -function scraper_nat() - -- documetation about nf_conntrack: - -- https://www.frozentux.net/iptables-tutorial/chunkyhtml/x1309.html - -- local natstat = line_split(get_contents("/proc/net/nf_conntrack")) - local natstat = line_split(get_contents("nf_conntrack")) - - nat_metric = metric("node_nat_traffic", "gauge" ) - for i, e in ipairs(natstat) do - -- output(string.format("%s\n",e )) - local fields = space_split(e) - local src, dest, bytes; - bytes = 0; - for ii, field in ipairs(fields) do - if src == nil and string.match(field, '^src') then - src = string.match(field,"src=([^ ]+)"); - elseif dest == nil and string.match(field, '^dst') then - dest = string.match(field,"dst=([^ ]+)"); - elseif string.match(field, '^bytes') then - local b = string.match(field, "bytes=([^ ]+)"); - bytes = bytes + b; - -- output(string.format("\t%d %s",ii,field )); - end - - end - -- local src, dest, bytes = string.match(natstat[i], "src=([^ ]+) dst=([^ ]+) .- bytes=([^ ]+)"); - -- local src, dest, bytes = string.match(natstat[i], "src=([^ ]+) dst=([^ ]+) sport=[^ ]+ dport=[^ ]+ packets=[^ ]+ bytes=([^ ]+)") - - local labels = { src = src, dest = dest } - -- output(string.format("src=|%s| dest=|%s| bytes=|%s|", src, dest, bytes )) - nat_metric(labels, bytes ) - end -end - -function timed_scrape(scraper) +function timed_scrape(collector) local start_time = socket.gettime() - -- build the function name and call it from global variable table - _G["scraper_"..scraper]() - local duration = socket.gettime() - start_time - return duration + local success = 1 + local status, err = pcall(collector.scrape) + if not status then + success = 0 + print(err) + end + return (socket.gettime() - start_time), success end -function run_all_scrapers() - times = {} - for i,scraper in ipairs(scrapers) do - runtime = timed_scrape(scraper) - times[scraper] = runtime - scrape_time_sums[scraper] = scrape_time_sums[scraper] + runtime - scrape_counts[scraper] = scrape_counts[scraper] + 1 - end - - local name = "node_exporter_scrape_duration_seconds" - local duration_metric = metric(name, "summary") - for i,scraper in ipairs(scrapers) do - local labels = {collector=scraper, result="success"} - duration_metric(labels, times[scraper]) - print_metric(name.."_sum", labels, scrape_time_sums[scraper]) - print_metric(name.."_count", labels, scrape_counts[scraper]) +function run_all_collectors(collectors) + local metric_duration = metric("node_scrape_collector_duration_seconds", "gauge") + local metric_success = metric("node_scrape_collector_success", "gauge") + for _,cname in pairs(collectors) do + if col_mods[cname] ~= nil then + local duration, success = timed_scrape(col_mods[cname]) + local labels = {collector=cname} + metric_duration(labels, duration) + metric_success(labels, success) + end end end -- Web server-specific functions function http_ok_header() - output("HTTP/1.1 200 OK\r") - output("Server: lua-metrics\r") - output("Content-Type: text/plain; version=0.0.4\r") - output("\r") + output("HTTP/1.0 200 OK\r\nServer: lua-metrics\r\nContent-Type: text/plain; version=0.0.4\r\n\r") end function http_not_found() - output("HTTP/1.1 404 Not Found\r") - output("Server: lua-metrics\r") - output("Content-Type: text/plain\r") - output("\r") - output("ERROR: File Not Found.") + output("HTTP/1.0 404 Not Found\r\nServer: lua-metrics\r\nContent-Type: text/plain\r\n\r\nERROR: File Not Found.") end function serve(request) - if not string.match(request, "GET /metrics.*") then + local q = request:match("^GET /metrics%??([^ ]*) HTTP/1%.[01]$") + if q == nil then http_not_found() else http_ok_header() - run_all_scrapers() + local cols = {} + for c in q:gmatch("collect[^=]*=([^&]+)") do + cols[#cols+1] = c + end + if #cols == 0 then + cols = col_names + end + run_all_collectors(cols) end client:close() return true @@ -363,11 +117,12 @@ for k,v in ipairs(arg) do end end -scrape_counts = {} -scrape_time_sums = {} -for i,scraper in ipairs(scrapers) do - scrape_counts[scraper] = 0 - scrape_time_sums[scraper] = 0 +col_mods = {} +col_names = {} +for c in io.popen("ls -1 /usr/lib/lua/prometheus-collectors/*.lua"):lines() do + c = c:match("([^/]+)%.lua$") + col_mods[c] = require('prometheus-collectors.'..c) + col_names[#col_names+1] = c end if port then @@ -387,5 +142,5 @@ if port then end else output = print - run_all_scrapers() + run_all_collectors(col_names) end diff --git a/utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/cpu.lua b/utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/cpu.lua new file mode 100644 index 000000000..9d083dbf0 --- /dev/null +++ b/utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/cpu.lua @@ -0,0 +1,40 @@ +-- stat/cpu collector +local function scrape() + local stat = get_contents("/proc/stat") + + -- system boot time, seconds since epoch + metric("node_boot_time", "gauge", nil, string.match(stat, "btime ([0-9]+)")) + + -- context switches since boot (all CPUs) + metric("node_context_switches", "counter", nil, string.match(stat, "ctxt ([0-9]+)")) + + -- cpu times, per CPU, per mode + local cpu_mode = {"user", "nice", "system", "idle", "iowait", "irq", + "softirq", "steal", "guest", "guest_nice"} + local i = 0 + local cpu_metric = metric("node_cpu", "counter") + while true do + local cpu = {string.match(stat, "cpu"..i.." (%d+) (%d+) (%d+) (%d+) (%d+) (%d+) (%d+) (%d+) (%d+) (%d+)")} + if #cpu ~= 10 then + break + end + for ii, mode in ipairs(cpu_mode) do + cpu_metric({cpu="cpu"..i, mode=mode}, cpu[ii] / 100) + end + i = i + 1 + end + + -- interrupts served + metric("node_intr", "counter", nil, string.match(stat, "intr ([0-9]+)")) + + -- processes forked + metric("node_forks", "counter", nil, string.match(stat, "processes ([0-9]+)")) + + -- processes running + metric("node_procs_running", "gauge", nil, string.match(stat, "procs_running ([0-9]+)")) + + -- processes blocked for I/O + metric("node_procs_blocked", "gauge", nil, string.match(stat, "procs_blocked ([0-9]+)")) +end + +return { scrape = scrape } diff --git a/utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/filefd.lua b/utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/filefd.lua new file mode 100644 index 000000000..7e2ff6391 --- /dev/null +++ b/utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/filefd.lua @@ -0,0 +1,8 @@ +local function scrape() + local file_nr = space_split(get_contents("/proc/sys/fs/file-nr")) + + metric("node_filefd_allocated", "gauge", nil, file_nr[1]) + metric("node_filefd_maximum", "gauge", nil, file_nr[3]) +end + +return { scrape = scrape } diff --git a/utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/loadavg.lua b/utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/loadavg.lua new file mode 100644 index 000000000..6bfab89b0 --- /dev/null +++ b/utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/loadavg.lua @@ -0,0 +1,9 @@ +local function scrape() + local loadavg = space_split(get_contents("/proc/loadavg")) + + metric("node_load1", "gauge", nil, loadavg[1]) + metric("node_load5", "gauge", nil, loadavg[2]) + metric("node_load15", "gauge", nil, loadavg[3]) +end + +return { scrape = scrape } diff --git a/utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/meminfo.lua b/utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/meminfo.lua new file mode 100644 index 000000000..01f262b47 --- /dev/null +++ b/utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/meminfo.lua @@ -0,0 +1,11 @@ +local function scrape() + for line in io.lines("/proc/meminfo") do + local name, size, unit = string.match(line, "([^:]+):%s+(%d+)%s?(k?B?)") + if unit == 'kB' then + size = size * 1024 + end + metric("node_memory_" .. name:gsub("[):]", ""):gsub("[(]", "_"), "gauge", nil, size) + end +end + +return { scrape = scrape } diff --git a/utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/nat_traffic.lua b/utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/nat_traffic.lua new file mode 100644 index 000000000..0b2da7dc3 --- /dev/null +++ b/utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/nat_traffic.lua @@ -0,0 +1,31 @@ +local function scrape() + -- documetation about nf_conntrack: + -- https://www.frozentux.net/iptables-tutorial/chunkyhtml/x1309.html + nat_metric = metric("node_nat_traffic", "gauge" ) + for e in io.lines("/proc/net/nf_conntrack") do + -- output(string.format("%s\n",e )) + local fields = space_split(e) + local src, dest, bytes; + bytes = 0; + for _, field in ipairs(fields) do + if src == nil and string.match(field, '^src') then + src = string.match(field,"src=([^ ]+)"); + elseif dest == nil and string.match(field, '^dst') then + dest = string.match(field,"dst=([^ ]+)"); + elseif string.match(field, '^bytes') then + local b = string.match(field, "bytes=([^ ]+)"); + bytes = bytes + b; + -- output(string.format("\t%d %s",ii,field )); + end + + end + -- local src, dest, bytes = string.match(natstat[i], "src=([^ ]+) dst=([^ ]+) .- bytes=([^ ]+)"); + -- local src, dest, bytes = string.match(natstat[i], "src=([^ ]+) dst=([^ ]+) sport=[^ ]+ dport=[^ ]+ packets=[^ ]+ bytes=([^ ]+)") + + local labels = { src = src, dest = dest } + -- output(string.format("src=|%s| dest=|%s| bytes=|%s|", src, dest, bytes )) + nat_metric(labels, bytes ) + end +end + +return { scrape = scrape } diff --git a/utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/netdev.lua b/utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/netdev.lua new file mode 100644 index 000000000..9127e12b4 --- /dev/null +++ b/utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/netdev.lua @@ -0,0 +1,25 @@ + +local netdevsubstat = {"receive_bytes", "receive_packets", "receive_errs", + "receive_drop", "receive_fifo", "receive_frame", "receive_compressed", + "receive_multicast", "transmit_bytes", "transmit_packets", + "transmit_errs", "transmit_drop", "transmit_fifo", "transmit_colls", + "transmit_carrier", "transmit_compressed"} +local pattern = "([^%s:]+):%s+(%d+)%s+(%d+)%s+(%d+)%s+(%d+)%s+(%d+)%s+(%d+)%s+(%d+)%s+(%d+)%s+(%d+)%s+(%d+)%s+(%d+)%s+(%d+)%s+(%d+)%s+(%d+)%s+(%d+)%s+(%d+)" + +local function scrape() + local nds_table = {} + for line in io.lines("/proc/net/dev") do + local t = {string.match(line, pattern)} + if #t == 17 then + nds_table[t[1]] = t + end + end + for i, ndss in ipairs(netdevsubstat) do + netdev_metric = metric("node_network_" .. ndss, "gauge") + for dev, nds_dev in pairs(nds_table) do + netdev_metric({device=dev}, nds_dev[i+1]) + end + end +end + +return { scrape = scrape } diff --git a/utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/netstat.lua b/utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/netstat.lua new file mode 100644 index 000000000..cd62bffac --- /dev/null +++ b/utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/netstat.lua @@ -0,0 +1,20 @@ +local function scrape() + -- NOTE: Both of these are missing in OpenWRT kernels. + -- See: https://dev.openwrt.org/ticket/15781 + local netstat = get_contents("/proc/net/netstat") .. get_contents("/proc/net/snmp") + + -- all devices + local netsubstat = {"IcmpMsg", "Icmp", "IpExt", "Ip", "TcpExt", "Tcp", "UdpLite", "Udp"} + for i, nss in ipairs(netsubstat) do + local substat_s = string.match(netstat, nss .. ": ([A-Z][A-Za-z0-9 ]+)") + if substat_s then + local substat = space_split(substat_s) + local substatv = space_split(string.match(netstat, nss .. ": ([0-9 -]+)")) + for ii, ss in ipairs(substat) do + metric("node_netstat_" .. nss .. "_" .. ss, "gauge", nil, substatv[ii]) + end + end + end +end + +return { scrape = scrape } diff --git a/utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/time.lua b/utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/time.lua new file mode 100644 index 000000000..d0abb66a1 --- /dev/null +++ b/utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/time.lua @@ -0,0 +1,6 @@ +local function scrape() + -- current time + metric("node_time", "counter", nil, os.time()) +end + +return { scrape = scrape } diff --git a/utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/uname.lua b/utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/uname.lua new file mode 100644 index 000000000..9874b53a9 --- /dev/null +++ b/utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/uname.lua @@ -0,0 +1,16 @@ +local labels = { + domainname = "", + nodename = "", + release = string.sub(get_contents("/proc/sys/kernel/osrelease"), 1, -2), + sysname = string.sub(get_contents("/proc/sys/kernel/ostype"), 1, -2), + version = string.sub(get_contents("/proc/sys/kernel/version"), 1, -2), + machine = string.sub(io.popen("uname -m"):read("*a"), 1, -2) +} + +local function scrape() + labels["domainname"] = string.sub(get_contents("/proc/sys/kernel/domainname"), 1, -2) + labels["nodename"] = string.sub(get_contents("/proc/sys/kernel/hostname"), 1, -2) + metric("node_uname_info", "gauge", labels, 1) +end + +return { scrape = scrape } diff --git a/utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/wifi.lua b/utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/wifi.lua new file mode 100644 index 000000000..975b7dd5f --- /dev/null +++ b/utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/wifi.lua @@ -0,0 +1,43 @@ +local ubus = require "ubus" +local iwinfo = require "iwinfo" + +local function scrape() + local metric_wifi_network_quality = metric("wifi_network_quality","gauge") + local metric_wifi_network_bitrate = metric("wifi_network_bitrate","gauge") + local metric_wifi_network_noise = metric("wifi_network_noise","gauge") + local metric_wifi_network_signal = metric("wifi_network_signal","gauge") + + local u = ubus.connect() + local status = u:call("network.wireless", "status", {}) + + for dev, dev_table in pairs(status) do + for _, intf in ipairs(dev_table['interfaces']) do + local ifname = intf['ifname'] + local iw = iwinfo[iwinfo.type(ifname)] + local labels = { + channel = iw.channel(ifname), + ssid = iw.ssid(ifname), + bssid = iw.bssid(ifname), + mode = iw.mode(ifname), + ifname = ifname, + country = iw.country(ifname), + frequency = iw.frequency(ifname), + device = dev, + } + + local qc = iw.quality(ifname) or 0 + local qm = iw.quality_max(ifname) or 0 + local quality = 0 + if qc > 0 and qm > 0 then + quality = math.floor((100 / qm) * qc) + end + + metric_wifi_network_quality(labels, quality) + metric_wifi_network_noise(labels, iw.noise(ifname) or 0) + metric_wifi_network_bitrate(labels, iw.bitrate(ifname) or 0) + metric_wifi_network_signal(labels, iw.signal(ifname) or -255) + end + end +end + +return { scrape = scrape } diff --git a/utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/wifi_stations.lua b/utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/wifi_stations.lua new file mode 100644 index 000000000..06c79a8bd --- /dev/null +++ b/utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/wifi_stations.lua @@ -0,0 +1,31 @@ +local ubus = require "ubus" +local iwinfo = require "iwinfo" + +local function scrape() + local metric_wifi_station_signal = metric("wifi_station_signal","gauge") + local metric_wifi_station_tx_packets = metric("wifi_station_tx_packets","gauge") + local metric_wifi_station_rx_packets = metric("wifi_station_rx_packets","gauge") + + local u = ubus.connect() + local status = u:call("network.wireless", "status", {}) + + for dev, dev_table in pairs(status) do + for _, intf in ipairs(dev_table['interfaces']) do + local ifname = intf['ifname'] + local iw = iwinfo[iwinfo.type(ifname)] + + local assoclist = iw.assoclist(ifname) + for mac, station in pairs(assoclist) do + local labels = { + ifname = ifname, + mac = mac, + } + metric_wifi_station_signal(labels, station.signal) + metric_wifi_station_tx_packets(labels, station.tx_packets) + metric_wifi_station_rx_packets(labels, station.rx_packets) + end + end + end +end + +return { scrape = scrape }