]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
REORG: cli: move "show info" to stats.c
authorWilly Tarreau <w@1wt.eu>
Tue, 22 Nov 2016 15:36:53 +0000 (16:36 +0100)
committerWilly Tarreau <w@1wt.eu>
Thu, 24 Nov 2016 15:59:27 +0000 (16:59 +0100)
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.

include/types/cli.h
include/types/stats.h
src/cli.c
src/stats.c

index 9c7bed5123402411e6db647c73d7d982ae06cb9b..883c72d1e2a8d694a2c297f702e5f30139844527 100644 (file)
@@ -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 */
index dd52bba10947f550f615c97138f657bb7cd75ccc..48cf645fc27825ee36f1ffdc7c9f833031e92f1b 100644 (file)
@@ -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
index cdfbebf0d798d81a7ea3c52c212cb8763b9e88fa..a395e238bec6739497af432c40d1eb5e7169241c 100644 (file)
--- a/src/cli.c
+++ b/src/cli.c
 #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.
index e8796147fcba062a67b8f46ea0a7f50564d21b38..56266eba7964c649fdf26cbdd344edf3976bbb50 100644 (file)
 #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 },
        {{},}
 }};