- "stdout" / "stderr", which are respectively aliases for "fd@1" and
"fd@2", see above.
+ - A ring buffer in the form "ring@<name>", 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.
- "stdout" / "stderr", which are respectively aliases for "fd@1"
and "fd@2", see above.
+ - A ring buffer in the form "ring@<name>", 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.
#include <common/config.h>
#include <common/hathreads.h>
#include <common/mini-clist.h>
+#include <types/ring.h>
#define NB_LOG_FACILITIES 24
#define NB_LOG_LEVELS 8
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 */
struct list list;
struct sockaddr_storage addr;
struct smp_info lb;
+ struct ring *ring;
enum log_tgt type;
int format;
int facility;
#include <proto/fd.h>
#include <proto/frontend.h>
#include <proto/log.h>
+#include <proto/ring.h>
#include <proto/sample.h>
+#include <proto/sink.h>
#include <proto/ssl_sock.h>
#include <proto/stream.h>
#include <proto/stream_interface.h>
/* 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;
if (!port1)
set_host_port(&logsrv->addr, SYSLOG_PORT);
}
+ done:
LIST_ADDQ(logsrvs, &logsrv->list);
return 1;
/* 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) {
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;
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;