diff options
| author | arf20 <aruizfernandez05@gmail.com> | 2025-10-27 03:38:48 +0100 |
|---|---|---|
| committer | arf20 <aruizfernandez05@gmail.com> | 2025-10-27 03:38:48 +0100 |
| commit | 55a1dc11e9bf5bbc643f0aa09bbdd09056b322b5 (patch) | |
| tree | dd8fb73c65a46e8bda752a5b06ce4fa21b1f3251 | |
| parent | 2e5c8fe2ed1443e7955e663e3fe49eb349b77ea0 (diff) | |
| download | arfnet2-status-55a1dc11e9bf5bbc643f0aa09bbdd09056b322b5.tar.gz arfnet2-status-55a1dc11e9bf5bbc643f0aa09bbdd09056b322b5.zip | |
timeline (fix: use events!)
| -rw-r--r-- | Makefile | 2 | ||||
| -rw-r--r-- | index.htm.tmpl | 22 | ||||
| -rw-r--r-- | monitor.c | 106 |
3 files changed, 117 insertions, 13 deletions
@@ -1,6 +1,6 @@ CC = gcc CFLAGS = -g -Wall -pedantic -LDFLAGS = -lmicrohttpd -lcurl +LDFLAGS = -lmicrohttpd -lcurl -lm BIN = monitor SRC = main.c monitor.c diff --git a/index.htm.tmpl b/index.htm.tmpl index 6637f05..1c5f13a 100644 --- a/index.htm.tmpl +++ b/index.htm.tmpl @@ -6,7 +6,14 @@ <title>ARFNET</title> <style> table, th, td { - border: 1px solid #abb2bf; + border: 1px solid #abb2bf; +} + +.graph { + border-collapse: collapse; + padding: 0px; + border: 0px; + height: 7pt; } .up { @@ -17,6 +24,15 @@ table, th, td { background-color: red; } +td.w-min { + white-space: nowrap; + width: 1%; +} + +td.w-last { + width: auto; +} + </style> </head> @@ -29,8 +45,8 @@ table, th, td { <h2 class="center">Status Monitor</h2> <p>This webapp monitors the status of the main ARFNET services from outside the ARFNET network</p> Services - <table> - <tr><th>Type</th><th>Service</th><th>Status</th><th>Uptime</th><th>%%up month</th><th>%%up total</th></tr> + <table width="100%"> + <tr><th>Type</th><th>Service</th><th>Status</th><th>Uptime</th><th>%%up month</th><th>%%up total</th><th>Timeline</th></tr> %s </table> <br><br> @@ -5,6 +5,7 @@ #include <errno.h> #include <time.h> #include <ctype.h> +#include <math.h> #include <curl/curl.h> @@ -36,7 +37,7 @@ typedef struct { char *name; char *target; - status_t status; + status_t status, status_1; event_t *events; size_t events_size, events_capacity; @@ -157,6 +158,8 @@ incidents_render() { char buff[256]; + incidents_size = 0; + for (size_t i = 0; i < targets_n; i++) { /* iterate through downs */ for (size_t j = 0; j < targets[i].events_size; j++) { @@ -335,7 +338,7 @@ target_perc_uptime_since(const target_t *target, time_t since) downtime += clamped_duration; } - return 100.0f * (1.0f - ((float)downtime / (float)(time(NULL) - since))); + return 1.0f - ((float)downtime / (float)(time(NULL) - since)); } float @@ -353,7 +356,74 @@ target_perc_uptime_total(const target_t *target) downtime += incidents[i].duration_time; } - return 100.0f * (1.0f - ((float)downtime / (float)(time(NULL) - since))); + return 1.0f - ((float)downtime / (float)(time(NULL) - since)); +} + +int +color_map(float perc) +{ + return 255.0f*exp2f(100.0f*perc-100.0f); +} + +const char * +generate_timeline(const target_t *target, time_t since, time_t span) +{ + static char buff[BUFF_SIZE]; + + char *pos = buff; + + pos += snprintf(pos, BUFF_SIZE - (pos - buff), + "<table class=\"graph\" style=\"width:100%%;\"><tr>"); + + const incident_t *last_incident = NULL; + + for (size_t i = 0; i < incidents_size; i++) { + if (strcmp(incidents[i].service, target->name) != 0) + continue; + + if (incidents[i].started_time + incidents[i].duration_time < since) + continue; + + time_t clamped_duration = incidents[i].duration_time; + if (incidents[i].started_time < since) + clamped_duration -= since - incidents[i].started_time; + + if (last_incident) { + pos += snprintf(pos, BUFF_SIZE - (pos - buff), + "<td class=\"up graph\" style=\"width:%2f%%;\"></td>", + 100.0f*((float)(incidents[i].started_time - + (last_incident->started_time + last_incident->duration_time) + )/(float)span) + ); + } else { + pos += snprintf(pos, BUFF_SIZE - (pos - buff), + "<td class=\"up graph\" style=\"width:%2f%%;\"></td>", + 100.0f*((float)(incidents[i].started_time - since) + /(float)span) + ); + } + + pos += snprintf(pos, BUFF_SIZE - (pos - buff), + "<td class=\"down graph\" style=\"width:%2f%%;\"></td>", + 100.0f*((float)clamped_duration/(float)span) + ); + + last_incident = &incidents[i]; + } + + if (last_incident && last_incident->resolved) { + pos += snprintf(pos, BUFF_SIZE - (pos - buff), + "<td class=\"up graph\" style=\"width:%2f%%;\"></td>", + 100.0f*((float)(time(NULL) - + (last_incident->started_time + last_incident->duration_time) + )/(float)span) + ); + + } + + pos += snprintf(pos, BUFF_SIZE - (pos - buff), "</tr></table>"); + + return buff; } const char * @@ -362,21 +432,30 @@ monitor_generate_status_html() static char buff[BUFF_SIZE]; static char *status_html[] = { - "<td class=\"down\">down</td>", - "<td class=\"up\">up</td>" + "<td class=\"w-min down\">down</td>", + "<td class=\"w-min up\">up</td>" }; char *pos = buff; for (size_t i = 0; i < targets_n; i++) { + float perc_month = target_perc_uptime_since(&targets[i], + time(NULL) - (30*24*3600)); + float perc_total = target_perc_uptime_total(&targets[i]); + pos += snprintf(pos, BUFF_SIZE - (pos - buff), - "<tr><td>%s</td><td>%s</td>%s<td>%s</td><td>%f</td><td>%f</td></tr>\n", + "<tr><td class=\"w-min\">%s</td>" + "<td class=\"w-min\">%s</td>%s<td class=\"w-min\">%s</td>" + "<td class=\"w-min\" style=\"background-color:rgb(%d,%d,0);\">%f</td>" + "<td class=\"w-min\" style=\"background-color:rgb(%d,%d,0);\">%f</td>" + "<td class=\"w-max\">%s</td></tr>\n", type_str[targets[i].type], /* type */ targets[i].target, /* target */ status_html[targets[i].status], /* status */ target_uptime(&targets[i]), /* uptime */ - target_perc_uptime_since(&targets[i], time(NULL) - (30*24*3600)), - target_perc_uptime_total(&targets[i]) + 255-color_map(perc_month), color_map(perc_month), 100.0f*perc_month, + 255-color_map(perc_total), color_map(perc_total), 100.0f*perc_total, + generate_timeline(&targets[i], time(NULL) - 7*24*3600, 7*24*3600) ); } @@ -540,15 +619,24 @@ monitor_update_events() continue; } + if (targets[i].status != targets[i].status_1) { + targets[i].status_1 = targets[i].status; + continue; + } + event_t event = { time_now, - STATUS_UP + targets[i].status }; target_events_push_ordered(&targets[i], &event); printf("[%s] [monitor] %s is now %s\n", timestr, targets[i].name, status_str[targets[i].status]); + + incidents_render(); + + targets[i].status_1 = targets[i].status; } } |
