From 6acd5a85f7ec11fe59b16d5e7fd621abf5ca49c6 Mon Sep 17 00:00:00 2001 From: arf20 Date: Wed, 22 Oct 2025 01:20:53 +0200 Subject: load events --- events.log | 74 +++++++++++++++++++++++++++ index.htm.tmpl | 40 +++++---------- main.c | 5 +- monitor.c | 157 +++++++++++++++++++++++++++++++++++++++++++++++++-------- monitor.cfg | 10 ++-- monitor.h | 2 +- 6 files changed, 231 insertions(+), 57 deletions(-) create mode 100644 events.log diff --git a/events.log b/events.log new file mode 100644 index 0000000..3c3ddf5 --- /dev/null +++ b/events.log @@ -0,0 +1,74 @@ +# ARFNET status monitor incident log +http,2024-11-30 22:23:07,down +http,2024-11-30 23:56:19,up +http,2024-12-05 06:51:49,down +http,2024-12-05 10:45:01,up +http,2024-12-10 23:26:30,down +http,2024-12-11 04:09:34,up +http,2024-12-11 15:28:06,down +http,2024-12-11 15:31:15,up +http,2024-12-16 09:19:30,down +http,2024-12-16 09:27:39,up +http,2025-01-10 01:30:00,down +http,2025-01-10 01:43:09,up +http,2025-01-11 16:13:35,down +http,2025-01-11 16:16:45,up +http,2025-01-11 16:24:26,down +http,2025-01-11 17:12:36,up +http,2025-01-31 19:17:38,down +http,2025-01-31 19:50:48,up +http,2025-02-04 07:10:33,down +http,2025-02-04 08:23:39,up +http,2025-02-05 07:18:57,down +http,2025-02-05 08:27:06,up +http,2025-02-07 02:29:16,down +http,2025-02-07 02:36:55,up +http,2025-02-18 01:11:37,down +http,2025-02-18 01:24:45,up +http,2025-02-18 01:32:24,down +http,2025-02-18 01:40:35,up +http,2025-02-28 19:11:04,down +http,2025-02-28 20:04:13,up +http,2025-03-06 19:10:07,down +http,2025-03-06 19:15:09,up +http,2025-03-12 01:09:30,down +http,2025-03-12 01:14:33,up +http,2025-03-12 01:20:15,down +http,2025-03-12 01:25:19,up +http,2025-04-08 23:15:32,down +http,2025-04-08 23:20:37,up +http,2025-04-28 10:44:56,down +http,2025-04-28 21:41:33,up +http,2025-06-25 08:07:38,down +http,2025-06-25 08:12:40,up +http,2025-06-25 08:23:39,down +http,2025-06-25 08:33:51,up +http,2025-06-25 12:37:58,down +http,2025-06-25 12:43:03,up +http,2025-06-26 20:36:44,down +http,2025-06-26 21:54:25,up +http,2025-06-27 13:02:01,down +http,2025-06-27 13:12:16,up +http,2025-06-27 14:14:15,down +http,2025-06-27 14:19:19,up +http,2025-06-29 15:58:44,down +http,2025-06-29 17:47:37,up +http,2025-06-29 18:59:38,down +http,2025-06-29 19:09:53,up +http,2025-07-02 09:33:20,down +http,2025-07-02 09:43:34,up +http,2025-07-20 23:48:33,down +http,2025-07-20 23:53:35,up +http,2025-08-10 08:06:27,down +http,2025-08-10 17:42:24,up +http,2025-08-20 13:40:45,down +http,2025-08-20 15:39:56,up +http,2025-08-21 11:47:02,down +http,2025-08-21 16:11:47,up +http,2025-08-26 11:04:32,down +http,2025-08-26 11:14:47,up +http,2025-08-26 11:46:20,down +http,2025-08-26 11:51:24,up +http,2025-08-26 14:39:43,down +http,2025-08-26 14:44:45,up + diff --git a/index.htm.tmpl b/index.htm.tmpl index 0372cc7..cf90884 100644 --- a/index.htm.tmpl +++ b/index.htm.tmpl @@ -17,15 +17,7 @@ table, th, td { background-color: red; } -.row { - -} - -.col { - float: left; - width: 50%; -} - + @@ -36,25 +28,17 @@ table, th, td {

Status Monitor

This webapp monitors the status of the main ARFNET services from outside the ARFNET network

-
- Services - - - %s -
TypeServiceStatus
-
-
- Uptime - - - -
Week %%upMonth %%upTotal %%up since %s
%s%s%s
- Incidents - - - %s -
ResolvedStartedDuration
-
+ Services + + + %s +
TypeServiceStatusUptime%%up month%%up total
+

+ Incidents + + + %s +
ResolvedStartedDuration
diff --git a/main.c b/main.c index 05925fd..fdfc5cd 100644 --- a/main.c +++ b/main.c @@ -51,8 +51,7 @@ enum MHD_Result answer_to_connection( if (strcmp(method, "GET") == 0 && strcmp(url, "/") == 0) { snprintf(buff, RES_BUFF, index_format_template, - monitor_generate_status_html(), "(since)", "(week %up)", - "(month %up)", "(total %up)", "(incidents)"); + monitor_generate_status_html(), "(incidents)"); response = MHD_create_response_from_buffer(strlen(buff), (void*)buff, MHD_RESPMEM_PERSISTENT); @@ -98,7 +97,7 @@ int main() { return 1; } - monitor_init("monitor.cfg"); + monitor_init("monitor.cfg", "events.log"); while (1) { monitor_check(); diff --git a/monitor.c b/monitor.c index f965417..41bcc61 100644 --- a/monitor.c +++ b/monitor.c @@ -1,3 +1,4 @@ +#define _GNU_SOURCE /* forgive me */ #include #include #include @@ -8,6 +9,9 @@ #include "monitor.h" +#define BUFF_SIZE 65535 +#define INIT_VEC_CAPACITY 256 + typedef enum { TYPE_REACH, TYPE_DNS, @@ -21,28 +25,109 @@ typedef enum { STATUS_UP } status_t; +typedef struct { + time_t time; + status_t status; +} event_t; + typedef struct { type_t type; + char *name; char *target; + status_t status; + + event_t *events; + size_t event_size, event_capacity; } target_t; -static target_t targets[256]; +static target_t targets[INIT_VEC_CAPACITY]; static size_t target_n = 0; static char timestr[256]; -static size_t -write_data(void *ptr, size_t size, size_t nmemb, void *stream) + + +static void +target_events_push(target_t *target, event_t event) { - return size * nmemb; + if (target->event_size + 1 > target->event_capacity) + target->events = realloc(target->events, 2 * target->event_capacity); + + target->events[target->event_size++] = event; +} + +static size_t +target_events_load(target_t *target, const char *logbuff) { + char line[256]; + size_t n = 0; + + while (*logbuff) { + char *nlpos = strchr(logbuff, '\n'); + if (!nlpos) + return n; + + size_t linelen = nlpos - logbuff; + strncpy(line, logbuff, linelen); + line[linelen] = '\0'; + logbuff += linelen + 1; + + /* process line */ + if (line[0] == '\0' || line[0] == '#') + continue; + + char *name = strtok(line, ","); + char *time = strtok(NULL, ","); + char *status = strtok(NULL, ","); + + if (!name || !time || !status) { + fprintf(stderr, "malformed log line: %s\n", line); + continue; + } + + if (strcmp(name, target->name) != 0) + continue; + + struct tm event_time; + strptime(time, "%Y-%m-%d %H-%M-%S", &event_time); + + event_t event = { + mktime(&event_time), + strcmp(status, "up") == 0 ? STATUS_UP : STATUS_DOWN + }; + + target_events_push(target, event); + + n++; + } + + return n; } int -monitor_init(const char *cfg_file) { - FILE *cfgf = fopen(cfg_file, "r"); +monitor_init(const char *cfg_path, const char *log_path) { + /* read monitor log */ + FILE *logf = fopen(log_path, "r"); + if (!logf) { + fprintf(stderr, "Error opening log: %s\n", strerror(errno)); + return -1; + } + + fseek(logf, 0, SEEK_END); + size_t logsize = ftell(logf); + rewind(logf); + + char *logbuff = malloc(logsize + 1); + size_t logread = fread(logbuff, 1, logsize, logf); + fclose(logf); + + logbuff[logread] = '\0'; + + + /* read monitoring configuration */ + FILE *cfgf = fopen(cfg_path, "r"); if (!cfgf) { fprintf(stderr, "Error opening config: %s\n", strerror(errno)); return -1; @@ -57,16 +142,15 @@ monitor_init(const char *cfg_file) { line[strlen(line) - 1] = '\0'; /* strip \n */ - char *type = line; - char *target = strchr(line, '='); - if (!target) { + char *type = strtok(line, ","); + char *name = strtok(NULL, ","); + char *target = strtok(NULL, ","); + + if (!target || !name || !target) { fprintf(stderr, "malformed config line: %s\n", line); continue; } - *target = '\0'; - target++; - if (strcmp(type, "reach") == 0) targets[target_n].type = TYPE_REACH; else if (strcmp(type, "dns") == 0) @@ -74,11 +158,23 @@ monitor_init(const char *cfg_file) { else if (strcmp(type, "web") == 0) targets[target_n].type = TYPE_WEB; + targets[target_n].name = strdup(name); targets[target_n].target = strdup(target); targets[target_n].status = STATUS_DOWN; - printf("\t%s: %s\n", type_str[targets[target_n].type], - targets[target_n].target); + /* read monitor logs */ + targets[target_n].event_capacity = INIT_VEC_CAPACITY; + targets[target_n].event_size = 0; + targets[target_n].events = malloc(INIT_VEC_CAPACITY * sizeof(event_t)); + + size_t event_n = target_events_load(&targets[target_n], logbuff); + + printf("\t%s: %s,%s %ld events\n", + targets[target_n].name, + type_str[targets[target_n].type], + targets[target_n].target, + event_n + ); target_n++; } @@ -98,7 +194,7 @@ monitor_init(const char *cfg_file) { const char * monitor_generate_status_html() { - static char buff[65535]; + static char buff[BUFF_SIZE]; static char *status_html[] = { "down", @@ -108,16 +204,31 @@ monitor_generate_status_html() char *pos = buff; for (size_t i = 0; i < target_n; i++) { - pos += snprintf(pos, 65535, - "%s%s%s\n", + pos += snprintf(pos, BUFF_SIZE, + "%s%s%s%s%s%s\n", type_str[targets[i].type], targets[i].target, - status_html[targets[i].status]); + status_html[targets[i].status], + "", + "", + "" + ); } return buff; } + +const char * +monitor_generate_incidents_html() +{ + static char buff[BUFF_SIZE]; + + snprintf(buff, BUFF_SIZE, ""); + + return buff; +} + static int check_reach(const char *target) { @@ -169,6 +280,12 @@ check_dns(const char *name) return STATUS_UP; } +static size_t +write_data(void *ptr, size_t size, size_t nmemb, void *stream) +{ + return size * nmemb; +} + static int check_http(const char *endpoint) { @@ -215,8 +332,8 @@ monitor_check() }; for (size_t i = 0; i < target_n; i++) { - printf("[%s] [monitor] check #%ld %s: %s: ", - timestr, check_num, type_str[targets[i].type], targets[i].target); + printf("[%s] [monitor] check #%ld %s: ", + timestr, check_num, targets[i].name); targets[i].status = check_funcs[targets[i].type](targets[i].target); } diff --git a/monitor.cfg b/monitor.cfg index b34ec8a..ee4c4a1 100644 --- a/monitor.cfg +++ b/monitor.cfg @@ -1,7 +1,7 @@ # Monitor config -# type=target -reach=10.0.0.0 -dns=arf20.co -web=http://arf20.com:4321 -web=https://arf20.co +# type,name,target +reach,ipv4,10.0.0.0 +dns,dns,arf20.co +web,http,http://arf20.com:4321 +web,https,https://arf20.co diff --git a/monitor.h b/monitor.h index f9d4458..b9ab3c9 100644 --- a/monitor.h +++ b/monitor.h @@ -1,7 +1,7 @@ #ifndef _MONITOR_H #define _MONITOR_H -int monitor_init(const char *cfg_file); +int monitor_init(const char *cfg_file, const char *log_file); const char *monitor_generate_status_html(); void monitor_check(); -- cgit v1.2.3