]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: log-format: Use standard HAProxy log system to report errors
authorThierry FOURNIER / OZON.IO <thierry.fournier@ozon.io>
Tue, 22 Nov 2016 23:41:28 +0000 (00:41 +0100)
committerWilly Tarreau <w@1wt.eu>
Fri, 25 Nov 2016 06:32:58 +0000 (07:32 +0100)
The function log format emit its own error message using Alert(). This
patch replaces this behavior and uses the standard HAProxy error system
(with memprintf).

The benefits are:
 - cleaning the log system

 - the logformat can ignore the caller (actually the caller must set
   a flag designing the caller function).

 - Make the usage of the logformat function easy for future components.

include/proto/log.h
src/cfgparse.c
src/log.c
src/proto_http.c

index f5a4f3fc9fcecb9e55974966221b0ad90245b8ee..2d4ca84f175b8d1c85d52499f759d7ed12bc1bc2 100644 (file)
@@ -67,14 +67,14 @@ void strm_log(struct stream *s);
 /*
  * add to the logformat linked list
  */
-int add_to_logformat_list(char *start, char *end, int type, struct list *list_format);
+int add_to_logformat_list(char *start, char *end, int type, struct list *list_format, char **err);
 
 /*
  * Parse the log_format string and fill a linked list.
  * Variable name are preceded by % and composed by characters [a-zA-Z0-9]* : %varname
  * You can set arguments using { } : %{many arguments}varname
  */
-int parse_logformat_string(const char *str, struct proxy *curproxy, struct list *list_format, int options, int cap);
+int parse_logformat_string(const char *str, struct proxy *curproxy, struct list *list_format, int options, int cap, char **err);
 /*
  * Displays the message on stderr with the date and pid. Overrides the quiet
  * mode during startup.
index db1641e98c98e7fb88ca19d362c0b87d68d951f8..fbd7364662124bad36194b6bc863b49271568ca5 100644 (file)
@@ -7502,6 +7502,7 @@ int check_config_validity()
        int err_code = 0;
        unsigned int next_pxid = 1;
        struct bind_conf *bind_conf;
+       char *err;
 
        bind_conf = NULL;
        /*
@@ -7801,7 +7802,11 @@ int check_config_validity()
                        curproxy->conf.args.ctx = ARGC_UBK;
                        curproxy->conf.args.file = rule->file;
                        curproxy->conf.args.line = rule->line;
-                       if (!parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR)) {
+                       err = NULL;
+                       if (!parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR, &err)) {
+                               Alert("Parsing [%s:%d]: failed to parse use_backend rule '%s' : %s.\n",
+                                     rule->file, rule->line, pxname, err);
+                               free(err);
                                cfgerr++;
                                continue;
                        }
@@ -8288,8 +8293,12 @@ out_uri_auth_compat:
                        curproxy->conf.args.ctx = ARGC_LOG;
                        curproxy->conf.args.file = curproxy->conf.lfs_file;
                        curproxy->conf.args.line = curproxy->conf.lfs_line;
+                       err = NULL;
                        if (!parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
-                                                   SMP_VAL_FE_LOG_END)) {
+                                                   SMP_VAL_FE_LOG_END, &err)) {
+                               Alert("Parsing [%s:%d]: failed to parse log-format : %s.\n",
+                                     curproxy->conf.lfs_file, curproxy->conf.lfs_line, err);
+                               free(err);
                                cfgerr++;
                        }
                        curproxy->conf.args.file = NULL;
@@ -8300,10 +8309,17 @@ out_uri_auth_compat:
                        curproxy->conf.args.ctx = ARGC_LOGSD;
                        curproxy->conf.args.file = curproxy->conf.lfsd_file;
                        curproxy->conf.args.line = curproxy->conf.lfsd_line;
+                       err = NULL;
                        if (!parse_logformat_string(curproxy->conf.logformat_sd_string, curproxy, &curproxy->logformat_sd, LOG_OPT_MANDATORY,
-                                                   SMP_VAL_FE_LOG_END)) {
+                                                   SMP_VAL_FE_LOG_END, &err)) {
+                               Alert("Parsing [%s:%d]: failed to parse log-format-sd : %s.\n",
+                                     curproxy->conf.lfs_file, curproxy->conf.lfs_line, err);
+                               free(err);
                                cfgerr++;
-                       } else if (!add_to_logformat_list(NULL, NULL, LF_SEPARATOR, &curproxy->logformat_sd)) {
+                       } else if (!add_to_logformat_list(NULL, NULL, LF_SEPARATOR, &curproxy->logformat_sd, &err)) {
+                               Alert("Parsing [%s:%d]: failed to parse log-format-sd : %s.\n",
+                                     curproxy->conf.lfs_file, curproxy->conf.lfs_line, err);
+                               free(err);
                                cfgerr++;
                        }
                        curproxy->conf.args.file = NULL;
@@ -8314,8 +8330,12 @@ out_uri_auth_compat:
                        curproxy->conf.args.ctx = ARGC_UIF;
                        curproxy->conf.args.file = curproxy->conf.uif_file;
                        curproxy->conf.args.line = curproxy->conf.uif_line;
+                       err = NULL;
                        if (!parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, LOG_OPT_HTTP,
-                                                   (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR)) {
+                                                   (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR, &err)) {
+                               Alert("Parsing [%s:%d]: failed to parse unique-id : %s.\n",
+                                     curproxy->conf.uif_file, curproxy->conf.uif_line, err);
+                               free(err);
                                cfgerr++;
                        }
                        curproxy->conf.args.file = NULL;
index 9ec89b2b35caf2a1eb8260cc3e6700c4eb6ce8a2..3a6f781d910b59c3f07d8902aeed88b7967e4f96 100644 (file)
--- a/src/log.c
+++ b/src/log.c
@@ -291,15 +291,17 @@ int prepare_addrsource(struct logformat_node *node, struct proxy *curproxy)
  * Parse args in a logformat_var. Returns 0 in error
  * case, otherwise, it returns 1.
  */
-int parse_logformat_var_args(char *args, struct logformat_node *node)
+int parse_logformat_var_args(char *args, struct logformat_node *node, char **err)
 {
        int i = 0;
        int end = 0;
        int flags = 0;  // 1 = +  2 = -
        char *sp = NULL; // start pointer
 
-       if (args == NULL)
+       if (args == NULL) {
+               memprintf(err, "internal error: parse_logformat_var_args() expects non null 'args'");
                return 0;
+       }
 
        while (1) {
                if (*args == '\0')
@@ -345,7 +347,7 @@ int parse_logformat_var_args(char *args, struct logformat_node *node)
  * ignored when arg_len is 0. Neither <var> nor <var_len> may be null.
  * Returns false in error case and err is filled, otherwise returns true.
  */
-int parse_logformat_var(char *arg, int arg_len, char *var, int var_len, struct proxy *curproxy, struct list *list_format, int *defoptions)
+int parse_logformat_var(char *arg, int arg_len, char *var, int var_len, struct proxy *curproxy, struct list *list_format, int *defoptions, char **err)
 {
        int j;
        struct logformat_node *node;
@@ -356,14 +358,14 @@ int parse_logformat_var(char *arg, int arg_len, char *var, int var_len, struct p
                        if (logformat_keywords[j].mode != PR_MODE_HTTP || curproxy->mode == PR_MODE_HTTP) {
                                node = calloc(1, sizeof(*node));
                                if (!node) {
-                                       Alert("Out of memory error.\n");
+                                       memprintf(err, "out of memory error");
                                        return 0;
                                }
                                node->type = logformat_keywords[j].type;
                                node->options = *defoptions;
                                if (arg_len) {
                                        node->arg = my_strndup(arg, arg_len);
-                                       if (!parse_logformat_var_args(node->arg, node))
+                                       if (!parse_logformat_var_args(node->arg, node, err))
                                                return 0;
                                }
                                if (node->type == LOG_FMT_GLOBAL) {
@@ -384,9 +386,8 @@ int parse_logformat_var(char *arg, int arg_len, char *var, int var_len, struct p
                                                logformat_keywords[j].name, fmt_directive(curproxy), logformat_keywords[j].replace_by);
                                return 1;
                        } else {
-                               Alert("parsing [%s:%d] : '%s' : format variable '%s' is reserved for HTTP mode.\n",
-                                     curproxy->conf.args.file, curproxy->conf.args.line, fmt_directive(curproxy),
-                                     logformat_keywords[j].name);
+                               memprintf(err, "format variable '%s' is reserved for HTTP mode",
+                                         logformat_keywords[j].name);
                                return 0;
                        }
                }
@@ -394,8 +395,7 @@ int parse_logformat_var(char *arg, int arg_len, char *var, int var_len, struct p
 
        j = var[var_len];
        var[var_len] = 0;
-       Alert("parsing [%s:%d] : no such format variable '%s' in '%s'. If you wanted to emit the '%%' character verbatim, you need to use '%%%%' in log-format expressions.\n",
-             curproxy->conf.args.file, curproxy->conf.args.line, var, fmt_directive(curproxy));
+       memprintf(err, "no such format variable '%s'. If you wanted to emit the '%%' character verbatim, you need to use '%%%%'", var);
        var[var_len] = j;
        return 0;
 }
@@ -411,14 +411,14 @@ int parse_logformat_var(char *arg, int arg_len, char *var, int var_len, struct p
  *  LOG_TEXT: copy chars from start to end excluding end.
  *
 */
-int add_to_logformat_list(char *start, char *end, int type, struct list *list_format)
+int add_to_logformat_list(char *start, char *end, int type, struct list *list_format, char **err)
 {
        char *str;
 
        if (type == LF_TEXT) { /* type text */
                struct logformat_node *node = calloc(1, sizeof(*node));
                if (!node) {
-                       Alert("Out of memory error.\n");
+                       memprintf(err, "out of memory error");
                        return 0;
                }
                str = calloc(1, end - start + 1);
@@ -430,7 +430,7 @@ int add_to_logformat_list(char *start, char *end, int type, struct list *list_fo
        } else if (type == LF_SEPARATOR) {
                struct logformat_node *node = calloc(1, sizeof(*node));
                if (!node) {
-                       Alert("Out of memory error.\n");
+                       memprintf(err, "out of memory error");
                        return 0;
                }
                node->type = LOG_FMT_SEPARATOR;
@@ -446,29 +446,26 @@ int add_to_logformat_list(char *start, char *end, int type, struct list *list_fo
  *
  * In error case, the function returns 0, otherwise it returns 1.
  */
-int add_sample_to_logformat_list(char *text, char *arg, int arg_len, struct proxy *curpx, struct list *list_format, int options, int cap, const char *file, int line)
+int add_sample_to_logformat_list(char *text, char *arg, int arg_len, struct proxy *curpx, struct list *list_format, int options, int cap, char **err)
 {
        char *cmd[2];
        struct sample_expr *expr;
        struct logformat_node *node;
        int cmd_arg;
-       char *errmsg = NULL;
 
        cmd[0] = text;
        cmd[1] = "";
        cmd_arg = 0;
 
-       expr = sample_parse_expr(cmd, &cmd_arg, file, line, &errmsg, &curpx->conf.args);
+       expr = sample_parse_expr(cmd, &cmd_arg, curpx->conf.args.file, curpx->conf.args.line, err, &curpx->conf.args);
        if (!expr) {
-               Alert("parsing [%s:%d] : '%s' : sample fetch <%s> failed with : %s\n",
-                     curpx->conf.args.file, curpx->conf.args.line, fmt_directive(curpx),
-                     text, errmsg);
+               memprintf(err, "failed to parse sample expression <%s> : %s", text, *err);
                return 0;
        }
 
        node = calloc(1, sizeof(*node));
        if (!node) {
-               Alert("Out of memory error.\n");
+               memprintf(err, "out of memory error");
                return 0;
        }
        node->type = LOG_FMT_EXPR;
@@ -477,7 +474,7 @@ int add_sample_to_logformat_list(char *text, char *arg, int arg_len, struct prox
 
        if (arg_len) {
                node->arg = my_strndup(arg, arg_len);
-               if (!parse_logformat_var_args(node->arg, node))
+               if (!parse_logformat_var_args(node->arg, node, err))
                        return 0;
        }
        if (expr->fetch->val & cap & SMP_VAL_REQUEST)
@@ -487,9 +484,8 @@ int add_sample_to_logformat_list(char *text, char *arg, int arg_len, struct prox
                node->options |= LOG_OPT_RES_CAP; /* fetch method is response-compatible */
 
        if (!(expr->fetch->val & cap)) {
-               Alert("parsing [%s:%d] : '%s' : sample fetch <%s> may not be reliably used here because it needs '%s' which is not available here.\n",
-                     curpx->conf.args.file, curpx->conf.args.line, fmt_directive(curpx),
-                     text, sample_src_names(expr->fetch->use));
+               memprintf(err, "sample fetch <%s> may not be reliably used here because it needs '%s' which is not available here",
+                         text, sample_src_names(expr->fetch->use));
                return 0;
        }
 
@@ -519,9 +515,9 @@ int add_sample_to_logformat_list(char *text, char *arg, int arg_len, struct prox
  *  options: LOG_OPT_* to force on every node
  *  cap: all SMP_VAL_* flags supported by the consumer
  *
- * The function returns 1 in success case, otherwise, it returns 0.
+ * The function returns 1 in success case, otherwise, it returns 0 and err is filled.
  */
-int parse_logformat_string(const char *fmt, struct proxy *curproxy, struct list *list_format, int options, int cap)
+int parse_logformat_string(const char *fmt, struct proxy *curproxy, struct list *list_format, int options, int cap, char **err)
 {
        char *sp, *str, *backfmt; /* start pointer for text parts */
        char *arg = NULL; /* start pointer for args */
@@ -534,7 +530,7 @@ int parse_logformat_string(const char *fmt, struct proxy *curproxy, struct list
 
        sp = str = backfmt = strdup(fmt);
        if (!str) {
-               Alert("Out of memory error.\n");
+               memprintf(err, "out of memory error");
                return 0;
        }
        curproxy->to_log |= LW_INIT;
@@ -579,8 +575,8 @@ int parse_logformat_string(const char *fmt, struct proxy *curproxy, struct list
                                cformat = LF_TEXT;
                                pformat = LF_TEXT; /* finally we include the previous char as well */
                                sp = str - 1; /* send both the '%' and the current char */
-                               Alert("parsing [%s:%d] : Unexpected variable name near '%c' at position %d in %s line : '%s'. Maybe you want to write a simgle '%%', use the syntax '%%%%'.\n",
-                                     curproxy->conf.args.file, curproxy->conf.args.line, *str, (int)(str - backfmt), fmt_directive(curproxy), fmt);
+                               memprintf(err, "unexpected variable name near '%c' at position %d line : '%s'. Maybe you want to write a simgle '%%', use the syntax '%%%%'",
+                                         *str, (int)(str - backfmt), fmt);
                                return 0;
 
                        }
@@ -607,8 +603,7 @@ int parse_logformat_string(const char *fmt, struct proxy *curproxy, struct list
                                var = str;
                                break;
                        }
-                       Alert("parsing [%s:%d] : Parse argument modifier without variable name, in '%s' near '%%{%s}'\n",
-                             curproxy->conf.args.file, curproxy->conf.args.line, fmt_directive(curproxy), arg);
+                       memprintf(err, "parse argument modifier without variable name near '%%{%s}'", arg);
                        return 0;
 
                case LF_STEXPR:                        // text immediately following '%['
@@ -641,17 +636,16 @@ int parse_logformat_string(const char *fmt, struct proxy *curproxy, struct list
                if (cformat != pformat || pformat == LF_SEPARATOR) {
                        switch (pformat) {
                        case LF_VAR:
-                               if (!parse_logformat_var(arg, arg_len, var, var_len, curproxy, list_format, &options))
+                               if (!parse_logformat_var(arg, arg_len, var, var_len, curproxy, list_format, &options, err))
                                        return 0;
                                break;
                        case LF_STEXPR:
-                               if (!add_sample_to_logformat_list(var, arg, arg_len, curproxy, list_format, options, cap,
-                                                            curproxy->conf.args.file, curproxy->conf.args.line))
+                               if (!add_sample_to_logformat_list(var, arg, arg_len, curproxy, list_format, options, cap, err))
                                        return 0;
                                break;
                        case LF_TEXT:
                        case LF_SEPARATOR:
-                               if (!add_to_logformat_list(sp, str, pformat, list_format))
+                               if (!add_to_logformat_list(sp, str, pformat, list_format, err))
                                        return 0;
                                break;
                        }
@@ -660,9 +654,7 @@ int parse_logformat_string(const char *fmt, struct proxy *curproxy, struct list
        }
 
        if (pformat == LF_STARTVAR || pformat == LF_STARG || pformat == LF_STEXPR) {
-               Alert("parsing [%s:%d] : Truncated '%s' line after '%s'\n",
-                     curproxy->conf.args.file, curproxy->conf.args.line, fmt_directive(curproxy),
-                     var ? var : arg ? arg : "%");
+               memprintf(err, "truncated line after '%s'", var ? var : arg ? arg : "%");
                return 0;
        }
        free(backfmt);
index 725ea9c0a702e92d85394ef3171e43e927798418..6dfc8f9c9de942e6f86c5541b3f08f7c116a9c7f 100644 (file)
@@ -9139,8 +9139,12 @@ struct act_rule *parse_http_req_cond(const char **args, const char *file, int li
                LIST_INIT(&rule->arg.hdr_add.fmt);
 
                proxy->conf.args.ctx = ARGC_HRQ;
+               error = NULL;
                if (!parse_logformat_string(args[cur_arg + 1], proxy, &rule->arg.hdr_add.fmt, LOG_OPT_HTTP,
-                                           (proxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR)) {
+                                           (proxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR, &error)) {
+                       Alert("parsing [%s:%d]: 'http-request %s': %s.\n",
+                             file, linenum, args[0], error);
+                       free(error);
                        goto out_err;
                }
                free(proxy->conf.lfs_file);
@@ -9171,8 +9175,12 @@ struct act_rule *parse_http_req_cond(const char **args, const char *file, int li
                }
 
                proxy->conf.args.ctx = ARGC_HRQ;
+               error = NULL;
                if (!parse_logformat_string(args[cur_arg + 2], proxy, &rule->arg.hdr_add.fmt, LOG_OPT_HTTP,
-                                           (proxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR)) {
+                                           (proxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR, &error)) {
+                       Alert("parsing [%s:%d]: 'http-request %s': %s.\n",
+                             file, linenum, args[0], error);
+                       free(error);
                        goto out_err;
                }
 
@@ -9285,8 +9293,12 @@ struct act_rule *parse_http_req_cond(const char **args, const char *file, int li
 
                LIST_INIT(&rule->arg.map.key);
                proxy->conf.args.ctx = ARGC_HRQ;
+               error = NULL;
                if (!parse_logformat_string(args[cur_arg], proxy, &rule->arg.map.key, LOG_OPT_HTTP,
-                                           (proxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR)) {
+                                           (proxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR, &error)) {
+                       Alert("parsing [%s:%d]: 'http-request %s': %s.\n",
+                             file, linenum, args[0], error);
+                       free(error);
                        goto out_err;
                }
                free(proxy->conf.lfs_file);
@@ -9313,8 +9325,12 @@ struct act_rule *parse_http_req_cond(const char **args, const char *file, int li
 
                LIST_INIT(&rule->arg.map.key);
                proxy->conf.args.ctx = ARGC_HRQ;
+               error = NULL;
                if (!parse_logformat_string(args[cur_arg], proxy, &rule->arg.map.key, LOG_OPT_HTTP,
-                                           (proxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR)) {
+                                           (proxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR, &error)) {
+                       Alert("parsing [%s:%d]: 'http-request %s': %s.\n",
+                             file, linenum, args[0], error);
+                       free(error);
                        goto out_err;
                }
                free(proxy->conf.lfs_file);
@@ -9341,8 +9357,12 @@ struct act_rule *parse_http_req_cond(const char **args, const char *file, int li
 
                LIST_INIT(&rule->arg.map.key);
                proxy->conf.args.ctx = ARGC_HRQ;
+               error = NULL;
                if (!parse_logformat_string(args[cur_arg], proxy, &rule->arg.map.key, LOG_OPT_HTTP,
-                                           (proxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR)) {
+                                           (proxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR, &error)) {
+                       Alert("parsing [%s:%d]: 'http-request %s': %s.\n",
+                             file, linenum, args[0], error);
+                       free(error);
                        goto out_err;
                }
                free(proxy->conf.lfs_file);
@@ -9372,14 +9392,22 @@ struct act_rule *parse_http_req_cond(const char **args, const char *file, int li
                proxy->conf.args.ctx = ARGC_HRQ;
 
                /* key pattern */
+               error = NULL;
                if (!parse_logformat_string(args[cur_arg], proxy, &rule->arg.map.key, LOG_OPT_HTTP,
-                                           (proxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR)) {
+                                           (proxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR, &error)) {
+                       Alert("parsing [%s:%d]: 'http-request %s' key: %s.\n",
+                             file, linenum, args[0], error);
+                       free(error);
                        goto out_err;
                }
 
                /* value pattern */
+               error = NULL;
                if (!parse_logformat_string(args[cur_arg + 1], proxy, &rule->arg.map.value, LOG_OPT_HTTP,
-                                           (proxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR)) {
+                                           (proxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR, &error)) {
+                       Alert("parsing [%s:%d]: 'http-request %s' pattern: %s.\n",
+                             file, linenum, args[0], error);
+                       free(error);
                        goto out_err;
                }
                free(proxy->conf.lfs_file);
@@ -9551,8 +9579,12 @@ struct act_rule *parse_http_res_cond(const char **args, const char *file, int li
                LIST_INIT(&rule->arg.hdr_add.fmt);
 
                proxy->conf.args.ctx = ARGC_HRS;
+               error = NULL;
                if (!parse_logformat_string(args[cur_arg + 1], proxy, &rule->arg.hdr_add.fmt, LOG_OPT_HTTP,
-                                           (proxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR)) {
+                                           (proxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR, &error)) {
+                       Alert("parsing [%s:%d]: 'http-response %s': %s.\n",
+                             file, linenum, args[0], error);
+                       free(error);
                        goto out_err;
                }
                free(proxy->conf.lfs_file);
@@ -9583,8 +9615,12 @@ struct act_rule *parse_http_res_cond(const char **args, const char *file, int li
                }
 
                proxy->conf.args.ctx = ARGC_HRQ;
+               error = NULL;
                if (!parse_logformat_string(args[cur_arg + 2], proxy, &rule->arg.hdr_add.fmt, LOG_OPT_HTTP,
-                                           (proxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR)) {
+                                           (proxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR, &error)) {
+                       Alert("parsing [%s:%d]: 'http-response %s': %s.\n",
+                             file, linenum, args[0], error);
+                       free(error);
                        goto out_err;
                }
 
@@ -9631,8 +9667,12 @@ struct act_rule *parse_http_res_cond(const char **args, const char *file, int li
 
                LIST_INIT(&rule->arg.map.key);
                proxy->conf.args.ctx = ARGC_HRS;
+               error = NULL;
                if (!parse_logformat_string(args[cur_arg], proxy, &rule->arg.map.key, LOG_OPT_HTTP,
-                                           (proxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR)) {
+                                           (proxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR, &error)) {
+                       Alert("parsing [%s:%d]: 'http-response %s': %s.\n",
+                             file, linenum, args[0], error);
+                       free(error);
                        goto out_err;
                }
                free(proxy->conf.lfs_file);
@@ -9660,8 +9700,12 @@ struct act_rule *parse_http_res_cond(const char **args, const char *file, int li
 
                LIST_INIT(&rule->arg.map.key);
                proxy->conf.args.ctx = ARGC_HRS;
+               error = NULL;
                if (!parse_logformat_string(args[cur_arg], proxy, &rule->arg.map.key, LOG_OPT_HTTP,
-                                           (proxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR)) {
+                                           (proxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR, &error)) {
+                       Alert("parsing [%s:%d]: 'http-response %s': %s.\n",
+                             file, linenum, args[0], error);
+                       free(error);
                        goto out_err;
                }
                free(proxy->conf.lfs_file);
@@ -9688,8 +9732,12 @@ struct act_rule *parse_http_res_cond(const char **args, const char *file, int li
 
                LIST_INIT(&rule->arg.map.key);
                proxy->conf.args.ctx = ARGC_HRS;
+               error = NULL;
                if (!parse_logformat_string(args[cur_arg], proxy, &rule->arg.map.key, LOG_OPT_HTTP,
-                                           (proxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR)) {
+                                           (proxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR, &error)) {
+                       Alert("parsing [%s:%d]: 'http-response %s' %s.\n",
+                             file, linenum, args[0], error);
+                       free(error);
                        goto out_err;
                }
                free(proxy->conf.lfs_file);
@@ -9720,14 +9768,22 @@ struct act_rule *parse_http_res_cond(const char **args, const char *file, int li
                proxy->conf.args.ctx = ARGC_HRS;
 
                /* key pattern */
+               error = NULL;
                if (!parse_logformat_string(args[cur_arg], proxy, &rule->arg.map.key, LOG_OPT_HTTP,
-                                           (proxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR)) {
+                                           (proxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR, &error)) {
+                       Alert("parsing [%s:%d]: 'http-response %s' name: %s.\n",
+                             file, linenum, args[0], error);
+                       free(error);
                        goto out_err;
                }
 
                /* value pattern */
+               error = NULL;
                if (!parse_logformat_string(args[cur_arg + 1], proxy, &rule->arg.map.value, LOG_OPT_HTTP,
-                                           (proxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR)) {
+                                           (proxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR, &error)) {
+                       Alert("parsing [%s:%d]: 'http-response %s' value: %s.\n",
+                             file, linenum, args[0], error);
+                       free(error);
                        goto out_err;
                }
 
@@ -9975,7 +10031,8 @@ struct redirect_rule *http_parse_redirect_rule(const char *file, int linenum, st
                if (!(type == REDIRECT_TYPE_PREFIX && destination[0] == '/' && destination[1] == '\0')) {
                        if (!parse_logformat_string(destination, curproxy, &rule->rdr_fmt, LOG_OPT_HTTP,
                                                    dir ? (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRS_HDR : SMP_VAL_BE_HRS_HDR
-                                                       : (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR)) {
+                                                       : (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
+                                                   errmsg)) {
                                return  NULL;
                        }
                        free(curproxy->conf.lfs_file);
@@ -12471,7 +12528,7 @@ enum act_parse_ret parse_set_req_line(const char **args, int *orig_arg, struct p
        LIST_INIT(&rule->arg.http.logfmt);
        proxy->conf.args.ctx = ARGC_HRQ;
        if (!parse_logformat_string(args[cur_arg], proxy, &rule->arg.http.logfmt, LOG_OPT_HTTP,
-                                   (proxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR)) {
+                                   (proxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR, err)) {
                return ACT_RET_PRS_ERR;
        }