From 8f34320e15c336a7ea5f37107d7264ca557d055c Mon Sep 17 00:00:00 2001 From: Aurelien DARRAGON Date: Mon, 6 May 2024 14:13:11 +0200 Subject: [PATCH] MINOR: log: provide log origin in logformat expressions using '%OG' '%OG' logformat alias may be used to report the log origin (when/where) that triggered log generation using sess_build_logline(). Possible values are: - "sess_error": log was generated during session error handling - "sess_killed": log was generated during session abortion (killed embryonic session) - "txn_accept": log was generated right after frontend conn was accepted - "txn_request": log was generated after client request was received - "txn_connect": log was generated after backend connection establishment - "txn_response": log was generated during server response handling - "txn_close": log was generated at the final txn step, before closing - "unspec": unknown or not specified Documentation was updated. --- doc/configuration.txt | 20 +++++++++++++++++++- include/haproxy/log.h | 21 +++++++++++++++++++-- src/log.c | 38 ++++++++++++++++++++++++++++---------- 3 files changed, 66 insertions(+), 13 deletions(-) diff --git a/doc/configuration.txt b/doc/configuration.txt index 05ea7fdc16..d85d403609 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -25948,6 +25948,22 @@ Special alias "%o" may be used to propagate its flags to all other logformat items on the same format string. This is particularly handy with quoted ("Q") and escaped ("E") string formats. +Special alias "%OG" may be used to retrieve the log origin (when / where +the log was generated) in a human readable format. It is particularly useful +with "option logasap" because some log variables or sample fetches could report +incomplete values or behave diffently depending on when / where the logformat +expression was evaluated. Possible values are: + - "sess_error": log was generated during session error handling + - "sess_killed": log was generated during session abortion (killed + embryonic session) + - "txn_accept": log was generated right after frontend conn was accepted + - "txn_request": log was generated after client request was received + - "txn_connect": log was generated after backend connection establishment + - "txn_response": log was generated during server response handling + - "txn_close": log was generated at the final txn step, before closing + - "unspec": unknown or not specified +"%OG" is only relevant in logging context. + Items can optionally be named using ('()'). The name must be provided right after '%' (before arguments). It will automatically be used as key name when encoding flag such as "json" or "cbor" is set. When no encoding flag is @@ -26174,6 +26190,8 @@ Please refer to the table below for currently defined aliases : | | %hsl | captured_response_headers CLF style | string | | | | | list | +---+------+------------------------------------------------------+---------+ + | L | %OG | human readable log origin | string | + +---+------+------------------------------------------------------+---------+ | | %pid | PID | | | | | %[pid] | numeric | +---+------+------------------------------------------------------+---------+ @@ -26211,7 +26229,7 @@ Please refer to the table below for currently defined aliases : | H | %tsc | termination_state with cookie status | string | +---+------+------------------------------------------------------+---------+ - R = Restrictions : H = mode http only ; S = SSL only + R = Restrictions : H = mode http only ; S = SSL only ; L = log only 8.3. Advanced logging options diff --git a/include/haproxy/log.h b/include/haproxy/log.h index 984ef4a0a2..48b363dd43 100644 --- a/include/haproxy/log.h +++ b/include/haproxy/log.h @@ -82,7 +82,15 @@ void free_logformat_list(struct list *fmt); void free_logformat_node(struct logformat_node *node); /* build a log line for the session and an optional stream */ -int sess_build_logline(struct session *sess, struct stream *s, char *dst, size_t maxsize, struct lf_expr *lf_expr); +int sess_build_logline_orig(struct session *sess, struct stream *s, char *dst, size_t maxsize, + struct lf_expr *lf_expr, enum log_orig orig); + +/* wrapper for sess_build_logline_orig(), uses LOG_ORIG_UNSPEC log origin */ +static inline int sess_build_logline(struct session *sess, struct stream *s, char *dst, size_t maxsize, + struct lf_expr *lf_expr) +{ + return sess_build_logline_orig(sess, s, dst, maxsize, lf_expr, LOG_ORIG_UNSPEC); +} /* * send a log for the stream when we have enough info about it. @@ -163,9 +171,18 @@ char * get_format_pid_sep2(int format, size_t *len); /* * Builds a log line for the stream (must be valid). */ +static inline int build_logline_orig(struct stream *s, char *dst, size_t maxsize, + struct lf_expr *lf_expr, enum log_orig orig) +{ + return sess_build_logline_orig(strm_sess(s), s, dst, maxsize, lf_expr, orig); +} + +/* + * Wrapper for build_logline_orig, uses LOG_ORIG_UNSPEC log origin + */ static inline int build_logline(struct stream *s, char *dst, size_t maxsize, struct lf_expr *lf_expr) { - return sess_build_logline(strm_sess(s), s, dst, maxsize, lf_expr); + return build_logline_orig(s, dst, maxsize, lf_expr, LOG_ORIG_UNSPEC); } struct ist *build_log_header(struct log_header hdr, size_t *nbelem); diff --git a/src/log.c b/src/log.c index 2061c066bf..0cd704da9f 100644 --- a/src/log.c +++ b/src/log.c @@ -151,6 +151,7 @@ int prepare_addrsource(struct logformat_node *node, struct proxy *curproxy); /* logformat alias types (internal use) */ enum logformat_alias_type { LOG_FMT_GLOBAL, + LOG_FMT_ORIGIN, LOG_FMT_CLIENTIP, LOG_FMT_CLIENTPORT, LOG_FMT_BACKENDIP, @@ -219,6 +220,7 @@ enum logformat_alias_type { /* log_format alias names */ static const struct logformat_alias logformat_aliases[] = { { "o", LOG_FMT_GLOBAL, PR_MODE_TCP, 0, NULL }, /* global option */ + { "OG", LOG_FMT_ORIGIN, PR_MODE_TCP, 0, NULL }, /* human readable log origin */ /* please keep these lines sorted ! */ { "B", LOG_FMT_BYTES, PR_MODE_TCP, LW_BYTES, NULL }, /* bytes from server to client */ @@ -3603,7 +3605,9 @@ int lf_expr_dup(const struct lf_expr *orig, struct lf_expr *dest) * is not zero. It requires a valid session and optionally a stream. If the * stream is NULL, default values will be assumed for the stream part. */ -int sess_build_logline(struct session *sess, struct stream *s, char *dst, size_t maxsize, struct lf_expr *lf_expr) +int sess_build_logline_orig(struct session *sess, struct stream *s, + char *dst, size_t maxsize, struct lf_expr *lf_expr, + enum log_orig log_orig) { struct lf_buildctx *ctx = &lf_buildctx; struct proxy *fe = sess->fe; @@ -4865,6 +4869,14 @@ int sess_build_logline(struct session *sess, struct stream *s, char *dst, size_t tmplog = ret; break; + case LOG_FMT_ORIGIN: // %OG + ret = lf_text(tmplog, log_orig_to_str(log_orig), + dst + maxsize - tmplog, ctx); + if (ret == NULL) + goto out; + tmplog = ret; + break; + } next_fmt: if (value_beg == tmplog) { @@ -4960,11 +4972,11 @@ void strm_log(struct stream *s, int origin) } if (!lf_expr_isempty(&sess->fe->logformat_sd)) { - sd_size = build_logline(s, logline_rfc5424, global.max_syslog_len, - &sess->fe->logformat_sd); + sd_size = build_logline_orig(s, logline_rfc5424, global.max_syslog_len, + &sess->fe->logformat_sd, origin); } - size = build_logline(s, logline, global.max_syslog_len, &sess->fe->logformat); + size = build_logline_orig(s, logline, global.max_syslog_len, &sess->fe->logformat, origin); if (size > 0) { struct process_send_log_ctx ctx; @@ -4995,6 +5007,7 @@ void _sess_log(struct session *sess, int embryonic) { int size, level; int sd_size = 0; + int orig = (embryonic) ? LOG_ORIG_SESS_KILL : LOG_ORIG_SESS_ERROR; if (!sess) return; @@ -5007,15 +5020,20 @@ void _sess_log(struct session *sess, int embryonic) level = LOG_ERR; if (!lf_expr_isempty(&sess->fe->logformat_sd)) { - sd_size = sess_build_logline(sess, NULL, - logline_rfc5424, global.max_syslog_len, - &sess->fe->logformat_sd); + sd_size = sess_build_logline_orig(sess, NULL, + logline_rfc5424, global.max_syslog_len, + &sess->fe->logformat_sd, + orig); } if (!lf_expr_isempty(&sess->fe->logformat_error)) - size = sess_build_logline(sess, NULL, logline, global.max_syslog_len, &sess->fe->logformat_error); + size = sess_build_logline_orig(sess, NULL, logline, + global.max_syslog_len, &sess->fe->logformat_error, + orig); else if (!embryonic) - size = sess_build_logline(sess, NULL, logline, global.max_syslog_len, &sess->fe->logformat); + size = sess_build_logline_orig(sess, NULL, logline, + global.max_syslog_len, &sess->fe->logformat, + orig); else { /* no logformat_error and embryonic==1 */ struct buffer buf; @@ -5027,7 +5045,7 @@ void _sess_log(struct session *sess, int embryonic) struct process_send_log_ctx ctx; _HA_ATOMIC_INC(&sess->fe->log_count); - ctx.origin = (embryonic) ? LOG_ORIG_SESS_KILL : LOG_ORIG_SESS_ERROR; + ctx.origin = orig; ctx.sess = sess; ctx.stream = NULL; __send_log(&ctx, &sess->fe->loggers, -- 2.39.5