Software /
code /
prosody-modules
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 |
child | 2227: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 }) |