summaryrefslogtreecommitdiffstats
path: root/utils/prometheus-node-exporter-lua/files/usr/bin/prometheus-node-exporter-lua
blob: 35addf1dcdab1106d4564e1657a17e0da81e825f (plain)
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
137
138
139
140
141
142
143
144
145
146
147
148
#!/usr/bin/lua

-- Metrics web server

-- Copyright (c) 2016 Jeff Schornick <jeff@schornick.org>
-- Copyright (c) 2015 Kevin Lyda
-- Licensed under the Apache License, Version 2.0

socket = require("socket")

-- 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)
  local label_string = ""
  if labels then
    for label,value in pairs(labels) do
      label_string =  label_string .. label .. '="' .. value .. '",'
    end
    label_string = "{" .. string.sub(label_string, 1, -2) .. "}"
  end
  output(string.format("%s%s %s", metric, label_string, value))
end

function metric(name, mtype, labels, value)
  output("# TYPE " .. name .. " " .. mtype)
  local outputter = function(labels, value)
    print_metric(name, labels, value)
  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
    print(err)
  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 http_ok_header()
  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.0 404 Not Found\r\nServer: lua-metrics\r\nContent-Type: text/plain\r\n\r\nERROR: File Not Found.")
end

function serve(request)
  local q = request:match("^GET /metrics%??([^ ]*) HTTP/1%.[01]$")
  if q == nil then
    http_not_found()
  else
    http_ok_header()
    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
end

-- Main program

for k,v in ipairs(arg) do
  if (v == "-p") or (v == "--port") then
    port = arg[k+1]
  end
  if (v == "-b") or (v == "--bind") then
    bind = arg[k+1]
  end
end

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 port then
  server = assert(socket.bind(bind, port))

  while 1 do
    client = server:accept()
    client:settimeout(60)
    local request, err = client:receive()

    if not err then
      output = function (str) client:send(str.."\n") end
      if not serve(request) then
        break
      end
    end
  end
else
  output = print
  run_all_collectors(col_names)
end