MEDIUM: stats: add delimiter for static proxy stats on csv
Use the character '-' to mark the end of static statistics on proxy
domain. After this marker, the order of the fields is not guaranteed and
should be parsed with care.
diff --git a/doc/management.txt b/doc/management.txt
index 9a749e4..151c96e 100644
--- a/doc/management.txt
+++ b/doc/management.txt
@@ -961,10 +961,14 @@
do not insert any column before these ones in order not to break tools which
use hard-coded column positions.
-In brackets after each field name are the types which may have a value for
-that field. The types are L (Listeners), F (Frontends), B (Backends), and
-S (Servers).
+For proxy statistics, after each field name, the types which may have a value
+for that field are specified in brackets. The types are L (Listeners), F
+(Frontends), B (Backends), and S (Servers). There is a fixed set of static
+fields that are always available in the same order. A column containing the
+character '-' delimits the end of the static fields, after which presence or
+order of the fields are not guaranteed.
+Here is the list of static fields using the proxy statistics domain:
0. pxname [LFBS]: proxy name
1. svname [LFBS]: service name (FRONTEND for frontend, BACKEND for backend,
any name for server/listener)
@@ -1122,6 +1126,9 @@
93. ttime_max [..BS]: the maximum observed total session time in ms
94. eint [LFBS]: cumulative number of internal errors
+For all other statistics domains, the presence or the order of the fields are
+not guaranteed. In this case, the header line should always be used to parse
+the CSV data.
9.2) Typed output format
------------------------
diff --git a/src/stats.c b/src/stats.c
index 6ab1c06..ed0abc7 100644
--- a/src/stats.c
+++ b/src/stats.c
@@ -324,14 +324,21 @@
* NOTE: Some tools happen to rely on the field position instead of its name,
* so please only append new fields at the end, never in the middle.
*/
-static void stats_dump_csv_header()
+static void stats_dump_csv_header(enum stats_domain domain)
{
int field;
chunk_appendf(&trash, "# ");
- for (field = 0; field < ST_F_TOTAL_FIELDS; field++)
+ for (field = 0; field < ST_F_TOTAL_FIELDS; field++) {
chunk_appendf(&trash, "%s,", stat_fields[field].name);
+ /* print special delimiter on proxy stats to mark end of
+ static fields */
+ if (domain == STATS_DOMAIN_PROXY && field + 1 == ST_F_TOTAL_FIELDS) {
+ chunk_appendf(&trash, "-,");
+ }
+ }
+
chunk_appendf(&trash, "\n");
}
@@ -523,16 +530,25 @@
/* Dump all fields from <stats> into <out> using CSV format */
static int stats_dump_fields_csv(struct buffer *out,
const struct field *stats, size_t stats_count,
- unsigned int flags)
+ unsigned int flags,
+ enum stats_domain domain)
{
int field;
- for (field = 0; field < stats_count; field++) {
+ for (field = 0; field < stats_count; ++field) {
if (!stats_emit_raw_data_field(out, &stats[field]))
return 0;
if (!chunk_strcat(out, ","))
return 0;
+
+ /* print special delimiter on proxy stats to mark end of
+ static fields */
+ if (domain == STATS_DOMAIN_PROXY && field + 1 == ST_F_TOTAL_FIELDS) {
+ if (!chunk_strcat(out, "-,"))
+ return 0;
+ }
}
+
chunk_strcat(out, "\n");
return 1;
}
@@ -1435,7 +1451,7 @@
else if (appctx->ctx.stats.flags & STAT_FMT_JSON)
ret = stats_dump_fields_json(&trash, stats, stats_count, appctx->ctx.stats.flags, appctx->ctx.stats.domain);
else
- ret = stats_dump_fields_csv(&trash, stats, stats_count, appctx->ctx.stats.flags);
+ ret = stats_dump_fields_csv(&trash, stats, stats_count, appctx->ctx.stats.flags, appctx->ctx.stats.domain);
if (ret)
appctx->ctx.stats.flags |= STAT_STARTED;
@@ -2837,7 +2853,7 @@
else if (appctx->ctx.stats.flags & STAT_FMT_JSON)
stats_dump_json_header();
else if (!(appctx->ctx.stats.flags & STAT_FMT_TYPED))
- stats_dump_csv_header();
+ stats_dump_csv_header(appctx->ctx.stats.domain);
if (!stats_putchk(rep, htx, &trash))
goto full;