mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-09-23 14:51:27 +02:00
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.
This commit is contained in:
parent
72b16e5173
commit
50660a894d
@ -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
|
do not insert any column before these ones in order not to break tools which
|
||||||
use hard-coded column positions.
|
use hard-coded column positions.
|
||||||
|
|
||||||
In brackets after each field name are the types which may have a value for
|
For proxy statistics, after each field name, the types which may have a value
|
||||||
that field. The types are L (Listeners), F (Frontends), B (Backends), and
|
for that field are specified in brackets. The types are L (Listeners), F
|
||||||
S (Servers).
|
(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
|
0. pxname [LFBS]: proxy name
|
||||||
1. svname [LFBS]: service name (FRONTEND for frontend, BACKEND for backend,
|
1. svname [LFBS]: service name (FRONTEND for frontend, BACKEND for backend,
|
||||||
any name for server/listener)
|
any name for server/listener)
|
||||||
@ -1122,6 +1126,9 @@ S (Servers).
|
|||||||
93. ttime_max [..BS]: the maximum observed total session time in ms
|
93. ttime_max [..BS]: the maximum observed total session time in ms
|
||||||
94. eint [LFBS]: cumulative number of internal errors
|
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
|
9.2) Typed output format
|
||||||
------------------------
|
------------------------
|
||||||
|
28
src/stats.c
28
src/stats.c
@ -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,
|
* 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.
|
* 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;
|
int field;
|
||||||
|
|
||||||
chunk_appendf(&trash, "# ");
|
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);
|
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");
|
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 */
|
/* Dump all fields from <stats> into <out> using CSV format */
|
||||||
static int stats_dump_fields_csv(struct buffer *out,
|
static int stats_dump_fields_csv(struct buffer *out,
|
||||||
const struct field *stats, size_t stats_count,
|
const struct field *stats, size_t stats_count,
|
||||||
unsigned int flags)
|
unsigned int flags,
|
||||||
|
enum stats_domain domain)
|
||||||
{
|
{
|
||||||
int field;
|
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]))
|
if (!stats_emit_raw_data_field(out, &stats[field]))
|
||||||
return 0;
|
return 0;
|
||||||
if (!chunk_strcat(out, ","))
|
if (!chunk_strcat(out, ","))
|
||||||
return 0;
|
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");
|
chunk_strcat(out, "\n");
|
||||||
return 1;
|
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)
|
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);
|
ret = stats_dump_fields_json(&trash, stats, stats_count, appctx->ctx.stats.flags, appctx->ctx.stats.domain);
|
||||||
else
|
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)
|
if (ret)
|
||||||
appctx->ctx.stats.flags |= STAT_STARTED;
|
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)
|
else if (appctx->ctx.stats.flags & STAT_FMT_JSON)
|
||||||
stats_dump_json_header();
|
stats_dump_json_header();
|
||||||
else if (!(appctx->ctx.stats.flags & STAT_FMT_TYPED))
|
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))
|
if (!stats_putchk(rep, htx, &trash))
|
||||||
goto full;
|
goto full;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user