如何用LogQL在几秒内查询TB级的日志
时间:2021-09-07 11:27:34
手机看文章
扫描二维码
随时随地手机看文章
[导读]LogQL在很大程度上受Prometheus的PromQL启发。但是,当涉及到在过滤海量日志时,我们就像面临在大海捞针一样复杂。LogQL是Loki特有的语句,在本文中,我们将提供LogQL的快速过滤器查询技巧,这些查询可以在几秒钟内过滤掉数TB的数据。在Loki中,我们可以使用...
LogQL在很大程度上受Prometheus的PromQL启发。但是,当涉及到在过滤海量日志时,我们就像面临在大海捞针一样复杂。LogQL是Loki特有的语句,在本文中,我们将提供LogQL的快速过滤器查询技巧,这些查询可以在几秒钟内过滤掉数TB的数据。在Loki中,我们可以使用三种类型的过滤器:
Label matchers
Label matchers(标签匹配器)是你的第一道防线,是大幅减少你搜索的日志数量(例如,从100TB到1TB)的最好方法。当然,这意味着你需要在的日志采集端上有良好的标签定义规范。基本上,标签应该定义的类型包括,工作负载、集群、命名空间和容器等,这样你就可以在多个不同的维度上对数据进行切分。比如说- 一个应用在多个集群上运行
- 落在多个k8s集群命名空间的开发环境
- 生产环境的命名空间
=
匹配器(例如,{cluster="us-central1"})
。否则,你将不得不提取整个索引数据。但有一个例外。如果匹配器包含一个或多个字元,比如{container=~"promtail|agent"}
,同时只有一个单一的regex匹配器,Loki可以自行优化查询
下面就是一些实用的样例:好例子:{cluster="us-central1"}
{container="istio"}
{cluster="us-central1", container=~"agent|promtail"}
坏例子:{job=~".*/queue"}
{namespace!~"dev-.*"}
Line filters
Line filters(行过滤器)是您的第二个好朋友,因为它们执行过程超级快。它允许你过滤包含(|=
)或不包含(!=
)字符串的日志,你也可以使用正则来匹配(|~
)或不匹配(!~
)日志,但你应该把它们放在标签匹配器之后
。现在,当我们将这些过滤器连起来使用时,要注意过滤器的顺序
。先用那些能过滤最多日志的过滤器,然后再使用正则,它比=
和!=
慢。但有一个例外。|~ "error|fatal "
可以被Loki优化掉 实际上这两个字符串被loki自动过滤掉了,所以不会执行正则匹配
一个好的方法是先添加一个符合你要找的东西的过滤器,例如,|= "err"
。然后再添加越来越多的不等式来过滤你不想要的东西,直到最终得到类似于下面这样的结果|= "err" != "timeout" != "cancelled" |~ "failed.*" != "memcached"
现在,如果你意识到你的大部分错误来自memcached,那么就把它移到第一个位置!= "memcached" |= "err" != "timeout" != "cancelled" |~ "failed.*"
这样一来,后续过滤器的执行次数就会减少。除此之外,行过滤器也很适合查找IP、TraceID、UUID等类型的日志。比如下面这个也一个很好的查询方式{namespace="prod"} |= "traceID=2e2er8923100"
如果你想让这个traceID的所有日志都符合某个regex,可以在ID过滤器后面加上|~ "/api/v. /query"
,这样就不会对prod命名空间的每个pod中去添加查询。Label filters
Label filters(标签过滤器)提供了更复杂的计算功能(duration,numerical等),但是它们通常需要先提取标签,然后再将标签值转换为另一种类型。这意味着它们通常是最慢的,因此我们应该最后使用它们。实际上我们可以在不提取标签的情况下使用标签过滤器(使用尽管|json
或|logfmt
等解析器)。标签过滤器也可以在索引标签上工作。例如,{job="ingress/nginx"}。| status_code >= 400 and cluster="us-central2"
可以正常工作,但你真正应该问自己的是,你是否需要将 status_code 作为索引标签。一般来说,你不应该,但你可以考虑提取 status_code 作为标签,这可以将大批量的流(每秒超过一千行)分解成独立的流。
| json
和| logfmt
解析器很快,但是解析| regex
却很慢。这就是为什么在使用解析器时,我总是在它前面加上一个行过滤器。例如,在我的Go应用程序(包括Loki)中,我的所有日志均支持显示文件名和行号(此处为caller=metrics.go:83
)level=info ts=2020-12-07T21:03:22.885781801Z caller=metrics.go:83 org_id=29 traceID=4078dafcbc079822 latency=slow query="{cluster=\"ops-tools1\",job=\"loki-ops/querier\"} != \"logging.go\" != \"metrics.go\" |= \"recover\"" query_type=filter range_type=range length=168h0m1s step=5m0s duration=54.82511258s status=200 throughput=8.3GB total_bytes=454GB
因此,当我们想过滤缓慢的请求时,应该先对记录文件和行号
进行过滤,然后再进行解析,最后再将提取的标签进行比较。{namespace="loki-ops",container="query-frontend"}
|= "caller=metrics.go:83"
| logfmt
| throughput > 1GB and duration > 10s and org_id=29