返回

LogQL: 巧妙查询TB级海量日志,让您轻松发现关键点

开发工具

LogQL,Loki特有的查询语,灵感源于Prometheus的PromQL,然而,如果说我们大海捞针,那些正在LogQL中查询海量日志的人,俨然就身处巨型航母上淘针尖似的。现在,就由这篇文章为你提供LogQL高效过滤海量日志,数秒搞定TB数据的查询技术。

快速过滤的套路,即是将查询作用在日志记录的元数据属性上,而不是文本。这样我们就无需阅读成千上万条日志,只需用过滤条件将目标结果缩小到数千条,再用文本筛选它们,直接了明。

举个例子,比如说你想要找到所有关于“mysql”的错误日志,就可以使用:

"mysql"

作为一个查询。与此同时,假设你想要的条件更为苛刻,比如说,某个pod里名为“example-app”的container中,“mysql”错误已重现3次以上,这种时候我们的查询就该变成:

log=mysql AND (container_name=example-app AND kube_pod_name=example-pod)

当然,有时候我们又想要相反的查询,即排除特定条件的查询。对于第一个问题,只须在前面加个“NOT”;对于第二个,我们将取第一个查询,加个“AND NOT”将其延展:

NOT "mysql"
log=mysql AND (container_name=example-app AND kube_pod_name=example-pod)
AND NOT log_level=Error

现在让我们深入看看其他例子:

  • 查看不同服务里最近一小时的所有error日志:
timestamp >= (current_timestamp() - 1h)
AND (
  (source_service = "filebeat-weblog")
  OR (source_service = "logspout-fluentd")
  OR (source_service = "filebeat-weblog")
)
AND log_level = error
  • 用正则表达式筛选出匹配特定时间格式的日志记录,以便排查问题:
"2023-03-10T09:15:32Z"
  • 使用正则表达式过滤含ERROR关键字,同时记录下ERROR出现的容器名称:
container_name=~".*" AND message=~ "Error"
  • 查验error日志里有多少不同的pod,以及各个pod的错误日志数量分布:
count_over_time(count({pod_name}), 5m) | matrix_relabel(pod_name, name)

目前为止,日志的过滤可能仅仅是基于它的属性或一部分内容,是否能实现对日志内容进行检索呢?当然能,我们只需要用“free text”,用英文里的术语叫“自由文本查询”,查询针对文本和元数据的混合体进行查询。

以下举几个例子:

  • 找到所有error等级的,而且关于“mysql”且带“error”标签的日志记录:
"error" "mysql" label=error log_level=error
  • 寻出ERRor级别的带“failed”一词的日志记录:
"failed" log_level=error
  • 用正则表达式找到错误里那些以特定形式开头的条目:
^Failed:.*
  • 用正则表达式找到错误里那些以特定形式结束的条目:
.*product_page_views.*
  • 筛选出错的service:
service=~".*" error
  • 找到出错的pod:
pod=~".*" error

最后,让我们总结出一些小建议,以期对你之后查询日志有所帮助:

  • 提升查询速度,务必剔除不必要的信息。
  • 多尝试不同的filter查询。
  • 检查Loki服务性能情况。
  • 设置查询超时。
  • 保存重复查询,以供日后参考。

相信这篇文章能帮助你提升过滤海量日志的效率,快速定位重点。