@Greptime:**可观测性现在有了版本号**。大多数团队还在使用 1.0 而不自知……

X AI KOLs Following 产品

摘要

本帖子解释了可观测性 2.0,即从预聚合指标转向存储包含所有字段的宽事件,从而在读取时支持即席查询。它强调了 AI 智能体可观测性的紧迫性,以及 GreptimeDB 如何支持这一模型。

**可观测性现在有了版本号**。大多数团队还在使用 1.0 而不自知。 三支柱模型是有效的。但它是围绕一个已不再存在的约束设计的:存储昂贵,所以你必须在写入之前对所有内容进行预聚合。 写入时的赌注就是问题所在。 当你为一个服务添加可观测性时,你要事先决定指标携带哪些维度。像 build_id、region、payment_provider 这样的高基数维度通常会被排除,因为它们会爆炸式增长基数。日志保留文本但放弃 schema。链路追踪经常被采样。每个支柱都丢弃了一些东西,当你需要时再也拿不回来。 **可观测性 2.0 颠覆了这一点**。 每个请求或 span 对应一个宽事件,保留所有字段。指标、链路视图和日志视图成为对同一原始数据的不同查询,在读取时派生。你可以在事故发生后按 build_id 进行 GROUP BY,而不仅仅是在之前。 这个想法并不新鲜。Meta 的 Scuba 在 2013 年就已经做到了。变化在于,对象存储上的列式存储使其变得负担得起。数月的高基数原始事件,而存储账单不会毁掉项目。 **AI 智能体正是升级变得紧迫的地方。** 单个智能体步骤包含模型名称、令牌、完整提示、工具调用参数、推理过程、内存状态。每个事件有 50 到 200 个字段。问题不再是“它是否正常运行”,而是“答案准确吗”、“它是否产生幻觉”、“为什么选择那个工具”。只有保留原始事件才能回答这些问题。Honeycomb 的数据:成熟的可观测性数据集运行超过 **100 个维度**。预聚合无法覆盖这些。 我们在构建 GreptimeDB 的过程中一直在权衡这些取舍。三篇文章涵盖了完整的推理过程: 1. 宽事件详解:可观测性 2.0 背后的数据模型:https://greptime.com/tech-content/2026-06-10-wide-events-observability-2-0… 2. 智能体可观测性:https://greptime.com/blogs/2025-12-11-agent-observability#why-o11y-1-0-struggles-with-agent-data… 3. 面向可观测性 2.0 的数据库:https://greptime.com/blogs/2025-04-25-greptimedb-observability2-new-database…
查看原文
查看缓存全文

缓存时间: 2026/07/02 14:24

可观测性现在有了版本号。大多数团队还在用1.0,而且自己没意识到。

三支柱模型管用。但它是围绕一个已经不复存在的限制设计的:存储很贵,所以你在写入数据之前就先聚合好一切。

这个“写入时预聚合“的选择就是问题的根源。

当你给一个服务做监控埋点时,你得事先决定你的指标携带哪些维度。像build_id、region、payment_provider这些高基数字段通常会被排除,因为它们会让基数爆炸。日志保留了文本但丢掉了结构。追踪链路通常会被采样。每个支柱都丢弃了一些东西,等你需要的时候再也找不回来了。

Observability 2.0把这个逻辑翻转了。 每个请求或span对应一个宽事件,每一个字段都保留。指标、trace视图和日志视图变成了针对同一份原始数据的不同查询,在读取时动态衍生出来。你可以在事故发生后按build_id做GROUP BY,不只是事前。 这个想法并不新鲜。Meta的Scuba在2013年就这么做了。变化在于,对象存储上的列式存储让它变得负担得起。存储几个月的原始高基数事件,不会再导致项目预算被存储成本压垮。

AI代理让升级变得迫在眉睫。 一个代理步骤携带模型名称、token数、完整提示词、工具调用参数、推理过程和内存状态。每个事件50到200个字段。问题不再是“服务是否在线“——而是“答案是否准确“、“是否产生了幻觉”、“为什么选择了那个工具”。只有保留原始事件才能回答这些问题。Honeycomb的数据显示:成熟的可观测数据集通常有100多个维度。预聚合无法覆盖这种场景。

我们在构建GreptimeDB的过程中一直在权衡这些取舍。以下三篇文章包含了完整的推理过程:

  1. 宽事件详解:Observability 2.0背后的数据模型:https://greptime.com/tech-content/2026-06-10-wide-events-observability-2-0…
  2. 代理可观测性:https://greptime.com/blogs/2025-12-11-agent-observability#why-o11y-1-0-struggles-with-agent-data…
  3. 面向Observability 2.0的数据库:https://greptime.com/blogs/2025-04-25-greptimedb-observability2-new-database…

宽事件详解:Observability 2.0背后的数据模型

来源:https://greptime.com/tech-content/2026-06-10-wide-events-observability-2-0

引言 (https://greptime.com/tech-content/2026-06-10-wide-events-observability-2-0#introduction)

大多数监控方案让你不得不猜测。当你对服务进行埋点时,你得事先决定要发出哪些指标、它们携带哪些标签、日志行包含哪些字段。这些决定发生在写入时。但真正需要回答的问题往往出现在读取时,通常是凌晨2点,而且几乎都不是你之前预料到的。“为什么结账请求变慢了,而且只影响使用新版移动端、在一个特定区域、使用某个特定支付提供商的用户?“如果build_idregionpayment_provider没有包含在指标标签中,这个问题就无法回答。用来回答问题的数据在存储之前就已经被丢弃了。

这种“写入时预决策“与“读取时真问题“之间的差距,就是“Observability 2.0“试图弥合的,而宽事件就是让这一切运作的数据模型。

宽事件的本质是什么 (https://greptime.com/tech-content/2026-06-10-wide-events-observability-2-0#what-a-wide-event-actually-is)

一个宽事件就是每个工作单元对应的一条结构化记录,携带你能附加到它上面的尽可能多的上下文。对于Web服务来说,工作单元通常是一个单独的请求。服务不是在请求结束时递增几个计数器并写几条日志行,而是发出一个事件,包含所有可能重要的字段:

{
  "timestamp": "2026-06-10T14:22:03.221Z",
  "service": "checkout",
  "endpoint": "POST /api/checkout",
  "status_code": 500,
  "duration_ms": 1840,
  "user_id": "u_8821",
  "region": "ap-southeast-1",
  "build_id": "2026.6.2-rc1",
  "payment_provider": "stripe",
  "db_query_ms": 1620,
  "cache_hit": false,
  "feature_flags": ["new_checkout_ui", "async_receipts"],
  "trace_id": "a1b2c3...",
  "error": "payment gateway timeout"
}

这就是一行数据。一个繁忙的端点会产生数百万行这样的数据。每一行都是一个关于真实发生的事件的事实,其维度被完整保留,而不是被平均掉。

相比之下,看看三支柱模型。像http_requests_total{status="500"}这样的指标告诉你500错误增加了,但它无法告诉你这些错误是否集中在某个构建版本上,因为把build_iduser_id作为标签添加会使得基数爆炸并增加成本。纯文本的日志行包含上下文但没有结构,所以你只能用grep去搜索并碰运气。Trace有结构但通常会被采样,所以你在意的那一个请求很可能已经被丢弃了。宽事件以可查询的形式保留了结构和上下文。

一个包含所有列的结账请求事件表。通过GROUP BY endpoint, status将其投射为指标时,只保留了这两个低基数列,丢弃了其余部分。该指标统计了3个500错误,但无法按build_id、region或payment_provider分组,因为这些列在写入时就已经被丢弃了。图1:一个指标就是这张表在写入时删除了大部分列。它可以统计500错误的数量,但无法解释原因,因为GROUP BY build_id需要指标从未保存过的列。## 这个想法从何而来 (https://greptime.com/tech-content/2026-06-10-wide-events-observability-2-0#where-the-idea-came-from)

这并非新鲜事。Meta在2013年左右构建了一个名为Scuba的内部系统,目的正是这个:摄入原始的宽事件,然后在查询时沿着任意维度切片,速度快到足以进行交互式探索。Scuba论文描述了一个每秒摄入数百万事件的数据库,专门为了让工程师在事故期间可以提出未经计划的问题。Stripe后来写了关于“规范日志行“(canonical log lines)的文章,即每个请求只发出一行丰富、结构化的摘要行,而不是将上下文分散到多行中。Honeycomb将该方法推广到更广泛的行业,并多年来一直论证这才是真正的调试所需。

这个模式不断被重新发明,因为它解决了一个聚合无法解决的问题:你只能按你仍然拥有的维度进行分组。

Observability 2.0意味着什么 (https://greptime.com/tech-content/2026-06-10-wide-events-observability-2-0#what-observability-2-0-means)

核心主张是关于数据源头的。Honeycomb的联合创始人Charity Majors在一篇题为《是时候给可观测性定版本了》的文章中提出了“1.0与2.0“的标签,这个区别比通常的“收集更多遥测数据“的提法更鲜明。

在1.0模型中,你维护三个独立的存储:指标系统、日志系统和追踪系统。每个都有自己的存储、自己的查询语言,以及一份重叠信息副本。要调查一个事故,你在这三者之间跳转,手动拼接故事。更糟的是,每个存储已经在写入时丢弃了一些东西:指标预聚合了高基数字段,trace采样了大部分请求,日志保留了文本但丢弃了结构。

在2.0模型中,只有一个数据源:宽事件。指标、trace和日志风格的视图都是在查询时从这些事件中衍生出来的,而不是作为独立的原始存储。请求速率是按时间分组的事件COUNT。延迟热力图是duration_ms字段的分布。trace是共享相同trace_id的事件集合。因为原始维度依然存在,你可以在事故发生后按build_id分组,而不仅仅是事前。你可以提出你未曾预料到的问题,这正是可观测性相对于监控的意义所在。

只有一个事件表被存储。指标是一个带有时间桶上的count的SELECT,trace是一个按共享trace_id过滤的SELECT,日志视图是按谓词过滤的SELECT。所有这些都是从同一事件在查询时衍生出来的。图2:在Observability 2.0中,事件表是唯一存储的东西。指标、trace和日志只是同一事件表上的不同SELECT查询,在查询时衍生,而不是写入三个独立的存储。## 为什么现在发生 (https://greptime.com/tech-content/2026-06-10-wide-events-observability-2-0#why-this-is-happening-now)

如果宽事件对于调试明显更好,为什么行业最开始要把所有东西预聚合到指标中呢?成本。

高基数数据的存储和查询都很昂贵。一个以user_id为键的指标数据库会崩溃,因为每个唯一值都会创建新的时间序列。因此,十年的标准建议是保持标签低基数,丢弃有趣的维度。三支柱模型在某种程度上是对无法经济地处理宽型高基数数据的存储的一种变通方案。

两件事改变了这一点。列式存储处理具有许多稀疏字段的宽行的能力远优于指标系统所基于的行式或序列式引擎,因为查询只读取它触及的列,并且对重复度高的字段的列式压缩效果非常好。对象存储使得字节本身变得便宜,因此保留数月的原始事件不再是预算问题。我们自己的针对Loki和Elasticsearch的日志基准测试展示了列式引擎在对象存储上对大规模可观测性数据造成的开销。Observability 2.0与其说是一个新想法,不如说是一个最终变得负担得起的旧想法。

这便将整个问题重新定义为数据库问题。“存储宽事件,从中衍生出指标、trace和日志“是一个关于查询引擎的陈述,而不是关于仪表盘的。你需要一个能够摄入高基数结构化数据、在对象存储上压缩它、并同时回答分析性问题(“按构建和区域分组过去一周的所有结账错误”)和时间序列问题(“每分钟P99延迟”)的存储,而不用被迫再次使用两个系统。

为什么AI代理让这变得紧迫 (https://greptime.com/tech-content/2026-06-10-wide-events-observability-2-0#why-ai-agents-make-this-urgent)

当前宽事件最清晰的用例是AI代理。代理应用正是发出这种形状的数据:一次执行步骤携带模型名称、token数、延迟、完整的提示词和响应、带有动态参数的工具调用列表、决策背后的推理过程以及它读取的内存状态。每个事件有几十到几百个字段,其中很多是半结构化的,每行都有session_idtrace_id这样的高基数键。

三支柱模型处理起来很糟糕。将提示词和工具输出塞进日志中,你就丢失了查询它们所需的结构。将动态工具调用schema强塞进trace中,又太死板难以兼容。将token使用量预聚合到指标中,你就无法再将延迟峰值追溯到导致它的具体提示词。而团队对代理提出的问题不是“服务是否在线“或“速度有多快“,而是“答案是否正确,工具选择是否合理,是否产生了幻觉“。这些是语义质量的问题,你只能通过保留原始事件并在事后从中衍生新维度来回答。Honeycomb指出,成熟的可观测数据集通常会携带数百个维度,这正是指标预聚合无法覆盖的。

这让宽事件从“更好“变成了“近乎必须“,数据库厂商已经注意到了:ClickHouse围绕宽事件模型构建了ClickStack,统一的可观测性数据库也正朝着同样的方向发展。我们将在《代理可观测性:旧剧本能应对新游戏吗?》中详细讨论代理场景。

宽事件存储在哪 (https://greptime.com/tech-content/2026-06-10-wide-events-observability-2-0#where-wide-events-get-stored)

如今团队有几种不同的方式来做这件事。

Honeycomb仍然是该模型作为托管产品的最清晰体现,其查询接口围绕按维度探索事件构建。许多团队在列式分析数据库上构建自己的版本,最常见的是ClickHouse,自己搭建摄入和查询层。还有一些数据库直接针对这种统一形态。

GreptimeDB是一个例子:一个开源数据库,在对象存储上的单一引擎中存储指标、日志和trace,并允许你使用SQL进行分析性切片、使用PromQL查询人们已有的仪表板的时间序列视图,来查询同一份数据。它用Rust构建,计算与存储分离,这正是该模型所需的形态,并直接围绕Observability 2.0和宽事件来设计自己的架构。CrateDB从搜索和分析的起点出发追求同一个统一目标,而InfluxDB的列式3.0方向也是朝它迈进。

重点不在于选择哪个产品。关键在于,存储层是“Observability 2.0“中真正缺失的部分,而它现在已经足够完善,可以在此基础上构建了。

什么时候宽事件不是答案 (https://greptime.com/tech-content/2026-06-10-wide-events-observability-2-0#when-wide-events-are-not-the-answer)

有必要坦诚地谈谈限制,因为这个模型确实有真实的代价。

宽事件无法替代高容量的基础设施指标。如果你要从一万个容器中采集CPU和内存,计数器是正确的工具,而每个样本发出一个宽事件则是浪费。当你已经知道问题且基数较低时,指标是一种很好且廉价的聚合。

宽事件也将工作转移到了你的埋点上。这个模型的好坏取决于你附加的字段,而将build_idfeature_flags和正确的业务维度附加到每个事件上需要在整个代码库中刻意努力。OpenTelemetry span属性有所帮助,因为span已经是一个带有挂载上下文位置的结构化事件,但团队仍然需要决定哪些上下文是重要的。

存储虽然更便宜了,但并不是免费的。以全保真度保留每一行原始事件一年时间,在对象存储上比以前负担得起了,但并非零成本,非常高吞吐量的系统仍然需要采样策略。优势在于,你现在可以有意识地做出这种权衡,而不是被迫接受一个根本无法容纳数据的指标后端。

简短总结 (https://greptime.com/tech-content/2026-06-10-wide-events-observability-2-0#the-short-version)

Observability 1.0要求你在出问题之前就决定你想知道什么,并悄悄丢弃掉其余部分。宽事件以结构化的、可查询的形式保留每个工作单元的完整上下文,而Observability 2.0在读取时从这个单一数据源中衍生出指标、trace和日志。这个想法已有十年历史;变化的是,对象存储上的列式引擎让它变得足够便宜,以至于可以成为默认选择,而不是奢侈品。如果你曾在凌晨2点因为某个你没想到要添加为标签的维度而受阻,你就已经理解为什么团队正在切换了。

关于Greptime (https://greptime.com/tech-content/2026-06-10-wide-events-observability-2-0#about-greptime)

GreptimeDB 是一款开源的、云原生的数据库,专为实时可观测性而设计。它使用 Rust 构建,针对云原生环境进行了优化,为指标、日志和追踪提供统一的存储与处理能力,提

相似文章

@Greptime: GreptimeDB v1.1.2 已发布 — 这是一个值得升级的 v1.1 补丁。主要修复:定时 Flows 现在绑定 now()/current_timest…

X AI KOLs Following

GreptimeDB v1.1.2 是一个补丁版本,修复了定时 Flows 中 now() 的绑定问题,以确保 EVAL INTERVAL 窗口的确定性。此外还修复了以下问题:Kafka SASL 密码在调试输出中的屏蔽、GC 索引文件列表、parquet 元数据缓存大小、Prometheus 标签发现扫描以及 PromQL 时间二元聚合。建议用户升级。