]> git.ipfire.org Git - oddments/collecty.git/commitdiff
sources: Collect metrics from suricata
authorMichael Tremer <michael.tremer@ipfire.org>
Wed, 22 Oct 2025 20:23:00 +0000 (20:23 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Wed, 22 Oct 2025 20:23:00 +0000 (20:23 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
Makefile.am
src/daemon/sources.c
src/daemon/sources/suricata.c [new file with mode: 0644]
src/daemon/sources/suricata.h [new file with mode: 0644]

index 3e9ae768236ff6ffeaa39ea8f9a7542fb044b673..33ef4663e3a16f9c34f205281ed454d80a3a5dec 100644 (file)
@@ -175,6 +175,8 @@ dist_telemetryd_SOURCES = \
        src/daemon/sources/processor.h \
        src/daemon/sources/softirq.c \
        src/daemon/sources/softirq.h \
+       src/daemon/sources/suricata.c \
+       src/daemon/sources/suricata.h \
        src/daemon/sources/test-error.c \
        src/daemon/sources/test-error.h \
        src/daemon/sources/test-flapping.c \
index 90d024f1eca48c4ba99c57129fc6143abc9ce2d4..da920eec1abcf236fa1c6844a54f7580f92c0186 100644 (file)
@@ -42,6 +42,7 @@
 #include "sources/pressure-memory.h"
 #include "sources/processor.h"
 #include "sources/softirq.h"
+#include "sources/suricata.h"
 #include "sources/unbound.h"
 #include "sources/uptime.h"
 
@@ -67,6 +68,7 @@ static const td_source_impl* source_impls[] = {
        &pressure_memory_source,
        &processor_source,
        &softirq_source,
+       &suricata_source,
        &unbound_source,
        &uptime_source,
 
diff --git a/src/daemon/sources/suricata.c b/src/daemon/sources/suricata.c
new file mode 100644 (file)
index 0000000..e317566
--- /dev/null
@@ -0,0 +1,213 @@
+/*#############################################################################
+#                                                                             #
+# telemetryd - The IPFire Telemetry Collection Service                        #
+# Copyright (C) 2025 IPFire Development Team                                  #
+#                                                                             #
+# This program is free software: you can redistribute it and/or modify        #
+# it under the terms of the GNU General Public License as published by        #
+# the Free Software Foundation, either version 3 of the License, or           #
+# (at your option) any later version.                                         #
+#                                                                             #
+# This program is distributed in the hope that it will be useful,             #
+# but WITHOUT ANY WARRANTY; without even the implied warranty of              #
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               #
+# GNU General Public License for more details.                                #
+#                                                                             #
+# You should have received a copy of the GNU General Public License           #
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.       #
+#                                                                             #
+#############################################################################*/
+
+#include <errno.h>
+
+#include <systemd/sd-json.h>
+
+#include "../command.h"
+#include "../ctx.h"
+#include "../source.h"
+#include "../string.h"
+#include "suricata.h"
+
+static int suricata_check_result(td_ctx* ctx, sd_json_variant* json) {
+       sd_json_variant* ret = NULL;
+       const char* value = NULL;
+
+       // Fetch the value of "return"
+       ret = sd_json_variant_by_key(json, "return");
+       if (!ret) {
+               ERROR(ctx, "JSON response does not have a \"return\" field\n");
+               return -EBADMSG;
+       }
+
+       // Fetch the value of "return"
+       value = sd_json_variant_string(ret);
+       if (!value)
+               return -EBADMSG;
+
+       // Check if the value says "OK"
+       if (!td_string_equals(value, "OK"))
+               return -EBADMSG;
+
+       return 0;
+}
+
+static int suricata_parse_uptime(td_ctx* ctx, td_metrics* metrics, sd_json_variant* json) {
+       sd_json_variant* uptime = NULL;
+       uint64_t value = 0;
+
+       // Fetch the uptime
+       uptime = sd_json_variant_by_key(json, "uptime");
+       if (!uptime)
+               return 0;
+
+       // Fetch the value
+       value = sd_json_variant_unsigned(uptime);
+
+       // Submit the value
+       return td_metrics_push_uint64(metrics, "uptime", value);
+}
+
+static int suricata_parse_decoder(td_ctx* ctx, td_metrics* metrics, sd_json_variant* json) {
+       sd_json_variant* decoder = NULL;
+       sd_json_variant* bytes = NULL;
+       sd_json_variant* pkts = NULL;
+       uint64_t value = 0;
+       int r;
+
+       // Fetch the decoder object
+       decoder = sd_json_variant_by_key(json, "decoder");
+       if (!decoder)
+               return 0;
+
+       // Fetch pkts
+       pkts = sd_json_variant_by_key(decoder, "pkts");
+       if (pkts) {
+               // Fetch the value
+               value = sd_json_variant_unsigned(pkts);
+
+               // Submit value
+               r = td_metrics_push_uint64(metrics, "decoder_pkts", value);
+               if (r < 0)
+                       return r;
+       }
+
+       // Fetch bytes
+       bytes = sd_json_variant_by_key(decoder, "bytes");
+       if (bytes) {
+               // Fetch the value
+               value = sd_json_variant_unsigned(bytes);
+
+               // Submit value
+               r = td_metrics_push_uint64(metrics, "decoder_bytes", value);
+               if (r < 0)
+                       return r;
+       }
+
+       return 0;
+}
+
+
+static int suricata_parse_message(td_ctx* ctx, td_metrics* metrics, sd_json_variant* json) {
+       sd_json_variant* msg = NULL;
+       int r;
+
+       // Fetch the message
+       msg = sd_json_variant_by_key(json, "message");
+       if (!msg) {
+               ERROR(ctx, "JSON response does not have a \"message\" field\n");
+               return -EBADMSG;
+       }
+
+       // Parse the uptime
+       r = suricata_parse_uptime(ctx, metrics, msg);
+       if (r < 0)
+               return r;
+
+       // Parse the decoder
+       r = suricata_parse_decoder(ctx, metrics, msg);
+       if (r < 0)
+               return r;
+
+       return 0;
+}
+
+static int suricata_on_success(td_ctx* ctx, int rc, td_file* stdout, void* data) {
+       sd_json_variant* json = NULL;
+       td_metrics* metrics = NULL;
+       td_source* source = data;
+       int r;
+
+       // Parse the output as JSON
+       r = td_file_parse_json(stdout, &json, 0);
+       if (r < 0)
+               goto ERROR;
+
+       // Check the result
+       r = suricata_check_result(ctx, json);
+       if (r < 0)
+               goto ERROR;
+
+       // Create a new metrics object
+       r = td_source_create_metrics(source, &metrics, NULL);
+       if (r < 0)
+               goto ERROR;
+
+       // Parse the message
+       r = suricata_parse_message(ctx, metrics, json);
+       if (r < 0)
+               goto ERROR;
+
+       // Submit all collected metrics
+       r = td_source_submit_metrics(source, metrics);
+
+ERROR:
+       if (json)
+               sd_json_variant_unref(json);
+       if (metrics)
+               td_metrics_unref(metrics);
+
+       return r;
+}
+
+static int suricata_heartbeat(td_ctx* ctx, td_source* source) {
+       td_command* command = NULL;
+       int r;
+
+       // Run suricatasc to fetch all counters
+       const char* argv[] = { "suricatasc", "--command=dump-counters", NULL };
+
+       // Create a new command
+       r = td_source_create_command(source, &command);
+       if (r < 0)
+               goto ERROR;
+
+       // Register the success callback
+       td_command_on_success(command, suricata_on_success, source);
+
+       // Execute the command
+       r = td_command_execute(command, argv);
+
+ERROR:
+       if (command)
+               td_command_unref(command);
+
+       return r;
+}
+
+const td_source_impl suricata_source = {
+       .name = "suricata",
+
+       // RRD Data Sources
+       .rrd_dss = {
+               { "uptime",          "COUNTER",  0, -1, },
+
+               // Decoder
+               { "decoder_pkts",    "DERIVE",   0, -1, },
+               { "decoder_bytes",   "DERIVE",   0, -1, },
+
+               { NULL },
+       },
+
+       // Methods
+       .heartbeat = suricata_heartbeat,
+};
diff --git a/src/daemon/sources/suricata.h b/src/daemon/sources/suricata.h
new file mode 100644 (file)
index 0000000..bdf9295
--- /dev/null
@@ -0,0 +1,28 @@
+/*#############################################################################
+#                                                                             #
+# telemetryd - The IPFire Telemetry Collection Service                        #
+# Copyright (C) 2025 IPFire Development Team                                  #
+#                                                                             #
+# This program is free software: you can redistribute it and/or modify        #
+# it under the terms of the GNU General Public License as published by        #
+# the Free Software Foundation, either version 3 of the License, or           #
+# (at your option) any later version.                                         #
+#                                                                             #
+# This program is distributed in the hope that it will be useful,             #
+# but WITHOUT ANY WARRANTY; without even the implied warranty of              #
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               #
+# GNU General Public License for more details.                                #
+#                                                                             #
+# You should have received a copy of the GNU General Public License           #
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.       #
+#                                                                             #
+#############################################################################*/
+
+#ifndef TELEMETRY_SOURCE_SURICATA_H
+#define TELEMETRY_SOURCE_SURICATA_H
+
+#include "../source.h"
+
+extern const td_source_impl suricata_source;
+
+#endif /* TELEMETRY_SOURCE_SURICATA_H */