【问题标题】:syslog-ng value mapping for variable sub-string变量子字符串的 syslog-ng 值映射
【发布时间】:2022-01-14 18:34:49
【问题描述】:

我正在容器 balabit/syslog-ng:3.35.1 中运行 syslog-ng

我想为vpnrd变量中的值做值映射

下面是值映射配置 + CSV 文件示例


parser p_json {
    json-parser(prefix(".json."));
};

parser p_acd_vrf {
    add-contextual-data(
        selector("${.json.vpnrd}")
        database("vrf_map.csv")
        default-selector("UNKNOWN")
        prefix(".meta_vrf.")
    );
};

CSV 文件内容:

111,vrf_id,vrf_1
222,vrf_id,vrf_2
zzz,vrf_id,vrf_example
UNKNOWN,vrf_id,[No VRF; Global Instance peer]
...

问题在于vpnrd 包含格式为xxx:yyy:zzz 的字符串,我需要将其拆分(分隔符:)并仅使用最后一部分zzz,因为只有该部分与值映射相关。

有没有办法在 syslog-ng 中做到这一点?

我正在查看自定义 python 解析器,它可以很容易地执行这种操作,但是我不知道如何将 python 解析器的结果与值映射解析器连接起来。

感谢大家的指点


更新:我基于this blog 编写了python 解析器,但不幸的是映射仍然不起作用,我总是得到[No VRF; Global Instance peer],它被映射为默认值。 我也看不到来自 python 脚本的日志(它们发送到哪里?)所以很难判断发生了什么

parser p_py_vrf_id {
    python(
        class("GetVrfId")
    );
};

python {
from syslogng import Logger
logger = Logger()
class GetVrfId(object):
    def parse(self, log_message):
        """
        extract vrf_id from rd variable
        """
        logger.info(f'log: {log_message}')
        try:
            vpnrd = log_message['.json.rd'].split(':')[-1].strip()
            log_message['.json.vpnrd'] = vpnrd
            logger.info(f'vpnrd: {vpnrd}')
        except KeyError:
            log_message['.json.vpnrd'] = 'UNKNOWN'
            logger.error(f'key-error: rd not present')
        except Exception as e:
            logger.error(f'catch-all-error: {e}')
        # return True, other way message is dropped
        return True
};

【问题讨论】:

  • log_message['.json.vpnrd'] = vpnrd 应该可以解决问题。请注意,LogMessage 字段是 Python 3 中的字节对象,因此您可能希望在转换它们之前将它们解码为字符串(例如:log_message['.json.vpnrd'].decode("utf8"))。

标签: syslog syslog-ng


【解决方案1】:

您有多种选择,其中之一是用 Python 编写您自己的解析器。

解析器通常会产生新的名称-值对。 add-contextual-data() 和您的解析器之间的连接将是您在 selector() 中指定的键。

LogMessage 字段是 Python 3 中的字节对象,因此在转换它们之前必须将它们解码为字符串(例如:log_message['.json.vpnrd'].decode("utf-8"))。

syslogng.Logger 登录到internal() 源。


xxx:yyy:zzz 似乎是固定长度,所以你可以只删除不必要的部分(不需要自定义解析器):

parser p_acd_vrf {
    add-contextual-data(
        selector("$(substr ${.json.vpnrd} 8)")
        database("vrf_map.csv")
        prefix(".meta_vrf.")
    );
};

或者,$(explode) 可用于将字符串拆分为列表(+ $(list-nth) 选择最后一个元素)。


另一种选择是使用内置的csv-parser(),将:配置为分隔符。

【讨论】:

  • 嗨,谢谢你的灵感。 vpnrd 不是固定长度,我可能提供了误导性示例。` xxx` 部分是固定长度,yyy 是 IP 地址(不是固定长度字符),最后一部分 zzz 是可变长度。此外,vpnrd 是 json 消息中的可选元素,因此它可能不会出现在每条消息中。我认为涵盖所有情况的最佳方法是自定义 Python 解析器,如果 vpnrd 不是 json 的一部分,则仅返回子字符串或某个默认值,然后基于该映射进行映射......现在是困难的部分,为此创建配置:)
  • 在这种情况下,if-else 块可以与 $(explode) 模板函数一起使用。有条件地将其拆分为列表后,可以轻松选择第三个元素。
  • internal + .decode("utf-8") 添加日志修复了这两个问题,现在我可以看到日志和python解析器按预期工作,谢谢!
猜你喜欢
  • 2018-10-24
  • 2022-01-14
  • 2012-08-21
  • 1970-01-01
  • 1970-01-01
  • 2021-01-15
  • 2017-11-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多