ClickHouseInc

ClickStack SQL:重塑你的可观测性工作流,深度洞察数据

图片

本文字数:6538;估计阅读时间:17 分钟

作者:Drew Davis and Dale McDiarmid

Image
Image
引言

今天,我们将在 ClickStack 中推出 SQL 可视化 (SQL-based visualizations) 和 SQL 告警 (SQL-based alerting) 功能。用户现在可以使用任意 ClickHouse SQL 查询来构建图表和告警,从而直接在 ClickStack UI (用户界面) 内部实现更高级的分析。SQL 可视化使用户能够超越预定义的 查询构建器 (query builders),充分利用 ClickHouse SQL 进行仪表板和探索性分析。SQL 告警在此基础上进一步扩展,允许任何通过 SQL 表达的逻辑作为告警条件,从 滚动平均值 (rolling averages) 和 异常检测 (anomaly detection) 到 分组统计检查 (grouped statistical checks) 和自定义操作逻辑。本文将探讨我们构建这些功能的原因、它们如何改变 可观测性工作流 (observability workflow),并通过一些示例来展示 SQL 驱动的分析和告警在哪些场景下能发挥尤其强大的作用。

Image
第一步:SQL 驱动的图表

引入 SQL 图表和 SQL 告警的契机源于一个简单的发现:尽管查询构建器对于常见工作流来说表现出色,但高级用户往往很快就会发现它们无法满足更深层次的需求。

随着可观测性用例的日益成熟,团队希望计算 滚动基线 (rolling baselines)、构建统计 异常检测 (anomaly detection)、关联事件 (correlate events)、计算 服务等级目标 (SLOs),并表达那些无法通过预定义 UI 控件清晰表达的复杂逻辑。查询构建器虽然有助于快速入门,但它们不可避免地在灵活性和简便性之间进行了权衡。

99th_by_service.png

查询构建器本身具有局限性,仅能满足用户部分查询需求

由于 ClickStack 构建于 ClickHouse 之上,因此支持原生 SQL 感觉是平台能力的自然延伸,而非生硬的附加功能。SQL 图表使用户能够充分利用 ClickHouse 强大的表达性分析能力,同时仍可无缝集成到仪表板、过滤器和可视化中。

尽管 SQL 可视化也可用于基础图表,但其真正价值在于帮助用户不再局限于简单的聚合操作,并直接在可观测性工作流中应用更丰富的分析逻辑。

示例 - 使用滚动基线检测异常

高级可观测性团队最普遍的需求之一是,能够可视化相对于系统近期行为(而非 静态阈值 (static thresholds))的异常情况。

例如,一个支付结算端点在高峰流量时段耗时 800 毫秒可能属于正常表现,但对于轻量级内部服务而言,则极其异常。

通过 SQL 图表,用户可以使用 ClickHouse 窗口函数直接在查询中构建滚动平均值和标准差基线。这样,图表不仅能显示原始延迟,还能展示服务在一段时间内延迟何时偏离其预期范围。

WITH buckets AS (

  SELECT

    toStartOfInterval(

      Timestamp,

      INTERVAL {intervalSeconds:Int64} second

    ) AS ts,

    ServiceName,

    quantile(0.95)(Duration) / 1000000 AS p95_latency_ms

  FROM $__sourceTable

  WHERE Timestamp >= fromUnixTimestamp64Milli({startDateMilliseconds:Int64})

    AND Timestamp < fromUnixTimestamp64Milli({endDateMilliseconds:Int64})

    AND SpanKind = 'Server'

    AND $__filters

  GROUP BY

    ts,

    ServiceName

),

baselines AS (

  SELECT

    ts,

    ServiceName,

    p95_latency_ms,

    avg(p95_latency_ms) OVER (

      PARTITION BY ServiceName

      ORDER BY ts

      ROWS BETWEEN 12 PRECEDING AND 1 PRECEDING

    ) AS rolling_avg_latency_ms,

    stddevPop(p95_latency_ms) OVER (

      PARTITION BY ServiceName

      ORDER BY ts

      ROWS BETWEEN 12 PRECEDING AND 1 PRECEDING

    ) AS rolling_stddev_latency_ms

  FROM buckets

)

SELECT

  ts,                                      -- Timestamp column

  ServiceName,                             -- Group name column

  p95_latency_ms,                          -- Series value column

  rolling_avg_latency_ms,                  -- Series value column

  rolling_avg_latency_ms

    + 3 * rolling_stddev_latency_ms

      AS upper_bound_latency_ms            -- Series value column

FROM baselines

WHERE rolling_avg_latency_ms IS NOT NULL

ORDER BY ts ASC

由此生成的时间序列图表,将 ts 用作时间戳列,ServiceName 作为分组列,每个数值列都绘制为一个独立的序列。该图表展示了每个服务的当前 p95 延迟、滚动平均值以及统计上限。

sql-chart.png

团队由此能够发现延迟是否偏离了其近期基线,而非依赖固定的阈值,因为此类阈值可能对某些工作负载过于敏感,而对另一些则过于宽松。在传统的查询构建器中,这种分析极难实现,因为它需要涉及窗口函数、历史基线、百分位数计算、分组时间序列逻辑以及多阶段查询组合。但通过原生 SQL,这些工作流变得简单直接。

细心的读者可能已经注意到,之前的 SQL 查询包含了用于查询时间范围、仪表板过滤和源表选择的宏。对于 Grafana 用户而言,这些宏可能也十分眼熟……

允许动态 SQL 图表

静态 SQL 查询固然有用,但可观测性仪表板仍需保持动态交互。图表需要自动响应仪表板的时间范围、间隔和过滤器,无需用户在仪表板每次变化时手动重写查询。

这正是查询参数和宏发挥关键作用的地方。

查询参数直接将仪表板状态传递给 SQL 查询。这些参数包括仪表板的开始时间、结束时间和时间间隔等值。它们采用 ClickHouse 的参数语法,如 {startDateMilliseconds:Int64} 和 {intervalSeconds:Int64},使查询能够动态适应当前的仪表板上下文。

基于这些参数,宏可以为常见的可观测性工作流提供快捷表达式。例如,$__filters 和 $__sourceTable 等宏能够自动将仪表板过滤器和源表引用直接注入到查询中。时间过滤和分桶宏则进一步简化了动态时间序列图表的创建。

我们构建基于 SQL 的可视化 (SQL-based visualizations) 的目标之一,是让现有 Grafana 和 ClickHouse 用户能够即刻感到熟悉。因此,许多支持的宏有意地模仿了 ClickHouse Grafana 插件所使用的约定。在许多情况下,用户可以直接将 Grafana 中现有的 SQL 查询导入 ClickStack,并使其仅需少量修改或无需修改即可运行。

这种兼容性对我们而言是一个重要的设计理念。团队已投入大量时间构建运维查询、仪表盘和告警逻辑,我们希望基于 SQL 的可视化能够自然地融入现有工作流,而不是强制用户从头开始重写所有内容。

这些宏还确保 SQL 图表在仪表盘中保持完全交互性。当用户更改仪表盘时间范围、应用过滤器或切换底层数据源时,SQL 查询会自动调整以反映新的上下文。

结合之前的可视化和查询,如果我们应用一个仪表盘时间范围和服务级别过滤器,这些宏会自动将相应的 SQL 条件注入到查询执行中,同时保留可视化逻辑。

Image

对所有支持的宏和查询参数感兴趣的用户,请参阅基于 SQL 的可视化文档:SQL-based visualizations documentation(https://clickhouse.com/docs/use-cases/observability/clickstack/dashboards/sql-visualizations?utm_source=chatgpt.com)。

查询结果制图

尽管基于 SQL 的可视化在查询逻辑上提供了完全的灵活性,ClickStack 仍然需要理解返回的查询列应如何映射到可视化元素。这种映射取决于可视化类型以及查询本身返回的数据类型。例如,对于折线图 (Line chart) 和堆叠柱状图 (Stacked Bar chart),第一个 Date 或 DateTime 列被解释为时间戳轴 (timestamp axis),数值列则作为系列值 (series values) 进行绘制;而 String、Map 和 Array 列则被视为分组维度 (grouping dimensions),从而允许为每个组渲染单独的折线或柱状图。

饼图、数字图和表格图等其他可视化类型,其映射规则略有不同。关于查询结果在不同可视化类型中如何呈现的详细说明,请参阅文档中查询结果绘制方式一节(https://clickhouse.com/docs/use-cases/observability/clickstack/dashboards/sql-visualizations#how-results-are-plotted)。

Image
下一步:SQL告警

尽管SQL支持的图表(SQL-powered charting)显著拓宽了用户可视化数据的范围,但SQL支持的告警(SQL-powered alerting)才是其真正运营价值的体现。

去年,我们推出了ClickStack中的原生告警支持,集成了 PagerDuty 和 Incident.io 等平台,使团队能够直接从搜索和图表中构建告警。这极大方便了用户在 ClickStack 内部直接定义基于阈值的日志、追踪和指标告警。

但归根结底,告警的表达能力取决于其底层查询能力的强弱。

传统的阈值告警适用于简单的条件,但可观测性团队日益希望对更高级的运营模式进行告警。他们需要检测相对于滚动基线的异常情况、识别行为的突发变化、将多个信号关联起来,或者基于统计分析而非固定值来构建告警。

以往,这常常迫使团队维护独立的工具,例如 Grafana,专门用于高级告警工作流,尽管 ClickHouse 已是他们的主要可观测性数据存储。

基于 SQL 的告警是 SQL 支持图表的自然演进。一旦用户可以在 SQL 可视化中表达任意分析逻辑,他们就可以将同样的强大能力直接应用于告警。

尽管 SQL 告警仍可用于更丰富的阈值条件,例如对滚动平均值或动态计算的基线进行告警,但其真正的强大之处在于将复杂性移至查询本身,而非阈值配置。

sql-chart-alert.png

不同于仅仅返回原始指标并与静态阈值进行比较,SQL 查询能够封装整个告警决策。一个查询可以回溯过去的时间窗口,计算统计边界,比较历史行为,并最终返回一个二元结果(例如 1 或 0),以判断告警条件是否应该触发。

这从根本上改变了告警逻辑的表达方式。用户无需配置日益复杂的阈值规则,而是可以直接在查询语句中充分利用 ClickHouse 强大的分析能力。

示例:使用滞后平均值 (Lagging Averages) 进行异常检测 (Anomaly Detection)

例如,考虑检测相对于历史行为,错误量突然激增的情况。与在错误计数超过固定阈值时触发告警不同,我们可以在过去的时间间隔上计算一个滚动平均值 (Rolling Average) 和标准差 (Standard Deviation),然后判断当前时间段是否显著偏离其近期基线。

WITH buckets AS (

  SELECT

    toStartOfInterval(

      Timestamp,

      INTERVAL {intervalSeconds:Int64} second

    ) AS ts,

    countIf(StatusCode = 'Error') AS error_count

  FROM $__sourceTable

  WHERE Timestamp >= fromUnixTimestamp64Milli({startDateMilliseconds:Int64})

        - toIntervalSecond({intervalSeconds:Int64} * 30)

    AND Timestamp < fromUnixTimestamp64Milli({endDateMilliseconds:Int64})

    AND SpanKind = 'Server'

    AND $__filters

  GROUP BY ts

  ORDER BY ts

),

baselines AS (

  SELECT

    ts,

    error_count,

    avg(error_count) OVER (

      ORDER BY ts

      ROWS BETWEEN 30 PRECEDING AND 1 PRECEDING

    ) AS rolling_avg,

    stddevPop(error_count) OVER (

      ORDER BY ts

      ROWS BETWEEN 30 PRECEDING AND 1 PRECEDING

    ) AS rolling_stddev

  FROM buckets

)

SELECT

  ts,

  if(

    error_count > rolling_avg + (2 * rolling_stddev),

    1,

  ) AS anomaly_detected

FROM baselines

WHERE rolling_avg IS NOT NULL

ORDER BY ts ASC

此查询首先将失败请求按时间间隔聚合,并统计每个时间段的总错误数。接着,它使用 ClickHouse 窗口函数 (Window Functions) 计算前 30 个间隔的滚动平均值和标准差。最后,查询将当前错误数与该滚动基线进行比较,如果当前时间段的错误数超过滚动平均值两个标准差以上,则返回 1;否则返回 0。

在此,SQL 查询本身就将告警逻辑完全封装其中。无需可视化原始错误数并在外部配置固定阈值,查询本身就能判断当前时间段是否相对于近期历史呈现出统计学上的显著异常。

这样一来,告警配置本身变得极其简单。如果查询返回 1,告警就会触发。

这种方法开辟了更广泛的告警策略,因为其复杂性内化于 SQL 之中,而非受限于既有的告警配置模型。

threshold_alerting.png

基于查询结果的告警

基于 SQL 的告警通过检查 SQL 查询返回的结果,并根据预设阈值评估特定值来触发。对于线形图和堆叠柱状图等时间序列可视化,ClickStack 将返回的时间戳列识别为评估区间,并独立评估查询为每个区间返回的最终数值列。任何非数值列都被视为分组维度,从而允许告警针对每个服务、环境或其他分组键独立触发。有关告警触发的完整规则,请参阅我们的文档(https://clickhouse.com/docs/use-cases/observability/clickstack/alerts#sql-result-interpretation)。

与基于 SQL 的可视化功能类似,SQL 告警查询完全支持查询参数和宏。这使得告警能够保持动态,并自动适应仪表盘的时间范围、评估间隔和过滤器设置。在大多数情况下,查询应同时包含间隔宏和时间范围过滤器,以确保告警评估限定在配置的执行窗口内,避免在每次告警运行时扫描整个数据集。

Image
结论

基于 SQL 的告警是 SQL 驱动图表功能的自然演进。一旦用户能够在可视化中表达任意分析逻辑,将这些相同能力扩展到告警领域便成为水到渠成的下一步。

/END/

试用阿里云 ClickHouse企业版

轻松节省30%云资源成本?阿里云数据库ClickHouse 云原生架构全新升级,首次购买ClickHouse企业版计算和存储资源组合,首月消费不超过99.58元(包含最大16CCU+450G OSS用量)了解详情:https://t.aliyun.com/Kz5Z0q9G

图片
图片

征稿启示

面向社区长期正文,文章内容包括但不限于关于 ClickHouse 的技术研究、项目实践和创新做法等。建议行文风格干货输出&图文并茂。质量合格的文章将会发布在本公众号,优秀者也有机会推荐到 ClickHouse 官网。请将文章稿件的 WORD 版本发邮件至:[email protected]

图片图片