From: Aurelien DARRAGON Date: Thu, 22 Feb 2024 19:20:41 +0000 (+0100) Subject: MEDIUM: log: carry tag context in logformat node X-Git-Tag: v3.0-dev7~16 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=7d8f45b6471984fedd7153e842de9baa03d8f669;p=thirdparty%2Fhaproxy.git MEDIUM: log: carry tag context in logformat node This is a pretty simple patch despite requiring to make some visible changes in the code: When parsing a logformat string, log tags (ie: '%tag', AKA log tags) are turned into logformat nodes with their type set to the type of the corresponding logformat_tag element which was matched by name. Thus, when "compiling" a logformat tag, we only keep a reference to the tag type from the original logformat_tag. For example, for "%B" log tag, we have the following logformat_tag element: { .name = "B", .type = LOG_FMT_BYTES, .mode = PR_MODE_TCP, .lw = LW_BYTES, .config_callback = NULL } When parsing "%B" string, we search for a matching logformat tag inside logformat_tags[] array using the provided name, once we find a matching element, we craft a logformat node whose type will be LOG_FMT_BYTES, but from the node itself, we no longer have access to other informations that are set in the logformat_tag struct element. Thus from a logformat_node resulting from a log tag, with current implementation, we cannot easily get back to matching logformat_tag struct element as it would require us to scan the whole logformat_tags array at runtime using node->type to find the matching element. Let's take a simpler path and consider all tag-specific LOG_FMT_* subtypes as being part of the same logformat node type: LOG_FMT_TAG. Thanks to that, we're now able to distinguish logformat nodes made from logformat tag from other logformat nodes, and link them to their corresponding logformat_tag element from logformat_tags[] array. All it costs is a simple indirection and an extra pointer in logformat_node struct. While at it, all LOG_FMT_* types related to logformat tags were moved inside log.c as they have no use outside of it since they are simply lookup indexes for sess_build_logline() and could even be replaced by function pointers some day... --- diff --git a/include/haproxy/log-t.h b/include/haproxy/log-t.h index 5f77c2b5d6..91e418051d 100644 --- a/include/haproxy/log-t.h +++ b/include/haproxy/log-t.h @@ -122,75 +122,10 @@ enum log_tgt { /* lists of fields that can be logged, for logformat_node->type */ enum { - LOG_FMT_TEXT = 0, /* raw text */ - LOG_FMT_EXPR, /* sample expression */ + LOG_FMT_TEXT = 0, /* raw text */ + LOG_FMT_EXPR, /* sample expression */ LOG_FMT_SEPARATOR, /* separator replaced by one space */ - - /* information fields */ - LOG_FMT_GLOBAL, - LOG_FMT_CLIENTIP, - LOG_FMT_CLIENTPORT, - LOG_FMT_BACKENDIP, - LOG_FMT_BACKENDPORT, - LOG_FMT_FRONTENDIP, - LOG_FMT_FRONTENDPORT, - LOG_FMT_SERVERPORT, - LOG_FMT_SERVERIP, - LOG_FMT_COUNTER, - LOG_FMT_LOGCNT, - LOG_FMT_PID, - LOG_FMT_DATE, - LOG_FMT_DATEGMT, - LOG_FMT_DATELOCAL, - LOG_FMT_TS, - LOG_FMT_MS, - LOG_FMT_FRONTEND, - LOG_FMT_FRONTEND_XPRT, - LOG_FMT_BACKEND, - LOG_FMT_SERVER, - LOG_FMT_BYTES, - LOG_FMT_BYTES_UP, - LOG_FMT_Ta, - LOG_FMT_Th, - LOG_FMT_Ti, - LOG_FMT_TQ, - LOG_FMT_TW, - LOG_FMT_TC, - LOG_FMT_Tr, - LOG_FMT_tr, - LOG_FMT_trg, - LOG_FMT_trl, - LOG_FMT_TR, - LOG_FMT_TD, - LOG_FMT_TT, - LOG_FMT_TU, - LOG_FMT_STATUS, - LOG_FMT_CCLIENT, - LOG_FMT_CSERVER, - LOG_FMT_TERMSTATE, - LOG_FMT_TERMSTATE_CK, - LOG_FMT_ACTCONN, - LOG_FMT_FECONN, - LOG_FMT_BECONN, - LOG_FMT_SRVCONN, - LOG_FMT_RETRIES, - LOG_FMT_SRVQUEUE, - LOG_FMT_BCKQUEUE, - LOG_FMT_HDRREQUEST, - LOG_FMT_HDRRESPONS, - LOG_FMT_HDRREQUESTLIST, - LOG_FMT_HDRRESPONSLIST, - LOG_FMT_REQ, - LOG_FMT_HTTP_METHOD, - LOG_FMT_HTTP_URI, - LOG_FMT_HTTP_PATH, - LOG_FMT_HTTP_PATH_ONLY, - LOG_FMT_HTTP_QUERY, - LOG_FMT_HTTP_VERSION, - LOG_FMT_HOSTNAME, - LOG_FMT_UNIQUEID, - LOG_FMT_SSL_CIPHER, - LOG_FMT_SSL_VERSION, + LOG_FMT_TAG, /* reference to logformat_tag */ }; /* enum for parse_logformat_string */ @@ -230,6 +165,7 @@ struct logformat_node { char *name; // printable name for output types that require named fields (ie: json) char *arg; // text for LOG_FMT_TEXT, arg for others void *expr; // for use with LOG_FMT_EXPR + const struct logformat_tag *tag; // set if ->type == LOG_FMT_TAG }; /* Range of indexes for log sampling. */ diff --git a/src/log.c b/src/log.c index ecb475f1e7..1dcdd4ba4f 100644 --- a/src/log.c +++ b/src/log.c @@ -121,6 +121,74 @@ const char sess_fin_state[8] = "-RCHDLQT"; /* cliRequest, srvConnect, srvHeader int prepare_addrsource(struct logformat_node *node, struct proxy *curproxy); +/* logformat tag types (internal use) */ +enum logformat_tag_type { + LOG_FMT_GLOBAL, + LOG_FMT_CLIENTIP, + LOG_FMT_CLIENTPORT, + LOG_FMT_BACKENDIP, + LOG_FMT_BACKENDPORT, + LOG_FMT_FRONTENDIP, + LOG_FMT_FRONTENDPORT, + LOG_FMT_SERVERPORT, + LOG_FMT_SERVERIP, + LOG_FMT_COUNTER, + LOG_FMT_LOGCNT, + LOG_FMT_PID, + LOG_FMT_DATE, + LOG_FMT_DATEGMT, + LOG_FMT_DATELOCAL, + LOG_FMT_TS, + LOG_FMT_MS, + LOG_FMT_FRONTEND, + LOG_FMT_FRONTEND_XPRT, + LOG_FMT_BACKEND, + LOG_FMT_SERVER, + LOG_FMT_BYTES, + LOG_FMT_BYTES_UP, + LOG_FMT_Ta, + LOG_FMT_Th, + LOG_FMT_Ti, + LOG_FMT_TQ, + LOG_FMT_TW, + LOG_FMT_TC, + LOG_FMT_Tr, + LOG_FMT_tr, + LOG_FMT_trg, + LOG_FMT_trl, + LOG_FMT_TR, + LOG_FMT_TD, + LOG_FMT_TT, + LOG_FMT_TU, + LOG_FMT_STATUS, + LOG_FMT_CCLIENT, + LOG_FMT_CSERVER, + LOG_FMT_TERMSTATE, + LOG_FMT_TERMSTATE_CK, + LOG_FMT_ACTCONN, + LOG_FMT_FECONN, + LOG_FMT_BECONN, + LOG_FMT_SRVCONN, + LOG_FMT_RETRIES, + LOG_FMT_SRVQUEUE, + LOG_FMT_BCKQUEUE, + LOG_FMT_HDRREQUEST, + LOG_FMT_HDRRESPONS, + LOG_FMT_HDRREQUESTLIST, + LOG_FMT_HDRRESPONSLIST, + LOG_FMT_REQ, + LOG_FMT_HTTP_METHOD, + LOG_FMT_HTTP_URI, + LOG_FMT_HTTP_PATH, + LOG_FMT_HTTP_PATH_ONLY, + LOG_FMT_HTTP_QUERY, + LOG_FMT_HTTP_VERSION, + LOG_FMT_HOSTNAME, + LOG_FMT_UNIQUEID, + LOG_FMT_SSL_CIPHER, + LOG_FMT_SSL_VERSION, +}; + /* log_format tag names */ static const struct logformat_tag logformat_tags[] = { { "o", LOG_FMT_GLOBAL, PR_MODE_TCP, 0, NULL }, /* global option */ @@ -316,7 +384,8 @@ int parse_logformat_tag(char *arg, int arg_len, char *name, int name_len, int ty memprintf(err, "out of memory error"); goto error_free; } - node->type = logformat_tags[j].type; + node->type = LOG_FMT_TAG; + node->tag = &logformat_tags[j]; node->typecast = typecast; if (name) node->name = my_strndup(name, name_len); @@ -326,7 +395,7 @@ int parse_logformat_tag(char *arg, int arg_len, char *name, int name_len, int ty if (!parse_logformat_tag_args(node->arg, node, err)) goto error_free; } - if (node->type == LOG_FMT_GLOBAL) { + if (node->tag->type == LOG_FMT_GLOBAL) { *defoptions = node->options; free_logformat_node(node); } else { @@ -2692,7 +2761,13 @@ int sess_build_logline(struct session *sess, struct stream *s, char *dst, size_t goto out; tmplog = ret; break; + } + + if (tmp->type != LOG_FMT_TAG) + goto next_fmt; + /* logformat tag */ + switch (tmp->tag->type) { case LOG_FMT_CLIENTIP: // %ci addr = (s ? sc_src(s->scf) : sess_src(sess)); if (addr) @@ -3540,6 +3615,7 @@ int sess_build_logline(struct session *sess, struct stream *s, char *dst, size_t break; } + next_fmt: if (tmp->type != LOG_FMT_SEPARATOR) last_isspace = 0; // not a separator, hence not a space