MINOR: stats: support age in stats-file

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.
This commit is contained in:
Amaury Denoyelle 2024-04-30 14:09:36 +02:00
parent 634cc2a5d8
commit e92ae8f0ba
2 changed files with 33 additions and 2 deletions

View 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;

View 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();