]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
output/stats: Handle stat names w/out scope
authorJeff Lucovsky <jlucovsky@oisf.net>
Wed, 26 Jul 2023 12:46:00 +0000 (08:46 -0400)
committerVictor Julien <vjulien@oisf.net>
Thu, 27 Jul 2023 07:21:30 +0000 (09:21 +0200)
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

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

index 7acdeae62636c0439e5b8db0c356a32f38f04b5f..e3ed5244cdfe688e0091ae795098bfff0a8e4db5 100644 (file)
@@ -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) {
index d43538b1d8d02cf3b9a2dae15eb1c7f0847f5344..b1505e750a7dad99932d1efa1fad28465e94b676 100644 (file)
@@ -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;
index d08d62044b6a65a7b269eb6c87008b1a9ef3cfd5..7bfcfc58cad24aa8c962245f2967f057048e9bf2 100644 (file)
@@ -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));
                     }
index d2df64c343de3b0fb13e77c265b15b8ab82a8914..f6fc6a8b2716d7133e090b5104416e96b666d709 100644 (file)
@@ -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) */