]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
json-stats: print engine stats
authorGiuseppe Longo <glongo@stamus-networks.com>
Fri, 9 Oct 2015 07:16:40 +0000 (09:16 +0200)
committerVictor Julien <victor@inliniac.net>
Fri, 8 Dec 2017 14:22:57 +0000 (15:22 +0100)
This adds the engine stats in stats event.
If multi-tenancy is enabled, it will add
stats for each tenant

The following is a snippet of the generated EVE entry:

"detect":{"engines":[{"last_reload":"2015-10-13T09:59:48.044996+0200","rules_loaded":17184,"rules_failed":0}],"alert":28}

Multi-tenancy enabled:

"detect":{"engines":[{"id":1,"last_reload":"2015-10-13T09:56:46.447153+0200","rules_loaded":17084,"rules_failed":0},
                     {"id":2,"last_reload":"2015-10-13T09:56:36.504877+0200","rules_loaded":3268,"rules_failed":0}],
                     "alert":28}

src/output-json-stats.c
src/output-json-stats.h

index 6e78d06acc39111efc37d399f821d368707d0168..1e3dc8dc9a9bd81045ea4edeb21b8b5216a9b42f 100644 (file)
@@ -28,6 +28,7 @@
 #include "detect.h"
 #include "pkt-var.h"
 #include "conf.h"
+#include "detect-engine.h"
 
 #include "threads.h"
 #include "threadvars.h"
 
 #ifdef HAVE_LIBJANSSON
 
+/**
+ * specify which engine info will be printed in stats log.
+ * ALL means both last reload and ruleset stats.
+ */
+typedef enum OutputEngineInfo_ {
+    OUTPUT_ENGINE_LAST_RELOAD = 0,
+    OUTPUT_ENGINE_RULESET,
+    OUTPUT_ENGINE_ALL,
+} OutputEngineInfo;
+
 typedef struct OutputStatsCtx_ {
     LogFileCtx *file_ctx;
     uint32_t flags; /** Store mode */
@@ -61,6 +72,98 @@ typedef struct JsonStatsLogThread_ {
     MemBuffer *buffer;
 } JsonStatsLogThread;
 
+static json_t *EngineStats2Json(const DetectEngineCtx *de_ctx,
+                                const OutputEngineInfo output)
+{
+    struct timeval last_reload;
+    char timebuf[64];
+    const SigFileLoaderStat *sig_stat = NULL;
+
+    json_t *jdata = json_object();
+    if (jdata == NULL) {
+        return NULL;
+    }
+
+    if (output == OUTPUT_ENGINE_LAST_RELOAD || output == OUTPUT_ENGINE_ALL) {
+        last_reload = de_ctx->last_reload;
+        CreateIsoTimeString(&last_reload, timebuf, sizeof(timebuf));
+        json_object_set_new(jdata, "last_reload", json_string(timebuf));
+    }
+
+    sig_stat = &de_ctx->sig_stat;
+    if ((output == OUTPUT_ENGINE_RULESET || output == OUTPUT_ENGINE_ALL) &&
+        sig_stat != NULL)
+    {
+        json_object_set_new(jdata, "rules_loaded",
+                            json_integer(sig_stat->good_sigs_total));
+        json_object_set_new(jdata, "rules_failed",
+                            json_integer(sig_stat->bad_sigs_total));
+    }
+
+    return jdata;
+}
+
+static TmEcode OutputEngineStats2Json(json_t **jdata, const OutputEngineInfo output)
+{
+    DetectEngineCtx *de_ctx = DetectEngineGetCurrent();
+    if (de_ctx == NULL) {
+        goto err1;
+    }
+    /* Since we need to deference de_ctx pointer, we don't want to lost it. */
+    DetectEngineCtx *list = de_ctx;
+
+    json_t *js_tenant_list = json_array();
+    json_t *js_tenant = NULL;
+
+    if (js_tenant_list == NULL) {
+        goto err2;
+    }
+
+    while(list) {
+        js_tenant = json_object();
+        if (js_tenant == NULL) {
+            goto err3;
+        }
+        json_object_set_new(js_tenant, "id", json_integer(list->tenant_id));
+
+        json_t *js_stats = EngineStats2Json(list, output);
+        if (js_stats == NULL) {
+            goto err4;
+        }
+        json_object_update(js_tenant, js_stats);
+        json_array_append_new(js_tenant_list, js_tenant);
+        json_decref(js_stats);
+        list = list->next;
+    }
+
+    DetectEngineDeReference(&de_ctx);
+    *jdata = js_tenant_list;
+    return TM_ECODE_OK;
+
+err4:
+    json_object_clear(js_tenant);
+    json_decref(js_tenant);
+
+err3:
+    json_object_clear(js_tenant_list);
+    json_decref(js_tenant_list);
+
+err2:
+    DetectEngineDeReference(&de_ctx);
+
+err1:
+    json_object_set_new(*jdata, "message", json_string("Unable to get info"));
+    return TM_ECODE_FAILED;
+}
+
+TmEcode OutputEngineStatsReloadTime(json_t **jdata) {
+    return OutputEngineStats2Json(jdata, OUTPUT_ENGINE_LAST_RELOAD);
+}
+
+TmEcode OutputEngineStatsRuleset(json_t **jdata) {
+    return OutputEngineStats2Json(jdata, OUTPUT_ENGINE_RULESET);
+}
+
 static json_t *OutputStats2Json(json_t *js, const char *key)
 {
     void *iter;
@@ -83,6 +186,15 @@ static json_t *OutputStats2Json(json_t *js, const char *key)
     json_t *value = json_object_iter_value(iter);
     if (value == NULL) {
         value = json_object();
+
+        if (!strncmp(s, "detect", 6)) {
+            json_t *js_engine = NULL;
+
+            TmEcode ret = OutputEngineStats2Json(&js_engine, OUTPUT_ENGINE_ALL);
+            if (ret == TM_ECODE_OK && js_engine) {
+                json_object_set_new(value, "engines", js_engine);
+            }
+        }
         json_object_set_new(js, s, value);
     }
     if (s2 != NULL) {
index 94962a3c99bbab737dfaa1af6d114589a04db7e0..6cdec99e07a95626dc46edcf905576f53dd1c4ab 100644 (file)
@@ -32,6 +32,8 @@
 
 #ifdef HAVE_LIBJANSSON
 json_t *StatsToJSON(const StatsTable *st, uint8_t flags);
+TmEcode OutputEngineStatsReloadTime(json_t **jdata);
+TmEcode OutputEngineStatsRuleset(json_t **jdata);
 #endif
 void JsonStatsLogRegister(void);