可以有条件地为 rsyslog 8.32 中的 imfile 输入设置严重性吗?

Can severity be set conditionally for imfile input in rsyslog 8.32?

我有一个来自应用程序的文本日志文件,其格式如下...

2019-12-18 12:32:00 DEBUG This is a debugging line
2019-12-18 12:32:15 This is a informational line
2019-12-18 12:32:17 WARNING This is a warning line
2019-12-18 12:32:33 ERROR This is an error line
2019-12-18 12:33:44 ERROR This is a multi-line error message
    This is more of the previous error message
2019-12-18 12:34:15 This is back to another informational line

我已将 rsyslog 配置为使用 imfile 模块提取此文件并将其发送到我的中央系统日志服务器...

module(load="imfile")

input(type="imfile"
      file="/usr/share/myapplication/myapplication.log"
      tag="myapplication-log:"
      facility="local4"
      severity="info"
      startmsg.regex="^[0-9]{4}-[0-9]{1,2}-[0-9]{1,2} [0-9]{1,2}:[0-9]{2}:[0-9]{2} "
      readTimeout="5"
)

*.* @192.168.1.4

到目前为止一切顺利。远程系统日志服务器正确接收行并将多行错误作为单个消息处理。几乎完美,但现在我想扩展一下。

上面的所有系统日志消息都按预期作为 local4.info 发送。原始消息行包含足够的信息,使我能够正确识别消息的正确 'severity' 级别,我希望能够做到这一点,但我似乎无法弄清楚该方法。

这个无效伪代码的效果...

if $programname == "myapplication-log" then {
    if ($msg contains " DEBUG ") then severity debug;
    if ($msg contains " WARNING ") then severity warn;
    if ($msg contains " ERROR ") then severity error;
}

感谢任何帮助。谢谢

-- 为清楚起见进行编辑 --

正如@meuh 所指出的,这可以在输出阶段使用模板来完成,但我更喜欢在输入阶段正确确定严重性。这样,此消息日志的任何输出的处理方式与任何其他日志的处理方式完全相同,如果我的输出从现在起一年后发生变化,我不必记住执行特殊的输出处理。

我正在寻找的更好的伪代码示例是...

input(type="imfile"
      file="/usr/share/myapplication/myapplication.log"
      tag="myapplication-log:"
      facility="local4"
      severity="info"
      severity="debug" if ($msg contains " DEBUG ");
      severity="warn" if ($msg contains " WARNING ");
      severity="error" if ($msg contains " ERROR ");
      startmsg.regex="^[0-9]{4}-[0-9]{1,2}-[0-9]{1,2} [0-9]{1,2}:[0-9]{2}:[0-9]{2} "
      readTimeout="5"
)

一旦输入被解析,您将进入第二阶段,在该阶段您可以访问属性并可以在通常的网络输出上创建模板变体。输出的 <prio> 部分由

组成
prio = facility*8 + severity

其中 rfc5424 列出了每个设施的编号和严重性:Local4 是 20,严重性调试是 7,警告 4,错误 3。

用于发送消息的标准RSYSLOG_ForwardFormat定义为

template(name="RSYSLOG_ForwardFormat" type="string"
 string="<%PRI%>%TIMESTAMP:::date-rfc3339% %HOSTNAME% %syslogtag:1:32% 
  %msg:::sp-if-no-1st-sp%%msg%")

您想重新计算 %PRI% 属性。您不能更改 属性 但您可以拥有自己的局部变量,例如 $.myprio 并使用它。结果是:

template(name="myformat" type="string"
 string="<%$.myprio%>%TIMESTAMP:::date-rfc3339% %HOSTNAME% %syslogtag:1:32% %msg:::sp-if-no-1st-sp%%msg%")
if $programname == "myapplication-log" then {
    set $.myseverity = 6;
    if ($msg contains " DEBUG ") then set $.myseverity = 7;
    if ($msg contains " WARNING ") then set $.myseverity = 4;
    if ($msg contains " ERROR ") then set $.myseverity = 3;
    set $.myprio = 20*8+$.myseverity;
   *.* @192.168.1.4;myformat
}

对于替代方案,请查看 rsyslog modules 以了解输入、解析、消息修改和输出。可能性是

  1. 输入模块 improg 可以 运行 一个程序并接受来自它的输入,
  2. 使用 liblognorm 的解析器 pmnormalize 可以根据您的规则解析数据,
  3. 修改模块mmnormalize使用相同的liblognorm可以修改消息。

lognorm 解析器可能是最终的解决方案,但相当复杂,我无法提供进一步的使用建议。

然而,improg 是一种将预处理外部化到用任何合适的语言编写的单独程序中的简单方法,甚至是 shell 脚本,使用 inotify 到 tail 输入文件并在将它们传递到 rsyslog 之前修改这些行。