#log-messages #logging #batch #logs #first-line #single-line

app multiline

将包含跨越多行的消息的实时日志消息流转换为每行一个消息的流

2 个版本

0.1.1 2019 年 8 月 27 日
0.1.0 2019 年 7 月 15 日

#10 in #first-line

MIT 许可证

16KB
111

Latest Version Documentation License

多行

multiline 是一个 CLI 工具,可以将包含跨越多行的消息的实时日志消息流(例如应用程序日志文件的日志条目)转换为每行一个消息的流。

它可以用作在将日志文件数据发送到 syslogs 之前的一个预处理步骤,否则 syslogs 会将跨越多行的消息解释为单独的消息,每行一个。

用法

multiline 程序将从标准输入读取 UTF-8 数据,一次一行,并将由 --join 字符串连接的潜在多行消息写入标准输出。

要配置消息开始或结束匹配算法正则表达式,可以使用 --message-pattern--negate--match-last 标志。可以使用 --strip-pattern 标志从输出中删除匹配的消息模式。

此外,multiline 可以使用 --stream-id-pattern 正则表达式匹配每个流的识别模式来处理标准输入中交织在一起的多条日志数据流。

可以使用 --max-size 标志配置实时处理参数,该标志限制每个流将累积的最大行数,以及 --max-duration,该标志限制每个消息将继续聚合行的时间长度。在达到这些限制之一后,连接的消息将被刷新到输出。

指定 --timestamp 标志将启用打印基于读取消息第一行的时间构建的每个消息的时间戳(ISO 8601 UTC 格式)。

示例

连接堆栈跟踪

使用 negate 将以空格开头的每一行匹配为属于前一条消息。

multiline --message-pattern '^\s+' --negate --strip-pattern --join "; " <<EOF
Exception in thread "main" java.lang.NullPointerException
        at com.example.myproject.Book.getTitle(Book.java:16)
        at com.example.myproject.Author.getBookTitles(Author.java:25)
        at com.example.myproject.Bootstrap.main(Bootstrap.java:14)
Exception in thread "main" java.lang.NullPointerException
        at com.example.myproject.Book.getTitle(Book.java:16)
        at com.example.myproject.Author.getBookTitles(Author.java:25)
        at com.example.myproject.Bootstrap.main(Bootstrap.java:14)
Hello world!
Exception in thread "main" java.lang.NullPointerException
        at com.example.myproject.Book.getTitle(Book.java:16)
        at com.example.myproject.Author.getBookTitles(Author.java:25)
        at com.example.myproject.Bootstrap.main(Bootstrap.java:14)
EOF

输出

Exception in thread "main" java.lang.NullPointerException; at com.example.myproject.Book.getTitle(Book.java:16); at com.example.myproject.Author.getBookTitles(Author.java:25); at com.example.myproject.Bootstrap.main(Bootstrap.java:14)
Exception in thread "main" java.lang.NullPointerException; at com.example.myproject.Book.getTitle(Book.java:16); at com.example.myproject.Author.getBookTitles(Author.java:25); at com.example.myproject.Bootstrap.main(Bootstrap.java:14)
Hello world!
Exception in thread "main" java.lang.NullPointerException; at com.example.myproject.Book.getTitle(Book.java:16); at com.example.myproject.Author.getBookTitles(Author.java:25); at com.example.myproject.Bootstrap.main(Bootstrap.java:14)

连接以特殊转义符结束的行

使用 match-lastnegate 将锚定在不包含转义符的行上。添加 strip-pattern 确保转义符不是输出的一部分。

multiline --message-pattern ' >$' --negate --match-last --strip-pattern --join "; " <<EOF
Exception in thread "main" java.lang.NullPointerException >
at com.example.myproject.Book.getTitle(Book.java:16) >
at com.example.myproject.Author.getBookTitles(Author.java:25) >
at com.example.myproject.Bootstrap.main(Bootstrap.java:14)
Exception in thread "main" java.lang.NullPointerException >
at com.example.myproject.Book.getTitle(Book.java:16) >
at com.example.myproject.Author.getBookTitles(Author.java:25) >
at com.example.myproject.Bootstrap.main(Bootstrap.java:14)
Hello world!
Exception in thread "main" java.lang.NullPointerException >
at com.example.myproject.Book.getTitle(Book.java:16) >
at com.example.myproject.Author.getBookTitles(Author.java:25) >
at com.example.myproject.Bootstrap.main(Bootstrap.java:14)
EOF

输出

Exception in thread "main" java.lang.NullPointerException; at com.example.myproject.Book.getTitle(Book.java:16); at com.example.myproject.Author.getBookTitles(Author.java:25); at com.example.myproject.Bootstrap.main(Bootstrap.java:14)
Exception in thread "main" java.lang.NullPointerException; at com.example.myproject.Book.getTitle(Book.java:16); at com.example.myproject.Author.getBookTitles(Author.java:25); at com.example.myproject.Bootstrap.main(Bootstrap.java:14)
Hello world!
Exception in thread "main" java.lang.NullPointerException; at com.example.myproject.Book.getTitle(Book.java:16); at com.example.myproject.Author.getBookTitles(Author.java:25); at com.example.myproject.Bootstrap.main(Bootstrap.java:14)

从多个交织的日志数据流中连接消息

正则表达式 stream-id-pattern 将匹配流名称。对于每个流,将维护一个单独的连接缓冲区。时间戳用于匹配每个流中消息的开始。

multiline --message-pattern '^20' --stream-id-pattern '.*: ' --join " " <<EOF
bar: 2019-07-05 15:42:16 Lorem ipsum dolor sit amet,
foo: 2019-07-05 15:42:16 Lorem ipsum dolor sit amet,
foo: consectetur adipiscing elit
bar: consectetur adipiscing elit
foo: 2019-07-05 15:42:17 Phasellus eleifend scelerisque lorem,
foo: a placerat ex dictum iaculis.
foo: 2019-07-05 15:42:18 Nam porta hendrerit fermentum.
foo: 2019-07-05 15:42:19 Vivamus vitae faucibus purus.
bar: 2019-07-05 15:42:17 Phasellus eleifend scelerisque lorem,
foo: 2019-07-05 15:42:20 Cras suscipit lacus ex.
bar: a placerat ex dictum iaculis.
bar: 2019-07-05 15:42:18 Nam porta hendrerit fermentum.
bar: 2019-07-05 15:42:19 Vivamus vitae faucibus purus.
foo: 2019-07-05 15:42:21 Phasellus sed nulla faucibus,
foo: bibendum dolor vitae,
foo: faucibus dui.
bar: 2019-07-05 15:42:20 Cras suscipit lacus ex.
bar: 2019-07-05 15:42:21 Phasellus sed nulla faucibus,
bar: bibendum dolor vitae,
bar: faucibus dui.
EOF

输出

foo: 2019-07-05 15:42:16 Lorem ipsum dolor sit amet, consectetur adipiscing elit
foo: 2019-07-05 15:42:17 Phasellus eleifend scelerisque lorem, a placerat ex dictum iaculis.
foo: 2019-07-05 15:42:18 Nam porta hendrerit fermentum.
bar: 2019-07-05 15:42:16 Lorem ipsum dolor sit amet, consectetur adipiscing elit
foo: 2019-07-05 15:42:19 Vivamus vitae faucibus purus.
bar: 2019-07-05 15:42:17 Phasellus eleifend scelerisque lorem, a placerat ex dictum iaculis.
bar: 2019-07-05 15:42:18 Nam porta hendrerit fermentum.
foo: 2019-07-05 15:42:20 Cras suscipit lacus ex.
bar: 2019-07-05 15:42:19 Vivamus vitae faucibus purus.
bar: 2019-07-05 15:42:20 Cras suscipit lacus ex.
foo: 2019-07-05 15:42:21 Phasellus sed nulla faucibus, bibendum dolor vitae, faucibus dui.
bar: 2019-07-05 15:42:21 Phasellus sed nulla faucibus, bibendum dolor vitae, faucibus dui.

时间戳消息

使用 --timestamp 标志启用时间戳。

seq 1 10 | while read I; do echo $I; sleep 0.2; done | multiline --message-pattern '.' --timestamp

输出

2019-07-12T13:29:12.872375Z 1
2019-07-12T13:29:13.071095Z 2
2019-07-12T13:29:13.273488Z 3
2019-07-12T13:29:13.475585Z 4
2019-07-12T13:29:13.677506Z 5
2019-07-12T13:29:13.879438Z 6
2019-07-12T13:29:14.082132Z 7
2019-07-12T13:29:14.284793Z 8
2019-07-12T13:29:14.487547Z 9
2019-07-12T13:29:14.690270Z 10

依赖关系

约13MB
约227K SLoC