summaryrefslogtreecommitdiff
path: root/files/common/openwrt/chrony_prometheus-node-exporter.lua
blob: eeaceb1f25e47067eaa962fe578b600b7e189725 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
#!/usr/bin/lua
-- this is a lua-fied version of the python script that can be found here:
--  https://www.mail-archive.com/chrony-users@chrony.tuxfamily.org/msg02179.html

local chrony_sourcestats_cmd = 'chronyc -n -c sourcestats'
local chrony_sources_cmd = 'chronyc -n -c sources'
local chrony_tracking_cmd = 'chronyc -n -c tracking'

local status_types = {}
status_types['x'] = 0
status_types['?'] = 1
status_types['-'] = 2
status_types['+'] = 3
status_types['*'] = 4

local metrics_mode = {}
metrics_mode['^'] = "server"
metrics_mode['='] = "peer"
metrics_mode['#'] = "reference clock"


function get_cmdoutput(cmd)
    local chrony_sourcestats, err = io.popen(cmd)
    if err ~= nil then return nil, err end

    local lines = {}
    for line in chrony_sourcestats:lines() do table.insert(lines, line) end
    return lines
end

function comma_split(s)
    local elements = {}
    for element in s:gmatch("([^,]*)") do
        if element ~= "" then table.insert(elements, element) end
    end
    return elements
end

function weight(value)
    -- the reachability value is an octal number between 0 and 255
    -- the python script does rather complicated computations that
    -- boil down to: value == 255 (377 oct)
    if value == "377" then return 1 end
    return 0
end


local function scrape()
    local metric_freq = metric("chronyd_freq_ppm", "gauge")
    local metric_freq_skew = metric("chronyd_freq_skew_ppm", "gauge")
    local metric_std_dev = metric("chronyd_std_dev_seconds", "gauge")
    local chrony_sourcestats = get_cmdoutput(chrony_sourcestats_cmd)
    local line
    for _, line in ipairs(chrony_sourcestats) do
        local items = comma_split(line)
        local labels = { remote = items[1] }
        metric_freq(labels, tonumber(items[5]))
        metric_freq_skew(labels, tonumber(items[6]))
        metric_std_dev(labels, tonumber(items[8]))
    end

    local metric_peer_status = metric("chronyd_peer_status", "gauge")
    local metric_offset_seconds = metric("chronyd_offset_seconds", "gauge")
    local metric_peer_reachable = metric("chronyd_peer_reachable", "gauge")
    local chrony_sources = get_cmdoutput(chrony_sources_cmd)
    for _, line in ipairs(chrony_sources) do
        local items = comma_split(line)
        local common_labels = { remote = items[3] }
        local peer_labels = { remote = items[3], stratum = tonumber(items[4]), mode = metrics_mode[items[1]] }
        metric_peer_status(peer_labels, status_types[items[2]])
        metric_offset_seconds(common_labels, tonumber(items[9]))
        metric_peer_reachable(peer_labels, weight(items[6]))
    end

    local chrony_tracking = get_cmdoutput(chrony_tracking_cmd)
    for _, line in ipairs(chrony_tracking) do
        local items = comma_split(line)
        metric("chronyd_tracking_source", "gauge", { value = items[2]}, 1)
        metric("chronyd_tracking_stratum", "gauge", nil, tonumber(items[3]))
        metric("chronyd_tracking_ref_time", "gauge", nil, tonumber(items[4]))
        metric("chronyd_tracking_system_time", "gauge", nil, tonumber(items[5]))
        metric("chronyd_tracking_last_offset", "gauge", nil, tonumber(items[6]))
        metric("chronyd_tracking_rms_offset", "gauge", nil, tonumber(items[7]))
        metric("chronyd_tracking_frequency_error", "gauge", nil, tonumber(items[8]))
        metric("chronyd_tracking_frequency_residual", "gauge", nil, tonumber(items[9]))
        metric("chronyd_tracking_frequency_skew", "gauge", nil, tonumber(items[10]))
        metric("chronyd_tracking_root_delay", "gauge", nil, tonumber(items[11]))
        metric("chronyd_tracking_root_dispersion", "gauge", nil, tonumber(items[12]))
        metric("chronyd_tracking_update_interval", "gauge", nil, tonumber(items[13]))
        metric("chronyd_tracking_leap_status", "gauge", { value = items[14]}, 1)
    end
end

return { scrape = scrape }