> Hi!
>
> As discussed few weeks ago in issue #2856 , this is a PR
> that adds two useful options to the log-forward section.
>
> ```
> option dontparselog
> Enables HAProxy to relay syslog messages
> without attempting to parse and
> restructure them, useful for
> forwarding messages that may not conform to
> traditional formats.
> This option should be used with the format raw setting on
> destination log targets to ensure the original message content is
> preserved.
>
> option assume-rfc6587-ntf
> Directs HAProxy to
> treat incoming TCP log streams always as using
> non-transparent
> framing. This option simplifies the framing logic and ensures
> consistent handling of messages, particularly useful when dealing with
> improperly formed starting characters.
> ```
>
> Thanks a lot
> in advance for taking this into consideration.
> Best,
> Rober
Hi Rober,
Thanks for your contribution.
Here are some remarks:
> diff --git a/src/log.c b/src/log.c
> index 90b5645cb2e6..234f83e2426f 100644
> --- a/src/log.c
> +++ b/src/log.c
> @@ -5376,6 +5376,24 @@ void app_log(struct list *loggers, struct buffer *tag,
> int level, const char *fo
>
> __send_log(NULL, loggers, tag, level, logline, data_len,
> default_rfc5424_sd_log_format, 2);
> }
> +
> +/*
> + * This function sets up the initial state for a log message by preparing
> + * the buffer, setting default values for the log level and facility, and
> + * initializing metadata fields. It is used before parsing or constructing
> + * a log message to ensure all fields are in a known state.
> + */
> +void prepare_log_message(char *buf, size_t buflen, int *level, int *facility,
idendation issue below
> +
> struct ist *metadata, char **message, size_t *size)
> +{
> + *level = *facility = -1;
> +
> + *message = buf;
> + *size = buflen;
> +
> + memset(metadata, 0, LOG_META_FIELDS*sizeof(struct ist));
> +}
> @@ -6203,6 +6206,34 @@ int cfg_parse_log_forward(const char *file, int
> linenum, char **args, int kwm)
> }
> cfg_log_forward->timeout.client = MS_TO_TICKS(timeout);
> }
> + else if (strcmp(args[0], "option") == 0) {
> + int optnum;
> +
> + if (*(args[1]) == '\0') {
> + ha_alert("parsing [%s:%d]: '%s' expects an option
> name.\n",
> + file, linenum, args[0]);
> + err_code |= ERR_ALERT | ERR_FATAL;
identation issue below
> + goto out;
> + }
> +
> +
> + for (optnum = 0; cfg_opts_log[optnum].name; optnum++) {
> + if (strcmp(args[1], cfg_opts_log[optnum].name) == 0) {
> + if (cfg_opts_log[optnum].cap == PR_CAP_NONE) {
> + ha_alert("parsing [%s:%d]: option
> '%s' is not supported due to build options.\n",
identation issue below
> + file, linenum, cfg_opts2[optnum].name);
> + err_code |= ERR_ALERT | ERR_FATAL;
> + goto out;
> + }
> + if (alertif_too_many_args_idx(0, 1, file,
> linenum, args, &err_code))
> + goto out;
> + if (warnifnotcap(cfg_log_forward,
> cfg_opts_log[optnum].cap, file, linenum, args[1], NULL)) {
> + err_code |= ERR_WARN;
> + goto out;
> + }
> + cfg_log_forward->options_log |=
> cfg_opts_log[optnum].val;
> + }
> + }
> + }
> diff --git a/src/proxy.c b/src/proxy.c
> index a1143fc68631..9000f63b751e 100644
> --- a/src/proxy.c
> +++ b/src/proxy.c
> @@ -134,6 +134,13 @@ const struct cfg_opt cfg_opts2[] =
> { NULL, 0, 0, 0 }
> };
>
> +/* proxy->options_log */
> +const struct cfg_opt cfg_opts_log[] = {
identation issue below
> + {"dontparselog", PR_OL_DONTPARSELOG,
> PR_CAP_FE, 0, PR_MODE_SYSLOG },
> + {"assume-rfc6587-ntf", PR_OL_ASSUME_RFC6587_NTF, PR_CAP_FE, 0,
> PR_MODE_SYSLOG },
> + { NULL, 0, 0, 0 }
> +};
> +
> /* Helper function to resolve a single sticking rule after config parsing.
> * Returns 1 for success and 0 for failure
> */
> diff --git a/src/log.c b/src/log.c
> index 234f83e2426f..af9c4c704e94 100644
> --- a/src/log.c
> +++ b/src/log.c
> @@ -5759,7 +5759,8 @@ void syslog_fd_handler(int fd)
>
> prepare_log_message(buf->area, buf->data, &level,
> &facility, metadata, &message, &size);
>
> - parse_log_message(buf->area, buf->data, &level,
> &facility, metadata, &message, &size);
> + if (!(l->bind_conf->frontend->options_log &
> PR_OL_DONTPARSELOG))
I would rather have "struct proxy *frontend = strm_fe(s);" and use that
frontend pointer to access options instead of l->bind_conf->frontend.
> + parse_log_message(buf->area, buf->data,
> &level, &facility, metadata, &message, &size);
Well, aside from indentation issues, I'm fine with the first patch.
Regarding the second one, the doc and behavior look good to me, However
I don't have an opinion regarding the "proxy->options_log" options
dedicated to log-forward proxies. Since log-forward section only
supports keywords explicitly handled in cfg_parse_log_forward() (so
proxy->options and proxy->options2 are currently unused), I'm wondering
if we could re-use the same memory area, either have PR_O_* flags that
have a different meaning when set on log-forward proxy, or share the
same memory area by leveraging an union for options_log member. Also it
looks like cfg_opts_log[] is a bit overkill because only the name->flag
value association is used. I'll let other give their opinion on that point.
Thanks :)
Aurelien