From ea07715ccff4b46c3a9aa40afe80dd3943f1a9c6 Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Thu, 11 May 2023 16:14:02 +0200 Subject: [PATCH] MINOR: master/cli: also implement the timed prompt on the master CLI This provides more consistency between the master and the worker. When "prompt timed" is passed on the master, the timed mode is toggled. When enabled, for a master it will show the master process' uptime, and for a worker it will show this worker's uptime. Example: master> prompt timed [0:00:00:50] master> show proc # 11940 master 1 [failed: 0] 0d00h02m10s 2.8-dev11-474c14-21 # workers 11955 worker 0 0d00h00m59s 2.8-dev11-474c14-21 # old workers 11942 worker 1 0d00h02m10s 2.8-dev11-474c14-21 # programs [0:00:00:58] master> @!11955 [0:00:01:03] 11955> @!11942 [0:00:02:17] 11942> @ [0:00:01:10] master> --- doc/management.txt | 12 ++++++++++ include/haproxy/stream-t.h | 1 + src/cli.c | 47 ++++++++++++++++++++++++++++++++++---- 3 files changed, 56 insertions(+), 4 deletions(-) diff --git a/doc/management.txt b/doc/management.txt index f226d997b..2bac0e9c3 100644 --- a/doc/management.txt +++ b/doc/management.txt @@ -1511,6 +1511,18 @@ of hours, minutes and seconds on two digits each: [23:03:34:41]> quit +When the timed prompt is set on the master CLI, the prompt will display the +currently selected process' uptime, so this will work for the master, current +worker or an older worker: + + master> prompt timed + [0:00:00:50] master> show proc + (...) + [0:00:00:58] master> @!11955 <-- master, switch to current worker + [0:00:01:03] 11955> @!11942 <-- current worker, switch to older worker + [0:00:02:17] 11942> @ <-- older worker, switch back to master + [0:00:01:10] master> + Since multiple commands may be issued at once, haproxy uses the empty line as a delimiter to mark an end of output for each command, and takes care of ensuring that no command can emit an empty line on output. A script can thus easily diff --git a/include/haproxy/stream-t.h b/include/haproxy/stream-t.h index 14293d5b8..aa84ebf71 100644 --- a/include/haproxy/stream-t.h +++ b/include/haproxy/stream-t.h @@ -132,6 +132,7 @@ static forceinline char *strm_show_flags(char *buf, size_t len, const char *deli #define PCLI_F_PROMPT 0x10000 #define PCLI_F_PAYLOAD 0x20000 #define PCLI_F_RELOAD 0x40000 /* this is the "reload" stream, quits after displaying reload status */ +#define PCLI_F_TIMED 0x80000 /* the prompt shows the process' uptime */ /* error types reported on the streams for more accurate reporting. diff --git a/src/cli.c b/src/cli.c index f81cfa652..d8675e10f 100644 --- a/src/cli.c +++ b/src/cli.c @@ -2221,11 +2221,46 @@ void pcli_write_prompt(struct stream *s) if (s->pcli_flags & PCLI_F_PAYLOAD) { chunk_appendf(msg, "+ "); } else { - if (s->pcli_next_pid == 0) + if (s->pcli_next_pid == 0) { + /* master's prompt */ + if (s->pcli_flags & PCLI_F_TIMED) { + uint up = ns_to_sec(now_ns - start_time_ns); + chunk_appendf(msg, "[%u:%02u:%02u:%02u] ", + (up / 86400), (up / 3600) % 24, (up / 60) % 60, up % 60); + } + chunk_appendf(msg, "master%s", (proc_self->failedreloads > 0) ? "[ReloadFailed]" : ""); - else + } + else { + /* worker's prompt */ + if (s->pcli_flags & PCLI_F_TIMED) { + const struct mworker_proc *tmp, *proc; + uint up; + + /* set proc to the worker corresponding to pcli_next_pid or NULL */ + proc = NULL; + list_for_each_entry(tmp, &proc_list, list) { + if (!(tmp->options & PROC_O_TYPE_WORKER)) + continue; + if (tmp->pid == s->pcli_next_pid) { + proc = tmp; + break; + } + } + + if (!proc) + chunk_appendf(msg, "[gone] "); + else { + up = date.tv_sec - proc->timestamp; + if ((int)up < 0) /* must never be negative because of clock drift */ + up = 0; + chunk_appendf(msg, "[%u:%02u:%02u:%02u] ", + (up / 86400), (up / 3600) % 24, (up / 60) % 60, up % 60); + } + } chunk_appendf(msg, "%d", s->pcli_next_pid); + } if (s->pcli_flags & (ACCESS_EXPERIMENTAL|ACCESS_EXPERT|ACCESS_MCLI_DEBUG)) { chunk_appendf(msg, "("); @@ -2368,9 +2403,13 @@ int pcli_find_and_exec_kw(struct stream *s, char **args, int argl, char **errmsg *next_pid = target_pid; return 1; } else if (strcmp("prompt", args[0]) == 0) { - s->pcli_flags ^= PCLI_F_PROMPT; + if (argl >= 2 && strcmp(args[1], "timed") == 0) { + s->pcli_flags |= PCLI_F_PROMPT; + s->pcli_flags ^= PCLI_F_TIMED; + } + else + s->pcli_flags ^= PCLI_F_PROMPT; return argl; /* return the number of elements in the array */ - } else if (strcmp("quit", args[0]) == 0) { sc_schedule_abort(s->scf); sc_schedule_shutdown(s->scf);