#!/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 print("########") 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 }