Encore 分布式追踪(Distributed Tracing)实战指南:全环境自动采集、敏感数据脱敏与采样/预算控制
【免费下载链接】encoreThe infrastructure platform for the intelligence era项目地址: https://gitcode.com/GitHub_Trending/encor/encore
分布式系统组件繁多、链路复杂,定位一个 Bug 往往需要跨服务串联排查。本指南围绕 Encore 平台的分布式追踪能力展开:讲解 Encore 如何自动为你的整个应用(含本地开发环境)捕获端到端 Trace、如何对敏感字段进行脱敏、如何通过 Trace Sampling 与 Trace Budgets 精确控制追踪成本,并结合仓库源码揭示其背后的实现机制。读完你将掌握 Encore 追踪的完整使用与调优方案。
什么是 Encore 的分布式追踪
分布式系统往往由大量独立组件构成,仅凭日志很难理解代码到底做了什么、问题根因出在哪里。分布式追踪(Distributed Tracing)通过捕获代码执行期间发生的一系列事件(即一条 "trace"),在所有参与的系统之间传播 trace id,再把各系统记录的信息关联、拼接起来,最终呈现一次请求端到端的完整统一视图。
传统上,接入追踪意味着大量手工埋点与复杂的前置工作。而 Encore 的核心卖点是自动捕获:Encore 会为你的整个应用自动记录追踪数据,覆盖所有环境。独一无二地,这意味着你在本地开发阶段就能使用追踪来调试问题、加速迭代,而无需任何额外配置。
你可以通过以下两个入口查看 Trace:
- Local Development Dashboard:本地开发时内置的追踪视图(详见 本地开发仪表盘文档);
- Encore Cloud 仪表盘:用于 Production 及其他云端环境。
在本地,只需运行encore run,仪表盘会自动打开,也可通过终端输出的链接访问(见 dev-dash.md):
$ encore run API Base URL: http://localhost:4000 Dev Dashboard URL: http://localhost:9400/hello-world-cgu2为什么 Encore 的追踪比其他工具更全面、更高效
不同于大多数"黑盒"式追踪方案,Encore 理解每一条 trace 事件的具体语义,并为每种事件捕获独有洞察。这意味着你能获取比以往更多的信息,包括但不限于:
- Stack traces(堆栈信息):定位异常抛出的确切代码位置;
- Structured logging(结构化日志):与请求关联的日志消息及字段;
- HTTP requests(HTTP 请求):方法、URL、请求头、响应头;
- Network connection information(网络连接信息):DNS 解析、连接建立、TLS 握手、连接复用等细节;
- API calls(API 调用):服务到服务的 RPC 调用;
- Database queries(数据库查询):SQL 文本、事务提交/回滚;
- 以及其他更多事件类型。
从源码看:一条 Trace 到底记录了什么
仓库的 cli/daemon/engine/trace/trace.go 是本地追踪数据的解析器(parser),它完整展示了 Encore 追踪协议能够承载的事件类型。以parseEventV3的分派逻辑为例(trace.go 的 parseEventV3 函数),每条 trace 由以下事件组成:
RequestStart/RequestEnd:请求的开始与结束,记录 trace id、parent trace id、span id、服务名、端点名、绝对开始时间、路径参数、请求/响应载荷与错误栈;GoStart/GoEnd/GoClear:goroutine 的生命周期(goroutineStart);TxStart/TxEnd:数据库事务开始与结束,含 commit / rollback 完成状态(transactionStart);QueryStart/QueryEnd:数据库查询,记录 SQL 语句文本与耗时(queryStart);CallStart/CallEnd:服务间的 RPC 调用(callStart);HTTPCallStart/HTTPCallEnd/HTTPCallBodyClosed:出站 HTTP 调用;LogMessage:结构化日志消息及其字段(logMessage);ServiceInitStart/ServiceInitEnd:服务初始化;CacheOpStart/CacheOpEnd:缓存操作;BodyStream:请求/响应体流(bodyStream)。
值得留意的是,HTTP 调用的内部还细粒度记录了多种网络事件(httpEvent),包括GET_CONN/GOT_CONN(连接获取与复用,是否 reused、idle 时长)、DNS_START/DNS_DONE(DNS 解析出的地址列表)、CONNECT_START/CONNECT_DONE(网络类型与地址)、TLS_HANDSHAKE_START/TLS_HANDSHAKE_DONE(TLS 版本、密码套件、服务器名)、WROTE_HEADERS/WROTE_REQUEST等。这正是文档中"network connection information"的来源——你不需要在代码里做任何埋点,这些底层细节就会被自动捕获。
解析后的 Trace 会交给 cli/daemon/engine/trace/trace.go 中的 Store 统一存储:它按应用 ID 维护 trace 列表,并通过requestIDMapping(trace id → request)建立索引,GetRootTrace还能沿 parent trace id 一路回溯到整条链路的根请求(GetRootTrace 实现)。也就是说,"通过 trace id 把各系统的信息关联拼接成统一视图"在代码层面由这套索引机制保证。在较新的架构中,新版运行时事件流则交由 cli/daemon/engine/trace2/recorder.go 的RecordTrace处理:它从 bufio.Reader 中逐条解析事件并异步写入存储(事件通道缓冲为 100),保证追踪采集不影响请求本身的性能。Rust 侧运行时的事件缓冲实现位于 runtimes/core/src/trace/eventbuf.rs,协议与时间锚点定义见 runtimes/core/src/trace/protocol.rs 与 runtimes/core/src/trace/time_anchor.rs。
自动脱敏敏感数据(Sensitive Data Redaction)
Encore 的追踪会自动捕获请求与响应载荷以简化调试。但在某些场景下这并不合适——例如密码、个人身份信息(PII)等敏感数据。为此,Encore 支持对标记为包含敏感数据的字段进行自动脱敏。
如何标记敏感端点
将端点声明中的sensitive: true打开即可。以 TypeScript 为例(见 定义 API 文档的 Sensitive data 小节):
export const processPayment = api( { expose: true, method: "POST", path: "/payments", sensitive: true }, async (params: PaymentParams): Promise<PaymentResponse> => { return { /* ... */ }; } );当sensitive: true被设置后,Encore 会自动脱敏(redact)所有请求与响应载荷,并从 Trace 中排除 HTTP 请求头。
底层如何实现脱敏
从源码看,Go 运行时的脱敏逻辑位于 runtimes/go/appruntime/exported/scrub/,其测试用例 scrub_test.go 验证了脱敏行为的细节:
- 匹配到敏感路径的字段会被替换为
"[sensitive]"占位符(scrub_test.go 第 176 行); - 脱敏支持嵌套结构(对象内嵌对象、数组内嵌对象),递归地对整个 JSON 树进行扫描;
- 大小写匹配行为有专门用例覆盖(
case_sensitive_match与case_sensitive_mismatch,见 scrub_test.go 第 51-60 行),且顶层字段名的大小写并不影响脱敏判断(第 192 行用例展示"a"与"A"的字段值差异)。
也就是说,即使请求体中包含多层嵌套的敏感对象,Trace 中呈现的也是经过脱敏的"[sensitive]"占位值,不会泄露真实内容。
Trace Sampling(追踪采样):按环境、服务、端点精细控制
Trace Sampling 允许你控制有多少百分比的 Trace 会被记录与存储。你可以在每个环境、每个服务、每个端点三个粒度上分别配置采样率,从而对追踪量做细粒度控制。
采样是如何工作的
采样的判定发生在trace 的根部(root):
- 如果你把某个端点设为 10% 采样,那么当该端点作为请求的初始入口被调用时,才会以 10% 的概率决定是否创建一条新 trace;
- 如果同一个端点是被一个已在进行中的 trace调用(例如服务间的内部调用),那么无论它自己的采样率是多少,都总是被包含在既有 trace 中。
这一设计确保了所有 trace 都是完整的——你永远不会看到缺 span 的部分 trace。要么整条 trace 被完整采样,要么完全不采样。
如何配置采样率
采样率在 Encore Cloud 仪表盘中配置,支持三个层级:
| 粒度 | 作用 | 优先级 |
|---|---|---|
| Environment level(环境级) | 为环境中所有 trace 设置默认采样率 | 最低 |
| Service level(服务级) | 为特定服务覆盖环境默认值 | 中 |
| Endpoint level(端点级) | 为特定端点覆盖服务默认值 | 最高 |
越具体的设置优先级越高。例如:环境采样率设为 100%,但某个高流量端点设为 10%,那么该端点作为请求根时,只有 10% 的调用会生成新 trace。
从源码看:root trace 的判定
前文提到的 GetRootTrace 正是"采样判定发生在 root"的代码体现:本地 Store 通过requestIDMapping沿ParentTraceId链回溯,直到找到没有父 trace 的根请求。这意味着采样决策只针对根请求生效,而链路上的所有子请求(内部调用)都会继承根请求的采样结果,从实现上保证"要么整条 trace 完整采样,要么完全不采样"。
Trace Budgets(追踪预算):让追踪成本完全可预测
Trace Budgets 让你通过设置每日(daily)与每月(monthly)的支出上限,获得对追踪成本的完全可预测性。当预算达到上限时,追踪会暂停直到下一个计费周期开始,确保不会出现意外的账单。
各套餐包含的事件量
Encore Cloud 在每个套餐中都包含可观的追踪事件额度:
- Free tier(免费版):每月包含100 万(1M)个 trace events;
- Pro tier(专业版):每月包含2000 万(20M)个 trace events。
超出包含额度后,Pro tier 按每 100 万个事件 $1.20计费。
如何设置预算
在 Encore Cloud 仪表盘中配置 trace budgets:同时设置每日与每月的限额,即可精确定义你愿意为追踪支付的费用。通过"日限额兜底 + 月限额兜底"的双重机制,追踪成本变得完全可预测,账单上不会出现任何意外。
采样与预算如何配合使用
实际生产实践中,通常建议将两者组合使用:
- 先用Sampling从源头控制流量:高流量端点设较低的采样率(如 10%),关键但低频的端点保持 100%,按服务/端点差异化控制追踪体量;
- 再用Budgets兜底防失控:即便采样配置出现疏漏或流量突增,日/月预算也会在达到上限后暂停追踪,从成本侧保证绝不超支。
两者结合后,既能保证关键链路的可观测性,又能把追踪的开销限制在预算之内。
总结
Encore 的分布式追踪能力覆盖了从"自动采集"到"成本控制"的完整链路:
- 零埋点自动追踪:本地与云端所有环境自动捕获 trace,事件类型涵盖 RPC 调用、数据库查询/事务、HTTP 与网络细节、结构化日志、缓存操作等(见 cli/daemon/engine/trace/trace.go);
- 敏感数据脱敏:通过端点选项
sensitive: true一键脱敏请求/响应载荷并排除 HTTP 头,底层由 runtimes/go/appruntime/exported/scrub/ 实现; - 细粒度采样:环境 / 服务 / 端点三级采样率,采样在 trace 根部判定,保证 trace 完整性;
- 可预测成本:日/月双预算限制,达到上限自动暂停追踪,配合各套餐包含的免费事件额度与明确的超量单价,成本完全可控。
无论你是在本地用encore run启动应用后打开 Dev Dashboard 排查问题,还是在生产环境通过 Encore Cloud 仪表盘观测线上链路,这套自动化的追踪体系都能显著加速你定位和修复 Bug 的效率。
【免费下载链接】encoreThe infrastructure platform for the intelligence era项目地址: https://gitcode.com/GitHub_Trending/encor/encore
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考