MINOR: ring: support arbitrary delimiters through ring_dispatch_messages()

In order to support delimiting output events with other characters than
just the LF, let's pass the delimiter through the API. The default remains
the LF, used by applet_append_line(), and ignored by the log forwarder.
This commit is contained in:
Willy Tarreau 2025-03-31 18:17:35 +02:00
parent 038a372684
commit 0be6d73e88
7 changed files with 14 additions and 12 deletions

View File

@ -58,7 +58,7 @@ size_t appctx_raw_snd_buf(struct appctx *appctx, struct buffer *buf, size_t coun
size_t appctx_snd_buf(struct stconn *sc, struct buffer *buf, size_t count, unsigned int flags); size_t appctx_snd_buf(struct stconn *sc, struct buffer *buf, size_t count, unsigned int flags);
int appctx_fastfwd(struct stconn *sc, unsigned int count, unsigned int flags); int appctx_fastfwd(struct stconn *sc, unsigned int count, unsigned int flags);
ssize_t applet_append_line(void *ctx, struct ist v1, struct ist v2, size_t ofs, size_t len); ssize_t applet_append_line(void *ctx, struct ist v1, struct ist v2, size_t ofs, size_t len, char delim);
static forceinline void applet_fl_set(struct appctx *appctx, uint on); static forceinline void applet_fl_set(struct appctx *appctx, uint on);
static forceinline void applet_fl_clr(struct appctx *appctx, uint off); static forceinline void applet_fl_clr(struct appctx *appctx, uint off);

View File

@ -144,7 +144,7 @@ void app_log(struct list *loggers, struct buffer *tag, int level, const char *fo
*/ */
int add_to_logformat_list(char *start, char *end, int type, struct lf_expr *lf_expr, char **err); int add_to_logformat_list(char *start, char *end, int type, struct lf_expr *lf_expr, char **err);
ssize_t syslog_applet_append_event(void *ctx, struct ist v1, struct ist v2, size_t ofs, size_t len); ssize_t syslog_applet_append_event(void *ctx, struct ist v1, struct ist v2, size_t ofs, size_t len, char delim);
/* /*
* Parse the log_format string and fill a linked list. * Parse the log_format string and fill a linked list.

View File

@ -43,7 +43,8 @@ void cli_io_release_show_ring(struct appctx *appctx);
size_t ring_max_payload(const struct ring *ring); size_t ring_max_payload(const struct ring *ring);
int ring_dispatch_messages(struct ring *ring, void *ctx, size_t *ofs_ptr, size_t *last_ofs_ptr, uint flags, int ring_dispatch_messages(struct ring *ring, void *ctx, size_t *ofs_ptr, size_t *last_ofs_ptr, uint flags,
ssize_t (*msg_handler)(void *ctx, struct ist v1, struct ist v2, size_t ofs, size_t len), ssize_t (*msg_handler)(void *ctx, struct ist v1, struct ist v2, size_t ofs, size_t len, char delim),
char delim,
size_t *processed); size_t *processed);
/* returns the ring storage's usable area */ /* returns the ring storage's usable area */

View File

@ -737,7 +737,7 @@ end:
return ret; return ret;
} }
/* Atomically append a line to applet <ctx>'s output, appending a trailing LF. /* Atomically append a line to applet <ctx>'s output, appending a delimiter.
* The line is read from vectors <v1> and <v2> at offset <ofs> relative to the * The line is read from vectors <v1> and <v2> at offset <ofs> relative to the
* area's origin, for <len> bytes. It returns the number of bytes consumed from * area's origin, for <len> bytes. It returns the number of bytes consumed from
* the input vectors on success, -1 if it temporarily cannot (buffer full), -2 * the input vectors on success, -1 if it temporarily cannot (buffer full), -2
@ -745,7 +745,7 @@ end:
* The caller is responsible for making sure that there are at least ofs+len * The caller is responsible for making sure that there are at least ofs+len
* bytes in the input vectors. * bytes in the input vectors.
*/ */
ssize_t applet_append_line(void *ctx, struct ist v1, struct ist v2, size_t ofs, size_t len) ssize_t applet_append_line(void *ctx, struct ist v1, struct ist v2, size_t ofs, size_t len, char delim)
{ {
struct appctx *appctx = ctx; struct appctx *appctx = ctx;
@ -757,7 +757,7 @@ ssize_t applet_append_line(void *ctx, struct ist v1, struct ist v2, size_t ofs,
chunk_reset(&trash); chunk_reset(&trash);
vp_peek_ofs(v1, v2, ofs, trash.area, len); vp_peek_ofs(v1, v2, ofs, trash.area, len);
trash.data += len; trash.data += len;
trash.area[trash.data++] = '\n'; trash.area[trash.data++] = delim;
if (applet_putchk(appctx, &trash) == -1) if (applet_putchk(appctx, &trash) == -1)
return -1; return -1;
return len; return len;

View File

@ -5976,7 +5976,7 @@ static struct applet syslog_applet = {
* large msg). The input vectors are not modified. The caller is responsible for * large msg). The input vectors are not modified. The caller is responsible for
* making sure that there are at least ofs+len bytes in the input buffer. * making sure that there are at least ofs+len bytes in the input buffer.
*/ */
ssize_t syslog_applet_append_event(void *ctx, struct ist v1, struct ist v2, size_t ofs, size_t len) ssize_t syslog_applet_append_event(void *ctx, struct ist v1, struct ist v2, size_t ofs, size_t len, char delim)
{ {
struct appctx *appctx = ctx; struct appctx *appctx = ctx;
char *p; char *p;

View File

@ -550,7 +550,8 @@ int ring_attach_cli(struct ring *ring, struct appctx *appctx, uint flags)
* processed by the function (even when the function returns 0) * processed by the function (even when the function returns 0)
*/ */
int ring_dispatch_messages(struct ring *ring, void *ctx, size_t *ofs_ptr, size_t *last_ofs_ptr, uint flags, int ring_dispatch_messages(struct ring *ring, void *ctx, size_t *ofs_ptr, size_t *last_ofs_ptr, uint flags,
ssize_t (*msg_handler)(void *ctx, struct ist v1, struct ist v2, size_t ofs, size_t len), ssize_t (*msg_handler)(void *ctx, struct ist v1, struct ist v2, size_t ofs, size_t len, char delim),
char delim,
size_t *processed) size_t *processed)
{ {
size_t head_ofs, tail_ofs, prev_ofs; size_t head_ofs, tail_ofs, prev_ofs;
@ -644,7 +645,7 @@ int ring_dispatch_messages(struct ring *ring, void *ctx, size_t *ofs_ptr, size_t
BUG_ON(msg_len + cnt + 1 > vp_size(v1, v2)); BUG_ON(msg_len + cnt + 1 > vp_size(v1, v2));
copied = msg_handler(ctx, v1, v2, cnt, msg_len); copied = msg_handler(ctx, v1, v2, cnt, msg_len, delim);
if (copied == -2) { if (copied == -2) {
/* too large a message to ever fit, let's skip it */ /* too large a message to ever fit, let's skip it */
goto skip; goto skip;
@ -703,7 +704,7 @@ int cli_io_handler_show_ring(struct appctx *appctx)
MT_LIST_DELETE(&appctx->wait_entry); MT_LIST_DELETE(&appctx->wait_entry);
ret = ring_dispatch_messages(ring, appctx, &ctx->ofs, &last_ofs, ctx->flags, applet_append_line, NULL); ret = ring_dispatch_messages(ring, appctx, &ctx->ofs, &last_ofs, ctx->flags, applet_append_line, '\n', NULL);
if (ret && (ctx->flags & RING_WF_WAIT_MODE)) { if (ret && (ctx->flags & RING_WF_WAIT_MODE)) {
/* we've drained everything and are configured to wait for more /* we've drained everything and are configured to wait for more

View File

@ -412,7 +412,7 @@ void sink_setup_proxy(struct proxy *px)
} }
static void _sink_forward_io_handler(struct appctx *appctx, static void _sink_forward_io_handler(struct appctx *appctx,
ssize_t (*msg_handler)(void *ctx, struct ist v1, struct ist v2, size_t ofs, size_t len)) ssize_t (*msg_handler)(void *ctx, struct ist v1, struct ist v2, size_t ofs, size_t len, char delim))
{ {
struct stconn *sc = appctx_sc(appctx); struct stconn *sc = appctx_sc(appctx);
struct sink_forward_target *sft = appctx->svcctx; struct sink_forward_target *sft = appctx->svcctx;
@ -446,7 +446,7 @@ static void _sink_forward_io_handler(struct appctx *appctx,
MT_LIST_DELETE(&appctx->wait_entry); MT_LIST_DELETE(&appctx->wait_entry);
ret = ring_dispatch_messages(ring, appctx, &sft->ofs, &last_ofs, 0, ret = ring_dispatch_messages(ring, appctx, &sft->ofs, &last_ofs, 0,
msg_handler, &processed); msg_handler, '\n', &processed);
sft->e_processed += processed; sft->e_processed += processed;
/* if server's max-reuse is set (>= 0), destroy the applet once the /* if server's max-reuse is set (>= 0), destroy the applet once the