]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: log: support "raw" logformat node typecast
authorAurelien DARRAGON <adarragon@haproxy.com>
Tue, 1 Apr 2025 18:25:08 +0000 (20:25 +0200)
committerAurelien DARRAGON <adarragon@haproxy.com>
Wed, 2 Apr 2025 09:04:43 +0000 (11:04 +0200)
"raw" logformat node typecast is a special value (unlike str,bool,int..)
which tells haproxy to completely ignore logformat options (including
encoding ones) and force binary output for the current node only. It is
mainly intended for use with JSON or CBOR encoders in order to generate
nested CBOR or nested JSON by storing intermediate log-formats within
variables and assembling the final object in the parent log-format.

Example:

  http-request set-var-fmt(txn.intermediate) "%{+json}o %(lower)[str(value)]"

  log-format "%{+json}o %(upper)[str(value)] %(intermediate:raw)[var(txn.intermediate)]"

Would produce:

   {"upper": "value", "intermediate": {"lower": "value"}}

src/log.c

index 0ab89a1e1b6f7234e4fa6bffd32ed5bdd9dccb0c..1ddac9cb064970c168d1e2030d35002178f19b29 100644 (file)
--- a/src/log.c
+++ b/src/log.c
@@ -759,11 +759,17 @@ int lf_expr_compile(struct lf_expr *lf_expr,
                                else {
                                        /* custom type */
                                        *str = 0; // so that typecast_str is 0 terminated
-                                       typecast = type_to_smp(typecast_str);
-                                       if (typecast != SMP_T_STR && typecast != SMP_T_SINT &&
-                                           typecast != SMP_T_BOOL) {
-                                               memprintf(err, "unexpected output type '%.*s' at position %d line : '%s'. Supported types are: str, sint, bool", (int)(str - typecast_str), typecast_str, (int)(typecast_str - backfmt), fmt);
-                                               goto fail;
+                                       if (strcmp(typecast_str, "raw") == 0) {
+                                               /* special case */
+                                               typecast = SMP_TYPES;
+                                       }
+                                       else {
+                                               typecast = type_to_smp(typecast_str);
+                                               if (typecast != SMP_T_STR && typecast != SMP_T_SINT &&
+                                                   typecast != SMP_T_BOOL) {
+                                                       memprintf(err, "unexpected output type '%.*s' at position %d line : '%s'. Supported types are: str, sint, bool, raw", (int)(str - typecast_str), typecast_str, (int)(typecast_str - backfmt), fmt);
+                                                       goto fail;
+                                               }
                                        }
                                }
                                cformat = LF_EDONAME;
@@ -4104,9 +4110,16 @@ int sess_build_logline_orig(struct session *sess, struct stream *s,
                         * know how to deal with binary data.
                         */
                        if (ctx->options & LOG_OPT_ENCODE) {
-                               if (ctx->typecast == SMP_T_STR ||
-                                   ctx->typecast == SMP_T_SINT ||
-                                   ctx->typecast == SMP_T_BOOL) {
+                               if (ctx->typecast == SMP_TYPES) {
+                                       /* raw data, ignore LOG opts and enforce binary
+                                        * to dump smp as-is
+                                        */
+                                       ctx->options = LOG_OPT_NONE;
+                                       type = SMP_T_BIN;
+                               }
+                               else if (ctx->typecast == SMP_T_STR ||
+                                        ctx->typecast == SMP_T_SINT ||
+                                        ctx->typecast == SMP_T_BOOL) {
                                        /* enforce type */
                                        type = ctx->typecast;
                                }