]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: master/cli: also implement the timed prompt on the master CLI
authorWilly Tarreau <w@1wt.eu>
Thu, 11 May 2023 14:14:02 +0000 (16:14 +0200)
committerWilly Tarreau <w@1wt.eu>
Thu, 11 May 2023 14:38:52 +0000 (16:38 +0200)
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
  #<PID>          <type>          <reloads>       <uptime>        <version>
  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
include/haproxy/stream-t.h
src/cli.c

index f226d997b774e2a02a764002d31e77657470b422..2bac0e9c30d4ba384a472c6e2e4752b91a2cf19f 100644 (file)
@@ -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
index 14293d5b825d2a8e700832bd126913b2dc73f8ec..aa84ebf7169438057f273294d0af938682b899d5 100644 (file)
@@ -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.
index f81cfa65299838904352e2e0dba1f805151ddda0..d8675e10f687c26536e2077a4d0de04bf8c957ea 100644 (file)
--- 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);