[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH 07/23] load events


MIME-Version: 1.0
Content-Transfer-Encoding: 8bit

From: arf20 <aruizfernandez05@xxxxxxxxx>

---
 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%;
-}
-        </style>
+</style>
     </head>
 
     <body>
@@ -36,25 +28,17 @@ table, th, td {
         <main>
             <h2 class="center">Status Monitor</h2>
             <p>This webapp monitors the status of the main ARFNET services from outside the ARFNET network</p>
-            <div class="col">
-                Services
-                <table>
-                    <tr><th>Type</th><th>Service</th><th>Status</th></tr>
-                    %s
-                </table>
-            </div>
-            <div class="col">
-                Uptime
-                <table>
-                    <tr><th>Week %%up</th><th>Month %%up</th><th>Total %%up since %s</th></tr>
-                    <tr><td>%s</td><td>%s</td><td>%s</td></tr>
-                </table>
-                Incidents
-                <table>
-                    <tr><th>Resolved</th><th>Started</th><th>Duration</th></tr>
-                    <tr>%s</tr>
-                </table>
-            </div>
+            Services
+            <table>
+                <tr><th>Type</th><th>Service</th><th>Status</th><th>Uptime</th><th>%%up month</th><th>%%up total</th></tr>
+                %s
+            </table>
+            <br><br>
+            Incidents
+            <table>
+                <tr><th>Resolved</th><th>Started</th><th>Duration</th></tr>
+                %s
+            </table>
         </main>
     </body>
 </html>
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 <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -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[] = {
         "<td class=\"down\">down</td>",
@@ -108,16 +204,31 @@ monitor_generate_status_html()
     char *pos = buff;
 
     for (size_t i = 0; i < target_n; i++) {
-        pos += snprintf(pos, 65535,
-            "<tr><td>%s</td><td>%s</td>%s</tr>\n",
+        pos += snprintf(pos, BUFF_SIZE,
+            "<tr><td>%s</td><td>%s</td>%s<td></td><td>%s</td><td>%s</td>%s</tr>\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, "<tr><td></td><td></td><td></td></tr>");
+
+    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();
 
-- 
2.47.3


References:
[arfnet2-status PATCH 00/23] First releasearf20 <arf20@xxxxxxxxx>