#!/usr/bin/lua -- this tries to create the same metrics as: https://github.com/SuperQ/chrony_exporter -- local chrony_sources_cmd = 'chronyc -n -c sources' local chrony_tracking_cmd = 'chronyc -n -c tracking' local source_states = {} source_states['*'] = "sync" source_states['?'] = "unreach" source_states['x'] = "falseticker" source_states['~'] = "jittery" source_states['+'] = "candidate" source_states['-'] = "outlier" local source_modes = {} source_modes['^'] = "client" source_modes['='] = "peer" source_modes['#'] = "reference clock" function get_cmdoutput(cmd) local chronyc_out, err = io.popen(cmd) if err ~= nil then return nil, err end local lines = {} for line in chronyc_out:lines() do if line == "506 Cannot talk to daemon" then return nil, "line" end 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 local function scrape() local chrony_tracking = get_cmdoutput(chrony_tracking_cmd) local chrony_sources = get_cmdoutput(chrony_sources_cmd) local metric_up = metric("chrony_up", "gauge") if chrony_tracking == nil or chrony_sources == nil then metric_up(nil, 0) return end metric_up(nil, 1) for _, line in ipairs(chrony_tracking) do local items = comma_split(line) metric("chrony_tracking_info", "gauge", { tracking_address = items[2], tracking_refid = items[1]}, 1) metric("chrony_tracking_last_offset_seconds", "gauge", nil, tonumber(items[6])) metric("chrony_tracking_reference_timestamp_seconds", "gauge", nil, tonumber(items[4])) metric("chrony_tracking_rms_offset_seconds", "gauge", nil, tonumber(items[7])) metric("chrony_tracking_root_delay_seconds", "gauge", nil, tonumber(items[11])) metric("chrony_tracking_root_dispersion_seconds", "gauge", nil, tonumber(items[12])) metric("chrony_tracking_stratum", "gauge", nil, tonumber(items[3])) metric("chrony_tracking_system_time_seconds", "gauge", nil, tonumber(items[5])) end local metric_sources_ls_age = metric("chrony_sources_last_sample_age_seconds", "gauge") for _, line in ipairs(chrony_sources) do local items = comma_split(line) metric_sources_ls_age({ source_address = items[3] }, tonumber(items[7])) end local metric_sources_ls_error = metric("chrony_sources_last_sample_error_margin_seconds", "gauge") for _, line in ipairs(chrony_sources) do local items = comma_split(line) metric_sources_ls_error({ source_address = items[3] }, tonumber(items[10])) end local metric_sources_ls_offset = metric("chrony_sources_last_sample_offset_seconds", "gauge") for _, line in ipairs(chrony_sources) do local items = comma_split(line) metric_sources_ls_offset({ source_address = items[3] }, tonumber(items[8])) end local metric_sources_polling_int = metric("chrony_sources_polling_interval_seconds", "gauge") for _, line in ipairs(chrony_sources) do local items = comma_split(line) metric_sources_polling_int({ source_address = items[3] }, 2^tonumber(items[5])) end local metric_sources_info = metric("chrony_sources_state_info", "gauge") for _, line in ipairs(chrony_sources) do local items = comma_split(line) metric_sources_info({ source_address = items[3], source_mode = source_modes[items[1]], source_state = source_states[items[2]] }, 1) end local metric_sources_stratum = metric("chrony_sources_stratum", "gauge") for _, line in ipairs(chrony_sources) do local items = comma_split(line) metric_sources_stratum({ source_address = items[3] }, tonumber(items[4])) end end return { scrape = scrape }