HAProxy 设置日志记录变量

HAProxy 设置日志记录变量

目标

我试图将请求的完整负载作为错误消息的一部分输出,因为我认为请求者给了我一个垃圾负载。原始的工作日志是

  setenv TCP_LOG "%ci:%cp [%t] %ft %b/%s %Tw/%Tc/%Tt %B %ts %ac/%fc/%bc/%sc/%rc %sq/%bq"
  log-format "${TCP_LOG} %[var(txn.sendercompid)] %[var(txn.errormessage)] %[var(txn.sendercompid)] %[var(txn.mapped_sendercompid)]"
  tcp-request content set-var(txn.errormessage) str("ERROR: SenderCompID not in request") unless { var(txn.sendercompid) -m found }

这正是HAProxy 的标准 tcp 日志格式加上一些我们关心的字符串。

当失败时我想改变的值txn.errormessage以包含完整的请求负载。


到目前为止我已经尝试过:

tcp-request content set-var(txn.errormessage) str("ERROR: SenderCompID not in request %[req.payload(0,0),regsub(\001,|,g)]")

失败了

> [ALERT] (1) : config : 解析 [/bitnami/haproxy/conf/haproxy.cfg:44] : 获取方法 'str' : 预期 ')' 在 ',0),regsub(\001,|,g)])' 之前

tcp-request content set-var(txn.errormessage) req.payload(0,0)

我相信这会记录空字符串

$IP:43384 [11/Jul/2023:20:05:00.748] fix_listener fix_listener/ -1/-1/0 0 PR 1/1/0/0/0 0/0 - - -

虽然我可以看到我被赋予了一个有效载荷

tcp-request content set-var(txn.errormessage) req.len

给我

$IP:43536 [11/Jul/2023:20:25:26.805] fix_listener fix_listener/ -1/-1/0 0 PR 1/1/0/0/0 0/0 - 206 - -
$IP:43540 [11/Jul/2023:20:26:15.825] fix_listener fix_listener/ -1/-1/0 0 PR 1/1/0/0/0 0/0 - 206 - -
$IP:43544 [11/Jul/2023:20:27:04.879] fix_listener fix_listener/ -1/-1/0 0 PR 1/1/0/0/0 0/0 - 206 - -

我能最接近工作的是

tcp-request content set-var(txn.errormessage) req.payload(0,0),hex unless { var(txn.sendercompid) -m found }

它输出十六进制,如果我将其输入到管道中,xxd -r -p我会得到一堆垃圾,末尾带有一个 IP 地址。

我有阅读大量文档,但tcp-request content set-var(重定向到后http-request set-var)仅描述我可以使用作为的表达式

<expr> 是由 sample-fetch 和一些转换器形成的标准 HAProxy 表达式。

并且没有明显的部分描述标准的 HAProxy 表达式。我读了引用和转义部分并且也不明白为什么里面不能有逗号str()

问题

  1. 如何str("ERROR: SenderCompID not in request %[req.payload(0,0),regsub(\001,|,g)]")正确引用/格式化才能将字符串与变量连接起来?
  2. 为什么没有设置在我的日志中txn.errormessage打印req.payload(0,0)任何内容?
  3. 在日志语句中打印出请求的完整负载的最简单方法是什么?

答案1

答案

  1. 见下文
  2. 我不知道
  3. 我不知道

经过多次尝试后,我终于得到了我想要的东西:

tcp-request content set-var(txn.errormessage) \
  req.payload(0,0),regsub(\x01,|,g),regsub(^,"ERROR: invalid FIX: <"),concat(">") \
  unless { req.payload(0,0),fix_is_valid }

在此过程中我学到的一些东西可能会对其他人有所帮助:

  • ,=|在 bash 中,但,也用于分隔参数
  • 您需要包装硬编码字符串str()(除非它们已经是转换器中的参数,在这种情况下您甚至不需要引号)
  • 单引号转义双引号并开始自己的强引用字符串,我不关心文档怎么说
  • 您不能嵌套转换器,并且您不应该尝试。
  • concat()比文档让你相信的还要糟糕,并且无法让这一行变得更简单
  • HAProxy 有.if / .endif顶级语句(试图避免尾随unless),但它们只接受 6 个谓词,而且对我来说没用。
  • 文档说非打印字符将自动转换为#X其中 X 是字符的 ASCII 十六进制,但这不是我的经验,并且\x01被打印为非打印字符或空字符串(我正在读取,stdout所以如果它是实际的 SOH 字符,终端会将其打印为空字符串 - 无论如何,它不会被打印为#01

相关内容