mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-08-07 15:47:01 +02:00
BUG/MEDIUM: stats: Rely on a local trash buffer to dump the stats
It is possible to block the stats applet if a line exceeds the free space in the responsse buffer while the buffer is empty. It is only an issue in HTTP becaues of the HTX overhead and, AFAIK, only with json output. In this case, the applet is unable to write anything in the response buffer and waits for some free space to proceed further. On the other hand, because the response channel is empty, nothing is sent and thus no space can be freed. At this stage, the stream and the applet are blocked waiting for the other side. To avoid this situation, we must take care to not dump a line exceeding the free space in the HTX message. It means we cannot rely anymore on the global trash buffer. At least, not directly. The trick is to use a local trash buffer, mapped on the global one but with a different size. We use b_make() to do so. The local trash buffer is thread local to avoid any concurrency issue. It is a valid fix. However it could be good to review the internal API of the stats applet to not rely on a global variable. This patch should solve the #1873. It must be backported at least as far as 2.6. Older versions must be evaluated first but it is probably possible to hit this bug with long proxy/server names.
This commit is contained in:
parent
ad4ed003f3
commit
a8b7684319
208
src/stats.c
208
src/stats.c
@ -282,6 +282,8 @@ static struct list stats_module_list[STATS_DOMAIN_COUNT] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
THREAD_LOCAL void *trash_counters;
|
THREAD_LOCAL void *trash_counters;
|
||||||
|
static THREAD_LOCAL struct buffer trash_chunk = BUF_NULL;
|
||||||
|
|
||||||
|
|
||||||
static inline uint8_t stats_get_domain(uint32_t domain)
|
static inline uint8_t stats_get_domain(uint32_t domain)
|
||||||
{
|
{
|
||||||
@ -346,8 +348,8 @@ static const char *stats_scope_ptr(struct appctx *appctx, struct stconn *sc)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
/* Dumps the stats CSV header to the trash buffer which. The caller is responsible
|
/* Dumps the stats CSV header to the local trash buffer. The caller is
|
||||||
* for clearing it if needed.
|
* responsible for clearing it if needed.
|
||||||
* 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.
|
||||||
*/
|
*/
|
||||||
@ -355,19 +357,19 @@ static void stats_dump_csv_header(enum stats_domain domain)
|
|||||||
{
|
{
|
||||||
int field;
|
int field;
|
||||||
|
|
||||||
chunk_appendf(&trash, "# ");
|
chunk_appendf(&trash_chunk, "# ");
|
||||||
if (stat_f[domain]) {
|
if (stat_f[domain]) {
|
||||||
for (field = 0; field < stat_count[domain]; ++field) {
|
for (field = 0; field < stat_count[domain]; ++field) {
|
||||||
chunk_appendf(&trash, "%s,", stat_f[domain][field].name);
|
chunk_appendf(&trash_chunk, "%s,", stat_f[domain][field].name);
|
||||||
|
|
||||||
/* print special delimiter on proxy stats to mark end of
|
/* print special delimiter on proxy stats to mark end of
|
||||||
static fields */
|
static fields */
|
||||||
if (domain == STATS_DOMAIN_PROXY && field + 1 == ST_F_TOTAL_FIELDS)
|
if (domain == STATS_DOMAIN_PROXY && field + 1 == ST_F_TOTAL_FIELDS)
|
||||||
chunk_appendf(&trash, "-,");
|
chunk_appendf(&trash_chunk, "-,");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
chunk_appendf(&trash, "\n");
|
chunk_appendf(&trash_chunk, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Emits a stats field without any surrounding element and properly encoded to
|
/* Emits a stats field without any surrounding element and properly encoded to
|
||||||
@ -1648,13 +1650,13 @@ int stats_dump_one_line(const struct field *stats, size_t stats_count,
|
|||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (ctx->flags & STAT_FMT_HTML)
|
if (ctx->flags & STAT_FMT_HTML)
|
||||||
ret = stats_dump_fields_html(&trash, stats, ctx);
|
ret = stats_dump_fields_html(&trash_chunk, stats, ctx);
|
||||||
else if (ctx->flags & STAT_FMT_TYPED)
|
else if (ctx->flags & STAT_FMT_TYPED)
|
||||||
ret = stats_dump_fields_typed(&trash, stats, stats_count, ctx);
|
ret = stats_dump_fields_typed(&trash_chunk, stats, stats_count, ctx);
|
||||||
else if (ctx->flags & STAT_FMT_JSON)
|
else if (ctx->flags & STAT_FMT_JSON)
|
||||||
ret = stats_dump_fields_json(&trash, stats, stats_count, ctx);
|
ret = stats_dump_fields_json(&trash_chunk, stats, stats_count, ctx);
|
||||||
else
|
else
|
||||||
ret = stats_dump_fields_csv(&trash, stats, stats_count, ctx);
|
ret = stats_dump_fields_csv(&trash_chunk, stats, stats_count, ctx);
|
||||||
|
|
||||||
if (ret)
|
if (ret)
|
||||||
ctx->flags |= STAT_STARTED;
|
ctx->flags |= STAT_STARTED;
|
||||||
@ -1842,9 +1844,10 @@ int stats_fill_fe_stats(struct proxy *px, struct field *stats, int len,
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Dumps a frontend's line to the trash for the current proxy <px> and uses
|
/* Dumps a frontend's line to the local trash buffer for the current proxy <px>
|
||||||
* the state from stream connector <sc>. The caller is responsible for clearing
|
* and uses the state from stream connector <sc>. The caller is responsible for
|
||||||
* the trash if needed. Returns non-zero if it emits anything, zero otherwise.
|
* clearing the local trash buffer if needed. Returns non-zero if it emits
|
||||||
|
* anything, zero otherwise.
|
||||||
*/
|
*/
|
||||||
static int stats_dump_fe_stats(struct stconn *sc, struct proxy *px)
|
static int stats_dump_fe_stats(struct stconn *sc, struct proxy *px)
|
||||||
{
|
{
|
||||||
@ -2010,9 +2013,10 @@ int stats_fill_li_stats(struct proxy *px, struct listener *l, int flags,
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Dumps a line for listener <l> and proxy <px> to the trash and uses the state
|
/* Dumps a line for listener <l> and proxy <px> to the local trash buffer and
|
||||||
* from stream connector <sc>. The caller is responsible for clearing the trash
|
* uses the state from stream connector <sc>. The caller is responsible for
|
||||||
* if needed. Returns non-zero if it emits anything, zero otherwise.
|
* clearing the local trash buffer if needed. Returns non-zero if it emits
|
||||||
|
* anything, zero otherwise.
|
||||||
*/
|
*/
|
||||||
static int stats_dump_li_stats(struct stconn *sc, struct proxy *px, struct listener *l)
|
static int stats_dump_li_stats(struct stconn *sc, struct proxy *px, struct listener *l)
|
||||||
{
|
{
|
||||||
@ -2524,10 +2528,10 @@ int stats_fill_sv_stats(struct proxy *px, struct server *sv, int flags,
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Dumps a line for server <sv> and proxy <px> to the trash and uses the state
|
/* Dumps a line for server <sv> and proxy <px> to the local trash vbuffer and
|
||||||
* from stream connector <sc>, and server state <state>. The caller is
|
* uses the state from stream connector <sc>, and server state <state>. The
|
||||||
* responsible for clearing the trash if needed. Returns non-zero if it emits
|
* caller is responsible for clearing the local trash buffer if needed. Returns
|
||||||
* anything, zero otherwise.
|
* non-zero if it emits anything, zero otherwise.
|
||||||
*/
|
*/
|
||||||
static int stats_dump_sv_stats(struct stconn *sc, struct proxy *px, struct server *sv)
|
static int stats_dump_sv_stats(struct stconn *sc, struct proxy *px, struct server *sv)
|
||||||
{
|
{
|
||||||
@ -2855,9 +2859,10 @@ int stats_fill_be_stats(struct proxy *px, int flags, struct field *stats, int le
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Dumps a line for backend <px> to the trash for and uses the state from stream
|
/* Dumps a line for backend <px> to the local trash buffer for and uses the
|
||||||
* interface <si>. The caller is responsible for clearing the trash if needed.
|
* state from stream interface <si>. The caller is responsible for clearing the
|
||||||
* Returns non-zero if it emits anything, zero otherwise.
|
* local trash buffer if needed. Returns non-zero if it emits anything, zero
|
||||||
|
* otherwise.
|
||||||
*/
|
*/
|
||||||
static int stats_dump_be_stats(struct stconn *sc, struct proxy *px)
|
static int stats_dump_be_stats(struct stconn *sc, struct proxy *px)
|
||||||
{
|
{
|
||||||
@ -2897,9 +2902,9 @@ static int stats_dump_be_stats(struct stconn *sc, struct proxy *px)
|
|||||||
return stats_dump_one_line(stats, stats_count, appctx);
|
return stats_dump_one_line(stats, stats_count, appctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Dumps the HTML table header for proxy <px> to the trash for and uses the state from
|
/* Dumps the HTML table header for proxy <px> to the local trash buffer for and
|
||||||
* stream connector <sc> and per-uri parameters <uri>. The caller is responsible
|
* uses the state from stream connector <sc> and per-uri parameters <uri>. The
|
||||||
* for clearing the trash if needed.
|
* caller is responsible for clearing the local trash buffer if needed.
|
||||||
*/
|
*/
|
||||||
static void stats_dump_html_px_hdr(struct stconn *sc, struct proxy *px)
|
static void stats_dump_html_px_hdr(struct stconn *sc, struct proxy *px)
|
||||||
{
|
{
|
||||||
@ -2922,17 +2927,17 @@ static void stats_dump_html_px_hdr(struct stconn *sc, struct proxy *px)
|
|||||||
scope_txt[strlen(STAT_SCOPE_PATTERN) + ctx->scope_len] = 0;
|
scope_txt[strlen(STAT_SCOPE_PATTERN) + ctx->scope_len] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
chunk_appendf(&trash,
|
chunk_appendf(&trash_chunk,
|
||||||
"<form method=\"post\">");
|
"<form method=\"post\">");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* print a new table */
|
/* print a new table */
|
||||||
chunk_appendf(&trash,
|
chunk_appendf(&trash_chunk,
|
||||||
"<table class=\"tbl\" width=\"100%%\">\n"
|
"<table class=\"tbl\" width=\"100%%\">\n"
|
||||||
"<tr class=\"titre\">"
|
"<tr class=\"titre\">"
|
||||||
"<th class=\"pxname\" width=\"10%%\">");
|
"<th class=\"pxname\" width=\"10%%\">");
|
||||||
|
|
||||||
chunk_appendf(&trash,
|
chunk_appendf(&trash_chunk,
|
||||||
"<a name=\"%s\"></a>%s"
|
"<a name=\"%s\"></a>%s"
|
||||||
"<a class=px href=\"#%s\">%s</a>",
|
"<a class=px href=\"#%s\">%s</a>",
|
||||||
px->id,
|
px->id,
|
||||||
@ -2941,13 +2946,13 @@ static void stats_dump_html_px_hdr(struct stconn *sc, struct proxy *px)
|
|||||||
|
|
||||||
if (ctx->flags & STAT_SHLGNDS) {
|
if (ctx->flags & STAT_SHLGNDS) {
|
||||||
/* cap, mode, id */
|
/* cap, mode, id */
|
||||||
chunk_appendf(&trash, "<div class=tips>cap: %s, mode: %s, id: %d",
|
chunk_appendf(&trash_chunk, "<div class=tips>cap: %s, mode: %s, id: %d",
|
||||||
proxy_cap_str(px->cap), proxy_mode_str(px->mode),
|
proxy_cap_str(px->cap), proxy_mode_str(px->mode),
|
||||||
px->uuid);
|
px->uuid);
|
||||||
chunk_appendf(&trash, "</div>");
|
chunk_appendf(&trash_chunk, "</div>");
|
||||||
}
|
}
|
||||||
|
|
||||||
chunk_appendf(&trash,
|
chunk_appendf(&trash_chunk,
|
||||||
"%s</th>"
|
"%s</th>"
|
||||||
"<th class=\"%s\" width=\"90%%\">%s</th>"
|
"<th class=\"%s\" width=\"90%%\">%s</th>"
|
||||||
"</tr>\n"
|
"</tr>\n"
|
||||||
@ -2960,17 +2965,17 @@ static void stats_dump_html_px_hdr(struct stconn *sc, struct proxy *px)
|
|||||||
if (ctx->flags & STAT_ADMIN) {
|
if (ctx->flags & STAT_ADMIN) {
|
||||||
/* Column heading for Enable or Disable server */
|
/* Column heading for Enable or Disable server */
|
||||||
if ((px->cap & PR_CAP_BE) && px->srv)
|
if ((px->cap & PR_CAP_BE) && px->srv)
|
||||||
chunk_appendf(&trash,
|
chunk_appendf(&trash_chunk,
|
||||||
"<th rowspan=2 width=1><input type=\"checkbox\" "
|
"<th rowspan=2 width=1><input type=\"checkbox\" "
|
||||||
"onclick=\"for(c in document.getElementsByClassName('%s-checkbox')) "
|
"onclick=\"for(c in document.getElementsByClassName('%s-checkbox')) "
|
||||||
"document.getElementsByClassName('%s-checkbox').item(c).checked = this.checked\"></th>",
|
"document.getElementsByClassName('%s-checkbox').item(c).checked = this.checked\"></th>",
|
||||||
px->id,
|
px->id,
|
||||||
px->id);
|
px->id);
|
||||||
else
|
else
|
||||||
chunk_appendf(&trash, "<th rowspan=2></th>");
|
chunk_appendf(&trash_chunk, "<th rowspan=2></th>");
|
||||||
}
|
}
|
||||||
|
|
||||||
chunk_appendf(&trash,
|
chunk_appendf(&trash_chunk,
|
||||||
"<th rowspan=2></th>"
|
"<th rowspan=2></th>"
|
||||||
"<th colspan=3>Queue</th>"
|
"<th colspan=3>Queue</th>"
|
||||||
"<th colspan=3>Session rate</th><th colspan=6>Sessions</th>"
|
"<th colspan=3>Session rate</th><th colspan=6>Sessions</th>"
|
||||||
@ -2983,11 +2988,11 @@ static void stats_dump_html_px_hdr(struct stconn *sc, struct proxy *px)
|
|||||||
list_for_each_entry(mod, &stats_module_list[STATS_DOMAIN_PROXY], list) {
|
list_for_each_entry(mod, &stats_module_list[STATS_DOMAIN_PROXY], list) {
|
||||||
++stats_module_len;
|
++stats_module_len;
|
||||||
}
|
}
|
||||||
chunk_appendf(&trash, "<th colspan=%d>Extra modules</th>",
|
chunk_appendf(&trash_chunk, "<th colspan=%d>Extra modules</th>",
|
||||||
stats_module_len);
|
stats_module_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
chunk_appendf(&trash,
|
chunk_appendf(&trash_chunk,
|
||||||
"</tr>\n"
|
"</tr>\n"
|
||||||
"<tr class=\"titre\">"
|
"<tr class=\"titre\">"
|
||||||
"<th>Cur</th><th>Max</th><th>Limit</th>"
|
"<th>Cur</th><th>Max</th><th>Limit</th>"
|
||||||
@ -3001,26 +3006,27 @@ static void stats_dump_html_px_hdr(struct stconn *sc, struct proxy *px)
|
|||||||
|
|
||||||
if (ctx->flags & STAT_SHMODULES) {
|
if (ctx->flags & STAT_SHMODULES) {
|
||||||
list_for_each_entry(mod, &stats_module_list[STATS_DOMAIN_PROXY], list) {
|
list_for_each_entry(mod, &stats_module_list[STATS_DOMAIN_PROXY], list) {
|
||||||
chunk_appendf(&trash, "<th>%s</th>", mod->name);
|
chunk_appendf(&trash_chunk, "<th>%s</th>", mod->name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
chunk_appendf(&trash, "</tr>");
|
chunk_appendf(&trash_chunk, "</tr>");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Dumps the HTML table trailer for proxy <px> to the trash for and uses the state from
|
/* Dumps the HTML table trailer for proxy <px> to the local trash buffer for and
|
||||||
* stream connector <sc>. The caller is responsible for clearing the trash if needed.
|
* uses the state from stream connector <sc>. The caller is responsible for
|
||||||
|
* clearing the local trash buffer if needed.
|
||||||
*/
|
*/
|
||||||
static void stats_dump_html_px_end(struct stconn *sc, struct proxy *px)
|
static void stats_dump_html_px_end(struct stconn *sc, struct proxy *px)
|
||||||
{
|
{
|
||||||
struct appctx *appctx = __sc_appctx(sc);
|
struct appctx *appctx = __sc_appctx(sc);
|
||||||
struct show_stat_ctx *ctx = appctx->svcctx;
|
struct show_stat_ctx *ctx = appctx->svcctx;
|
||||||
|
|
||||||
chunk_appendf(&trash, "</table>");
|
chunk_appendf(&trash_chunk, "</table>");
|
||||||
|
|
||||||
if ((px->cap & PR_CAP_BE) && px->srv && (ctx->flags & STAT_ADMIN)) {
|
if ((px->cap & PR_CAP_BE) && px->srv && (ctx->flags & STAT_ADMIN)) {
|
||||||
/* close the form used to enable/disable this proxy servers */
|
/* close the form used to enable/disable this proxy servers */
|
||||||
chunk_appendf(&trash,
|
chunk_appendf(&trash_chunk,
|
||||||
"Choose the action to perform on the checked servers : "
|
"Choose the action to perform on the checked servers : "
|
||||||
"<select name=action>"
|
"<select name=action>"
|
||||||
"<option value=\"\"></option>"
|
"<option value=\"\"></option>"
|
||||||
@ -3044,7 +3050,7 @@ static void stats_dump_html_px_end(struct stconn *sc, struct proxy *px)
|
|||||||
px->uuid);
|
px->uuid);
|
||||||
}
|
}
|
||||||
|
|
||||||
chunk_appendf(&trash, "<p>\n");
|
chunk_appendf(&trash_chunk, "<p>\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -3065,7 +3071,7 @@ int stats_dump_proxy_to_buffer(struct stconn *sc, struct htx *htx,
|
|||||||
struct listener *l;
|
struct listener *l;
|
||||||
int current_field;
|
int current_field;
|
||||||
|
|
||||||
chunk_reset(&trash);
|
chunk_reset(&trash_chunk);
|
||||||
more:
|
more:
|
||||||
current_field = ctx->field;
|
current_field = ctx->field;
|
||||||
|
|
||||||
@ -3117,7 +3123,7 @@ int stats_dump_proxy_to_buffer(struct stconn *sc, struct htx *htx,
|
|||||||
case STAT_PX_ST_TH:
|
case STAT_PX_ST_TH:
|
||||||
if (ctx->flags & STAT_FMT_HTML) {
|
if (ctx->flags & STAT_FMT_HTML) {
|
||||||
stats_dump_html_px_hdr(sc, px);
|
stats_dump_html_px_hdr(sc, px);
|
||||||
if (!stats_putchk(rep, htx, &trash))
|
if (!stats_putchk(rep, htx, &trash_chunk))
|
||||||
goto full;
|
goto full;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3127,7 +3133,7 @@ int stats_dump_proxy_to_buffer(struct stconn *sc, struct htx *htx,
|
|||||||
case STAT_PX_ST_FE:
|
case STAT_PX_ST_FE:
|
||||||
/* print the frontend */
|
/* print the frontend */
|
||||||
if (stats_dump_fe_stats(sc, px)) {
|
if (stats_dump_fe_stats(sc, px)) {
|
||||||
if (!stats_putchk(rep, htx, &trash))
|
if (!stats_putchk(rep, htx, &trash_chunk))
|
||||||
goto full;
|
goto full;
|
||||||
if (ctx->field)
|
if (ctx->field)
|
||||||
goto more;
|
goto more;
|
||||||
@ -3164,7 +3170,7 @@ int stats_dump_proxy_to_buffer(struct stconn *sc, struct htx *htx,
|
|||||||
|
|
||||||
/* print the frontend */
|
/* print the frontend */
|
||||||
if (stats_dump_li_stats(sc, px, l)) {
|
if (stats_dump_li_stats(sc, px, l)) {
|
||||||
if (!stats_putchk(rep, htx, &trash))
|
if (!stats_putchk(rep, htx, &trash_chunk))
|
||||||
goto full;
|
goto full;
|
||||||
if (ctx->field)
|
if (ctx->field)
|
||||||
goto more;
|
goto more;
|
||||||
@ -3229,7 +3235,7 @@ int stats_dump_proxy_to_buffer(struct stconn *sc, struct htx *htx,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (stats_dump_sv_stats(sc, px, sv)) {
|
if (stats_dump_sv_stats(sc, px, sv)) {
|
||||||
if (!stats_putchk(rep, htx, &trash))
|
if (!stats_putchk(rep, htx, &trash_chunk))
|
||||||
goto full;
|
goto full;
|
||||||
}
|
}
|
||||||
} /* for sv */
|
} /* for sv */
|
||||||
@ -3240,7 +3246,7 @@ int stats_dump_proxy_to_buffer(struct stconn *sc, struct htx *htx,
|
|||||||
case STAT_PX_ST_BE:
|
case STAT_PX_ST_BE:
|
||||||
/* print the backend */
|
/* print the backend */
|
||||||
if (stats_dump_be_stats(sc, px)) {
|
if (stats_dump_be_stats(sc, px)) {
|
||||||
if (!stats_putchk(rep, htx, &trash))
|
if (!stats_putchk(rep, htx, &trash_chunk))
|
||||||
goto full;
|
goto full;
|
||||||
if (ctx->field)
|
if (ctx->field)
|
||||||
goto more;
|
goto more;
|
||||||
@ -3253,7 +3259,7 @@ int stats_dump_proxy_to_buffer(struct stconn *sc, struct htx *htx,
|
|||||||
case STAT_PX_ST_END:
|
case STAT_PX_ST_END:
|
||||||
if (ctx->flags & STAT_FMT_HTML) {
|
if (ctx->flags & STAT_FMT_HTML) {
|
||||||
stats_dump_html_px_end(sc, px);
|
stats_dump_html_px_end(sc, px);
|
||||||
if (!stats_putchk(rep, htx, &trash))
|
if (!stats_putchk(rep, htx, &trash_chunk))
|
||||||
goto full;
|
goto full;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3275,15 +3281,16 @@ int stats_dump_proxy_to_buffer(struct stconn *sc, struct htx *htx,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Dumps the HTTP stats head block to the trash for and uses the per-uri
|
/* Dumps the HTTP stats head block to the local trash buffer for and uses the
|
||||||
* parameters <uri>. The caller is responsible for clearing the trash if needed.
|
* per-uri parameters <uri>. The caller is responsible for clearing the local
|
||||||
|
* trash buffer if needed.
|
||||||
*/
|
*/
|
||||||
static void stats_dump_html_head(struct appctx *appctx, struct uri_auth *uri)
|
static void stats_dump_html_head(struct appctx *appctx, struct uri_auth *uri)
|
||||||
{
|
{
|
||||||
struct show_stat_ctx *ctx = appctx->svcctx;
|
struct show_stat_ctx *ctx = appctx->svcctx;
|
||||||
|
|
||||||
/* WARNING! This must fit in the first buffer !!! */
|
/* WARNING! This must fit in the first buffer !!! */
|
||||||
chunk_appendf(&trash,
|
chunk_appendf(&trash_chunk,
|
||||||
"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"\n"
|
"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"\n"
|
||||||
"\"http://www.w3.org/TR/html4/loose.dtd\">\n"
|
"\"http://www.w3.org/TR/html4/loose.dtd\">\n"
|
||||||
"<html><head><title>Statistics Report for " PRODUCT_NAME "%s%s</title>\n"
|
"<html><head><title>Statistics Report for " PRODUCT_NAME "%s%s</title>\n"
|
||||||
@ -3443,9 +3450,9 @@ static void stats_dump_html_head(struct appctx *appctx, struct uri_auth *uri)
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Dumps the HTML stats information block to the trash for and uses the state from
|
/* Dumps the HTML stats information block to the local trash buffer for and uses
|
||||||
* stream connector <sc> and per-uri parameters <uri>. The caller is responsible
|
* the state from stream connector <sc> and per-uri parameters <uri>. The caller
|
||||||
* for clearing the trash if needed.
|
* is responsible for clearing the local trash buffer if needed.
|
||||||
*/
|
*/
|
||||||
static void stats_dump_html_info(struct stconn *sc, struct uri_auth *uri)
|
static void stats_dump_html_info(struct stconn *sc, struct uri_auth *uri)
|
||||||
{
|
{
|
||||||
@ -3471,7 +3478,7 @@ static void stats_dump_html_info(struct stconn *sc, struct uri_auth *uri)
|
|||||||
* We are around 3.5 kB, add adding entries will
|
* We are around 3.5 kB, add adding entries will
|
||||||
* become tricky if we want to support 4kB buffers !
|
* become tricky if we want to support 4kB buffers !
|
||||||
*/
|
*/
|
||||||
chunk_appendf(&trash,
|
chunk_appendf(&trash_chunk,
|
||||||
"<body><h1><a href=\"" PRODUCT_URL "\" style=\"text-decoration: none;\">"
|
"<body><h1><a href=\"" PRODUCT_URL "\" style=\"text-decoration: none;\">"
|
||||||
PRODUCT_NAME "%s</a></h1>\n"
|
PRODUCT_NAME "%s</a></h1>\n"
|
||||||
"<h2>Statistics Report for pid %d%s%s%s%s</h2>\n"
|
"<h2>Statistics Report for pid %d%s%s%s%s</h2>\n"
|
||||||
@ -3529,7 +3536,7 @@ static void stats_dump_html_info(struct stconn *sc, struct uri_auth *uri)
|
|||||||
memcpy(scope_txt, scope_ptr, ctx->scope_len);
|
memcpy(scope_txt, scope_ptr, ctx->scope_len);
|
||||||
scope_txt[ctx->scope_len] = '\0';
|
scope_txt[ctx->scope_len] = '\0';
|
||||||
|
|
||||||
chunk_appendf(&trash,
|
chunk_appendf(&trash_chunk,
|
||||||
"<li><form method=\"GET\">Scope : <input value=\"%s\" name=\"" STAT_SCOPE_INPUT_NAME "\" size=\"8\" maxlength=\"%d\" tabindex=\"1\"/></form>\n",
|
"<li><form method=\"GET\">Scope : <input value=\"%s\" name=\"" STAT_SCOPE_INPUT_NAME "\" size=\"8\" maxlength=\"%d\" tabindex=\"1\"/></form>\n",
|
||||||
(ctx->scope_len > 0) ? scope_txt : "",
|
(ctx->scope_len > 0) ? scope_txt : "",
|
||||||
STAT_SCOPE_TXT_MAXLEN);
|
STAT_SCOPE_TXT_MAXLEN);
|
||||||
@ -3543,14 +3550,14 @@ static void stats_dump_html_info(struct stconn *sc, struct uri_auth *uri)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (ctx->flags & STAT_HIDE_DOWN)
|
if (ctx->flags & STAT_HIDE_DOWN)
|
||||||
chunk_appendf(&trash,
|
chunk_appendf(&trash_chunk,
|
||||||
"<li><a href=\"%s%s%s%s\">Show all servers</a><br>\n",
|
"<li><a href=\"%s%s%s%s\">Show all servers</a><br>\n",
|
||||||
uri->uri_prefix,
|
uri->uri_prefix,
|
||||||
"",
|
"",
|
||||||
(ctx->flags & STAT_NO_REFRESH) ? ";norefresh" : "",
|
(ctx->flags & STAT_NO_REFRESH) ? ";norefresh" : "",
|
||||||
scope_txt);
|
scope_txt);
|
||||||
else
|
else
|
||||||
chunk_appendf(&trash,
|
chunk_appendf(&trash_chunk,
|
||||||
"<li><a href=\"%s%s%s%s\">Hide 'DOWN' servers</a><br>\n",
|
"<li><a href=\"%s%s%s%s\">Hide 'DOWN' servers</a><br>\n",
|
||||||
uri->uri_prefix,
|
uri->uri_prefix,
|
||||||
";up",
|
";up",
|
||||||
@ -3559,14 +3566,14 @@ static void stats_dump_html_info(struct stconn *sc, struct uri_auth *uri)
|
|||||||
|
|
||||||
if (uri->refresh > 0) {
|
if (uri->refresh > 0) {
|
||||||
if (ctx->flags & STAT_NO_REFRESH)
|
if (ctx->flags & STAT_NO_REFRESH)
|
||||||
chunk_appendf(&trash,
|
chunk_appendf(&trash_chunk,
|
||||||
"<li><a href=\"%s%s%s%s\">Enable refresh</a><br>\n",
|
"<li><a href=\"%s%s%s%s\">Enable refresh</a><br>\n",
|
||||||
uri->uri_prefix,
|
uri->uri_prefix,
|
||||||
(ctx->flags & STAT_HIDE_DOWN) ? ";up" : "",
|
(ctx->flags & STAT_HIDE_DOWN) ? ";up" : "",
|
||||||
"",
|
"",
|
||||||
scope_txt);
|
scope_txt);
|
||||||
else
|
else
|
||||||
chunk_appendf(&trash,
|
chunk_appendf(&trash_chunk,
|
||||||
"<li><a href=\"%s%s%s%s\">Disable refresh</a><br>\n",
|
"<li><a href=\"%s%s%s%s\">Disable refresh</a><br>\n",
|
||||||
uri->uri_prefix,
|
uri->uri_prefix,
|
||||||
(ctx->flags & STAT_HIDE_DOWN) ? ";up" : "",
|
(ctx->flags & STAT_HIDE_DOWN) ? ";up" : "",
|
||||||
@ -3574,26 +3581,26 @@ static void stats_dump_html_info(struct stconn *sc, struct uri_auth *uri)
|
|||||||
scope_txt);
|
scope_txt);
|
||||||
}
|
}
|
||||||
|
|
||||||
chunk_appendf(&trash,
|
chunk_appendf(&trash_chunk,
|
||||||
"<li><a href=\"%s%s%s%s\">Refresh now</a><br>\n",
|
"<li><a href=\"%s%s%s%s\">Refresh now</a><br>\n",
|
||||||
uri->uri_prefix,
|
uri->uri_prefix,
|
||||||
(ctx->flags & STAT_HIDE_DOWN) ? ";up" : "",
|
(ctx->flags & STAT_HIDE_DOWN) ? ";up" : "",
|
||||||
(ctx->flags & STAT_NO_REFRESH) ? ";norefresh" : "",
|
(ctx->flags & STAT_NO_REFRESH) ? ";norefresh" : "",
|
||||||
scope_txt);
|
scope_txt);
|
||||||
|
|
||||||
chunk_appendf(&trash,
|
chunk_appendf(&trash_chunk,
|
||||||
"<li><a href=\"%s;csv%s%s\">CSV export</a><br>\n",
|
"<li><a href=\"%s;csv%s%s\">CSV export</a><br>\n",
|
||||||
uri->uri_prefix,
|
uri->uri_prefix,
|
||||||
(uri->refresh > 0) ? ";norefresh" : "",
|
(uri->refresh > 0) ? ";norefresh" : "",
|
||||||
scope_txt);
|
scope_txt);
|
||||||
|
|
||||||
chunk_appendf(&trash,
|
chunk_appendf(&trash_chunk,
|
||||||
"<li><a href=\"%s;json%s%s\">JSON export</a> (<a href=\"%s;json-schema\">schema</a>)<br>\n",
|
"<li><a href=\"%s;json%s%s\">JSON export</a> (<a href=\"%s;json-schema\">schema</a>)<br>\n",
|
||||||
uri->uri_prefix,
|
uri->uri_prefix,
|
||||||
(uri->refresh > 0) ? ";norefresh" : "",
|
(uri->refresh > 0) ? ";norefresh" : "",
|
||||||
scope_txt, uri->uri_prefix);
|
scope_txt, uri->uri_prefix);
|
||||||
|
|
||||||
chunk_appendf(&trash,
|
chunk_appendf(&trash_chunk,
|
||||||
"</ul></td>"
|
"</ul></td>"
|
||||||
"<td align=\"left\" valign=\"top\" nowrap width=\"1%%\">"
|
"<td align=\"left\" valign=\"top\" nowrap width=\"1%%\">"
|
||||||
"<b>External resources:</b><ul style=\"margin-top: 0.25em;\">\n"
|
"<b>External resources:</b><ul style=\"margin-top: 0.25em;\">\n"
|
||||||
@ -3609,7 +3616,7 @@ static void stats_dump_html_info(struct stconn *sc, struct uri_auth *uri)
|
|||||||
if (ctx->st_code) {
|
if (ctx->st_code) {
|
||||||
switch (ctx->st_code) {
|
switch (ctx->st_code) {
|
||||||
case STAT_STATUS_DONE:
|
case STAT_STATUS_DONE:
|
||||||
chunk_appendf(&trash,
|
chunk_appendf(&trash_chunk,
|
||||||
"<p><div class=active_up>"
|
"<p><div class=active_up>"
|
||||||
"<a class=lfsb href=\"%s%s%s%s\" title=\"Remove this message\">[X]</a> "
|
"<a class=lfsb href=\"%s%s%s%s\" title=\"Remove this message\">[X]</a> "
|
||||||
"Action processed successfully."
|
"Action processed successfully."
|
||||||
@ -3619,7 +3626,7 @@ static void stats_dump_html_info(struct stconn *sc, struct uri_auth *uri)
|
|||||||
scope_txt);
|
scope_txt);
|
||||||
break;
|
break;
|
||||||
case STAT_STATUS_NONE:
|
case STAT_STATUS_NONE:
|
||||||
chunk_appendf(&trash,
|
chunk_appendf(&trash_chunk,
|
||||||
"<p><div class=active_going_down>"
|
"<p><div class=active_going_down>"
|
||||||
"<a class=lfsb href=\"%s%s%s%s\" title=\"Remove this message\">[X]</a> "
|
"<a class=lfsb href=\"%s%s%s%s\" title=\"Remove this message\">[X]</a> "
|
||||||
"Nothing has changed."
|
"Nothing has changed."
|
||||||
@ -3629,7 +3636,7 @@ static void stats_dump_html_info(struct stconn *sc, struct uri_auth *uri)
|
|||||||
scope_txt);
|
scope_txt);
|
||||||
break;
|
break;
|
||||||
case STAT_STATUS_PART:
|
case STAT_STATUS_PART:
|
||||||
chunk_appendf(&trash,
|
chunk_appendf(&trash_chunk,
|
||||||
"<p><div class=active_going_down>"
|
"<p><div class=active_going_down>"
|
||||||
"<a class=lfsb href=\"%s%s%s%s\" title=\"Remove this message\">[X]</a> "
|
"<a class=lfsb href=\"%s%s%s%s\" title=\"Remove this message\">[X]</a> "
|
||||||
"Action partially processed.<br>"
|
"Action partially processed.<br>"
|
||||||
@ -3640,7 +3647,7 @@ static void stats_dump_html_info(struct stconn *sc, struct uri_auth *uri)
|
|||||||
scope_txt);
|
scope_txt);
|
||||||
break;
|
break;
|
||||||
case STAT_STATUS_ERRP:
|
case STAT_STATUS_ERRP:
|
||||||
chunk_appendf(&trash,
|
chunk_appendf(&trash_chunk,
|
||||||
"<p><div class=active_down>"
|
"<p><div class=active_down>"
|
||||||
"<a class=lfsb href=\"%s%s%s%s\" title=\"Remove this message\">[X]</a> "
|
"<a class=lfsb href=\"%s%s%s%s\" title=\"Remove this message\">[X]</a> "
|
||||||
"Action not processed because of invalid parameters."
|
"Action not processed because of invalid parameters."
|
||||||
@ -3656,7 +3663,7 @@ static void stats_dump_html_info(struct stconn *sc, struct uri_auth *uri)
|
|||||||
scope_txt);
|
scope_txt);
|
||||||
break;
|
break;
|
||||||
case STAT_STATUS_EXCD:
|
case STAT_STATUS_EXCD:
|
||||||
chunk_appendf(&trash,
|
chunk_appendf(&trash_chunk,
|
||||||
"<p><div class=active_down>"
|
"<p><div class=active_down>"
|
||||||
"<a class=lfsb href=\"%s%s%s%s\" title=\"Remove this message\">[X]</a> "
|
"<a class=lfsb href=\"%s%s%s%s\" title=\"Remove this message\">[X]</a> "
|
||||||
"<b>Action not processed : the buffer couldn't store all the data.<br>"
|
"<b>Action not processed : the buffer couldn't store all the data.<br>"
|
||||||
@ -3667,7 +3674,7 @@ static void stats_dump_html_info(struct stconn *sc, struct uri_auth *uri)
|
|||||||
scope_txt);
|
scope_txt);
|
||||||
break;
|
break;
|
||||||
case STAT_STATUS_DENY:
|
case STAT_STATUS_DENY:
|
||||||
chunk_appendf(&trash,
|
chunk_appendf(&trash_chunk,
|
||||||
"<p><div class=active_down>"
|
"<p><div class=active_down>"
|
||||||
"<a class=lfsb href=\"%s%s%s%s\" title=\"Remove this message\">[X]</a> "
|
"<a class=lfsb href=\"%s%s%s%s\" title=\"Remove this message\">[X]</a> "
|
||||||
"<b>Action denied.</b>"
|
"<b>Action denied.</b>"
|
||||||
@ -3677,7 +3684,7 @@ static void stats_dump_html_info(struct stconn *sc, struct uri_auth *uri)
|
|||||||
scope_txt);
|
scope_txt);
|
||||||
break;
|
break;
|
||||||
case STAT_STATUS_IVAL:
|
case STAT_STATUS_IVAL:
|
||||||
chunk_appendf(&trash,
|
chunk_appendf(&trash_chunk,
|
||||||
"<p><div class=active_down>"
|
"<p><div class=active_down>"
|
||||||
"<a class=lfsb href=\"%s%s%s%s\" title=\"Remove this message\">[X]</a> "
|
"<a class=lfsb href=\"%s%s%s%s\" title=\"Remove this message\">[X]</a> "
|
||||||
"<b>Invalid requests (unsupported method or chunked encoded request).</b>"
|
"<b>Invalid requests (unsupported method or chunked encoded request).</b>"
|
||||||
@ -3687,7 +3694,7 @@ static void stats_dump_html_info(struct stconn *sc, struct uri_auth *uri)
|
|||||||
scope_txt);
|
scope_txt);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
chunk_appendf(&trash,
|
chunk_appendf(&trash_chunk,
|
||||||
"<p><div class=active_no_check>"
|
"<p><div class=active_no_check>"
|
||||||
"<a class=lfsb href=\"%s%s%s%s\" title=\"Remove this message\">[X]</a> "
|
"<a class=lfsb href=\"%s%s%s%s\" title=\"Remove this message\">[X]</a> "
|
||||||
"Unexpected result."
|
"Unexpected result."
|
||||||
@ -3696,33 +3703,33 @@ static void stats_dump_html_info(struct stconn *sc, struct uri_auth *uri)
|
|||||||
(ctx->flags & STAT_NO_REFRESH) ? ";norefresh" : "",
|
(ctx->flags & STAT_NO_REFRESH) ? ";norefresh" : "",
|
||||||
scope_txt);
|
scope_txt);
|
||||||
}
|
}
|
||||||
chunk_appendf(&trash, "<p>\n");
|
chunk_appendf(&trash_chunk, "<p>\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Dumps the HTML stats trailer block to the trash. The caller is responsible
|
/* Dumps the HTML stats trailer block to the local trash buffer. The caller is
|
||||||
* for clearing the trash if needed.
|
* responsible for clearing the local trash buffer if needed.
|
||||||
*/
|
*/
|
||||||
static void stats_dump_html_end()
|
static void stats_dump_html_end()
|
||||||
{
|
{
|
||||||
chunk_appendf(&trash, "</body></html>\n");
|
chunk_appendf(&trash_chunk, "</body></html>\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Dumps the stats JSON header to the trash buffer which. The caller is responsible
|
/* Dumps the stats JSON header to the local trash buffer buffer which. The
|
||||||
* for clearing it if needed.
|
* caller is responsible for clearing it if needed.
|
||||||
*/
|
*/
|
||||||
static void stats_dump_json_header()
|
static void stats_dump_json_header()
|
||||||
{
|
{
|
||||||
chunk_strcat(&trash, "[");
|
chunk_strcat(&trash_chunk, "[");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Dumps the JSON stats trailer block to the trash. The caller is responsible
|
/* Dumps the JSON stats trailer block to the local trash buffer. The caller is
|
||||||
* for clearing the trash if needed.
|
* responsible for clearing the local trash buffer if needed.
|
||||||
*/
|
*/
|
||||||
static void stats_dump_json_end()
|
static void stats_dump_json_end()
|
||||||
{
|
{
|
||||||
chunk_strcat(&trash, "]\n");
|
chunk_strcat(&trash_chunk, "]\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Uses <appctx.ctx.stats.obj1> as a pointer to the current proxy and <obj2> as
|
/* Uses <appctx.ctx.stats.obj1> as a pointer to the current proxy and <obj2> as
|
||||||
@ -3786,7 +3793,7 @@ static int stats_dump_stat_to_buffer(struct stconn *sc, struct htx *htx,
|
|||||||
struct channel *rep = sc_ic(sc);
|
struct channel *rep = sc_ic(sc);
|
||||||
enum stats_domain domain = ctx->domain;
|
enum stats_domain domain = ctx->domain;
|
||||||
|
|
||||||
chunk_reset(&trash);
|
chunk_reset(&trash_chunk);
|
||||||
|
|
||||||
switch (ctx->state) {
|
switch (ctx->state) {
|
||||||
case STAT_STATE_INIT:
|
case STAT_STATE_INIT:
|
||||||
@ -3797,13 +3804,13 @@ static int stats_dump_stat_to_buffer(struct stconn *sc, struct htx *htx,
|
|||||||
if (ctx->flags & STAT_FMT_HTML)
|
if (ctx->flags & STAT_FMT_HTML)
|
||||||
stats_dump_html_head(appctx, uri);
|
stats_dump_html_head(appctx, uri);
|
||||||
else if (ctx->flags & STAT_JSON_SCHM)
|
else if (ctx->flags & STAT_JSON_SCHM)
|
||||||
stats_dump_json_schema(&trash);
|
stats_dump_json_schema(&trash_chunk);
|
||||||
else if (ctx->flags & STAT_FMT_JSON)
|
else if (ctx->flags & STAT_FMT_JSON)
|
||||||
stats_dump_json_header();
|
stats_dump_json_header();
|
||||||
else if (!(ctx->flags & STAT_FMT_TYPED))
|
else if (!(ctx->flags & STAT_FMT_TYPED))
|
||||||
stats_dump_csv_header(ctx->domain);
|
stats_dump_csv_header(ctx->domain);
|
||||||
|
|
||||||
if (!stats_putchk(rep, htx, &trash))
|
if (!stats_putchk(rep, htx, &trash_chunk))
|
||||||
goto full;
|
goto full;
|
||||||
|
|
||||||
if (ctx->flags & STAT_JSON_SCHM) {
|
if (ctx->flags & STAT_JSON_SCHM) {
|
||||||
@ -3816,7 +3823,7 @@ static int stats_dump_stat_to_buffer(struct stconn *sc, struct htx *htx,
|
|||||||
case STAT_STATE_INFO:
|
case STAT_STATE_INFO:
|
||||||
if (ctx->flags & STAT_FMT_HTML) {
|
if (ctx->flags & STAT_FMT_HTML) {
|
||||||
stats_dump_html_info(sc, uri);
|
stats_dump_html_info(sc, uri);
|
||||||
if (!stats_putchk(rep, htx, &trash))
|
if (!stats_putchk(rep, htx, &trash_chunk))
|
||||||
goto full;
|
goto full;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3855,7 +3862,7 @@ static int stats_dump_stat_to_buffer(struct stconn *sc, struct htx *htx,
|
|||||||
stats_dump_html_end();
|
stats_dump_html_end();
|
||||||
else
|
else
|
||||||
stats_dump_json_end();
|
stats_dump_json_end();
|
||||||
if (!stats_putchk(rep, htx, &trash))
|
if (!stats_putchk(rep, htx, &trash_chunk))
|
||||||
goto full;
|
goto full;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4375,6 +4382,7 @@ static void http_stats_io_handler(struct appctx *appctx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (appctx->st0 == STAT_HTTP_DUMP) {
|
if (appctx->st0 == STAT_HTTP_DUMP) {
|
||||||
|
trash_chunk = b_make(trash.area, channel_htx_recv_limit(res, res_htx), 0, 0);
|
||||||
if (stats_dump_stat_to_buffer(sc, res_htx, s->be->uri_auth))
|
if (stats_dump_stat_to_buffer(sc, res_htx, s->be->uri_auth))
|
||||||
appctx->st0 = STAT_HTTP_DONE;
|
appctx->st0 = STAT_HTTP_DONE;
|
||||||
}
|
}
|
||||||
@ -4619,18 +4627,18 @@ static int stats_dump_info_to_buffer(struct stconn *sc)
|
|||||||
if (!stats_fill_info(info, INF_TOTAL_FIELDS, ctx->flags))
|
if (!stats_fill_info(info, INF_TOTAL_FIELDS, ctx->flags))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
chunk_reset(&trash);
|
chunk_reset(&trash_chunk);
|
||||||
more:
|
more:
|
||||||
current_field = ctx->field;
|
current_field = ctx->field;
|
||||||
|
|
||||||
if (ctx->flags & STAT_FMT_TYPED)
|
if (ctx->flags & STAT_FMT_TYPED)
|
||||||
ret = stats_dump_typed_info_fields(&trash, info, ctx);
|
ret = stats_dump_typed_info_fields(&trash_chunk, info, ctx);
|
||||||
else if (ctx->flags & STAT_FMT_JSON)
|
else if (ctx->flags & STAT_FMT_JSON)
|
||||||
ret = stats_dump_json_info_fields(&trash, info, ctx);
|
ret = stats_dump_json_info_fields(&trash_chunk, info, ctx);
|
||||||
else
|
else
|
||||||
ret = stats_dump_info_fields(&trash, info, ctx);
|
ret = stats_dump_info_fields(&trash_chunk, info, ctx);
|
||||||
|
|
||||||
if (applet_putchk(appctx, &trash) == -1) {
|
if (applet_putchk(appctx, &trash_chunk) == -1) {
|
||||||
/* restore previous field */
|
/* restore previous field */
|
||||||
ctx->field = current_field;
|
ctx->field = current_field;
|
||||||
return 0;
|
return 0;
|
||||||
@ -4860,11 +4868,12 @@ static void stats_dump_json_schema(struct buffer *out)
|
|||||||
*/
|
*/
|
||||||
static int stats_dump_json_schema_to_buffer(struct appctx *appctx)
|
static int stats_dump_json_schema_to_buffer(struct appctx *appctx)
|
||||||
{
|
{
|
||||||
chunk_reset(&trash);
|
|
||||||
|
|
||||||
stats_dump_json_schema(&trash);
|
chunk_reset(&trash_chunk);
|
||||||
|
|
||||||
if (applet_putchk(appctx, &trash) == -1)
|
stats_dump_json_schema(&trash_chunk);
|
||||||
|
|
||||||
|
if (applet_putchk(appctx, &trash_chunk) == -1)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
@ -5074,6 +5083,7 @@ static int cli_parse_show_stat(char **args, char *payload, struct appctx *appctx
|
|||||||
|
|
||||||
static int cli_io_handler_dump_info(struct appctx *appctx)
|
static int cli_io_handler_dump_info(struct appctx *appctx)
|
||||||
{
|
{
|
||||||
|
trash_chunk = b_make(trash.area, trash.size, 0, 0);
|
||||||
return stats_dump_info_to_buffer(appctx_sc(appctx));
|
return stats_dump_info_to_buffer(appctx_sc(appctx));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5082,11 +5092,13 @@ static int cli_io_handler_dump_info(struct appctx *appctx)
|
|||||||
*/
|
*/
|
||||||
static int cli_io_handler_dump_stat(struct appctx *appctx)
|
static int cli_io_handler_dump_stat(struct appctx *appctx)
|
||||||
{
|
{
|
||||||
|
trash_chunk = b_make(trash.area, trash.size, 0, 0);
|
||||||
return stats_dump_stat_to_buffer(appctx_sc(appctx), NULL, NULL);
|
return stats_dump_stat_to_buffer(appctx_sc(appctx), NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cli_io_handler_dump_json_schema(struct appctx *appctx)
|
static int cli_io_handler_dump_json_schema(struct appctx *appctx)
|
||||||
{
|
{
|
||||||
|
trash_chunk = b_make(trash.area, trash.size, 0, 0);
|
||||||
return stats_dump_json_schema_to_buffer(appctx);
|
return stats_dump_json_schema_to_buffer(appctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user