]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: stats: support age in stats-file
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Tue, 30 Apr 2024 12:09:36 +0000 (14:09 +0200)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Thu, 2 May 2024 08:55:25 +0000 (10:55 +0200)
Extend generic stat column support to be able to fully support age stats
type. Several changes were required.

On output, me_generate_field() has been updated to report the difference
between the current tick with the stored value for FN_AGE type. Also, if
an age stats is hidden in show stats, -1 is returned instead of an empty
metric, which is the value to mark an age as unset.

On counters preload, load_ctr() was updated to handled FN_AGE. A similar
substraction is performed to the current tick value.

src/stats-file.c
src/stats.c

index 4f07ddc903b82da635e33a160cb01da06522b37d..c63916ea01ee48e852134f7e4e2268ac1efa9a49 100644 (file)
@@ -10,6 +10,7 @@
 #include <haproxy/api.h>
 #include <haproxy/buf.h>
 #include <haproxy/chunk.h>
+#include <haproxy/clock.h>
 #include <haproxy/errors.h>
 #include <haproxy/global.h>
 #include <haproxy/guid.h>
@@ -20,6 +21,7 @@
 #include <haproxy/proxy-t.h>
 #include <haproxy/server-t.h>
 #include <haproxy/stats.h>
+#include <haproxy/time.h>
 
 /* Dump all fields from <stats> into <out> for stats-file. */
 int stats_dump_fields_file(struct buffer *out,
@@ -211,6 +213,7 @@ static int load_ctr(const struct stat_col *col, const struct ist token,
                value.u.u64 = read_uint64(&ptr, istend(token));
                break;
 
+       case FF_S32:
        case FF_U32:
                value.u.u32 = read_uint(&ptr, istend(token));
                break;
@@ -230,6 +233,9 @@ static int load_ctr(const struct stat_col *col, const struct ist token,
        else if (fn == FN_RATE && ff == FF_U32) {
                preload_freq_ctr(counter, value.u.u32);
        }
+       else if (fn == FN_AGE && (ff == FF_U32 || ff == FF_S32)) {
+               *(uint32_t *)counter = ns_to_sec(now_ns) - value.u.u32;
+       }
        else {
                /* Unsupported field format/nature combination. */
                return 1;
index e792f86526ce5c0fc46ec9163e20ed73000032a8..57b386b6624e67f97db6e20578a22de75c1c13b3 100644 (file)
@@ -742,6 +742,8 @@ static struct field me_generate_field(const struct stat_col *col,
        /* Only generic stat column must be used as input. */
        BUG_ON(!stcol_is_generic(col));
 
+       fn = stcol_nature(col);
+
        switch (cap) {
        case STATS_PX_CAP_FE:
        case STATS_PX_CAP_LI:
@@ -786,11 +788,17 @@ static struct field me_generate_field(const struct stat_col *col,
        }
        else {
                /* Ensure metric is defined for the current cap. */
-               if (!(col->cap & cap) || stcol_hide(idx, objt))
+               if (!(col->cap & cap))
                        return (struct field){ .type = FF_EMPTY };
+
+               if (stcol_hide(idx, objt)) {
+                       if (fn == FN_AGE)
+                               return mkf_s32(FN_AGE, -1);
+                       else
+                               return (struct field){ .type = FF_EMPTY };
+               }
        }
 
-       fn = stcol_nature(col);
        if (fn == FN_COUNTER) {
                switch (stcol_format(col)) {
                case FF_U64:
@@ -806,6 +814,23 @@ static struct field me_generate_field(const struct stat_col *col,
                BUG_ON(stcol_format(col) != FF_U32);
                value = mkf_u32(FN_RATE, read_freq_ctr(counter));
        }
+       else if (fn == FN_AGE) {
+               unsigned long age = *(unsigned long *)counter;
+               if (age)
+                       age = ns_to_sec(now_ns) - age;
+
+               switch (stcol_format(col)) {
+               case FF_U32:
+                       value = mkf_u32(FN_AGE, age);
+                       break;
+               case FF_S32:
+                       value = mkf_s32(FN_AGE, age);
+                       break;
+               default:
+                       /* only FF_U32/FF+S32 for age as generic stat column */
+                       ABORT_NOW();
+               }
+       }
        else {
                /* No generic column available for other field nature. */
                ABORT_NOW();