]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: log: provide log origin in logformat expressions using '%OG'
authorAurelien DARRAGON <adarragon@haproxy.com>
Mon, 6 May 2024 12:13:11 +0000 (14:13 +0200)
committerAurelien DARRAGON <adarragon@haproxy.com>
Thu, 13 Jun 2024 13:43:09 +0000 (15:43 +0200)
'%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
include/haproxy/log.h
src/log.c

index 05ea7fdc16f25feea995f1583ff6d8e37a2c33b9..d85d403609a61705af67473da9d70f45fef7da36 100644 (file)
@@ -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
index 984ef4a0a2397cfb7f40c9d972e06bcac69788bc..48b363dd43d83e84aeb93f09ddf25621e71318fe 100644 (file)
@@ -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);
index 2061c066bf6cd52263ffed1d672fee48f6d06330..0cd704da9f6df748a000de460f9cd4c82080a0f5 100644 (file)
--- 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,