NocoBase 服务端 Telemetry 遥测开发指南:基于 OpenTelemetry 的指标采集与链路追踪
2026/9/17 6:24:11 网站建设 项目流程

NocoBase 服务端 Telemetry 遥测开发指南:基于 OpenTelemetry 的指标采集与链路追踪

【免费下载链接】nocobaseNocoBase is an open-source AI + no-code platform for building business systems fast. Instead of generating everything from scratch, AI works on top of production-proven infrastructure and a WYSIWYG no-code interface, so you get both speed and reliability.项目地址: https://gitcode.com/GitHub_Trending/no/nocobase

NocoBase 的遥测(Telemetry)模块基于 OpenTelemetry 封装,为插件开发者提供了一套统一、可插拔的可观测性 API,用于收集监控指标(Metric)和链路追踪(Trace)数据。本文将围绕 docs/docs/cn/plugin-development/server/telemetry.md 展开,结合 packages/core/telemetry 的源码实现,讲解如何在插件中完成指标插桩、链路插桩、插桩工具库注册,以及如何对接采集器(MetricReader / SpanProcessor),帮助你为 NocoBase 服务端构建完整的可观测性方案。

注意:该功能目前为实验性功能,API 与行为可能随版本演进调整。

Telemetry 模块架构概览

NocoBase 的遥测模块独立存在于 packages/core/telemetry/src/index.ts,对外导出TelemetryMetricTrace三个核心类,并透传 OpenTelemetry 生态的类型与工具(如PeriodicExportingMetricReaderMeter)。三者职责分明:

职责对应 OpenTelemetry 概念
Telemetry顶层入口,持有tracemetric两个子模块,负责插桩库注册与全局资源(Resource)构建InstrumentationResource
Trace管理NodeTracerProviderSpanProcessor注册,提供getTracer()TracerSpanProcessor
Metric管理MeterProviderMetricReader注册,提供getMeter()MeterMetricReader

在 packages/core/server/src/application.ts#L1300-L1304 中,Application构造时会创建Telemetry实例,并自动注入appName(应用名)与version(当前 NocoBase 版本号),之后暴露为app.telemetry。也就是说,在插件中可以通过app.telemetry直接访问metrictrace两个子模块。

遥测模块的生命周期与Application紧密绑定(application.ts#L617-L618、application.ts#L711-L715):

  • app.beforeLoad阶段:telemetry.init()被调用,注册所有插桩库,构建 Service Resource;
  • app.beforeLoad之后:若配置telemetry.enabled为真,则调用telemetry.start()启动数据导出;
  • 应用关闭时:调用telemetry.shutdown()优雅停止所有 Processor 与 Reader。

从源码结构看(telemetry.ts),init()内部通过registerInstrumentations注册插桩库,并用resourceFromAttributes构建包含service.nameservice.versionapp.name三个属性的 Resource,随后依次初始化TraceMetric

指标(Metric)插桩

获取 Meter 并创建计数器

指标插桩的第一步是从app.telemetry.metric获取Meter,再通过Meter创建各类指标仪器(Counter、Histogram、UpDownCounter 等):

const meter = app.telemetry.metric.getMeter(); const counter = meter.createCounter('event_counter', {}); counter.add(1);
  • getMeter()的默认标识为nocobase-meter,版本为当前 NocoBase 版本(见 metric.ts);
  • createCounter('event_counter', {})创建一个名为event_counter的单调递增计数器,业务代码每次发生对应事件时调用counter.add(1)累加。

Metric 的底层实现细节

从 metric.ts 的源码可以看到几个关键行为:

  1. 默认 Reader 已内置Metric构造时自动注册了名为consolePeriodicExportingMetricReader,其 exporter 为ConsoleMetricExporter,并指定AggregationTemporality.DELTA(增量聚合)。也就是说,不做任何配置时指标会周期性打印到控制台;
  2. 环境变量过滤指标start()时会读取TELEMETRY_METRICS环境变量(逗号分隔的指标名列表),通过 OpenTelemetry 的 Metric View 机制,仅保留列表中出现的指标,其余全部用AggregationType.DROP丢弃(metric.ts#L75-L94)。该机制可用于在生产环境控制指标上报的开销;
  3. 多 Reader 支持readerName既可以是单个字符串,也可以是逗号分隔的多个名称,start()时会逐个实例化并挂载到MeterProvider(metric.ts#L96-L114)。

指标数据采集(导出到控制台)

采集器(Reader)决定指标最终流向何处。注册自定义 Reader 同样通过registerReader完成,下面示例将指标导出到控制台:

import { Plugin } from '@nocobase/server'; import { PeriodicExportingMetricReader, ConsoleMetricExporter, } from '@opentelemetry/sdk-metrics'; class MetricReaderPlugin extends Plugin { afterAdd() { this.app.on('beforeLoad', (app) => { app.telemetry.metric.registerReader( 'console', () => new PeriodicExportingMetricReader({ exporter: new ConsoleMetricExporter(), }), ); }); } }

要点说明:

  • registerReader(name, getReader)的第一个参数是 Reader 的唯一标识,第二个参数是返回MetricReader实例的工厂函数(见 metric.ts#L62-L64);
  • PeriodicExportingMetricReader会按固定时间间隔拉取指标并交给 exporter 导出;ConsoleMetricExporter将数据以 JSON 形式打印到标准输出,适合本地调试;
  • 若要切换实际生效的 Reader,可通过MetricOptions.readerName(例如应用配置中的TELEMETRY_METRIC_READER环境变量)指定,start()时会按名称从注册表中取出对应的工厂并实例化。未找到对应名称时会被安全跳过(continue)。

链路(Trace)插桩

获取 Tracer 并创建 Span

链路追踪用于记录一次请求或任务在分布式系统中的完整调用链。NocoBase 中通过app.telemetry.trace获取Tracer,然后开启 Span:

const tracer = app.telemetry.trace.getTracer(); tracer.startActiveSpan(); tracer.startSpan();
  • getTracer()默认返回名为nocobase-trace的 Tracer(见 trace.ts#L86-L91);
  • startActiveSpan()会创建 Span 并将其设为当前活动上下文(需配合回调使用),适合在一个函数/请求的作用域内追踪;startSpan()则仅创建 Span,不自动设置活动上下文,适合手动管理 span 生命周期与父子关系。

Trace 的底层实现细节

从 trace.ts 源码可知:

  1. 默认 Processor 已内置Trace构造时自动注册名为consoleBatchSpanProcessor,exporter 为ConsoleSpanExporter,Span 会批量导出到控制台;
  2. NodeTracerProvider 注册为全局start()中创建NodeTracerProvider并调用provider.register()(trace.ts#L82-L83),使整个 Node.js 进程(包括未显式获取 Tracer 的第三方库)都能接入同一链路上下文;
  3. 多 Processor 支持processorName支持逗号分隔的多个名称,start()时逐个实例化并传入NodeTracerConfig(trace.ts#L58-L80)。

链路数据采集(导出到控制台)

Span 的导出由SpanProcessor决定。注册自定义 Processor 的完整示例:

import { Plugin } from '@nocobase/server'; import { BatchSpanProcessor, ConsoleSpanExporter, } from '@opentelemetry/sdk-trace-base'; class TraceSpanProcessorPlugin extends Plugin { afterAdd() { this.app.on('beforeLoad', (app) => { app.telemetry.trace.registerProcessor( 'console', () => new BatchSpanProcessor(new ConsoleSpanExporter()), ); }); } }

要点说明:

  • registerProcessor(name, getProcessor)注册后,可通过TraceOptions.processorName(或环境变量TELEMETRY_TRACE_PROCESSOR)指定启用哪个 Processor(见 trace.ts#L45-L51);
  • BatchSpanProcessor会将 Span 缓存后批量发送,避免每条 Span 都产生一次 I/O;ConsoleSpanExporter则把 Span 打印到控制台,便于开发期观察链路结构;
  • 实际生产环境中,可在此处替换为 OTLP、Jaeger 等 exporter,并分别通过registerReader/registerProcessor以「注册 + 名称启用」的方式接入。

插桩工具库(Instrumentation)注册

OpenTelemetry 生态提供了大量自动化插桩库(如 HTTP、数据库客户端、消息队列等),NocoBase 通过app.telemetry.addInstrumentation()批量注册:

import { Plugin } from '@nocobase/server'; import { getNodeAutoInstrumentations } from '@opentelemetry/auto-instrumentations-node'; class InstrumentationPlugin extends Plugin { afterAdd() { this.app.on('beforeLoad', (app) => { app.telemetry.addInstrumentation(getNodeAutoInstrumentations()); }); } }
  • getNodeAutoInstrumentations()会返回一组 Node.js 常用插桩库的集合,一次性覆盖常见 I/O 场景;
  • addInstrumentation(...)在内部将这些插桩库推入Telemetry.instrumentations数组(见 telemetry.ts#L70-L72),并在init()时通过registerInstrumentations统一生效。

插桩库的适用边界(重要限制)

:::warning 注意

NocoBase 中遥测模块的初始化位置为app.beforeLoad,因此并不是所有插桩库都适用于 NocoBase。

比如 instrumentation-koa 需要在Koa实例化之前引入,而 NocoBase 的Application虽然基于Koa,但遥测模块是在Application实例化之后才初始化的,所以无法使用。

:::

这一限制的根源在于遥测模块的生命周期设计:Telemetry实例在Application构造函数中创建(application.ts#L1300-L1304),而插桩库的注册发生在beforeLoad钩子中。凡是在「模块加载期」就必须对目标库进行 monkey-patch 的插桩(典型的如 Koa、Express 等 Web 框架插桩),都因错过实例化时机而无法生效。因此,建议优先选择在运行时按调用点进行拦截的插桩库,并始终以目标插桩库的文档说明其初始化时机要求为准。

应用级配置与环境变量

在 packages/core/app/src/config/telemetry.ts 中,NocoBase 通过环境变量提供了一套开箱即用的遥测配置:

环境变量作用默认值 / 示例
TELEMETRY_ENABLED是否启用遥测数据导出,值为on时启用未设置时不启动导出
TELEMETRY_SERVICE_NAME遥测服务名(对应 Resource 的service.namenocobase
TELEMETRY_METRIC_READER指定启用的MetricReader名称(对应metric.readerNameconsole
TELEMETRY_TRACE_PROCESSOR指定启用的SpanProcessor名称(对应trace.processorNameconsole
TELEMETRY_METRICS逗号分隔的指标名白名单,仅这些指标会被收集空(收集全部)

对应的AppTelemetryOptions结构(见 application.ts 中telemetry配置类型):

export interface TelemetryOptions { serviceName?: string; // 服务名,默认 'nocobase' appName?: string; // 应用名,由 Application 自动注入 version?: string; // 版本号,由 Application 自动注入 trace?: TraceOptions; // tracerName / version / processorName metric?: MetricOptions; // meterName / version / readerName }

部署时可据此在启动脚本中组合使用,例如:

TELEMETRY_ENABLED=on \ TELEMETRY_SERVICE_NAME=nocobase-prod \ TELEMETRY_METRIC_READER=console \ TELEMETRY_TRACE_PROCESSOR=console \ TELEMETRY_METRICS=event_counter,http_request_duration \ yarn start

插件开发中的推荐实践

综合文档与源码,在 NocoBase 插件中接入遥测的推荐模式如下:

  1. afterAdd()中挂载beforeLoad监听:因为遥测模块在app.beforeLoad阶段初始化,插桩与采集器的注册都应放在this.app.on('beforeLoad', ...)回调中执行,确保注册先于init()
  2. 注册命名工厂而非实例registerReader/registerProcessor的第二个参数是工厂函数(每次启动时调用),这样同一个名称可以按启动配置动态创建不同实例;
  3. 用环境变量控制采集目标:通过TELEMETRY_METRIC_READERTELEMETRY_TRACE_PROCESSORTELEMETRY_METRICS实现「同一套代码、不同环境不同采集策略」,避免在代码中写死导出目标;
  4. 与 Logger 配合:遥测负责结构性数据(指标、链路),日志负责事件详情,二者结合才能构成完整的可观测性方案,可参考 Logger 日志 与 服务端开发概述;
  5. 善用事件机制beforeLoad属于 NocoBase 应用生命周期事件,更多事件用法见 Event 事件;若需要在中间件中追踪请求链路,可参考 Middleware 中间件 并在中间件内通过app.telemetry.trace开启 Span。

相关文档导航

  • Logger 日志 — 日志与遥测配合使用,完善可观测性方案
  • Plugin 插件 — 在插件中注册遥测插桩和采集器
  • 服务端开发概述 — 遥测模块在服务端架构中的位置
  • Event 事件 — 通过事件机制在beforeLoad中初始化遥测
  • Middleware 中间件 — 在中间件中结合遥测追踪请求链路
  • Telemetry API 参考 —Telemetry类方法完整签名与默认值
  • Trace API 参考 —Trace类方法完整签名与默认值
  • Metric API 参考 —Metric类方法完整签名与默认值
  • 核心源码:packages/core/telemetry/src/telemetry.ts、packages/core/telemetry/src/trace.ts、packages/core/telemetry/src/metric.ts

【免费下载链接】nocobaseNocoBase is an open-source AI + no-code platform for building business systems fast. Instead of generating everything from scratch, AI works on top of production-proven infrastructure and a WYSIWYG no-code interface, so you get both speed and reliability.项目地址: https://gitcode.com/GitHub_Trending/no/nocobase

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询