diff --git a/src/stats.c b/src/stats.c index dad626172..7b664c129 100644 --- a/src/stats.c +++ b/src/stats.c @@ -282,6 +282,8 @@ static struct list stats_module_list[STATS_DOMAIN_COUNT] = { }; THREAD_LOCAL void *trash_counters; +static THREAD_LOCAL struct buffer trash_chunk = BUF_NULL; + 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 - * for clearing it if needed. +/* Dumps the stats CSV header to the local trash buffer. The caller is + * responsible for clearing it if needed. * 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. */ @@ -355,19 +357,19 @@ static void stats_dump_csv_header(enum stats_domain domain) { int field; - chunk_appendf(&trash, "# "); + chunk_appendf(&trash_chunk, "# "); if (stat_f[domain]) { 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 static 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 @@ -1648,13 +1650,13 @@ int stats_dump_one_line(const struct field *stats, size_t stats_count, int ret; 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) - 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) - ret = stats_dump_fields_json(&trash, stats, stats_count, ctx); + ret = stats_dump_fields_json(&trash_chunk, stats, stats_count, ctx); else - ret = stats_dump_fields_csv(&trash, stats, stats_count, ctx); + ret = stats_dump_fields_csv(&trash_chunk, stats, stats_count, ctx); if (ret) ctx->flags |= STAT_STARTED; @@ -1842,9 +1844,10 @@ int stats_fill_fe_stats(struct proxy *px, struct field *stats, int len, return 1; } -/* Dumps a frontend's line to the trash for the current proxy and uses - * the state from stream connector . The caller is responsible for clearing - * the trash if needed. Returns non-zero if it emits anything, zero otherwise. +/* Dumps a frontend's line to the local trash buffer for the current proxy + * and uses the state from stream connector . The caller is responsible for + * 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) { @@ -2010,9 +2013,10 @@ int stats_fill_li_stats(struct proxy *px, struct listener *l, int flags, return 1; } -/* Dumps a line for listener and proxy to the trash and uses the state - * from stream connector . The caller is responsible for clearing the trash - * if needed. Returns non-zero if it emits anything, zero otherwise. +/* Dumps a line for listener and proxy to the local trash buffer and + * uses the state from stream connector . The caller is responsible for + * 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) { @@ -2524,10 +2528,10 @@ int stats_fill_sv_stats(struct proxy *px, struct server *sv, int flags, return 1; } -/* Dumps a line for server and proxy to the trash and uses the state - * from stream connector , and server state . The caller is - * responsible for clearing the trash if needed. Returns non-zero if it emits - * anything, zero otherwise. +/* Dumps a line for server and proxy to the local trash vbuffer and + * uses the state from stream connector , and server state . The + * caller is responsible for clearing the local trash buffer if needed. Returns + * non-zero if it emits anything, zero otherwise. */ 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; } -/* Dumps a line for backend to the trash for and uses the state from stream - * interface . The caller is responsible for clearing the trash if needed. - * Returns non-zero if it emits anything, zero otherwise. +/* Dumps a line for backend to the local trash buffer for and uses the + * state from stream interface . The caller is responsible for clearing the + * 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) { @@ -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); } -/* Dumps the HTML table header for proxy to the trash for and uses the state from - * stream connector and per-uri parameters . The caller is responsible - * for clearing the trash if needed. +/* Dumps the HTML table header for proxy to the local trash buffer for and + * uses the state from stream connector and per-uri parameters . The + * caller is responsible for clearing the local trash buffer if needed. */ 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; } - chunk_appendf(&trash, + chunk_appendf(&trash_chunk, "
"); } /* print a new table */ - chunk_appendf(&trash, + chunk_appendf(&trash_chunk, "\n" "" "" "" "\n" @@ -2960,17 +2965,17 @@ static void stats_dump_html_px_hdr(struct stconn *sc, struct proxy *px) if (ctx->flags & STAT_ADMIN) { /* Column heading for Enable or Disable server */ if ((px->cap & PR_CAP_BE) && px->srv) - chunk_appendf(&trash, + chunk_appendf(&trash_chunk, "", px->id, px->id); else - chunk_appendf(&trash, ""); + chunk_appendf(&trash_chunk, ""); } - chunk_appendf(&trash, + chunk_appendf(&trash_chunk, "" "" "" @@ -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) { ++stats_module_len; } - chunk_appendf(&trash, "", + chunk_appendf(&trash_chunk, "", stats_module_len); } - chunk_appendf(&trash, + chunk_appendf(&trash_chunk, "\n" "" "" @@ -3001,26 +3006,27 @@ static void stats_dump_html_px_hdr(struct stconn *sc, struct proxy *px) if (ctx->flags & STAT_SHMODULES) { list_for_each_entry(mod, &stats_module_list[STATS_DOMAIN_PROXY], list) { - chunk_appendf(&trash, "", mod->name); + chunk_appendf(&trash_chunk, "", mod->name); } } - chunk_appendf(&trash, ""); + chunk_appendf(&trash_chunk, ""); } -/* Dumps the HTML table trailer for proxy to the trash for and uses the state from - * stream connector . The caller is responsible for clearing the trash if needed. +/* Dumps the HTML table trailer for proxy to the local trash buffer for and + * uses the state from stream connector . 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) { struct appctx *appctx = __sc_appctx(sc); struct show_stat_ctx *ctx = appctx->svcctx; - chunk_appendf(&trash, "
"); - chunk_appendf(&trash, + chunk_appendf(&trash_chunk, "%s" "%s", px->id, @@ -2941,13 +2946,13 @@ static void stats_dump_html_px_hdr(struct stconn *sc, struct proxy *px) if (ctx->flags & STAT_SHLGNDS) { /* cap, mode, id */ - chunk_appendf(&trash, "
cap: %s, mode: %s, id: %d", + chunk_appendf(&trash_chunk, "
cap: %s, mode: %s, id: %d", proxy_cap_str(px->cap), proxy_mode_str(px->mode), px->uuid); - chunk_appendf(&trash, "
"); + chunk_appendf(&trash_chunk, "
"); } - chunk_appendf(&trash, + chunk_appendf(&trash_chunk, "%s
%s
QueueSession rateSessionsExtra modulesExtra modules
CurMaxLimit%s%s
"); + chunk_appendf(&trash_chunk, ""); if ((px->cap & PR_CAP_BE) && px->srv && (ctx->flags & STAT_ADMIN)) { /* 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 : " "
\n", (ctx->scope_len > 0) ? scope_txt : "", 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) - chunk_appendf(&trash, + chunk_appendf(&trash_chunk, "
  • Show all servers
    \n", uri->uri_prefix, "", (ctx->flags & STAT_NO_REFRESH) ? ";norefresh" : "", scope_txt); else - chunk_appendf(&trash, + chunk_appendf(&trash_chunk, "
  • Hide 'DOWN' servers
    \n", uri->uri_prefix, ";up", @@ -3559,14 +3566,14 @@ static void stats_dump_html_info(struct stconn *sc, struct uri_auth *uri) if (uri->refresh > 0) { if (ctx->flags & STAT_NO_REFRESH) - chunk_appendf(&trash, + chunk_appendf(&trash_chunk, "
  • Enable refresh
    \n", uri->uri_prefix, (ctx->flags & STAT_HIDE_DOWN) ? ";up" : "", "", scope_txt); else - chunk_appendf(&trash, + chunk_appendf(&trash_chunk, "
  • Disable refresh
    \n", uri->uri_prefix, (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); } - chunk_appendf(&trash, + chunk_appendf(&trash_chunk, "
  • Refresh now
    \n", uri->uri_prefix, (ctx->flags & STAT_HIDE_DOWN) ? ";up" : "", (ctx->flags & STAT_NO_REFRESH) ? ";norefresh" : "", scope_txt); - chunk_appendf(&trash, + chunk_appendf(&trash_chunk, "
  • CSV export
    \n", uri->uri_prefix, (uri->refresh > 0) ? ";norefresh" : "", scope_txt); - chunk_appendf(&trash, + chunk_appendf(&trash_chunk, "
  • JSON export (schema)
    \n", uri->uri_prefix, (uri->refresh > 0) ? ";norefresh" : "", scope_txt, uri->uri_prefix); - chunk_appendf(&trash, + chunk_appendf(&trash_chunk, "" "" "External resources:
      \n" @@ -3609,7 +3616,7 @@ static void stats_dump_html_info(struct stconn *sc, struct uri_auth *uri) if (ctx->st_code) { switch (ctx->st_code) { case STAT_STATUS_DONE: - chunk_appendf(&trash, + chunk_appendf(&trash_chunk, "

      " "[X] " "Action processed successfully." @@ -3619,7 +3626,7 @@ static void stats_dump_html_info(struct stconn *sc, struct uri_auth *uri) scope_txt); break; case STAT_STATUS_NONE: - chunk_appendf(&trash, + chunk_appendf(&trash_chunk, "

      " "[X] " "Nothing has changed." @@ -3629,7 +3636,7 @@ static void stats_dump_html_info(struct stconn *sc, struct uri_auth *uri) scope_txt); break; case STAT_STATUS_PART: - chunk_appendf(&trash, + chunk_appendf(&trash_chunk, "

      " "[X] " "Action partially processed.
      " @@ -3640,7 +3647,7 @@ static void stats_dump_html_info(struct stconn *sc, struct uri_auth *uri) scope_txt); break; case STAT_STATUS_ERRP: - chunk_appendf(&trash, + chunk_appendf(&trash_chunk, "

      " "[X] " "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); break; case STAT_STATUS_EXCD: - chunk_appendf(&trash, + chunk_appendf(&trash_chunk, "

      " "[X] " "Action not processed : the buffer couldn't store all the data.
      " @@ -3667,7 +3674,7 @@ static void stats_dump_html_info(struct stconn *sc, struct uri_auth *uri) scope_txt); break; case STAT_STATUS_DENY: - chunk_appendf(&trash, + chunk_appendf(&trash_chunk, "

      " "[X] " "Action denied." @@ -3677,7 +3684,7 @@ static void stats_dump_html_info(struct stconn *sc, struct uri_auth *uri) scope_txt); break; case STAT_STATUS_IVAL: - chunk_appendf(&trash, + chunk_appendf(&trash_chunk, "

      " "[X] " "Invalid requests (unsupported method or chunked encoded request)." @@ -3687,7 +3694,7 @@ static void stats_dump_html_info(struct stconn *sc, struct uri_auth *uri) scope_txt); break; default: - chunk_appendf(&trash, + chunk_appendf(&trash_chunk, "

      " "[X] " "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" : "", scope_txt); } - chunk_appendf(&trash, "

      \n"); + chunk_appendf(&trash_chunk, "

      \n"); } } -/* Dumps the HTML stats trailer block to the trash. The caller is responsible - * for clearing the trash if needed. +/* Dumps the HTML stats trailer block to the local trash buffer. The caller is + * responsible for clearing the local trash buffer if needed. */ static void stats_dump_html_end() { - chunk_appendf(&trash, "\n"); + chunk_appendf(&trash_chunk, "\n"); } -/* Dumps the stats JSON header to the trash buffer which. The caller is responsible - * for clearing it if needed. +/* Dumps the stats JSON header to the local trash buffer buffer which. The + * caller is responsible for clearing it if needed. */ 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 - * for clearing the trash if needed. +/* Dumps the JSON stats trailer block to the local trash buffer. The caller is + * responsible for clearing the local trash buffer if needed. */ static void stats_dump_json_end() { - chunk_strcat(&trash, "]\n"); + chunk_strcat(&trash_chunk, "]\n"); } /* Uses as a pointer to the current proxy and as @@ -3786,7 +3793,7 @@ static int stats_dump_stat_to_buffer(struct stconn *sc, struct htx *htx, struct channel *rep = sc_ic(sc); enum stats_domain domain = ctx->domain; - chunk_reset(&trash); + chunk_reset(&trash_chunk); switch (ctx->state) { 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) stats_dump_html_head(appctx, uri); 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) stats_dump_json_header(); else if (!(ctx->flags & STAT_FMT_TYPED)) stats_dump_csv_header(ctx->domain); - if (!stats_putchk(rep, htx, &trash)) + if (!stats_putchk(rep, htx, &trash_chunk)) goto full; 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: if (ctx->flags & STAT_FMT_HTML) { stats_dump_html_info(sc, uri); - if (!stats_putchk(rep, htx, &trash)) + if (!stats_putchk(rep, htx, &trash_chunk)) goto full; } @@ -3855,7 +3862,7 @@ static int stats_dump_stat_to_buffer(struct stconn *sc, struct htx *htx, stats_dump_html_end(); else stats_dump_json_end(); - if (!stats_putchk(rep, htx, &trash)) + if (!stats_putchk(rep, htx, &trash_chunk)) goto full; } @@ -4375,6 +4382,7 @@ static void http_stats_io_handler(struct appctx *appctx) } 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)) 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)) return 0; - chunk_reset(&trash); + chunk_reset(&trash_chunk); more: current_field = ctx->field; 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) - ret = stats_dump_json_info_fields(&trash, info, ctx); + ret = stats_dump_json_info_fields(&trash_chunk, info, ctx); 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 */ ctx->field = current_field; 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) { - 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 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) { + trash_chunk = b_make(trash.area, trash.size, 0, 0); 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) { + trash_chunk = b_make(trash.area, trash.size, 0, 0); return stats_dump_stat_to_buffer(appctx_sc(appctx), NULL, NULL); } 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); }