aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--events.log74
-rw-r--r--index.htm.tmpl40
-rw-r--r--main.c5
-rw-r--r--monitor.c157
-rw-r--r--monitor.cfg10
-rw-r--r--monitor.h2
6 files changed, 231 insertions, 57 deletions
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,
@@ -22,27 +26,108 @@ typedef enum {
} 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();