From c043d5d37236d246b88407a9607f4c291205fa82 Mon Sep 17 00:00:00 2001 From: Aurelien DARRAGON Date: Wed, 31 Jul 2024 17:06:57 +0200 Subject: [PATCH] MINOR: log: introduce "log-steps" proxy keyword For now it is only available for proxies with frontend capability because log-steps are only evaluated under sess_log() or strm_log() which essentially focus on the frontend side when it comes to log settings so it's better to keep it this way for better consistency, at least for now. For now the setting does nothing (it is not considered during runtime), it will be implemented and documented in upcoming commits. --- include/haproxy/log-t.h | 1 + include/haproxy/proxy-t.h | 2 +- src/log.c | 106 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 108 insertions(+), 1 deletion(-) diff --git a/include/haproxy/log-t.h b/include/haproxy/log-t.h index 85ea15f04..7447c862d 100644 --- a/include/haproxy/log-t.h +++ b/include/haproxy/log-t.h @@ -59,6 +59,7 @@ * and appear as flags in session->logs.logwait, which are removed once the * required information has been collected. */ +#define LW_LOGSTEPS -1 /* special value: ignore LW_* fields and consider proxy log-steps */ #define LW_INIT 1 /* anything */ #define LW_CLIP 2 /* CLient IP */ #define LW_SVIP 4 /* SerVer IP */ diff --git a/include/haproxy/proxy-t.h b/include/haproxy/proxy-t.h index e404f9a80..677eacea0 100644 --- a/include/haproxy/proxy-t.h +++ b/include/haproxy/proxy-t.h @@ -379,7 +379,7 @@ struct proxy { struct buffer log_tag; /* override default syslog tag */ struct ist header_unique_id; /* unique-id header */ struct lf_expr format_unique_id; /* unique-id format */ - int to_log; /* things to be logged (LW_*) */ + int to_log; /* things to be logged (LW_*), special value LW_LOGSTEPS == follow log-steps */ int nb_req_cap, nb_rsp_cap; /* # of headers to be captured */ struct cap_hdr *req_cap; /* chained list of request headers to be captured */ struct cap_hdr *rsp_cap; /* chained list of response headers to be captured */ diff --git a/src/log.c b/src/log.c index 2d73d1b96..9e01ea3d1 100644 --- a/src/log.c +++ b/src/log.c @@ -1293,6 +1293,13 @@ static int _postcheck_log_backend_compat(struct proxy *be) err_code |= ERR_WARN; free_server_rules(&be->server_rules); } + if (be->to_log == LW_LOGSTEPS) { + ha_warning("Cannot use \"log-steps\" with 'mode log' in %s '%s'. It will be ignored.\n", + proxy_type_str(be), be->id); + + err_code |= ERR_WARN; + /* we don't have a convenient freeing function, let the proxy free it upon deinit */ + } if (balance_algo != BE_LB_ALGO_RR && balance_algo != BE_LB_ALGO_RND && balance_algo != BE_LB_ALGO_SS && @@ -6606,6 +6613,105 @@ static int postresolve_loggers() /* config parsers for this section */ REGISTER_CONFIG_SECTION("log-forward", cfg_parse_log_forward, NULL); REGISTER_CONFIG_SECTION("log-profile", cfg_parse_log_profile, NULL); + +static int px_parse_log_steps(char **args, int section_type, struct proxy *curpx, + const struct proxy *defpx, const char *file, int line, + char **err) +{ + char *str; + size_t cur_sep; + int retval = -1; + + if (!(curpx->cap & PR_CAP_FE)) { + memprintf(err, "%s will be ignored because %s '%s' has no frontend capability", + args[0], proxy_type_str(curpx), curpx->id); + retval = 1; + goto end; + } + + if (args[1] == NULL) { + memprintf(err, "%s: invalid arguments, expects 'all' or a composition of logging" + "steps separated by spaces.", + args[0]); + goto end; + } + + if (strcmp(args[1], "all") == 0) { + /* enable all logging steps */ + curpx->to_log = LW_LOGSTEPS; + retval = 0; + goto end; + } + + /* selectively enable logging steps */ + str = args[1]; + + while (str[0]) { + struct eb32_node *cur_step; + enum log_orig_id cur_id; + + cur_sep = strcspn(str, ","); + + /* check for valid logging step */ + if (cur_sep == 6 && strncmp(str, "accept", cur_sep) == 0) + cur_id = LOG_ORIG_TXN_ACCEPT; + else if (cur_sep == 7 && strncmp(str, "request", cur_sep) == 0) + cur_id = LOG_ORIG_TXN_REQUEST; + else if (cur_sep == 7 && strncmp(str, "connect", cur_sep) == 0) + cur_id = LOG_ORIG_TXN_CONNECT; + else if (cur_sep == 8 && strncmp(str, "response", cur_sep) == 0) + cur_id = LOG_ORIG_TXN_RESPONSE; + else if (cur_sep == 5 && strncmp(str, "close", cur_sep) == 0) + cur_id = LOG_ORIG_TXN_CLOSE; + else { + struct log_origin_node *cur; + + list_for_each_entry(cur, &log_origins, list) { + if (cur_sep == strlen(cur->name) && strncmp(str, cur->name, cur_sep) == 0) { + cur_id = cur->tree.key; + break; + } + } + + memprintf(err, + "invalid log step name (%.*s). Expected values are: " + "accept, request, connect, response, close", + (int)cur_sep, str); + list_for_each_entry(cur, &log_origins, list) + memprintf(err, "%s, %s", *err, cur->name); + + goto end; + } + + cur_step = malloc(sizeof(*cur_step)); + if (!cur_step) { + memprintf(err, "memory failure when trying to configure log-step (%.*s)", + (int)cur_sep, str); + goto end; + } + cur_step->key = cur_id; + eb32_insert(&curpx->conf.log_steps, cur_step); + next: + if (str[cur_sep]) + str += cur_sep + 1; + else + str += cur_sep; + } + + curpx->to_log = LW_LOGSTEPS; + retval = 0; + + end: + return retval; +} + +static struct cfg_kw_list cfg_kws_li = {ILH, { + { CFG_LISTEN, "log-steps", px_parse_log_steps }, + { 0, NULL, NULL }, +}}; + +INITCALL1(STG_REGISTER, cfg_register_keywords, &cfg_kws_li); + REGISTER_POST_CHECK(postresolve_loggers); REGISTER_POST_PROXY_CHECK(postcheck_log_backend); REGISTER_POST_PROXY_CHECK(postcheck_logformat_proxy);