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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
|
#!/usr/bin/lua
-- Metrics web server
-- Copyright (c) 2016 Jeff Schornick <jeff@schornick.org>
-- Copyright (c) 2015 Kevin Lyda <kevin@lyda.ie>
-- Licensed under the Apache License, Version 2.0
socket = require("socket")
-- get configs
local omit_zero_values = os.getenv("OMIT_ZERO_VALUES") == "1"
-- Parsing
function space_split(s)
local elements = {}
for element in s:gmatch("%S+") do
table.insert(elements, element)
end
return elements
end
function get_contents(filename)
local f = io.open(filename, "rb")
local contents = ""
if f then
contents = f:read "*a"
f:close()
end
return contents
end
-- Metric printing
function print_metric(metric, labels, value)
if type(value) == "nil" then
return
end
out:write(metric)
if labels then
out:write("{")
coma = ""
for label,value in pairs(labels) do
out:write(coma, label, '="', value, '"')
coma = ","
end
out:write("}")
end
out:write(" ", value, "\n")
end
function metric(name, mtype, labels, value)
out:write("# TYPE ", name, " ", mtype, "\n")
-- omit_zero_vales config supress time series always being zero
local printall = not (mtype == "counter" and omit_zero_values)
local outputter = function(labels, value)
if printall or tonumber(value) ~= 0 then
print_metric(name, labels, value)
end
end
if value then
outputter(labels, value)
end
return outputter
end
function timed_scrape(collector)
local start_time = socket.gettime()
local success = 1
local status, err = pcall(collector.scrape)
if not status then
success = 0
io.stderr:write(err .. '\n')
end
return (socket.gettime() - start_time), success
end
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 handle_request(env)
-- use buffered output instead uhttpd.send()
out = io.open("/proc/self/fd/1", "a+")
out:setvbuf("full")
if env.PATH_INFO ~= '/metrics' then
out:write("Status: 404 Not Found\r\n")
out:write("Server: lua-metrics\r\n")
out:write("Content-Type: text/plain\r\n\r\n")
out:write("ERROR: File Not Found.")
else
out:write("Status: 200 OK\r\n")
out:write("Server: lua-metrics\r\n")
out:write("Content-Type: text/plain; version=0.0.4\r\n\r\n")
local cols = {}
for c in env.QUERY_STRING:gmatch("collect[^=]*=([^&]+)") do
cols[#cols+1] = c
end
if #cols == 0 then
cols = col_names
end
run_all_collectors(cols)
end
out:flush()
end
-- Main program
col_mods = {}
col_names = {}
ls_fd = io.popen("ls -1 /usr/lib/lua/prometheus-collectors/*.lua")
for c in ls_fd:lines() do
c = c:match("([^/]+)%.lua$")
col_mods[c] = require('prometheus-collectors.'..c)
col_names[#col_names+1] = c
end
ls_fd:close()
if arg ~= nil then
out = io.output()
run_all_collectors(col_names)
end
|