第25章 OpenTelemetry 追踪集成
Open Telemetry 支持(实验性) 【反馈】请在 GitHub Discussion 中对该功能留下反馈。示例项目GitHub OpenTelemetry 追踪(traces)可以成为调试应用程序在测试中性能和行为的有用工具。如果启用,Vitest 集成会生成作用域限定于测试 worker 的 span。 警告:启用 OpenTelemetry 初始化会增加每个测试的启动时间,除非 Vitest 在无隔离模式下运行。你可以将这部分开销视为 `vitest.runtime.traces` span 包含在 `vitest.worker.start` 中。
要在 Vitest 中开始使用 OpenTelemetry,请通过 `experimental.openTelemetry.sdkPath` 指定 SDK 模块路径,并将 `experimental.openTelemetry.enabled` 设置为 `true`。Vitest 将自动对整个过程及每个独立的测试 worker 进行插桩。 请确保将 SDK 导出为默认导出(default export),以便 Vitest 能够在进程关闭前刷新网络请求。注意,Vitest 不会自动调用 `start`。
快速入门 在预览应用程序的追踪之前,请安装所需的包,并在配置文件中指定插桩文件的路径。
shell npm i @opentelemetry/sdk-node @opentelemetry/auto-instrumentations-node @opentelemetry/exporter-trace-otlp-proto
`otel.js` ```javascript import { getNodeAutoInstrumentations } from '@opentelemetry/auto-instrumentations-node' import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-proto' import { NodeSDK } from '@opentelemetry/sdk-node'
const sdk = new NodeSDK({ serviceName: 'vitest', traceExporter: new OTLPTraceExporter(), instrumentations: [getNodeAutoInstrumentations()], })
sdk.start() export default sdk ```
`vitest.config.js` ```javascript import { defineConfig } from 'vitest/config'
export default defineConfig({ test: { experimental: { openTelemetry: { enabled: true, sdkPath: './otel.js', }, }, }, }) ```
FAKE TIMERS 如果你正在使用 fake timers,务必在测试结束前重置它们,否则追踪可能无法正确记录。 Vitest 不处理 `sdkPath` 指向的模块,因此 SDK 必须能在你的 Node.js 环境中被导入。对于此文件,最好使用 `.js` 扩展名。使用其他扩展名会拖慢测试速度,并且可能需要提供额外的 Node.js 参数。 如果你想提供 TypeScript 文件,请务必熟悉 Node.js 文档中关于 TypeScript 的页面。
自定义追踪 你可以自行使用 OpenTelemetry API 来追踪代码中的特定操作。自定义追踪会自动继承 Vitest 的 OpenTelemetry 上下文:
```typescript import { trace } from '@opentelemetry/api' import { test } from 'vitest' import { db } from './src/db'
const tracer = trace.getTracer('vitest')
test('db connects properly', async () => { // 这在 `vitest.test.runner.test.callback` span 中显示 await tracer.startActiveSpan('db.connect', () => db.connect()) }) ```
Browser Mode 在浏览器模式下运行测试时,Vitest 会在 Node.js 和浏览器之间传播追踪上下文。无需额外配置即可获取 Node.js 端的追踪(测试编排、浏览器驱动程序通信)。 要捕获浏览器运行时中的追踪,请通过 `browserSdkPath` 提供浏览器兼容的 SDK:
shell npm i @opentelemetry/sdk-trace-web @opentelemetry/exporter-trace-otlp-proto
`otel-browser.js` ```javascript import { BatchSpanProcessor, WebTracerProvider, } from '@opentelemetry/sdk-trace-web' import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-proto'
const provider = new WebTracerProvider({ spanProcessors: [ new BatchSpanProcessor(new OTLPTraceExporter()), ], })
provider.register() export default provider ```
`vitest.config.js` ```javascript import { defineConfig } from 'vitest/config'
export default defineConfig({ test: { browser: { enabled: true, provider: 'playwright', instances: [{ browser: 'chromium' }], }, experimental: { openTelemetry: { enabled: true, sdkPath: './otel.js', browserSdkPath: './otel-browser.js', }, }, }, }) ```
ASYNC CONTEXT 与 Node.js 不同,浏览器没有自动的异步上下文传播。Vitest 内部处理测试执行时的上下文传播,但深嵌套异步代码中的自定义 span 可能不会自动传播上下文。
查看追踪 要生成追踪,像往常一样运行 Vitest 即可。你可以以 watch 模式或 run 模式运行 Vitest。Vitest 会在所有操作完成后手动调用 `sdk.shutdown()`,以确保追踪被正确处理。 你可以使用任何支持 OpenTelemetry API 的开源或商业产品来查看追踪。如果你之前没有使用过 OpenTelemetry,建议从 Jaeger 开始,因为它非常容易设置。
@opentelemetry/api Vitest 声明 `@opentelemetry/api` 为可选的 peer dependency,并内部使用它来生成 span。当未启用追踪收集时,Vitest 不会尝试使用该依赖项。 在配置 Vitest 使用 OpenTelemetry 时,你通常会安装 `@opentelemetry/sdk-node`,它包含 `@opentelemetry/api` 作为传递依赖,从而满足 Vitest 的 peer dependency 要求。如果遇到表明找不到 `@opentelemetry/api` 的错误,这通常意味着未启用追踪收集。如果在正确配置后错误仍然存在,你可能需要显式安装 `@opentelemetry/api`。
跨进程上下文传播 Vitest 支持通过 OpenTelemetry 规范中定义的 `TRACEPARENT` 和 `TRACESTATE` 环境变量,从父进程自动传播上下文。这在将 Vitest 作为更大的分布式追踪系统(例如带有 OpenTelemetry 插桩的 CI/CD 流水线)的一部分运行时特别有用。