MEDIUM: log: postpone the decision to send or not log with empty messages

As reported by Nick Ramirez in GH #2891, it is currently not possible to
use log-profile without a log-format set on the proxy.

This is due to historical reason, because all log sending functions avoid
trying to send a log with empty message. But now with log-profile which
can override log-format, it is possible that some loggers may actually
end up generating a valid log message that should be sent! Yet from the
upper logging functions we don't know about that because loggers are
evaluated in lower API functions.

Thus, to avoid skipping potentially valid messages (thanks to log-profile
overrides), in this patch we postpone the decision to send or not empty
log messages in lower log API layer, ie: _process_send_log_final(), once
the log-profile settings were evaluated for a given logger.

A known side-effect of this change is that fe->log_count statistic may
be increased even if no log message is sent because the message was empty
and even the log-profile didn't help to produce a non empty log message.
But since configurations lacking proxy log-format are not supposed to be
used without log-profile (+ log steps combination) anyway it shouldn't be
an issue.
This commit is contained in:
Aurelien DARRAGON 2025-03-05 11:28:14 +01:00
parent 9e9b110032
commit c7abe7778e

View File

@ -2912,6 +2912,9 @@ struct process_send_log_ctx {
static inline void _process_send_log_final(struct logger *logger, struct log_header hdr,
char *message, size_t size, int nblogger)
{
if (!size)
return; // don't try to send empty message
if (logger->target.type == LOG_TARGET_BACKEND) {
__do_send_log_backend(logger->target.be, hdr, nblogger, logger->maxlen, message, size);
}
@ -5188,6 +5191,7 @@ out:
*/
void do_log(struct session *sess, struct stream *s, struct log_orig origin)
{
struct process_send_log_ctx ctx;
int size;
int sd_size = 0;
int level = -1;
@ -5222,15 +5226,12 @@ void do_log(struct session *sess, struct stream *s, struct log_orig origin)
}
size = sess_build_logline_orig(sess, s, logline, global.max_syslog_len, &sess->fe->logformat, origin);
if (size > 0) {
struct process_send_log_ctx ctx;
ctx.origin = origin;
ctx.sess = sess;
ctx.stream = s;
__send_log(&ctx, &sess->fe->loggers, &sess->fe->log_tag, level,
logline, size, logline_rfc5424, sd_size);
}
ctx.origin = origin;
ctx.sess = sess;
ctx.stream = s;
__send_log(&ctx, &sess->fe->loggers, &sess->fe->log_tag, level,
logline, size, logline_rfc5424, sd_size);
}
/*
@ -5239,6 +5240,7 @@ void do_log(struct session *sess, struct stream *s, struct log_orig origin)
*/
void strm_log(struct stream *s, struct log_orig origin)
{
struct process_send_log_ctx ctx;
struct session *sess = s->sess;
int size, err, level;
int sd_size = 0;
@ -5280,17 +5282,14 @@ void strm_log(struct stream *s, struct log_orig origin)
}
size = build_logline_orig(s, logline, global.max_syslog_len, &sess->fe->logformat, origin);
if (size > 0) {
struct process_send_log_ctx ctx;
_HA_ATOMIC_INC(&sess->fe->log_count);
ctx.origin = origin;
ctx.sess = sess;
ctx.stream = s;
__send_log(&ctx, &sess->fe->loggers, &sess->fe->log_tag, level,
logline, size, logline_rfc5424, sd_size);
s->logs.logwait = 0;
}
_HA_ATOMIC_INC(&sess->fe->log_count);
ctx.origin = origin;
ctx.sess = sess;
ctx.stream = s;
__send_log(&ctx, &sess->fe->loggers, &sess->fe->log_tag, level,
logline, size, logline_rfc5424, sd_size);
s->logs.logwait = 0;
}
/*
@ -5308,6 +5307,7 @@ void strm_log(struct stream *s, struct log_orig origin)
*/
void _sess_log(struct session *sess, int embryonic)
{
struct process_send_log_ctx ctx;
int size, level;
int sd_size = 0;
struct log_orig orig;
@ -5349,17 +5349,14 @@ void _sess_log(struct session *sess, int embryonic)
session_embryonic_build_legacy_err(sess, &buf);
size = buf.data;
}
if (size > 0) {
struct process_send_log_ctx ctx;
_HA_ATOMIC_INC(&sess->fe->log_count);
ctx.origin = orig;
ctx.sess = sess;
ctx.stream = NULL;
__send_log(&ctx, &sess->fe->loggers,
&sess->fe->log_tag, level,
logline, size, logline_rfc5424, sd_size);
}
_HA_ATOMIC_INC(&sess->fe->log_count);
ctx.origin = orig;
ctx.sess = sess;
ctx.stream = NULL;
__send_log(&ctx, &sess->fe->loggers,
&sess->fe->log_tag, level,
logline, size, logline_rfc5424, sd_size);
}
void app_log(struct list *loggers, struct buffer *tag, int level, const char *format, ...)