comparison mod_http_host_status_check/mod_http_host_status_check.lua @ 2219:5fcf9d558250

Three new modules: mod_host_status_check, mod_host_status_heartbeat and mod_http_host_status_check
author Matthew Wild <mwild1@gmail.com>
date Tue, 28 Jun 2016 22:33:13 +0100
parents
children 7356d722e180
comparison
equal deleted inserted replaced
2218:0ca0fdad3b2c 2219:5fcf9d558250
1 local heartbeats = module:shared("/*/host_status_check/heartbeats");
2 local events = module:shared("/*/host_status_check/connection_events");
3
4 local time = require "socket".gettime;
5 local template = require "util.interpolation".new("%b{}", function (s) return s end)
6 local st = require "util.stanza";
7
8 module:depends "http"
9
10 local threshold = module:get_option_number("status_check_heartbeat_threshold", 5);
11
12 local function status_string(status, duration, comment)
13 local string_timestamp = "";
14 if duration then
15 string_timestamp = ("(%0.2fs%s)"):format(duration, comment or "");
16 elseif comment then
17 string_timestamp = ("(%s)"):format(comment);
18 else
19 return status and "UP" or "DOWN";
20 end
21 return (status and "UP " or "DOWN ")..string_timestamp;
22 end
23
24 local function string_pad(s, len)
25 return s..(" "):rep(len-#s);
26 end
27
28 local status_page_template = [[
29 STATUS {status}
30 {host_statuses%HOST {item} {idx}
31 }]];
32
33 function status_page()
34 local host_statuses = {};
35 local current_time = time();
36
37 local all_ok = true;
38
39 for host in pairs(hosts) do
40 local last_heartbeat_time = heartbeats[host];
41
42 local ok, status_text = true, "OK";
43
44 local is_component = hosts[host].type == "component" and hosts[host].modules.component;
45
46 if is_component then
47 local current_status = hosts[host].modules.component.connected;
48 if events[host] then
49 local tracked_status = events[host].connected;
50 if tracked_status == current_status then
51 status_text = status_string(current_status, time() - events[host].timestamp);
52 else
53 status_text = status_string(current_status, nil, "!");
54 end
55 else
56 status_text = status_string(current_status, nil, "?");
57 end
58 if not current_status then
59 ok = false;
60 end
61 else
62 local event_info = events[host];
63 local connected = true;
64 if event_info then
65 connected = event_info.connected;
66 end
67 status_text = status_string(connected, event_info and (time() - events[host].timestamp), not event_info and "?");
68 end
69
70 if last_heartbeat_time then
71 local time_since_heartbeat = current_time - last_heartbeat_time;
72 if ok then
73 if time_since_heartbeat > threshold then
74 status_text = ("TIMEOUT (%0.2fs)"):format(time_since_heartbeat);
75 ok = false;
76 else
77 status_text = status_text:gsub("^%S+", "GOOD");
78 end
79 end
80 end
81
82 if not ok then
83 all_ok = false;
84 end
85
86 if not ok or is_component or last_heartbeat_time then
87 host_statuses[host] = string_pad(status_text, 20);
88 end
89 end
90 local page = template(status_page_template, {
91 status = all_ok and "OK" or "FAIL";
92 host_statuses = host_statuses;
93 });
94 return page;
95 end
96
97 module:provides("http", {
98 route = {
99 GET = status_page;
100 };
101 })