From: Jeff Lucovsky Date: Wed, 26 Jul 2023 12:46:00 +0000 (-0400) Subject: output/stats: Handle stat names w/out scope X-Git-Tag: suricata-7.0.1~76 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=2d96b6e13b799fa40a5d3a7d5cd7729af614ab1a;p=thirdparty%2Fsuricata.git output/stats: Handle stat names w/out scope Issue: 6094 Not all stat names are scoped, e.g. decoder.pkts is scoped to decoder; mempressure_max is unscoped. The concept of a short-name is added to the underlying stat structure so - Calculation is done once, at stat registration time - The output code can easily determine if a stat has a scope --- diff --git a/src/counters.c b/src/counters.c index 7acdeae626..e3ed5244cd 100644 --- a/src/counters.c +++ b/src/counters.c @@ -611,6 +611,12 @@ static uint16_t StatsRegisterQualifiedCounter(const char *name, const char *tm_n * thread context. Please note that the id start from 1, and not 0 */ pc->id = ++(pctx->curr_id); pc->name = name; + + /* Precalculate the short name */ + if (strrchr(name, '.') != NULL) { + pc->short_name = &name[strrchr(name, '.') - name + 1]; + } + pc->type = type_q; pc->Func = Func; @@ -729,6 +735,7 @@ static int StatsOutput(ThreadVars *tv) } thread_table[pc->gid].updates = pc->updates; table[pc->gid].name = pc->name; + table[pc->gid].short_name = pc->short_name; pc = pc->next; } @@ -773,6 +780,7 @@ static int StatsOutput(ThreadVars *tv) r->pvalue = r->value; r->value = 0; r->name = table[c].name; + r->short_name = table[c].short_name; r->tm_name = sts->name; switch (e->type) { diff --git a/src/counters.h b/src/counters.h index d43538b1d8..b1505e750a 100644 --- a/src/counters.h +++ b/src/counters.h @@ -52,6 +52,7 @@ typedef struct StatsCounter_ { /* name of the counter */ const char *name; + const char *short_name; /* the next perfcounter for this tv's tm instance */ struct StatsCounter_ *next; diff --git a/src/output-json-stats.c b/src/output-json-stats.c index d08d62044b..7bfcfc58ca 100644 --- a/src/output-json-stats.c +++ b/src/output-json-stats.c @@ -227,20 +227,24 @@ json_t *StatsToJSON(const StatsTable *st, uint8_t flags) for (u = 0; u < st->nstats; u++) { if (st->stats[u].name == NULL) continue; - const char *name = st->stats[u].name; - const char *shortname = name; - if (strrchr(name, '.') != NULL) { - shortname = &name[strrchr(name, '.') - name + 1]; + json_t *js_type = NULL; + const char *stat_name = st->stats[u].short_name; + /* + * When there's no short-name, the stat is added to + * the "global" stats namespace, just like "uptime" + */ + if (st->stats[u].short_name == NULL) { + stat_name = st->stats[u].name; + js_type = js_stats; + } else { + js_type = OutputStats2Json(js_stats, st->stats[u].name); } - json_t *js_type = OutputStats2Json(js_stats, name); if (js_type != NULL) { - json_object_set_new(js_type, shortname, - json_integer(st->stats[u].value)); + json_object_set_new(js_type, stat_name, json_integer(st->stats[u].value)); if (flags & JSON_STATS_DELTAS) { - char deltaname[strlen(shortname) + strlen(delta_suffix) + 1]; - snprintf(deltaname, sizeof(deltaname), "%s%s", shortname, - delta_suffix); + char deltaname[strlen(stat_name) + strlen(delta_suffix) + 1]; + snprintf(deltaname, sizeof(deltaname), "%s%s", stat_name, delta_suffix); json_object_set_new(js_type, deltaname, json_integer(st->stats[u].value - st->stats[u].pvalue)); } @@ -265,18 +269,23 @@ json_t *StatsToJSON(const StatsTable *st, uint8_t flags) if (st->tstats[u].name == NULL) continue; - char str[256]; - snprintf(str, sizeof(str), "%s.%s", st->tstats[u].tm_name, st->tstats[u].name); - char *shortname = &str[strrchr(str, '.') - str + 1]; - json_t *js_type = OutputStats2Json(threads, str); + json_t *js_type = NULL; + const char *stat_name = st->tstats[u].short_name; + if (st->tstats[u].short_name == NULL) { + stat_name = st->tstats[u].name; + js_type = threads; + } else { + char str[256]; + snprintf(str, sizeof(str), "%s.%s", st->tstats[u].tm_name, st->tstats[u].name); + js_type = OutputStats2Json(threads, str); + } if (js_type != NULL) { - json_object_set_new(js_type, shortname, json_integer(st->tstats[u].value)); + json_object_set_new(js_type, stat_name, json_integer(st->tstats[u].value)); if (flags & JSON_STATS_DELTAS) { - char deltaname[strlen(shortname) + strlen(delta_suffix) + 1]; - snprintf(deltaname, sizeof(deltaname), "%s%s", - shortname, delta_suffix); + char deltaname[strlen(stat_name) + strlen(delta_suffix) + 1]; + snprintf(deltaname, sizeof(deltaname), "%s%s", stat_name, delta_suffix); json_object_set_new(js_type, deltaname, json_integer(st->tstats[u].value - st->tstats[u].pvalue)); } diff --git a/src/output-stats.h b/src/output-stats.h index d2df64c343..f6fc6a8b27 100644 --- a/src/output-stats.h +++ b/src/output-stats.h @@ -30,6 +30,7 @@ typedef struct StatsRecord_ { const char *name; + const char *short_name; const char *tm_name; int64_t value; /**< total value */ int64_t pvalue; /**< prev value (may be higher for memuse counters) */