Loki Adhoc 过滤器对结构化元数据失效问题

概述

在日志聚合系统 loki 中,结构化元数据为日志行提供了重要的非索引上下文信息,而 Grafana 的 adhoc 过滤器旨在让用户通过下拉菜单快速、交互式地筛选日志。然而,当前的实现存在一个关键缺陷:当基础 Loki 查询没有包含解析器时,针对结构化元数据字段添加的 adhoc 过滤器无法按预期工作,导致查询结果为空。这直接影响了用户进行即时数据探索的效率和体验,是构建基于日志的 SLI 时需要规避的一个潜在陷阱。

核心概念

要理解此问题,需澄清以下关键概念:

  1. 结构化元数据:这是 Loki 中的一种字段类型,它与日志标签和日志内容本身不同。它通常用于存储一些对调试和分析有用但不必在索引中的字段,例如 detected_level、trace_id 等。这些字段不能直接用于流选择器。
  2. adhoc 过滤器:这是 Grafana UI 中一项便捷功能,允许用户在查询构建器中点击字段值旁的 + 或 - 按钮,快速将该字段及其值作为过滤条件添加到查询中。
  3. 查询构造机制:
    • 正确路径(当查询包含解析器时):adhoc 过滤器会生成一个 |~ "field=value" 或类似形式的 logql 表达式,该表达式会被附加到管道的末尾,作为标签过滤器,在解析后的内容中进行匹配。
    • 问题路径(当查询不包含解析器时):系统会错误地将结构化元数据字段 field=value 添加到流选择器 {} 中。由于结构化元数据不是流选择器的一部分,Loki 引擎会尝试用它来匹配流,但没有任何流的标签包含这个字段,因此查询必然返回空结果。

实践

问题重现

  1. 在 Grafana 中创建一个仪表板,添加一个 Logs 面板。
  2. 配置一个数据源为 Loki 的简单查询,例如:
    {job=`my-app`} 
    关键点:此查询没有包含任何解析器(如 | json, | logfmt, | pattern 等)。
  3. 在查询结果或标签浏览器中找到一个结构化元数据字段,例如 detected_level,其值为 info。
  4. 点击该字段值旁的 + 按钮,将其作为过滤器添加。
  5. 观察生成的查询:它会变成 {job=my-app, detected_level=info}。这个查询几乎肯定会返回无数据,因为 Loki 没有任何流的标签中包含 detected_level。

解决方案与规避方法

目前,这是一个已知的产品缺陷,没有根本的客户端修复方法。用户和 SRE 需要采取以下规避策略:

  • 最佳实践:在构建用于分析和过滤的仪表板查询时,始终包含一个能够提取结构化元数据为标签的解析器。例如:

    {job=`my-app`} | json | detected_level=`info`

    这样,当用户使用 adhoc 过滤器时,生成的查询会是:

    {job=`my-app`} | json | detected_level=`info`

    这将是正确且有效的。

  • 手动查询构建:如果必须使用无解析器的简单查询,用户需要放弃使用 adhoc 过滤器,转而手动在查询的管道中添加 | detected_level=info“ 过滤器。

  • 字段可视化提示:在 UI 中,用户应留意字段的类型标识。通常,标签字段可以用于流选择器,而日志内容字段和结构化元数据字段则需要通过管道过滤。

SRE 要点

  • 与可靠性的关联:

    • 监控盲区:此问题可能导致依赖于 adhoc 过滤器的告警规则或仪表板静默失败(返回空结果),掩盖真实的系统问题,影响 Error Budget 的正确计算。
    • 故障排查障碍:在事件响应(Incident Response)期间,工程师依赖快速的日志过滤来定位问题。此缺陷会延长平均修复时间(MTTR),降低操作可靠性。
  • 最佳实践与反模式:

    • 反模式:依赖未经解析器处理的简单 Loki 查询,并期望 adhoc 过滤器能对所有字段(包括结构化元数据)正常工作。
    • 最佳实践:1) 明确区分标签(用于流选择)和可提取内容(用于管道过滤);2) 在面向用户的查询面板中,提供包含适当解析器的预定义查询;3) 在团队内部文档中记录此已知限制。
  • 相关指标与 SLO:

    • 此问题本身不直接产生 SLI,但它可能影响基于日志的 SLO 的有效性,例如 HTTP 5xx 错误率,如果工程师无法有效过滤和分析这些错误日志。
    • 在设计 SLO 监控时,应确保查询基础稳固(即包含正确解析器的查询),避免因工具缺陷导致监控失效。

loki 的 LogQL 是功能强大的工具,但正确理解其查询结构(流选择器 vs. 管道操作)是避免此类问题的关键。SRE 应将清晰的日志查询规范作为可观测性实践的一部分。