From: Giuseppe Longo Date: Fri, 9 Oct 2015 07:16:40 +0000 (+0200) Subject: json-stats: print engine stats X-Git-Tag: suricata-4.1.0-beta1~491 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=720cfcfcca6b2355b3d977a2d018f9e3bc068e6e;p=thirdparty%2Fsuricata.git json-stats: print engine stats 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} --- diff --git a/src/output-json-stats.c b/src/output-json-stats.c index 6e78d06acc..1e3dc8dc9a 100644 --- a/src/output-json-stats.c +++ b/src/output-json-stats.c @@ -28,6 +28,7 @@ #include "detect.h" #include "pkt-var.h" #include "conf.h" +#include "detect-engine.h" #include "threads.h" #include "threadvars.h" @@ -51,6 +52,16 @@ #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) { diff --git a/src/output-json-stats.h b/src/output-json-stats.h index 94962a3c99..6cdec99e07 100644 --- a/src/output-json-stats.h +++ b/src/output-json-stats.h @@ -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);