【问题标题】:How can I log messages to generic (changing) files如何将消息记录到通用(更改)文件
【发布时间】:2014-03-27 15:48:33
【问题描述】:

这个问题类似于未回答的rsyslog specific question on Server Fault。我不清楚最好的解决方案是通过 rsyslog 或 logstash 等现有软件,还是我必须自己构建一些东西。这就是我在这里问的原因。

问题

我有几个并行运行的 python 进程(由多处理处理)。他们构建需要写入该组的相同日志文件的组。从多个进程记录到同一个文件必须经过某种序列化以避免文件损坏,所以想到了 rsyslog 或 logstash。

我没能找到的(对于 rsyslog 和 logstash 都没有)是如何过滤包含我事先不知道的文件名的字段(或标签或在该系统中可能被调用的任何内容) (包含我无法控制的版本号)并将这些消息写入对应的文件。

所以,我知道对于具有动态输出的静态输入过滤器是如何做到的。但是我不知道动态输入和动态输出是怎么做的。

我最喜欢的幻想解决方案

在 Python 应用程序中:

  • 创建一个自定义格式化程序,添加一个包含目标日志文件名称的字段(例如 syslogtag 用于 rsyslog)

  • 添加一个 SyslogHandler 或类似于我的记录器的东西。

在 rsyslog 或 logstash 配置中添加类似的规则

<config of some logging system>
[filterfor] <field> -> write messages containing <value of field> to logfile /path/to/logs/<value of field>.log

完成。

问题

这可能是开箱即用的还是(在logstash中)使用(尚未编写的)插件?

编辑:也许一个例子会澄清我在寻找什么。

以括号中的目标为示例的日志消息示例:

<group_a> Message that will end up only in "group_a.log"
<group_a> Another Message for "group_a.log"
<group_b> Some interesting message for "group_b.log"
<group_c> Message for "group_c.log"

这些基于匹配名称的消息将在相应的日志文件中结束。对于上面的示例,日志文件及其内容将是:

/var/log/group_logs/group_a.log
   <group_a> Message that will end up only in "group_a.log"
   <group_a> Another Message for "group_a.log"

/var/log/group_logs/group_b.log
<group_b> Some interesting message for "group_b.log"

/var/log/group_logs/group_c.log
   <group_c> Message for "group_c.log"

所以它就像一个正则表达式,将匹配的名称保存在一个组中并将其用作文件的名称。

【问题讨论】:

  • 是的,但是在我自己构建一些东西之前,我想确定使用标准工具是不可能的(我更喜欢站在巨人的肩膀上;))。

标签: python logging multiprocessing logstash rsyslog


【解决方案1】:

rsyslog 的工作解决方案如下:

  1. 所有日志消息都包含由(任意)开始和结束分隔符分隔的目标文件名的名称。它们只能用于包装文件名(在这种情况下,我们使用 [[ 作为开始,]] 作为结束分隔符)
  2. 日志消息被发送到 local0 设施,以将它们与其他消息分开。

rsyslog 配置中的重要部分是:

$template debugFile,"/var/log/%msg:R,ERE,1,DFLT:\[\[(.*)\]\]--end%.log"

通过正则表达式从消息中生成日志文件的绝对路径 - rsyslog 团队提供的Regular Expression Checker/Generator 在这里会有所帮助。

$template rawFormat,"%msg%\n"

仅包含原始日志消息的输出模板(主要是装饰性的)。

local0.* ?debugFile;rawFormat

对发送到 local0 设施的所有日志使用此模板和格式。

【讨论】:

    【解决方案2】:

    以下解决方案适用于 logstash(无需插件)。

    我会让每个进程输出到一个单独的文件,比如/path/logs/process-&lt;unique-process-specific-id&gt;.log。该文件将包含以下行:

    <group> <rest of line>
    

    那么你可以使用这个配置:

    input {
      file {
        path => "/path/logs/process-*.log"
        start_position => beginning
      }
    }
    
    filter {
      grok {
        match => { "message" => "\A(?<group>[^ ]++) (?<rest>.*+)\z" }
      }
    }
    
    output {
      file {
        path => "/path/logs/group-%{group}.log"
        message_format => "%{rest}"
      }
    }
    

    因此,如果一个进程正在向/path/logs/process-foobar.log 写一行,看起来像:

    groupA Hello world!
    

    .. 那么这将产生一个日志文件/path/logs/group-groupA.log 的内容

    Hello world!
    

    【讨论】:

    • 看起来这个解决方案适用于logstash?你能澄清一下吗?
    • 是的,这是用于logstash,不需要任何插件。
    • 组名应该不包含空格,并且该行的其余部分用一个空格分隔。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-03-11
    • 1970-01-01
    • 1970-01-01
    • 2012-05-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多