Mercurial > 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 |
| 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 }) |
