From: Willy Tarreau Date: Tue, 22 Nov 2016 15:36:53 +0000 (+0100) Subject: REORG: cli: move "show info" to stats.c X-Git-Tag: v1.7.0~48 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=0baac8cf1f172663e4969ccd7127a4b90984cea1;p=thirdparty%2Fhaproxy.git REORG: cli: move "show info" to stats.c Move the "show info" command to stats.c using the CLI keyword API to register it on the CLI. The stats_dump_info_to_buffer() function is now static again. Note, we don't need proto_ssl anymore in cli.c. --- diff --git a/include/types/cli.h b/include/types/cli.h index 9c7bed5123..883c72d1e2 100644 --- a/include/types/cli.h +++ b/include/types/cli.h @@ -38,69 +38,6 @@ struct cli_kw_list { struct cli_kw kw[VAR_ARRAY]; }; -/* Show Info fields for CLI output. For any field added here, please add the text - * representation in the info_field_names array below. Please only append at the end, - * before the INF_TOTAL_FIELDS entry, and never insert anything in the middle - * nor at the beginning. - */ -enum info_field { - INF_NAME, - INF_VERSION, - INF_RELEASE_DATE, - INF_NBPROC, - INF_PROCESS_NUM, - INF_PID, - INF_UPTIME, - INF_UPTIME_SEC, - INF_MEMMAX_MB, - INF_POOL_ALLOC_MB, - INF_POOL_USED_MB, - INF_POOL_FAILED, - INF_ULIMIT_N, - INF_MAXSOCK, - INF_MAXCONN, - INF_HARD_MAXCONN, - INF_CURR_CONN, - INF_CUM_CONN, - INF_CUM_REQ, - INF_MAX_SSL_CONNS, - INF_CURR_SSL_CONNS, - INF_CUM_SSL_CONNS, - INF_MAXPIPES, - INF_PIPES_USED, - INF_PIPES_FREE, - INF_CONN_RATE, - INF_CONN_RATE_LIMIT, - INF_MAX_CONN_RATE, - INF_SESS_RATE, - INF_SESS_RATE_LIMIT, - INF_MAX_SESS_RATE, - INF_SSL_RATE, - INF_SSL_RATE_LIMIT, - INF_MAX_SSL_RATE, - INF_SSL_FRONTEND_KEY_RATE, - INF_SSL_FRONTEND_MAX_KEY_RATE, - INF_SSL_FRONTEND_SESSION_REUSE_PCT, - INF_SSL_BACKEND_KEY_RATE, - INF_SSL_BACKEND_MAX_KEY_RATE, - INF_SSL_CACHE_LOOKUPS, - INF_SSL_CACHE_MISSES, - INF_COMPRESS_BPS_IN, - INF_COMPRESS_BPS_OUT, - INF_COMPRESS_BPS_RATE_LIM, - INF_ZLIB_MEM_USAGE, - INF_MAX_ZLIB_MEM_USAGE, - INF_TASKS, - INF_RUN_QUEUE, - INF_IDLE_PCT, - INF_NODE, - INF_DESCRIPTION, - - /* must always be the last one */ - INF_TOTAL_FIELDS -}; - - /* stats socket states */ enum { STAT_CLI_INIT = 0, /* initial state, must leave to zero ! */ @@ -110,7 +47,6 @@ enum { STAT_CLI_PROMPT, /* display the prompt (first output, same code) */ STAT_CLI_PRINT, /* display message in cli->msg */ STAT_CLI_PRINT_FREE, /* display message in cli->msg. After the display, free the pointer */ - STAT_CLI_O_INFO, /* dump info */ STAT_CLI_O_ERR, /* dump errors */ STAT_CLI_O_TAB, /* dump tables */ STAT_CLI_O_CLR, /* clear tables */ diff --git a/include/types/stats.h b/include/types/stats.h index dd52bba109..48cf645fc2 100644 --- a/include/types/stats.h +++ b/include/types/stats.h @@ -224,6 +224,69 @@ struct field { } u; }; +/* Show Info fields for CLI output. For any field added here, please add the text + * representation in the info_field_names array below. Please only append at the end, + * before the INF_TOTAL_FIELDS entry, and never insert anything in the middle + * nor at the beginning. + */ +enum info_field { + INF_NAME, + INF_VERSION, + INF_RELEASE_DATE, + INF_NBPROC, + INF_PROCESS_NUM, + INF_PID, + INF_UPTIME, + INF_UPTIME_SEC, + INF_MEMMAX_MB, + INF_POOL_ALLOC_MB, + INF_POOL_USED_MB, + INF_POOL_FAILED, + INF_ULIMIT_N, + INF_MAXSOCK, + INF_MAXCONN, + INF_HARD_MAXCONN, + INF_CURR_CONN, + INF_CUM_CONN, + INF_CUM_REQ, + INF_MAX_SSL_CONNS, + INF_CURR_SSL_CONNS, + INF_CUM_SSL_CONNS, + INF_MAXPIPES, + INF_PIPES_USED, + INF_PIPES_FREE, + INF_CONN_RATE, + INF_CONN_RATE_LIMIT, + INF_MAX_CONN_RATE, + INF_SESS_RATE, + INF_SESS_RATE_LIMIT, + INF_MAX_SESS_RATE, + INF_SSL_RATE, + INF_SSL_RATE_LIMIT, + INF_MAX_SSL_RATE, + INF_SSL_FRONTEND_KEY_RATE, + INF_SSL_FRONTEND_MAX_KEY_RATE, + INF_SSL_FRONTEND_SESSION_REUSE_PCT, + INF_SSL_BACKEND_KEY_RATE, + INF_SSL_BACKEND_MAX_KEY_RATE, + INF_SSL_CACHE_LOOKUPS, + INF_SSL_CACHE_MISSES, + INF_COMPRESS_BPS_IN, + INF_COMPRESS_BPS_OUT, + INF_COMPRESS_BPS_RATE_LIM, + INF_ZLIB_MEM_USAGE, + INF_MAX_ZLIB_MEM_USAGE, + INF_TASKS, + INF_RUN_QUEUE, + INF_IDLE_PCT, + INF_NODE, + INF_DESCRIPTION, + + /* must always be the last one */ + INF_TOTAL_FIELDS +}; + + /* Stats fields for CSV output. For any field added here, please add the text * representation in the stat_field_names array below. Please only append at the end, * before the ST_F_TOTAL_FIELDS entry, and never insert anything in the middle diff --git a/src/cli.c b/src/cli.c index cdfbebf0d7..a395e238be 100644 --- a/src/cli.c +++ b/src/cli.c @@ -67,74 +67,7 @@ #include #include -#ifdef USE_OPENSSL -#include -#include -#endif - -/* These are the field names for each INF_* field position. Please pay attention - * to always use the exact same name except that the strings for new names must - * be lower case or CamelCase while the enum entries must be upper case. - */ -const char *info_field_names[INF_TOTAL_FIELDS] = { - [INF_NAME] = "Name", - [INF_VERSION] = "Version", - [INF_RELEASE_DATE] = "Release_date", - [INF_NBPROC] = "Nbproc", - [INF_PROCESS_NUM] = "Process_num", - [INF_PID] = "Pid", - [INF_UPTIME] = "Uptime", - [INF_UPTIME_SEC] = "Uptime_sec", - [INF_MEMMAX_MB] = "Memmax_MB", - [INF_POOL_ALLOC_MB] = "PoolAlloc_MB", - [INF_POOL_USED_MB] = "PoolUsed_MB", - [INF_POOL_FAILED] = "PoolFailed", - [INF_ULIMIT_N] = "Ulimit-n", - [INF_MAXSOCK] = "Maxsock", - [INF_MAXCONN] = "Maxconn", - [INF_HARD_MAXCONN] = "Hard_maxconn", - [INF_CURR_CONN] = "CurrConns", - [INF_CUM_CONN] = "CumConns", - [INF_CUM_REQ] = "CumReq", - [INF_MAX_SSL_CONNS] = "MaxSslConns", - [INF_CURR_SSL_CONNS] = "CurrSslConns", - [INF_CUM_SSL_CONNS] = "CumSslConns", - [INF_MAXPIPES] = "Maxpipes", - [INF_PIPES_USED] = "PipesUsed", - [INF_PIPES_FREE] = "PipesFree", - [INF_CONN_RATE] = "ConnRate", - [INF_CONN_RATE_LIMIT] = "ConnRateLimit", - [INF_MAX_CONN_RATE] = "MaxConnRate", - [INF_SESS_RATE] = "SessRate", - [INF_SESS_RATE_LIMIT] = "SessRateLimit", - [INF_MAX_SESS_RATE] = "MaxSessRate", - [INF_SSL_RATE] = "SslRate", - [INF_SSL_RATE_LIMIT] = "SslRateLimit", - [INF_MAX_SSL_RATE] = "MaxSslRate", - [INF_SSL_FRONTEND_KEY_RATE] = "SslFrontendKeyRate", - [INF_SSL_FRONTEND_MAX_KEY_RATE] = "SslFrontendMaxKeyRate", - [INF_SSL_FRONTEND_SESSION_REUSE_PCT] = "SslFrontendSessionReuse_pct", - [INF_SSL_BACKEND_KEY_RATE] = "SslBackendKeyRate", - [INF_SSL_BACKEND_MAX_KEY_RATE] = "SslBackendMaxKeyRate", - [INF_SSL_CACHE_LOOKUPS] = "SslCacheLookups", - [INF_SSL_CACHE_MISSES] = "SslCacheMisses", - [INF_COMPRESS_BPS_IN] = "CompressBpsIn", - [INF_COMPRESS_BPS_OUT] = "CompressBpsOut", - [INF_COMPRESS_BPS_RATE_LIM] = "CompressBpsRateLim", - [INF_ZLIB_MEM_USAGE] = "ZlibMemUsage", - [INF_MAX_ZLIB_MEM_USAGE] = "MaxZlibMemUsage", - [INF_TASKS] = "Tasks", - [INF_RUN_QUEUE] = "Run_queue", - [INF_IDLE_PCT] = "Idle_pct", - [INF_NODE] = "node", - [INF_DESCRIPTION] = "description", -}; - -/* one line of stats */ -static struct field info[INF_TOTAL_FIELDS]; - static int stats_dump_env_to_buffer(struct stream_interface *si); -static int stats_dump_info_to_buffer(struct stream_interface *si); static int stats_dump_errors_to_buffer(struct stream_interface *si); static int stats_table_request(struct stream_interface *si, int show); @@ -149,7 +82,6 @@ static const char stats_sock_usage_msg[] = " prompt : toggle interactive mode with prompt\n" " quit : disconnect\n" " show env [var] : dump environment variables known to the process\n" - " show info : report information about the running process\n" " show errors : report last request and response errors for each proxy\n" " show table [id]: report table usage stats or dump this table's contents\n" " set table [id] : update or create a table entry's data\n" @@ -1076,12 +1008,6 @@ static int stats_sock_parse_request(struct stream_interface *si, char *line) appctx->st2 = STAT_ST_END; } } - else if (strcmp(args[1], "info") == 0) { - if (strcmp(args[2], "typed") == 0) - appctx->ctx.stats.flags |= STAT_FMT_TYPED; - appctx->st2 = STAT_ST_INIT; - appctx->st0 = STAT_CLI_O_INFO; // stats_dump_info_to_buffer - } else if (strcmp(args[1], "errors") == 0) { if (strm_li(s)->bind_conf->level < ACCESS_LVL_OPER) { appctx->ctx.cli.msg = stats_permission_denied_msg; @@ -1807,10 +1733,6 @@ static void cli_io_handler(struct appctx *appctx) else si_applet_cant_put(si); break; - case STAT_CLI_O_INFO: - if (stats_dump_info_to_buffer(si)) - appctx->st0 = STAT_CLI_PROMPT; - break; case STAT_CLI_O_ERR: /* errors dump */ if (stats_dump_errors_to_buffer(si)) appctx->st0 = STAT_CLI_PROMPT; @@ -1894,167 +1816,6 @@ static void cli_io_handler(struct appctx *appctx) si->state, req->flags, res->flags, req->buf->i, req->buf->o, res->buf->i, res->buf->o); } -/* Dump all fields from into using the "show info" format (name: value) */ -static int stats_dump_info_fields(struct chunk *out, const struct field *info) -{ - int field; - - for (field = 0; field < INF_TOTAL_FIELDS; field++) { - if (!field_format(info, field)) - continue; - - if (!chunk_appendf(out, "%s: ", info_field_names[field])) - return 0; - if (!stats_emit_raw_data_field(out, &info[field])) - return 0; - if (!chunk_strcat(out, "\n")) - return 0; - } - return 1; -} - -/* Dump all fields from into using the "show info typed" format */ -static int stats_dump_typed_info_fields(struct chunk *out, const struct field *info) -{ - int field; - - for (field = 0; field < INF_TOTAL_FIELDS; field++) { - if (!field_format(info, field)) - continue; - - if (!chunk_appendf(out, "%d.%s.%u:", field, info_field_names[field], info[INF_PROCESS_NUM].u.u32)) - return 0; - if (!stats_emit_field_tags(out, &info[field], ':')) - return 0; - if (!stats_emit_typed_data_field(out, &info[field])) - return 0; - if (!chunk_strcat(out, "\n")) - return 0; - } - return 1; -} - -/* Fill with HAProxy global info. is preallocated - * array of length . The length of the aray must be - * INF_TOTAL_FIELDS. If this length is less then this value, the - * function returns 0, otherwise, it returns 1. - */ -int stats_fill_info(struct field *info, int len) -{ - unsigned int up = (now.tv_sec - start_date.tv_sec); - struct chunk *out = get_trash_chunk(); - -#ifdef USE_OPENSSL - int ssl_sess_rate = read_freq_ctr(&global.ssl_per_sec); - int ssl_key_rate = read_freq_ctr(&global.ssl_fe_keys_per_sec); - int ssl_reuse = 0; - - if (ssl_key_rate < ssl_sess_rate) { - /* count the ssl reuse ratio and avoid overflows in both directions */ - ssl_reuse = 100 - (100 * ssl_key_rate + (ssl_sess_rate - 1) / 2) / ssl_sess_rate; - } -#endif - - if (len < INF_TOTAL_FIELDS) - return 0; - - chunk_reset(out); - memset(info, 0, sizeof(*info) * len); - - info[INF_NAME] = mkf_str(FO_PRODUCT|FN_OUTPUT|FS_SERVICE, PRODUCT_NAME); - info[INF_VERSION] = mkf_str(FO_PRODUCT|FN_OUTPUT|FS_SERVICE, HAPROXY_VERSION); - info[INF_RELEASE_DATE] = mkf_str(FO_PRODUCT|FN_OUTPUT|FS_SERVICE, HAPROXY_DATE); - - info[INF_NBPROC] = mkf_u32(FO_CONFIG|FS_SERVICE, global.nbproc); - info[INF_PROCESS_NUM] = mkf_u32(FO_KEY, relative_pid); - info[INF_PID] = mkf_u32(FO_STATUS, pid); - - info[INF_UPTIME] = mkf_str(FN_DURATION, chunk_newstr(out)); - chunk_appendf(out, "%ud %uh%02um%02us", up / 86400, (up % 86400) / 3600, (up % 3600) / 60, (up % 60)); - - info[INF_UPTIME_SEC] = mkf_u32(FN_DURATION, up); - info[INF_MEMMAX_MB] = mkf_u32(FO_CONFIG|FN_LIMIT, global.rlimit_memmax); - info[INF_POOL_ALLOC_MB] = mkf_u32(0, (unsigned)(pool_total_allocated() / 1048576L)); - info[INF_POOL_USED_MB] = mkf_u32(0, (unsigned)(pool_total_used() / 1048576L)); - info[INF_POOL_FAILED] = mkf_u32(FN_COUNTER, pool_total_failures()); - info[INF_ULIMIT_N] = mkf_u32(FO_CONFIG|FN_LIMIT, global.rlimit_nofile); - info[INF_MAXSOCK] = mkf_u32(FO_CONFIG|FN_LIMIT, global.maxsock); - info[INF_MAXCONN] = mkf_u32(FO_CONFIG|FN_LIMIT, global.maxconn); - info[INF_HARD_MAXCONN] = mkf_u32(FO_CONFIG|FN_LIMIT, global.hardmaxconn); - info[INF_CURR_CONN] = mkf_u32(0, actconn); - info[INF_CUM_CONN] = mkf_u32(FN_COUNTER, totalconn); - info[INF_CUM_REQ] = mkf_u32(FN_COUNTER, global.req_count); -#ifdef USE_OPENSSL - info[INF_MAX_SSL_CONNS] = mkf_u32(FN_MAX, global.maxsslconn); - info[INF_CURR_SSL_CONNS] = mkf_u32(0, sslconns); - info[INF_CUM_SSL_CONNS] = mkf_u32(FN_COUNTER, totalsslconns); -#endif - info[INF_MAXPIPES] = mkf_u32(FO_CONFIG|FN_LIMIT, global.maxpipes); - info[INF_PIPES_USED] = mkf_u32(0, pipes_used); - info[INF_PIPES_FREE] = mkf_u32(0, pipes_free); - info[INF_CONN_RATE] = mkf_u32(FN_RATE, read_freq_ctr(&global.conn_per_sec)); - info[INF_CONN_RATE_LIMIT] = mkf_u32(FO_CONFIG|FN_LIMIT, global.cps_lim); - info[INF_MAX_CONN_RATE] = mkf_u32(FN_MAX, global.cps_max); - info[INF_SESS_RATE] = mkf_u32(FN_RATE, read_freq_ctr(&global.sess_per_sec)); - info[INF_SESS_RATE_LIMIT] = mkf_u32(FO_CONFIG|FN_LIMIT, global.sps_lim); - info[INF_MAX_SESS_RATE] = mkf_u32(FN_RATE, global.sps_max); - -#ifdef USE_OPENSSL - info[INF_SSL_RATE] = mkf_u32(FN_RATE, ssl_sess_rate); - info[INF_SSL_RATE_LIMIT] = mkf_u32(FO_CONFIG|FN_LIMIT, global.ssl_lim); - info[INF_MAX_SSL_RATE] = mkf_u32(FN_MAX, global.ssl_max); - info[INF_SSL_FRONTEND_KEY_RATE] = mkf_u32(0, ssl_key_rate); - info[INF_SSL_FRONTEND_MAX_KEY_RATE] = mkf_u32(FN_MAX, global.ssl_fe_keys_max); - info[INF_SSL_FRONTEND_SESSION_REUSE_PCT] = mkf_u32(0, ssl_reuse); - info[INF_SSL_BACKEND_KEY_RATE] = mkf_u32(FN_RATE, read_freq_ctr(&global.ssl_be_keys_per_sec)); - info[INF_SSL_BACKEND_MAX_KEY_RATE] = mkf_u32(FN_MAX, global.ssl_be_keys_max); - info[INF_SSL_CACHE_LOOKUPS] = mkf_u32(FN_COUNTER, global.shctx_lookups); - info[INF_SSL_CACHE_MISSES] = mkf_u32(FN_COUNTER, global.shctx_misses); -#endif - info[INF_COMPRESS_BPS_IN] = mkf_u32(FN_RATE, read_freq_ctr(&global.comp_bps_in)); - info[INF_COMPRESS_BPS_OUT] = mkf_u32(FN_RATE, read_freq_ctr(&global.comp_bps_out)); - info[INF_COMPRESS_BPS_RATE_LIM] = mkf_u32(FO_CONFIG|FN_LIMIT, global.comp_rate_lim); -#ifdef USE_ZLIB - info[INF_ZLIB_MEM_USAGE] = mkf_u32(0, zlib_used_memory); - info[INF_MAX_ZLIB_MEM_USAGE] = mkf_u32(FO_CONFIG|FN_LIMIT, global.maxzlibmem); -#endif - info[INF_TASKS] = mkf_u32(0, nb_tasks_cur); - info[INF_RUN_QUEUE] = mkf_u32(0, run_queue_cur); - info[INF_IDLE_PCT] = mkf_u32(FN_AVG, idle_pct); - info[INF_NODE] = mkf_str(FO_CONFIG|FN_OUTPUT|FS_SERVICE, global.node); - if (global.desc) - info[INF_DESCRIPTION] = mkf_str(FO_CONFIG|FN_OUTPUT|FS_SERVICE, global.desc); - - return 1; -} - -/* This function dumps information onto the stream interface's read buffer. - * It returns 0 as long as it does not complete, non-zero upon completion. - * No state is used. - */ -static int stats_dump_info_to_buffer(struct stream_interface *si) -{ - struct appctx *appctx = __objt_appctx(si->end); - - if (!stats_fill_info(info, INF_TOTAL_FIELDS)) - return 0; - - chunk_reset(&trash); - - if (appctx->ctx.stats.flags & STAT_FMT_TYPED) - stats_dump_typed_info_fields(&trash, info); - else - stats_dump_info_fields(&trash, info); - - if (bi_putchk(si_ic(si), &trash) == -1) { - si_applet_cant_put(si); - return 0; - } - - return 1; -} - - /* This is called when the stream interface is closed. For instance, upon an * external abort, we won't call the i/o handler anymore so we may need to * remove back references to the stream currently being dumped. diff --git a/src/stats.c b/src/stats.c index e8796147fc..56266eba79 100644 --- a/src/stats.c +++ b/src/stats.c @@ -74,6 +74,64 @@ #endif +/* These are the field names for each INF_* field position. Please pay attention + * to always use the exact same name except that the strings for new names must + * be lower case or CamelCase while the enum entries must be upper case. + */ +const char *info_field_names[INF_TOTAL_FIELDS] = { + [INF_NAME] = "Name", + [INF_VERSION] = "Version", + [INF_RELEASE_DATE] = "Release_date", + [INF_NBPROC] = "Nbproc", + [INF_PROCESS_NUM] = "Process_num", + [INF_PID] = "Pid", + [INF_UPTIME] = "Uptime", + [INF_UPTIME_SEC] = "Uptime_sec", + [INF_MEMMAX_MB] = "Memmax_MB", + [INF_POOL_ALLOC_MB] = "PoolAlloc_MB", + [INF_POOL_USED_MB] = "PoolUsed_MB", + [INF_POOL_FAILED] = "PoolFailed", + [INF_ULIMIT_N] = "Ulimit-n", + [INF_MAXSOCK] = "Maxsock", + [INF_MAXCONN] = "Maxconn", + [INF_HARD_MAXCONN] = "Hard_maxconn", + [INF_CURR_CONN] = "CurrConns", + [INF_CUM_CONN] = "CumConns", + [INF_CUM_REQ] = "CumReq", + [INF_MAX_SSL_CONNS] = "MaxSslConns", + [INF_CURR_SSL_CONNS] = "CurrSslConns", + [INF_CUM_SSL_CONNS] = "CumSslConns", + [INF_MAXPIPES] = "Maxpipes", + [INF_PIPES_USED] = "PipesUsed", + [INF_PIPES_FREE] = "PipesFree", + [INF_CONN_RATE] = "ConnRate", + [INF_CONN_RATE_LIMIT] = "ConnRateLimit", + [INF_MAX_CONN_RATE] = "MaxConnRate", + [INF_SESS_RATE] = "SessRate", + [INF_SESS_RATE_LIMIT] = "SessRateLimit", + [INF_MAX_SESS_RATE] = "MaxSessRate", + [INF_SSL_RATE] = "SslRate", + [INF_SSL_RATE_LIMIT] = "SslRateLimit", + [INF_MAX_SSL_RATE] = "MaxSslRate", + [INF_SSL_FRONTEND_KEY_RATE] = "SslFrontendKeyRate", + [INF_SSL_FRONTEND_MAX_KEY_RATE] = "SslFrontendMaxKeyRate", + [INF_SSL_FRONTEND_SESSION_REUSE_PCT] = "SslFrontendSessionReuse_pct", + [INF_SSL_BACKEND_KEY_RATE] = "SslBackendKeyRate", + [INF_SSL_BACKEND_MAX_KEY_RATE] = "SslBackendMaxKeyRate", + [INF_SSL_CACHE_LOOKUPS] = "SslCacheLookups", + [INF_SSL_CACHE_MISSES] = "SslCacheMisses", + [INF_COMPRESS_BPS_IN] = "CompressBpsIn", + [INF_COMPRESS_BPS_OUT] = "CompressBpsOut", + [INF_COMPRESS_BPS_RATE_LIM] = "CompressBpsRateLim", + [INF_ZLIB_MEM_USAGE] = "ZlibMemUsage", + [INF_MAX_ZLIB_MEM_USAGE] = "MaxZlibMemUsage", + [INF_TASKS] = "Tasks", + [INF_RUN_QUEUE] = "Run_queue", + [INF_IDLE_PCT] = "Idle_pct", + [INF_NODE] = "node", + [INF_DESCRIPTION] = "description", +}; + const char *stat_field_names[ST_F_TOTAL_FIELDS] = { [ST_F_PXNAME] = "pxname", [ST_F_SVNAME] = "svname", @@ -160,10 +218,13 @@ const char *stat_field_names[ST_F_TOTAL_FIELDS] = { [ST_F_DSES] = "dses", }; +/* one line of info */ +static struct field info[INF_TOTAL_FIELDS]; /* one line of stats */ static struct field stats[ST_F_TOTAL_FIELDS]; + /* * http_stats_io_handler() * -> stats_dump_stat_to_buffer() // same as above, but used for CSV or HTML @@ -2813,6 +2874,175 @@ static void http_stats_io_handler(struct appctx *appctx) /* just to make gcc happy */ ; } +/* Dump all fields from into using the "show info" format (name: value) */ +static int stats_dump_info_fields(struct chunk *out, const struct field *info) +{ + int field; + + for (field = 0; field < INF_TOTAL_FIELDS; field++) { + if (!field_format(info, field)) + continue; + + if (!chunk_appendf(out, "%s: ", info_field_names[field])) + return 0; + if (!stats_emit_raw_data_field(out, &info[field])) + return 0; + if (!chunk_strcat(out, "\n")) + return 0; + } + return 1; +} + +/* Dump all fields from into using the "show info typed" format */ +static int stats_dump_typed_info_fields(struct chunk *out, const struct field *info) +{ + int field; + + for (field = 0; field < INF_TOTAL_FIELDS; field++) { + if (!field_format(info, field)) + continue; + + if (!chunk_appendf(out, "%d.%s.%u:", field, info_field_names[field], info[INF_PROCESS_NUM].u.u32)) + return 0; + if (!stats_emit_field_tags(out, &info[field], ':')) + return 0; + if (!stats_emit_typed_data_field(out, &info[field])) + return 0; + if (!chunk_strcat(out, "\n")) + return 0; + } + return 1; +} + +/* Fill with HAProxy global info. is preallocated + * array of length . The length of the aray must be + * INF_TOTAL_FIELDS. If this length is less then this value, the + * function returns 0, otherwise, it returns 1. + */ +int stats_fill_info(struct field *info, int len) +{ + unsigned int up = (now.tv_sec - start_date.tv_sec); + struct chunk *out = get_trash_chunk(); + +#ifdef USE_OPENSSL + int ssl_sess_rate = read_freq_ctr(&global.ssl_per_sec); + int ssl_key_rate = read_freq_ctr(&global.ssl_fe_keys_per_sec); + int ssl_reuse = 0; + + if (ssl_key_rate < ssl_sess_rate) { + /* count the ssl reuse ratio and avoid overflows in both directions */ + ssl_reuse = 100 - (100 * ssl_key_rate + (ssl_sess_rate - 1) / 2) / ssl_sess_rate; + } +#endif + + if (len < INF_TOTAL_FIELDS) + return 0; + + chunk_reset(out); + memset(info, 0, sizeof(*info) * len); + + info[INF_NAME] = mkf_str(FO_PRODUCT|FN_OUTPUT|FS_SERVICE, PRODUCT_NAME); + info[INF_VERSION] = mkf_str(FO_PRODUCT|FN_OUTPUT|FS_SERVICE, HAPROXY_VERSION); + info[INF_RELEASE_DATE] = mkf_str(FO_PRODUCT|FN_OUTPUT|FS_SERVICE, HAPROXY_DATE); + + info[INF_NBPROC] = mkf_u32(FO_CONFIG|FS_SERVICE, global.nbproc); + info[INF_PROCESS_NUM] = mkf_u32(FO_KEY, relative_pid); + info[INF_PID] = mkf_u32(FO_STATUS, pid); + + info[INF_UPTIME] = mkf_str(FN_DURATION, chunk_newstr(out)); + chunk_appendf(out, "%ud %uh%02um%02us", up / 86400, (up % 86400) / 3600, (up % 3600) / 60, (up % 60)); + + info[INF_UPTIME_SEC] = mkf_u32(FN_DURATION, up); + info[INF_MEMMAX_MB] = mkf_u32(FO_CONFIG|FN_LIMIT, global.rlimit_memmax); + info[INF_POOL_ALLOC_MB] = mkf_u32(0, (unsigned)(pool_total_allocated() / 1048576L)); + info[INF_POOL_USED_MB] = mkf_u32(0, (unsigned)(pool_total_used() / 1048576L)); + info[INF_POOL_FAILED] = mkf_u32(FN_COUNTER, pool_total_failures()); + info[INF_ULIMIT_N] = mkf_u32(FO_CONFIG|FN_LIMIT, global.rlimit_nofile); + info[INF_MAXSOCK] = mkf_u32(FO_CONFIG|FN_LIMIT, global.maxsock); + info[INF_MAXCONN] = mkf_u32(FO_CONFIG|FN_LIMIT, global.maxconn); + info[INF_HARD_MAXCONN] = mkf_u32(FO_CONFIG|FN_LIMIT, global.hardmaxconn); + info[INF_CURR_CONN] = mkf_u32(0, actconn); + info[INF_CUM_CONN] = mkf_u32(FN_COUNTER, totalconn); + info[INF_CUM_REQ] = mkf_u32(FN_COUNTER, global.req_count); +#ifdef USE_OPENSSL + info[INF_MAX_SSL_CONNS] = mkf_u32(FN_MAX, global.maxsslconn); + info[INF_CURR_SSL_CONNS] = mkf_u32(0, sslconns); + info[INF_CUM_SSL_CONNS] = mkf_u32(FN_COUNTER, totalsslconns); +#endif + info[INF_MAXPIPES] = mkf_u32(FO_CONFIG|FN_LIMIT, global.maxpipes); + info[INF_PIPES_USED] = mkf_u32(0, pipes_used); + info[INF_PIPES_FREE] = mkf_u32(0, pipes_free); + info[INF_CONN_RATE] = mkf_u32(FN_RATE, read_freq_ctr(&global.conn_per_sec)); + info[INF_CONN_RATE_LIMIT] = mkf_u32(FO_CONFIG|FN_LIMIT, global.cps_lim); + info[INF_MAX_CONN_RATE] = mkf_u32(FN_MAX, global.cps_max); + info[INF_SESS_RATE] = mkf_u32(FN_RATE, read_freq_ctr(&global.sess_per_sec)); + info[INF_SESS_RATE_LIMIT] = mkf_u32(FO_CONFIG|FN_LIMIT, global.sps_lim); + info[INF_MAX_SESS_RATE] = mkf_u32(FN_RATE, global.sps_max); + +#ifdef USE_OPENSSL + info[INF_SSL_RATE] = mkf_u32(FN_RATE, ssl_sess_rate); + info[INF_SSL_RATE_LIMIT] = mkf_u32(FO_CONFIG|FN_LIMIT, global.ssl_lim); + info[INF_MAX_SSL_RATE] = mkf_u32(FN_MAX, global.ssl_max); + info[INF_SSL_FRONTEND_KEY_RATE] = mkf_u32(0, ssl_key_rate); + info[INF_SSL_FRONTEND_MAX_KEY_RATE] = mkf_u32(FN_MAX, global.ssl_fe_keys_max); + info[INF_SSL_FRONTEND_SESSION_REUSE_PCT] = mkf_u32(0, ssl_reuse); + info[INF_SSL_BACKEND_KEY_RATE] = mkf_u32(FN_RATE, read_freq_ctr(&global.ssl_be_keys_per_sec)); + info[INF_SSL_BACKEND_MAX_KEY_RATE] = mkf_u32(FN_MAX, global.ssl_be_keys_max); + info[INF_SSL_CACHE_LOOKUPS] = mkf_u32(FN_COUNTER, global.shctx_lookups); + info[INF_SSL_CACHE_MISSES] = mkf_u32(FN_COUNTER, global.shctx_misses); +#endif + info[INF_COMPRESS_BPS_IN] = mkf_u32(FN_RATE, read_freq_ctr(&global.comp_bps_in)); + info[INF_COMPRESS_BPS_OUT] = mkf_u32(FN_RATE, read_freq_ctr(&global.comp_bps_out)); + info[INF_COMPRESS_BPS_RATE_LIM] = mkf_u32(FO_CONFIG|FN_LIMIT, global.comp_rate_lim); +#ifdef USE_ZLIB + info[INF_ZLIB_MEM_USAGE] = mkf_u32(0, zlib_used_memory); + info[INF_MAX_ZLIB_MEM_USAGE] = mkf_u32(FO_CONFIG|FN_LIMIT, global.maxzlibmem); +#endif + info[INF_TASKS] = mkf_u32(0, nb_tasks_cur); + info[INF_RUN_QUEUE] = mkf_u32(0, run_queue_cur); + info[INF_IDLE_PCT] = mkf_u32(FN_AVG, idle_pct); + info[INF_NODE] = mkf_str(FO_CONFIG|FN_OUTPUT|FS_SERVICE, global.node); + if (global.desc) + info[INF_DESCRIPTION] = mkf_str(FO_CONFIG|FN_OUTPUT|FS_SERVICE, global.desc); + + return 1; +} + +/* This function dumps information onto the stream interface's read buffer. + * It returns 0 as long as it does not complete, non-zero upon completion. + * No state is used. + */ +static int stats_dump_info_to_buffer(struct stream_interface *si) +{ + struct appctx *appctx = __objt_appctx(si->end); + + if (!stats_fill_info(info, INF_TOTAL_FIELDS)) + return 0; + + chunk_reset(&trash); + + if (appctx->ctx.stats.flags & STAT_FMT_TYPED) + stats_dump_typed_info_fields(&trash, info); + else + stats_dump_info_fields(&trash, info); + + if (bi_putchk(si_ic(si), &trash) == -1) { + si_applet_cant_put(si); + return 0; + } + + return 1; +} + +static int cli_parse_show_info(char **args, struct appctx *appctx, void *private) +{ + if (strcmp(args[2], "typed") == 0) + appctx->ctx.stats.flags |= STAT_FMT_TYPED; + appctx->st2 = STAT_ST_INIT; + return 0; +} + + static int cli_parse_show_stat(char **args, struct appctx *appctx, void *private) { if (*args[2] && *args[3] && *args[4]) { @@ -2830,6 +3060,11 @@ static int cli_parse_show_stat(char **args, struct appctx *appctx, void *private return 0; } +static int cli_io_handler_dump_info(struct appctx *appctx) +{ + return stats_dump_info_to_buffer(appctx->owner); +} + /* This I/O handler runs as an applet embedded in a stream interface. It is * used to send raw stats over a socket. */ @@ -2840,6 +3075,7 @@ static int cli_io_handler_dump_stat(struct appctx *appctx) /* register cli keywords */ static struct cli_kw_list cli_kws = {{ },{ + { { "show", "info", NULL }, "show info : report information about the running process", cli_parse_show_info, cli_io_handler_dump_info, NULL }, { { "show", "stat", NULL }, "show stat : report counters for each proxy and server", cli_parse_show_stat, cli_io_handler_dump_stat, NULL }, {{},} }};