REORG: activity/cli: move the "show activity" handler to activity.c
Initially the code was placed into cli.c to keep activity.c small and
independent of the cli stuff, but that's no longer the case anyway and
keeping that code over there makes it harder to find. Let's move it to
its more natural place now.
diff --git a/src/activity.c b/src/activity.c
index 27914e0..f697358 100644
--- a/src/activity.c
+++ b/src/activity.c
@@ -18,6 +18,7 @@
#include <haproxy/channel.h>
#include <haproxy/cli.h>
#include <haproxy/freq_ctr.h>
+#include <haproxy/listener.h>
#include <haproxy/sc_strm.h>
#include <haproxy/stconn.h>
#include <haproxy/tools.h>
@@ -31,6 +32,11 @@
int aggr; /* 0=dump raw, 1=aggregate on callee */
};
+/* CLI context for the "show activity" command */
+struct show_activity_ctx {
+ int thr; /* thread ID to show or -1 for all */
+};
+
#if defined(DEBUG_MEM_STATS)
/* these ones are macros in bug.h when DEBUG_MEM_STATS is set, and will
* prevent the new ones from being redefined.
@@ -1007,6 +1013,148 @@
return 1;
}
+/* This function dumps some activity counters used by developers and support to
+ * rule out some hypothesis during bug reports. It returns 0 if the output
+ * buffer is full and it needs to be called again, otherwise non-zero. It dumps
+ * everything at once in the buffer and is not designed to do it in multiple
+ * passes.
+ */
+static int cli_io_handler_show_activity(struct appctx *appctx)
+{
+ struct stconn *sc = appctx_sc(appctx);
+ struct show_activity_ctx *actctx = appctx->svcctx;
+ int tgt = actctx->thr; // target thread, -1 for all, 0 for total only
+ struct timeval up;
+ int thr;
+
+ if (unlikely(sc_ic(sc)->flags & (CF_WRITE_ERROR|CF_SHUTW)))
+ return 1;
+
+ chunk_reset(&trash);
+
+#undef SHOW_TOT
+#define SHOW_TOT(t, x) \
+ do { \
+ unsigned int _v[MAX_THREADS]; \
+ unsigned int _tot; \
+ const unsigned int _nbt = global.nbthread; \
+ _tot = t = 0; \
+ do { \
+ _tot += _v[t] = (x); \
+ } while (++t < _nbt); \
+ if (_nbt == 1) { \
+ chunk_appendf(&trash, " %u\n", _tot); \
+ break; \
+ } \
+ if (tgt == -1) { \
+ chunk_appendf(&trash, " %u [", _tot); \
+ for (t = 0; t < _nbt; t++) \
+ chunk_appendf(&trash, " %u", _v[t]); \
+ chunk_appendf(&trash, " ]\n"); \
+ } else if (tgt == 0) \
+ chunk_appendf(&trash, " %u\n", _tot); \
+ else \
+ chunk_appendf(&trash, " %u\n", _v[tgt-1]);\
+ } while (0)
+
+#undef SHOW_AVG
+#define SHOW_AVG(t, x) \
+ do { \
+ unsigned int _v[MAX_THREADS]; \
+ unsigned int _tot; \
+ const unsigned int _nbt = global.nbthread; \
+ _tot = t = 0; \
+ do { \
+ _tot += _v[t] = (x); \
+ } while (++t < _nbt); \
+ if (_nbt == 1) { \
+ chunk_appendf(&trash, " %u\n", _tot); \
+ break; \
+ } \
+ if (tgt == -1) { \
+ chunk_appendf(&trash, " %u [", (_tot + _nbt/2) / _nbt); \
+ for (t = 0; t < _nbt; t++) \
+ chunk_appendf(&trash, " %u", _v[t]); \
+ chunk_appendf(&trash, " ]\n"); \
+ } else if (tgt == 0) \
+ chunk_appendf(&trash, " %u\n", (_tot + _nbt/2) / _nbt); \
+ else \
+ chunk_appendf(&trash, " %u\n", _v[tgt-1]);\
+ } while (0)
+
+ /* retrieve uptime */
+ tv_remain(&start_date, &now, &up);
+
+ chunk_appendf(&trash, "thread_id: %u (%u..%u)\n", tid + 1, 1, global.nbthread);
+ chunk_appendf(&trash, "date_now: %lu.%06lu\n", (ulong)now.tv_sec, (ulong)now.tv_usec);
+ chunk_appendf(&trash, "uptime_now: %lu.%06lu\n", (ulong)up.tv_sec, (ulong)up.tv_usec);
+ chunk_appendf(&trash, "ctxsw:"); SHOW_TOT(thr, activity[thr].ctxsw);
+ chunk_appendf(&trash, "tasksw:"); SHOW_TOT(thr, activity[thr].tasksw);
+ chunk_appendf(&trash, "empty_rq:"); SHOW_TOT(thr, activity[thr].empty_rq);
+ chunk_appendf(&trash, "long_rq:"); SHOW_TOT(thr, activity[thr].long_rq);
+ chunk_appendf(&trash, "loops:"); SHOW_TOT(thr, activity[thr].loops);
+ chunk_appendf(&trash, "wake_tasks:"); SHOW_TOT(thr, activity[thr].wake_tasks);
+ chunk_appendf(&trash, "wake_signal:"); SHOW_TOT(thr, activity[thr].wake_signal);
+ chunk_appendf(&trash, "poll_io:"); SHOW_TOT(thr, activity[thr].poll_io);
+ chunk_appendf(&trash, "poll_exp:"); SHOW_TOT(thr, activity[thr].poll_exp);
+ chunk_appendf(&trash, "poll_drop_fd:"); SHOW_TOT(thr, activity[thr].poll_drop_fd);
+ chunk_appendf(&trash, "poll_skip_fd:"); SHOW_TOT(thr, activity[thr].poll_skip_fd);
+ chunk_appendf(&trash, "conn_dead:"); SHOW_TOT(thr, activity[thr].conn_dead);
+ chunk_appendf(&trash, "stream_calls:"); SHOW_TOT(thr, activity[thr].stream_calls);
+ chunk_appendf(&trash, "pool_fail:"); SHOW_TOT(thr, activity[thr].pool_fail);
+ chunk_appendf(&trash, "buf_wait:"); SHOW_TOT(thr, activity[thr].buf_wait);
+ chunk_appendf(&trash, "cpust_ms_tot:"); SHOW_TOT(thr, activity[thr].cpust_total / 2);
+ chunk_appendf(&trash, "cpust_ms_1s:"); SHOW_TOT(thr, read_freq_ctr(&activity[thr].cpust_1s) / 2);
+ chunk_appendf(&trash, "cpust_ms_15s:"); SHOW_TOT(thr, read_freq_ctr_period(&activity[thr].cpust_15s, 15000) / 2);
+ chunk_appendf(&trash, "avg_loop_us:"); SHOW_AVG(thr, swrate_avg(activity[thr].avg_loop_us, TIME_STATS_SAMPLES));
+ chunk_appendf(&trash, "accepted:"); SHOW_TOT(thr, activity[thr].accepted);
+ chunk_appendf(&trash, "accq_pushed:"); SHOW_TOT(thr, activity[thr].accq_pushed);
+ chunk_appendf(&trash, "accq_full:"); SHOW_TOT(thr, activity[thr].accq_full);
+#ifdef USE_THREAD
+ chunk_appendf(&trash, "accq_ring:"); SHOW_TOT(thr, (accept_queue_rings[thr].tail - accept_queue_rings[thr].head + ACCEPT_QUEUE_SIZE) % ACCEPT_QUEUE_SIZE);
+ chunk_appendf(&trash, "fd_takeover:"); SHOW_TOT(thr, activity[thr].fd_takeover);
+#endif
+
+#if defined(DEBUG_DEV)
+ /* keep these ones at the end */
+ chunk_appendf(&trash, "ctr0:"); SHOW_TOT(thr, activity[thr].ctr0);
+ chunk_appendf(&trash, "ctr1:"); SHOW_TOT(thr, activity[thr].ctr1);
+ chunk_appendf(&trash, "ctr2:"); SHOW_TOT(thr, activity[thr].ctr2);
+#endif
+
+ if (applet_putchk(appctx, &trash) == -1) {
+ chunk_reset(&trash);
+ chunk_printf(&trash, "[output too large, cannot dump]\n");
+ }
+
+#undef SHOW_AVG
+#undef SHOW_TOT
+ /* dump complete */
+ return 1;
+}
+
+/* parse a "show activity" CLI request. Returns 0 if it needs to continue, 1 if it
+ * wants to stop here. It sets a show_activity_ctx context where, if a specific
+ * thread is requested, it puts the thread number into ->thr otherwise sets it to
+ * -1.
+ */
+static int cli_parse_show_activity(char **args, char *payload, struct appctx *appctx, void *private)
+{
+ struct show_activity_ctx *ctx = applet_reserve_svcctx(appctx, sizeof(*ctx));
+
+ if (!cli_has_level(appctx, ACCESS_LVL_OPER))
+ return 1;
+
+ ctx->thr = -1; // show all by default
+ if (*args[2])
+ ctx->thr = atoi(args[2]);
+
+ if (ctx->thr < -1 || ctx->thr > global.nbthread)
+ return cli_err(appctx, "Thread ID number must be between -1 and nbthread\n");
+
+ return 0;
+}
+
/* config keyword parsers */
static struct cfg_kw_list cfg_kws = {ILH, {
#ifdef USE_MEMORY_PROFILING
@@ -1021,6 +1169,7 @@
/* register cli keywords */
static struct cli_kw_list cli_kws = {{ },{
{ { "set", "profiling", NULL }, "set profiling <what> {auto|on|off} : enable/disable resource profiling (tasks,memory)", cli_parse_set_profiling, NULL },
+ { { "show", "activity", NULL }, "show activity [-1|0|thread_num] : show per-thread activity stats (for support/developers)", cli_parse_show_activity, cli_io_handler_show_activity, NULL },
{ { "show", "profiling", NULL }, "show profiling [<what>|<#lines>|<opts>]*: show profiling state (all,status,tasks,memory)", cli_parse_show_profiling, cli_io_handler_show_profiling, NULL },
{ { "show", "tasks", NULL }, "show tasks : show running tasks", NULL, cli_io_handler_show_tasks, NULL },
{{},}
diff --git a/src/cli.c b/src/cli.c
index 864031c..2cbc89e 100644
--- a/src/cli.c
+++ b/src/cli.c
@@ -26,7 +26,6 @@
#include <net/if.h>
-#include <haproxy/activity.h>
#include <haproxy/api.h>
#include <haproxy/applet.h>
#include <haproxy/base64.h>
@@ -87,11 +86,6 @@
struct proxy *mworker_proxy; /* CLI proxy of the master */
struct bind_conf *mcli_reload_bind_conf;
-/* CLI context for the "show activity" command */
-struct show_activity_ctx {
- int thr; /* thread ID to show or -1 for all */
-};
-
/* CLI context for the "show env" command */
struct show_env_ctx {
char **var; /* first variable to show */
@@ -1458,126 +1452,6 @@
return ret;
}
-/* This function dumps some activity counters used by developers and support to
- * rule out some hypothesis during bug reports. It returns 0 if the output
- * buffer is full and it needs to be called again, otherwise non-zero. It dumps
- * everything at once in the buffer and is not designed to do it in multiple
- * passes.
- */
-static int cli_io_handler_show_activity(struct appctx *appctx)
-{
- struct stconn *sc = appctx_sc(appctx);
- struct show_activity_ctx *actctx = appctx->svcctx;
- int tgt = actctx->thr; // target thread, -1 for all, 0 for total only
- struct timeval up;
- int thr;
-
- if (unlikely(sc_ic(sc)->flags & (CF_WRITE_ERROR|CF_SHUTW)))
- return 1;
-
- chunk_reset(&trash);
-
-#undef SHOW_TOT
-#define SHOW_TOT(t, x) \
- do { \
- unsigned int _v[MAX_THREADS]; \
- unsigned int _tot; \
- const unsigned int _nbt = global.nbthread; \
- _tot = t = 0; \
- do { \
- _tot += _v[t] = (x); \
- } while (++t < _nbt); \
- if (_nbt == 1) { \
- chunk_appendf(&trash, " %u\n", _tot); \
- break; \
- } \
- if (tgt == -1) { \
- chunk_appendf(&trash, " %u [", _tot); \
- for (t = 0; t < _nbt; t++) \
- chunk_appendf(&trash, " %u", _v[t]); \
- chunk_appendf(&trash, " ]\n"); \
- } else if (tgt == 0) \
- chunk_appendf(&trash, " %u\n", _tot); \
- else \
- chunk_appendf(&trash, " %u\n", _v[tgt-1]);\
- } while (0)
-
-#undef SHOW_AVG
-#define SHOW_AVG(t, x) \
- do { \
- unsigned int _v[MAX_THREADS]; \
- unsigned int _tot; \
- const unsigned int _nbt = global.nbthread; \
- _tot = t = 0; \
- do { \
- _tot += _v[t] = (x); \
- } while (++t < _nbt); \
- if (_nbt == 1) { \
- chunk_appendf(&trash, " %u\n", _tot); \
- break; \
- } \
- if (tgt == -1) { \
- chunk_appendf(&trash, " %u [", (_tot + _nbt/2) / _nbt); \
- for (t = 0; t < _nbt; t++) \
- chunk_appendf(&trash, " %u", _v[t]); \
- chunk_appendf(&trash, " ]\n"); \
- } else if (tgt == 0) \
- chunk_appendf(&trash, " %u\n", (_tot + _nbt/2) / _nbt); \
- else \
- chunk_appendf(&trash, " %u\n", _v[tgt-1]);\
- } while (0)
-
- /* retrieve uptime */
- tv_remain(&start_date, &now, &up);
-
- chunk_appendf(&trash, "thread_id: %u (%u..%u)\n", tid + 1, 1, global.nbthread);
- chunk_appendf(&trash, "date_now: %lu.%06lu\n", (ulong)now.tv_sec, (ulong)now.tv_usec);
- chunk_appendf(&trash, "uptime_now: %lu.%06lu\n", (ulong)up.tv_sec, (ulong)up.tv_usec);
- chunk_appendf(&trash, "ctxsw:"); SHOW_TOT(thr, activity[thr].ctxsw);
- chunk_appendf(&trash, "tasksw:"); SHOW_TOT(thr, activity[thr].tasksw);
- chunk_appendf(&trash, "empty_rq:"); SHOW_TOT(thr, activity[thr].empty_rq);
- chunk_appendf(&trash, "long_rq:"); SHOW_TOT(thr, activity[thr].long_rq);
- chunk_appendf(&trash, "loops:"); SHOW_TOT(thr, activity[thr].loops);
- chunk_appendf(&trash, "wake_tasks:"); SHOW_TOT(thr, activity[thr].wake_tasks);
- chunk_appendf(&trash, "wake_signal:"); SHOW_TOT(thr, activity[thr].wake_signal);
- chunk_appendf(&trash, "poll_io:"); SHOW_TOT(thr, activity[thr].poll_io);
- chunk_appendf(&trash, "poll_exp:"); SHOW_TOT(thr, activity[thr].poll_exp);
- chunk_appendf(&trash, "poll_drop_fd:"); SHOW_TOT(thr, activity[thr].poll_drop_fd);
- chunk_appendf(&trash, "poll_skip_fd:"); SHOW_TOT(thr, activity[thr].poll_skip_fd);
- chunk_appendf(&trash, "conn_dead:"); SHOW_TOT(thr, activity[thr].conn_dead);
- chunk_appendf(&trash, "stream_calls:"); SHOW_TOT(thr, activity[thr].stream_calls);
- chunk_appendf(&trash, "pool_fail:"); SHOW_TOT(thr, activity[thr].pool_fail);
- chunk_appendf(&trash, "buf_wait:"); SHOW_TOT(thr, activity[thr].buf_wait);
- chunk_appendf(&trash, "cpust_ms_tot:"); SHOW_TOT(thr, activity[thr].cpust_total / 2);
- chunk_appendf(&trash, "cpust_ms_1s:"); SHOW_TOT(thr, read_freq_ctr(&activity[thr].cpust_1s) / 2);
- chunk_appendf(&trash, "cpust_ms_15s:"); SHOW_TOT(thr, read_freq_ctr_period(&activity[thr].cpust_15s, 15000) / 2);
- chunk_appendf(&trash, "avg_loop_us:"); SHOW_AVG(thr, swrate_avg(activity[thr].avg_loop_us, TIME_STATS_SAMPLES));
- chunk_appendf(&trash, "accepted:"); SHOW_TOT(thr, activity[thr].accepted);
- chunk_appendf(&trash, "accq_pushed:"); SHOW_TOT(thr, activity[thr].accq_pushed);
- chunk_appendf(&trash, "accq_full:"); SHOW_TOT(thr, activity[thr].accq_full);
-#ifdef USE_THREAD
- chunk_appendf(&trash, "accq_ring:"); SHOW_TOT(thr, (accept_queue_rings[thr].tail - accept_queue_rings[thr].head + ACCEPT_QUEUE_SIZE) % ACCEPT_QUEUE_SIZE);
- chunk_appendf(&trash, "fd_takeover:"); SHOW_TOT(thr, activity[thr].fd_takeover);
-#endif
-
-#if defined(DEBUG_DEV)
- /* keep these ones at the end */
- chunk_appendf(&trash, "ctr0:"); SHOW_TOT(thr, activity[thr].ctr0);
- chunk_appendf(&trash, "ctr1:"); SHOW_TOT(thr, activity[thr].ctr1);
- chunk_appendf(&trash, "ctr2:"); SHOW_TOT(thr, activity[thr].ctr2);
-#endif
-
- if (applet_putchk(appctx, &trash) == -1) {
- chunk_reset(&trash);
- chunk_printf(&trash, "[output too large, cannot dump]\n");
- }
-
-#undef SHOW_AVG
-#undef SHOW_TOT
- /* dump complete */
- return 1;
-}
-
/*
* CLI IO handler for `show cli sockets`.
* Uses the svcctx as a show_sock_ctx to store/retrieve the bind_conf and the
@@ -1656,28 +1530,6 @@
return 0;
}
-
-/* parse a "show activity" CLI request. Returns 0 if it needs to continue, 1 if it
- * wants to stop here. It sets a show_activity_ctx context where, if a specific
- * thread is requested, it puts the thread number into ->thr otherwise sets it to
- * -1.
- */
-static int cli_parse_show_activity(char **args, char *payload, struct appctx *appctx, void *private)
-{
- struct show_activity_ctx *ctx = applet_reserve_svcctx(appctx, sizeof(*ctx));
-
- if (!cli_has_level(appctx, ACCESS_LVL_OPER))
- return 1;
-
- ctx->thr = -1; // show all by default
- if (*args[2])
- ctx->thr = atoi(args[2]);
-
- if (ctx->thr < -1 || ctx->thr > global.nbthread)
- return cli_err(appctx, "Thread ID number must be between -1 and nbthread\n");
-
- return 0;
-}
/* parse a "show env" CLI request. Returns 0 if it needs to continue, 1 if it
* wants to stop here. It reserves a sohw_env_ctx where it puts the variable to
@@ -3315,7 +3167,6 @@
{ { "show", "cli", "sockets", NULL }, "show cli sockets : dump list of cli sockets", cli_parse_default, cli_io_handler_show_cli_sock, NULL, NULL, ACCESS_MASTER },
{ { "show", "cli", "level", NULL }, "show cli level : display the level of the current CLI session", cli_parse_show_lvl, NULL, NULL, NULL, ACCESS_MASTER},
{ { "show", "fd", NULL }, "show fd [num] : dump list of file descriptors in use or a specific one", cli_parse_show_fd, cli_io_handler_show_fd, NULL },
- { { "show", "activity", NULL }, "show activity [-1|0|thread_num] : show per-thread activity stats (for support/developers)", cli_parse_show_activity, cli_io_handler_show_activity, NULL },
{ { "show", "version", NULL }, "show version : show version of the current process", cli_parse_show_version, NULL, NULL, NULL, ACCESS_MASTER },
{ { "operator", NULL }, "operator : lower the level of the current CLI session to operator", cli_parse_set_lvl, NULL, NULL, NULL, ACCESS_MASTER},
{ { "user", NULL }, "user : lower the level of the current CLI session to user", cli_parse_set_lvl, NULL, NULL, NULL, ACCESS_MASTER},