您第一次真正需要可观察性并不是当您平静地查看仪表板时。当用户写下“结帐速度很慢”时,错误图看起来很正常,并且在日志中您只能找到一行断开连接的消息。
OpenTelemetry 的创建就是为了避免这一时刻:不是为了拥有更多图形,而是为了将各个部分连接起来。请求进入API,调用数据库,通过外部提供程序,发布排队作业,并且可能会在三个服务之后失败。如果没有分布式跟踪,您就需要手动重建该故事。有了 OpenTelemetry 至少你就有了一张地图。
重点不是trace,而是故事
trace 是span 的序列。这么说听起来就冷了。实际上,每个span都是故事的一部分:POST /checkout、SELECT inventory、call payment provider、publish order.created。
当你开始回答真正的问题时,价值就来了:
- 哪个外部服务速度变慢?
- 错误是否来自特定版本?
- 该问题是否影响所有人还是仅影响一名租户?
- 重试是否隐藏超时?
- 异步作业启动但随后在其他地方终止?
这些问题并不是一个仓促抛出的console.log就能解决的。事实上,通常在紧急情况下添加的日志今天对您有帮助,明天就会变成噪音。
我如何将其放入应用程序中Node.js
最健康的设置很简单:应用程序生成遥测数据,Collector 决定将其发送到哪里。
Node.js app -> OpenTelemetry Collector -> backend di observability
为什么不直接向供应商出口?因为一开始它看起来更快,然后您意识到每个服务都有不同的配置、不同的重试、不同的过滤器,并且没有删除敏感数据或更改目标的中心点。
从各方面来说,Collector都很无聊。它接收OTLP,进行批处理,可以过滤,可以进行采样,可以添加公共属性并且可以导出到多个系统。
自我检测:很好,但还不够
在 Node.js 中,我将从自动检测开始。它使您可以立即了解 HTTP、支持的框架、数据库和公共库。
npm install @opentelemetry/sdk-node \ @opentelemetry/auto-instrumentations-node \ @opentelemetry/exporter-trace-otlp-http
然后在应用程序的其余部分之前初始化 SDK:
import { NodeSDK } from '@opentelemetry/sdk-node'; import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http'; import { getNodeAutoInstrumentations } from '@opentelemetry/auto-instrumentations-node'; const sdk = new NodeSDK({ traceExporter: new OTLPTraceExporter({ url: process.env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT, }), instrumentations: [getNodeAutoInstrumentations()], }); sdk.start();
然而,这看到的是框架,而不是你的产品。它知道您进行了查询,但不知道该查询位于“创建订单”或“续订订阅”中。为此,在需要占据主导地位的地方,您需要span手册。
const span = tracer.startSpan('checkout.create_order'); try { span.setAttribute('cart.items_count', input.items.length); const order = await createOrder(input); span.setAttribute('order.id', order.id); return order; } catch (error) { span.recordException(error as Error); throw error; } finally { span.end(); }
我不会把 span 手册放在任何地方。我会把它们放在凌晨三点的地方,我想在不阅读一半代码库的情况下了解发生了什么。
避免大量混乱的三个规则
第一条规则:每个服务必须有service.name、环境和版本。这看起来微不足道,但如果没有这些属性,trace就没那么有用了。当部署破坏某些内容时,您希望在两秒钟内按版本进行过滤。
第二条规则:不要将敏感数据放入属性中。电子邮件、令牌、整数有效负载和地址不应意外地出现在可观察性后端中。如果您需要识别用户,请考虑内部 ID、哈希或不太敏感的字段。
第三条规则:注意基数。 user.id 作为 trace 的属性是有意义的。作为度量标签,它可能会破坏您的成本和性能。
指标:很少,但很好
我将从非常实用的指标开始:
- 请求的比率、错误和持续时间;
- 外部依赖的延迟;
- 超时和重试次数;
- 尾部深度;
- 工作期限;
- 每个版本的错误百分比。
其余的在需要时添加。充满无人看的图表的仪表板只是家具,而不是可观察性。
日志:仍然有用,但已链接
日志不会消失。当它们携带 trace_id 和 span_id 时,它们就会变得更加有用。因此,您可以从错误日志开始并打开trace,或者从缓慢的trace开始并仅读取该路径中生成的日志。
没有相关性,你就是在寻找针。有了相关性,至少你知道该看哪个抽屉。
在说“我们已得到保障”之前我会使用的清单
- trace实际上跨多个服务。
- 日志包括
trace_id和span_id。 - Collector 配置了批处理和内存限制。
- 错误记录在span中。
- 有抽样政策。
- 指标控制了基数。
- 敏感数据被过滤。
- 警报从用户症状开始,而不是随机图表。
结论
OpenTelemetry本身并不能解决生产问题。但你对待他们的方式会改变。您不再盲目地添加日志,而是开始跟踪请求的实际路径。
对我来说,它起作用的迹象很简单:当事情发生时,团队不再问“我们在看哪里?”并开始问“为什么那首曲子很慢?”。这就是可观察性成为一种工具,而不是仪表板集合的地方。