]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: stats: add delimiter for static proxy stats on csv
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Mon, 5 Oct 2020 09:49:39 +0000 (11:49 +0200)
committerChristopher Faulet <cfaulet@haproxy.com>
Mon, 5 Oct 2020 10:02:14 +0000 (12:02 +0200)
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.

doc/management.txt
src/stats.c

index 9a749e48a3daccbf69fb9a339e4641fbe6e91a12..151c96ed8d644762ca7697dc7cf0ea93ba4165af 100644 (file)
@@ -961,10 +961,14 @@ text is doubled ('""'), which is the format that most tools recognize. Please
 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 @@ S (Servers).
  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
 ------------------------
index 6ab1c06c585b511dbf80af3cec7c7cf6348fc37c..ed0abc7b2991ce67f75903fd03789d8cb2328264 100644 (file)
@@ -324,14 +324,21 @@ static const char *stats_scope_ptr(struct appctx *appctx, struct stream_interfac
  * 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 @@ int stats_emit_json_field_tags(struct buffer *out, const struct field *f)
 /* 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 @@ int stats_dump_one_line(const struct field *stats, size_t stats_count,
        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 @@ static int stats_dump_stat_to_buffer(struct stream_interface *si, struct htx *ht
                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;