使用 Exemplars 分析异常值和错误

使用 exemplars 将指标连接到记录的跟踪,以分析错误或延迟的根本原因。

指标是多个事件的聚合,可以显示您的系统是否在定义的范围内运行。它们非常适合监控错误率或尾部延迟,以及设置警报或推动性能优化。然而,聚合使得查找指标中报告的延迟或错误的根本原因变得困难。

通过启用跟踪可以找到错误和延迟的根本原因。要将指标连接到记录的跟踪,可以使用 exemplars 的概念。

一旦设置了 exemplars,Keycloak 会报告指标,并将其最后记录的跟踪作为 exemplar。像 Grafana 这样的仪表板工具可以将指标仪表板中的 exemplar 链接到跟踪视图。

支持 exemplars 的指标有

  • http_server_requests_seconds_count (包括直方图)
    有关此指标的详细信息,请参阅指南 HTTP 指标

  • keycloak_credentials_password_hashing_validations_total
    有关此指标的详细信息,请参阅指南 自提供指标

  • keycloak_user_events_total
    有关此指标的详细信息,请参阅指南 自提供指标

请参阅下面的热图可视化截图,其中显示了延迟的 exemplar,当鼠标悬停在粉红色指示器之一上时会显示 exemplar。

exemplar
图 1. 带有 exemplar 的热图

设置 exemplars

要从 exemplars 中获益,请执行以下步骤

  1. 按照指南 通过指标获取洞察力 中的描述,为 Keycloak 启用指标。

  2. 按照指南 使用跟踪进行根本原因分析 中的描述,为 Keycloak 启用跟踪。

  3. 在您的监控系统中启用 exemplar 存储。

    对于 Prometheus,这是一个 预览功能,您需要启用它

  4. 使用 OpenMetricsText1.0.0 协议抓取指标,该协议在 Prometheus 中默认未启用。

    如果您在 Kubernetes 环境中使用 PodMonitors 或类似工具,则可以通过将其添加到自定义资源的 spec 中来实现。

    apiVersion: monitoring.coreos.com/v1
    kind: PodMonitor
    metadata:
      ...
    spec:
      scrapeProtocols:
        - OpenMetricsText1.0.0
  5. 配置您的指标数据源,以便链接到跟踪。

    当使用 Grafana 和 Prometheus 时,这将是为 Prometheus 数据源设置 exemplarTraceIdDestinations,然后指向由 Jaeger 或 Tempo 等工具提供的跟踪数据源。

  6. 在您的仪表板中启用 exemplars。

    在您要显示 exemplars 的每个仪表板上的每个查询中,启用 Exemplars 开关。正确设置后,您会在仪表板中注意到小点或星星,您可以单击它们以查看跟踪。

  • 如果您未指定抓取协议,Prometheus 默认情况下不会在内容协商中发送它,Keycloak 将回退到不包含 exemplars 的 PrometheusText 协议。

  • 如果您启用了跟踪和指标,但请求采样未记录跟踪,则公开的指标将不包含任何 exemplars。

  • 如果您使用浏览器访问指标端点,内容协商将导致返回 PrometheusText 格式,您将看不到任何 exemplars。

验证 exemplars 是否按预期工作

执行以下步骤以验证 Keycloak 是否为 exemplars 正确设置

  1. 按照说明设置 Keycloak 的指标和跟踪。

  2. 出于测试目的,通过将跟踪比率设置为 1.0 来记录所有跟踪。有关生产系统中建议的采样设置,请参阅 使用跟踪进行根本原因分析

  3. 登录到 Keycloak 实例以创建一些跟踪。

  4. 使用类似于以下命令的命令抓取指标,并搜索那些设置了 exemplar 的指标

    $ curl -s https://127.0.0.1:9000/metrics \
    -H 'Accept: application/openmetrics-text; version=1.0.0; charset=utf-8' \
    | grep "#.*trace_id"

    这应该产生类似于以下内容的输出。请注意额外的 #,在其后添加了 span 和 trace ID

    http_server_requests_seconds_count {...} ... # {span_id="...",trace_id="..."} ...
在此页