如何在 Logstash 中获取部分 Filebeat 源文件名

How to get parts of Filebeat source filename in Logstash

我有一个 Filebeat 实例(7.5.0 版,运行在 Windows 服务器上运行)监控本地文件夹中的日志文件,并将此数据发送到 Logstash(7.5 版) .0,运行宁在 Docker 大陆)。在 Logstash 中,我想提取其中一个文件夹名称(最后一个)并将其添加为一个字段。

一个具体的例子是,从两个日志条目中,一个来自文件 d:\Logs\Foo\Bar\lorem\currentlog.txt,一个来自文件 d:\Logs\Foo\Bar\ipsum\currentlog.txt,我想提取值 loremipsum 分别.

为此,我设置了以下(简化示例):

input {
    pipeline { address => "test" }
}

filter {
    grok {
        match => { "source" => ".*\\.*\\(?<product>.*)\\.*" }
    }
}

output {
    stdout { codec => rubydebug }
}

我已经在多个地方(grockconstructor, grockdebug and rubular)测试了用于在源字段上查找匹配项(名为 product)的正则表达式,它们似乎都产生了所需的结果:我使用路径中最后一个文件夹的预期值获得产品的命名匹配项。

但是,当我 运行 具有上述管道配置的 Logstash 时,它无法提取文件夹名称并将其值放入产品字段。相反,我看到一个标记被添加到 logstash 输出,其值为 grokparsefailure,表明我的 grok 表达式有问题。但是我在上述参考工具中的所有测试表明我的表达没有任何问题...

完整的 logstash 输出如下所示:

{
    "@version" => "1",
    "tags" => [
        [0]"beats_input_codec_plain_applied",
        [1]"_grokparsefailure"
    ],
    "host" => {
        "name" => "test"
    },
    "message" => "Another line in the log",
    "agent" => {
        "id" => "e00d2f50-b10c-406a-a4fa-be381d15b869",
        "ephemeral_id" => "28dfe105-b936-40de-bc97-16c4a9196e30",
        "hostname" => "my-host",
        "name" => "test",
        "type" => "filebeat",
        "version" => "7.5.0"
    },
    "@timestamp" => 2019 - 12 - 16T14: 04: 09.064Z,
    "ecs" => {
        "version" => "1.1.0"
    },
    "log" => {
        "file" => {
            "path" => "d:\Logs\Foo\Bar\ipsum\currentlog.txt"
        },
        "offset" => 21
    },
    "input" => {
        "type" => "log"
    }
}

我曾尝试将匹配项更改为 log.file.path 属性,但这给了我相同的 _grokparsefailure 标签。

我也很确定这适用于 Filebeat/Logstash 的早期安装(可能是一两个主要版本),但我记不清了。

所以问题是:为什么 Logstash 不能从 Filebeat 源中提取文件夹名称?有什么办法可以进一步调试这个 grok 问题吗?

上面的配置没有生效的原因是复合的,但我最终弄明白了:

首先,没有来自 Filebeat 的 source 字段(我很确定以前有一些版本,但那是另一回事),这显然会导致 grok 过滤器失败。

接下来,当我尝试在 log.file.path 字段上进行 grok 时,我使用了错误的语法。访问嵌套字段的正确方法是这样的:[log][file][path]

最后,即使输出显示 log.file.path 的值为 "d:\Logs\Foo\Bar\ipsum\currentlog.txt",双反斜杠显然已添加到输出管道的某处。因此,当我更改我的正则表达式以匹配单个反斜杠而不是双反斜杠时,它从 "d:\Logs\Foo\Bar\ipsum\currentlog.txt"

中正确地提取了 ipsum

我的最终管道配置如下所示:

input {
    pipeline { address => "test" }
}

filter {
    grok {
        match => { "[log][file][path]" => ".*(\|\/).*(\|\/)(?<product>.*)(\|\/).*"}
    }
}

output {
    stdout { codec => rubydebug }
}

现在我成功获取了提取到 product 字段的路径中最后一个文件夹的名称,没有 _grokparsefailure 标记。