]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: log: custom name for logformat node
authorAurelien DARRAGON <adarragon@haproxy.com>
Mon, 8 Jan 2024 17:38:29 +0000 (18:38 +0100)
committerAurelien DARRAGON <adarragon@haproxy.com>
Tue, 20 Feb 2024 14:18:39 +0000 (15:18 +0100)
Add the ability to specify custom name (will be used for representation
in verbose output types such as json) to logformat nodes.

For now, a custom name should be composed by characters [a-zA-Z0-9-_]*

include/haproxy/log-t.h
src/log.c

index a0a25acf14f7db59e2ef38ba87da8e7b8c8c1e96..d5474effc719eb867b1474120d07376e5149d690 100644 (file)
@@ -200,6 +200,8 @@ enum {
        LF_SEPARATOR,  // a single separator
        LF_VAR,        // variable name, after '%' or '%{..}'
        LF_STARTVAR,   // % in text
+       LF_STONAME,    // after '%(' and before ')'
+       LF_EDONAME,    // ')' after '%('
        LF_STARG,      // after '%{' and berore '}'
        LF_EDARG,      // '}' after '%{'
        LF_STEXPR,     // after '%[' or '%{..}[' and berore ']'
@@ -212,6 +214,7 @@ struct logformat_node {
        struct list list;
        int type;      // LOG_FMT_*
        int options;   // LOG_OPT_*
+       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
 };
index 5e704cddb1dadb3128810fce27ea2c07ad52adeb..8f0a2b6e24c5ea751afb214b594a9828a134f64f 100644 (file)
--- a/src/log.c
+++ b/src/log.c
@@ -306,7 +306,7 @@ int parse_logformat_var_args(char *args, struct logformat_node *node, char **err
  * 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, char **err)
+int parse_logformat_var(char *arg, int arg_len, char *name, int name_len, char *var, int var_len, struct proxy *curproxy, struct list *list_format, int *defoptions, char **err)
 {
        int j;
        struct logformat_node *node = NULL;
@@ -321,6 +321,8 @@ int parse_logformat_var(char *arg, int arg_len, char *var, int var_len, struct p
                                        goto error_free;
                                }
                                node->type = logformat_keywords[j].type;
+                               if (name)
+                                       node->name = my_strndup(name, name_len);
                                node->options = *defoptions;
                                if (arg_len) {
                                        node->arg = my_strndup(arg, arg_len);
@@ -356,6 +358,7 @@ int parse_logformat_var(char *arg, int arg_len, char *var, int var_len, struct p
   error_free:
        if (node) {
                free(node->arg);
+               free(node->name);
                free(node);
        }
        return 0;
@@ -409,7 +412,7 @@ 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, char **err, char **endptr)
+int add_sample_to_logformat_list(char *text, char *name, int name_len, char *arg, int arg_len, struct proxy *curpx, struct list *list_format, int options, int cap, char **err, char **endptr)
 {
        char *cmd[2];
        struct sample_expr *expr = NULL;
@@ -432,6 +435,8 @@ int add_sample_to_logformat_list(char *text, char *arg, int arg_len, struct prox
                memprintf(err, "out of memory error");
                goto error_free;
        }
+       if (name)
+               node->name = my_strndup(name, name_len);
        node->type = LOG_FMT_EXPR;
        node->expr = expr;
        node->options = options;
@@ -500,8 +505,10 @@ int parse_logformat_string(const char *fmt, struct proxy *curproxy, struct list
        char *sp, *str, *backfmt; /* start pointer for text parts */
        char *arg = NULL; /* start pointer for args */
        char *var = NULL; /* start pointer for vars */
+       char *name = NULL; /* token name (optional) */
        int arg_len = 0;
        int var_len = 0;
+       int name_len = 0;
        int cformat; /* current token format */
        int pformat; /* previous token format */
        struct logformat_node *tmplf, *back;
@@ -535,7 +542,31 @@ int parse_logformat_string(const char *fmt, struct proxy *curproxy, struct list
                switch (pformat) {
                case LF_STARTVAR:                      // text immediately following a '%'
                        arg = NULL; var = NULL;
+                       name = NULL;
+                       name_len = 0;
                        arg_len = var_len = 0;
+                       if (*str == '(') {             // custom output name
+                               cformat = LF_STONAME;
+                               name = str + 1;
+                       }
+                       else
+                               goto startvar;
+                       break;
+
+               case LF_STONAME:                       // text immediately following '%('
+                       if (*str == ')') {             // end of custom output name
+                               cformat = LF_EDONAME;
+                               name_len = str - name;
+                       } else if  (!isalnum((unsigned char)*str) && *str != '_' && *str != '-') {
+                               memprintf(err, "invalid character in custom name near '%c' at position %d line : '%s'",
+                                         *str, (int)(str - backfmt), fmt);
+
+                               goto fail;
+                       }
+                       break;
+
+               case LF_EDONAME:                       // text immediately following %(name)
+ startvar:
                        if (*str == '{') {             // optional argument
                                cformat = LF_STARG;
                                arg = str + 1;
@@ -592,7 +623,7 @@ int parse_logformat_string(const char *fmt, struct proxy *curproxy, struct list
                         * part of the expression, which MUST be the trailing
                         * angle bracket.
                         */
-                       if (!add_sample_to_logformat_list(var, arg, arg_len, curproxy, list_format, options, cap, err, &str))
+                       if (!add_sample_to_logformat_list(var, name, name_len, arg, arg_len, curproxy, list_format, options, cap, err, &str))
                                goto fail;
 
                        if (*str == ']') {
@@ -638,7 +669,7 @@ 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, err))
+                               if (!parse_logformat_var(arg, arg_len, name, name_len, var, var_len, curproxy, list_format, &options, err))
                                        goto fail;
                                break;
                        case LF_TEXT:
@@ -651,7 +682,7 @@ int parse_logformat_string(const char *fmt, struct proxy *curproxy, struct list
                }
        }
 
-       if (pformat == LF_STARTVAR || pformat == LF_STARG || pformat == LF_STEXPR) {
+       if (pformat == LF_STARTVAR || pformat == LF_STARG || pformat == LF_STEXPR || pformat == LF_STONAME || pformat == LF_EDONAME) {
                memprintf(err, "truncated line after '%s'", var ? var : arg ? arg : "%");
                goto fail;
        }
@@ -2586,6 +2617,7 @@ void free_logformat_list(struct list *fmt)
        list_for_each_entry_safe(lf, lfb, fmt, list) {
                LIST_DELETE(&lf->list);
                release_sample_expr(lf->expr);
+               free(lf->name);
                free(lf->arg);
                free(lf);
        }