Loki 2.3中的新功能:LogQL模式解析器使其更容易从非结构化日志中提取数据

633 阅读3分钟

由于Loki 2.3发布了新的模式解析器,编写LogQL查询以访问Loki的日志数据变得更加容易。它使编写非结构化日志格式的查询变得简单。而且模式分析器的速度比正则表达式分析器快一个数量级。让我们仔细看看。

日志解析的困境

Loki 2.0引入了新的LogQL解析器,处理JSON、logfmt和regex。虽然JSON和logfmt解析器是快速和易于使用的,但regex解析器却不是。

考虑对NGINX日志进行解析以提取标签和值。为了找到按方法和状态的请求率,查询是可怕的和繁琐的。在这个例子的查询中,强调了regex的作用:

我们可以让它简单而直观地解析常见的日志格式。毕竟,这些非结构化的日志条目是由字数和空格分隔的标记。

模式解析器的介绍

Loki v2.3.0引入了模式解析器。它既简单易用,又能从非结构化日志中提取数据,效率极高。

剧透一下!下面是使用模式分析器编写的同一个查询:

这个模式表达式和正则表达式之间有相当大的区别。我从我自己为这个例子生成正则表达式的经验中知道这一点。我花了好几次反复,花了20分钟才把它做对。除此之外,模式解析器解析日志行的速度比正则表达式解析器快。

模式分析器的语法和语义

通过指定在LogQL查询中调用模式解析器:

| pattern ""

| pattern ``

指定一个日志行的结构。它是由捕获和字词组成的。

一个捕获定义了一个字段名,并由<> 字符分隔。在这个例子中, 定义了字段名status。未命名的捕获<_> ,跳过并忽略了日志行中的匹配内容。

捕获的内容从该行的开始,或从上一组字词到该行的结束,或到下一组字词进行匹配。如果一个捕获不匹配,模式解析器就会停止处理该日志行。默认情况下,模式表达式被锚定在日志行的开头。如果你想改变这种行为,用一个未命名的捕获开始你的表达式,<_>

模式解析器的例子

模式解析器表达式的例子在NGINX日志行上操作。这里有三个NGINX日志行的例子:

192.0.2.0 - - [04/Aug/2021:21:12:04 +0000] "GET /api/plugins/versioncheck?slugIn=&grafanaVersion=6.3.5 HTTP/1.1" 200 2 "-" "Go-http-client/2.0" "220.248.51.226, 34.120.177.193" "TLSv1.2" "CN" "CN31"
198.51.100.0 - - [04/Aug/2021:21:12:04 +0000] "GET /ws/?EIO=3&transport=polling&t=NiJ0b8H HTTP/1.1" 200 103 "https://grafana.com/grafana/download?platform=mac" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1.1 Safari/605.1.15" "2001:240:168:3400::1:87, 2600:1901:0:b3ea::" "TLSv1.3" "JP" "JP13"
203.0.113.0 - - [04/Aug/2021:21:12:04 +0000] "GET /healthz HTTP/1.1" 200 15 "-" "GoogleHC/1.0" "-" "-" "-" "-"

这里的例子是 :

<_> - - <_> "<_> <_>"<_> <_> "<_>" <_>

该表与第三个NGINX日志行样本的模式表达式的部分字段相匹配。请注意, 中的最后一个<_> 字段消耗了日志行中的结尾四个字段,因为它在到达日志行的结尾时停止消耗:

NGINX日志行字段NGINX样本
$remote_addr203.0.113.0<_>
---
$remote_user--
[$time_local][04/Aug/2021:21:12:04 +0000]<_>
"$request""GET /healthz HTTP/1.1""<_> <_>"
$status200
$bytes_sent15<_>
"$http_referer""-"<_>
"$http_user_agent""GoogleHC/1.0""<_>"
"-" "-" "-" "-"<_>

这个例子的日志行定义了 method="GET" 和 status=200。

第二个例子是在Kubernetes环境中使用Envoy代理的模式解析器。这是一个指标查询,返回每个路径和方法的第99个百分点的延迟,单位是秒:

quantile_over_time(0.99,

  {container="envoy"} 

 | pattern `[<_>] "  <_>" <_> <_> <_> <_> `

 | unwrap latency\[$__interval]

  ) by (method,path) / 1e3

为了匹配日志行,这个例子定义了方法、路径和延迟。