diff --git a/doc/configuration.txt b/doc/configuration.txt index d4b7bcdef..ba5a8b360 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -933,6 +933,12 @@ log
[len ] [format ] [sample :] - "stdout" / "stderr", which are respectively aliases for "fd@1" and "fd@2", see above. + - A ring buffer in the form "ring@", which will correspond to an + in-memory ring buffer accessible over the CLI using the "show events" + command, which will also list existing rings and their sizes. Such + buffers are lost on reload or restart but when used as a complement + this can help troubleshooting by having the logs instantly available. + You may want to reference some environment variables in the address parameter, see section 2.3 about environment variables. @@ -5385,6 +5391,13 @@ no log - "stdout" / "stderr", which are respectively aliases for "fd@1" and "fd@2", see above. + - A ring buffer in the form "ring@", which will correspond + to an in-memory ring buffer accessible over the CLI using the + "show events" command, which will also list existing rings and + their sizes. Such buffers are lost on reload or restart but + when used as a complement this can help troubleshooting by + having the logs instantly available. + You may want to reference some environment variables in the address parameter, see section 2.3 about environment variables. diff --git a/include/types/log.h b/include/types/log.h index dbbd73bf7..a29ecf574 100644 --- a/include/types/log.h +++ b/include/types/log.h @@ -28,6 +28,7 @@ #include #include #include +#include #define NB_LOG_FACILITIES 24 #define NB_LOG_LEVELS 8 @@ -51,6 +52,7 @@ enum { enum log_tgt { LOG_TARGET_DGRAM = 0, // datagram address (udp, unix socket) LOG_TARGET_FD, // file descriptor + LOG_TARGET_BUFFER, // ring buffer }; /* lists of fields that can be logged */ @@ -203,6 +205,7 @@ struct logsrv { struct list list; struct sockaddr_storage addr; struct smp_info lb; + struct ring *ring; enum log_tgt type; int format; int facility; diff --git a/src/log.c b/src/log.c index 1b34c637e..b96c174be 100644 --- a/src/log.c +++ b/src/log.c @@ -39,7 +39,9 @@ #include #include #include +#include #include +#include #include #include #include @@ -1000,6 +1002,20 @@ int parse_logsrv(char **args, struct list *logsrvs, int do_del, char **err) /* now, back to the address */ logsrv->type = LOG_TARGET_DGRAM; + if (strncmp(args[1], "ring@", 5) == 0) { + struct sink *sink = sink_find(args[1] + 5); + + if (!sink || sink->type != SINK_TYPE_BUFFER) { + memprintf(err, "cannot find ring buffer '%s'", args[1] + 5); + goto error; + } + + logsrv->addr.ss_family = AF_UNSPEC; + logsrv->type = LOG_TARGET_BUFFER; + logsrv->ring = sink->ctx.ring; + goto done; + } + if (strncmp(args[1], "fd@", 3) == 0) logsrv->type = LOG_TARGET_FD; @@ -1017,6 +1033,7 @@ int parse_logsrv(char **args, struct list *logsrvs, int do_del, char **err) if (!port1) set_host_port(&logsrv->addr, SYSLOG_PORT); } + done: LIST_ADDQ(logsrvs, &logsrv->list); return 1; @@ -1510,12 +1527,15 @@ static inline void __do_send_log(struct logsrv *logsrv, int nblogger, char *pid_ /* the socket's address is a file descriptor */ plogfd = (int *)&((struct sockaddr_in *)&logsrv->addr)->sin_addr.s_addr; } + else if (logsrv->type == LOG_TARGET_BUFFER) { + plogfd = NULL; + } else if (logsrv->addr.ss_family == AF_UNIX) plogfd = &logfdunix; else plogfd = &logfdinet; - if (unlikely(*plogfd < 0)) { + if (plogfd && unlikely(*plogfd < 0)) { /* socket not successfully initialized yet */ if ((*plogfd = socket(logsrv->addr.ss_family, SOCK_DGRAM, (logsrv->addr.ss_family == AF_UNIX) ? 0 : IPPROTO_UDP)) < 0) { @@ -1652,7 +1672,7 @@ static inline void __do_send_log(struct logsrv *logsrv, int nblogger, char *pid_ max = MIN(size, maxlen - sd_max) - 1; send: if (logsrv->addr.ss_family == AF_UNSPEC) { - /* the target is a direct file descriptor */ + /* the target is a file descriptor or a ring buffer */ struct ist msg[7]; msg[0].ptr = hdr_ptr; msg[0].len = hdr_max; @@ -1663,7 +1683,10 @@ send: msg[5].ptr = sd; msg[5].len = sd_max; msg[6].ptr = dataptr; msg[6].len = max; - sent = fd_write_frag_line(*plogfd, ~0, NULL, 0, msg, 7, 1); + if (logsrv->type == LOG_TARGET_BUFFER) + sent = ring_write(logsrv->ring, ~0, NULL, 0, msg, 7); + else /* LOG_TARGET_FD */ + sent = fd_write_frag_line(*plogfd, ~0, NULL, 0, msg, 7, 1); } else { iovec[0].iov_base = hdr_ptr;