LogQL 中的正则表达式 JSON 过滤

Regexp JSON filtering in LogQL

我想将 Kibana 查询转换为 LogQL:

host:("test1-myservice-*") AND level:ERROR 
AND NOT logger_name:"com.example.ExampleClass" 
AND _exists_:stack_trace 
AND NOT stack_trace:(
    "interrupted"
    OR "Read timed out"
    OR "java.lang.InterruptedException"
)

我在 Grafana Explore 中尝试了以下操作,但它没有 return 我们的 JSON 日志消息的任何记录:

{host=~"test1-myservice-.*"} | json 
| logger_name != "com.example.ExampleClass" 
| stack_trace !="" 
| stack_trace =~ ".*InterruptedException.*"

虽然使用 != 而不是 =~ 它 return 所有记录:

{host=~"test1-myservice-.*"} | json 
| logger_name != "com.example.ExampleClass" 
| stack_trace !="" 
| stack_trace !~ ".*InterruptedException.*"

如果我是对的,文档中的以下内容适用于 JSON 日志行的 stack_trace 字段:

String type work exactly like Prometheus label matchers use in log stream selector. This means you can use the same operations (=,!=,=~,!~).

来源:Label filter expression

以下似乎有效但看起来很尴尬:

{host=~"test1-myservice-.*"} | json 
| logger_name != "com.example.ExampleClass" 
| stack_trace !="" 
!~ ".*InterruptedException.*|.*Read timed out.*"
| json

此外,如果我是对的,它会在完整的 JSON 字符串中搜索 InterruptedExceptionRead timed out 子字符串,而不是仅搜索其 stack_trace 字段。

是否有更类似 LogQL 的方法将上面的 Kibana 查询转换为 LogQL? !~ 运算符在这种情况下应该工作吗?

环境:Grafana 7.5.4 / 8.2.3,Loki:2.4.1

不确定您的日志行看起来如何,但我认为您不需要提取标签(通过使用 | json

这是一篇关于如何编写查询的非常有用的文章。 how-to-create-fast-queries-with-lokis-logql-to-filter-terabytes-of-logs-in-seconds 如果您想让查询更具可读性,您还可以使用新的 Pattern parser 而不是正则表达式。

因此,在不真正了解您的日志行的情况下,我认为这应该可以正常工作:

{host=~"test1-myservice-.*"}
!= "com.example.ExampleClass" 
!~ ".*InterruptedException.*|.*Read timed out.*"

根据您的需要,您还可以使用我之前提到的模式解析器。

这个有效:

{host=~"test1-myservice-.*"} | json 
| logger_name != "com.example.ExampleClass" 
| stack_trace !="" 
| stack_trace !~ "(?s).*InterruptedException.*"

注意 (?s) 可以匹配正则表达式 . 字符的新行。 (JSON 日志消息的 stack_trace 字段通常包含多行。)

这个在Log stream selector part of the documentation中也有提到:

Note: The =~ regex operator is fully anchored, meaning regex must match against the entire string, including newlines. The regex . character does not match newlines by default. If you want the regex dot character to match newlines you can use the single-line flag, like so: (?s)search_term.+ matches search_term\n.