]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: log: introduce "log-steps" proxy keyword
authorAurelien DARRAGON <adarragon@haproxy.com>
Wed, 31 Jul 2024 15:06:57 +0000 (17:06 +0200)
committerAurelien DARRAGON <adarragon@haproxy.com>
Thu, 26 Sep 2024 14:53:07 +0000 (16:53 +0200)
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
include/haproxy/proxy-t.h
src/log.c

index 85ea15f048b00e43acbf540d49cadc7e8a5081db..7447c862d3093257ee2d05c0e0a1d650bb60470a 100644 (file)
@@ -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 */
index e404f9a80bef2b88563954298f5248e2a719f0b2..677eacea0fd08b3003c49211ce7b0ed2abc08e8e 100644 (file)
@@ -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 */
index 2d73d1b963f516d114c69c93e13399b24a114130..9e01ea3d1985c6c37047d6d1c0cb1844fad45f2a 100644 (file)
--- 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);