mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2025-03-11 05:48:41 +00:00
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.
This commit is contained in:
parent
2b812e29f6
commit
0baac8cf1f
@ -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 */
|
||||
|
@ -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
|
||||
|
239
src/cli.c
239
src/cli.c
@ -67,74 +67,7 @@
|
||||
#include <proto/stream_interface.h>
|
||||
#include <proto/task.h>
|
||||
|
||||
#ifdef USE_OPENSSL
|
||||
#include <proto/ssl_sock.h>
|
||||
#include <types/ssl_sock.h>
|
||||
#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 <info> into <out> 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 <info> into <out> 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 <info> with HAProxy global info. <info> is preallocated
|
||||
* array of length <len>. 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.
|
||||
|
236
src/stats.c
236
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 <info> into <out> 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 <info> into <out> 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 <info> with HAProxy global info. <info> is preallocated
|
||||
* array of length <len>. 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 },
|
||||
{{},}
|
||||
}};
|
||||
|
Loading…
Reference in New Issue
Block a user