📊 我的应用程序数据应该发送到哪里?OpenTelemetry 数据导出完整指南

大家好!今天,我们将探讨如何将我们开发的应用程序中收集到的海量数据(跟踪、指标、日志)发送到我们想要的分析系统,包括其整个旅程和核心方法。🧐

许多人专注于“如何创建”数据,但如果不知道“如何发送”,数据就会被困在应用程序内部。理解从数据生成到最终目的地的整个流程至关重要!


🗺️ 数据的漫长旅程:它从何而来,又将去往何方?

应用程序中生成的遥测数据到达分析工具的旅程大致可分为4个阶段。

  1. 仪表化 (Instrumentation) 💻: 这是开发人员在代码中使用特定库(API Package)生成诸如“此操作耗时50毫秒”、“此处开始DB调用”等数据的阶段。
  2. 标准化 (Standardization) 🏷️: 在此阶段,为生成的数据附加人人都能理解的标准化标签(Semantic Conventions),例如 http.method = “GET”。这是统一数据“含义”的过程。
  3. 处理 (Processing) ⚙️: 收集到的数据会经过采样或过滤等中间处理。
  4. 导出 (Exporting) 🚀: 最后,这是将所有这些数据发送到Jaeger、Prometheus、Datadog等最终目的地的阶段。这是今天的主角!

理解这个整体图景比单独了解每个部分要重要得多。那么,我们首先来明确一下每个阶段的主要参与者API和Semantic Conventions与“导出”有何不同。


🤔 等等,API和Semantic Conventions不是负责发送数据的吗?

简单来说,不是!它们在“创建”和“描述”数据方面扮演着重要角色,但与向外部“传输”数据的功能相去甚远。

API Package: “创建”数据的架构师 🏗️

API包是我们代码中“创建”遥测数据的工具,例如启动跟踪数据(Span)和传播上下文。它提供了开发人员通过代码直接进行仪表化的接口。

主要作用:

  • 启动和结束新的Span
  • 向Span添加事件或属性(Attribute)
  • 在服务之间传播上下文

也就是说,它负责数据“生产”的第一个阶段。但是,它完全不涉及如何将这些数据配置发送到特定系统。

Semantic Conventions: 为数据“贴标签”的图书管理员 🏷️

语义约定是标准化数据“内容”的约定。例如,如果一个开发人员将HTTP方法记录为http_method,而另一个开发人员记录为http.req.method,那么整合和分析数据将非常困难,对吗?

语义约定定义了数据字段的标准名称,如http.method、db.system、rpc.service,确保无论数据是从哪种语言或框架收集的,都具有一致的含义。

主要作用:

  • 定义跟踪、指标、日志数据的标准命名规则
  • 确保数据的一致性和互操作性

因此,它们只标准化数据的内容,而不决定将这些数据“导出”到哪里。


🚀 真正的主角登场:Exporter Package!

那么,收集到的数据到底是谁导出的呢?正是Exporter承担了这一角色!

Exporter是一个插件,它将OpenTelemetry SDK收集和处理的数据转换为特定后端(分析系统)可以理解的格式,然后进行传输。

存在多种类型的Exporter,可以根据目的进行选择。

  • Console Exporter: 将数据输出到终端控制台。对于开发和调试非常有用。
  • OTLP Exporter: 使用OpenTelemetry的标准协议(OTLP)传输数据。它不依赖于特定供应商,可以灵活地与所有支持OpenTelemetry的后端集成。
  • Vendor-specific Exporter: 针对Jaeger、Prometheus、Zipkin等特定分析工具的专有格式发送数据的Exporter。

🛠️ 实战示例:通过代码配置Exporter并验证数据

光说不练可能不太直观,对吧?让我们在Node.js环境中配置Console Exporter,直接通过代码查看Span数据是如何生成并“输出”到外部的。

1. 代码配置 (Node.js)

这是使用ConsoleSpanExporter配置TracerProvider的代码。此代码指示将所有生成的Span信息输出到控制台。

// 导入所需模块
const { NodeTracerProvider } = require('@opentelemetry/sdk-trace-node');
const { ConsoleSpanExporter, SimpleSpanProcessor } = require('@opentelemetry/sdk-trace-base');
const { registerInstrumentations } = require('@opentelemetry/instrumentation');
const { HttpInstrumentation } = require('@opentelemetry/instrumentation-http');

// 1. Exporter配置:创建ConsoleSpanExporter,将所有Span输出到控制台。
const consoleExporter = new ConsoleSpanExporter();

// 2. Provider配置:这是创建和管理Tracer的主体。
const provider = new NodeTracerProvider();

// 3. 连接Provider和Exporter:通过SimpleSpanProcessor设置,使Span在每次结束时立即发送到consoleExporter。
provider.addSpanProcessor(new SimpleSpanProcessor(consoleExporter));

// 4. 注册Provider:将此Provider全局注册,供OpenTelemetry API使用。
provider.register();

// 自动仪表化设置(例如:HTTP请求)
registerInstrumentations({
  instrumentations: [new HttpInstrumentation()],
});

console.log("✅ OpenTelemetry with ConsoleExporter is running...");

// 运行一个简单的HTTP服务器进行测试
const http = require('http');
http.createServer((req, res) => {
  res.end('Hello, World!');
}).listen(8080);

2. 原始数据确认 (控制台输出)

运行上述代码并使用 curl 命令向服务器发送请求,您将在终端中看到如下Span数据(原始数据)输出。这正是ConsoleExporter“导出”的结果!

{
  "traceId": "a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6",
  "parentId": undefined,
  "name": "HTTP GET",
  "id": "1a2b3c4d5e6f7a8b",
  "kind": 1,
  "timestamp": 1762021445123456,
  "duration": 15678,
  "attributes": {
    "http.method": "GET",
    "http.target": "/",
    "http.status_code": 200,
    "net.peer.ip": "::1"
  },
  "status": {
    "code": 0
  },
  "events": []
}

如您所见,根据http.method等语义约定命名的S数据,通过Exporter以整洁的JSON格式输出。如果想将数据发送到Jaeger,只需将ConsoleSpanExporter替换为JaegerExporter即可。


✨ 总结

在构建数据可观测性(Observability)管道时,理解数据的整体流程至关重要。

  • API“生成”数据,
  • Semantic Conventions赋予数据一致的“含义”,
  • Exporter最终将这些数据“传输”到所需的目的地。

现在,您是否清楚地理解了每个组件的作用以及它们如何协调工作?选择适合您系统的Exporter,将分散的数据汇集到一处,从而获得强大的洞察力吧!


Comments

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注