OpenTelemetry (OTel) 是一套标准化的工具、API 和 SDK,旨在确保分布式系统的可观测性 (Observability)。在此生成的所有宝贵数据(追踪、指标、日志)都通过名为 OTLP (OpenTelemetry Protocol) 的标准协议传输到收集服务器。而 OTLP 的传输格式之一正是 JSON 格式! 📜
今天,我们将深入探讨 OTel 收集的三种核心数据如何以 OTLP JSON 形式进行结构化,并通过示例剖析其 原始数据的深层结构。理解这一结构将大大增强您的数据分析和处理能力! 💪

🔍 理解 OTLP 数据的通用分层结构
OTLP 数据,无论是追踪、指标还是日志,都具有共同的 分层结构。这是为了清晰地分离和传递有关生成数据的环境信息。
| 数据类型 | 根对象 | 主要子字段 | 数据内容 |
| — | — | — | — |
| Trace (追踪) | “resourceSpans” | “scopeSpans”, “spans” | 单个请求的执行流程 |
| Metric (指标) | “resourceMetrics” | “scopeMetrics”, “metrics” | 系统性能和数值数据 |
| Log (日志) | “resourceLogs” | “scopeLogs”, “logRecords” | 应用程序日志消息 |
🌳 1. Resource 块 (顶级标识符)
所有 OTLP 数据都包含一个 resource 块。它用于识别生成数据的实体(服务、主机等)。换句话说,这是告知我们数据来源的重要信息。
- “attributes”: 包含环境信息,以键值对形式呈现,例如 服务名称 (service.name)、实例 ID (service.instance.id) 和云信息 (cloud.provider)。
📦 2. Scope/Instrumentation Library 块
resource 块下方紧接着是 scope 或 instrumentation library 块。
- “scope”: 指明用于收集此数据的 库 或 版本。例如:io.opentelemetry.instrumentation.http, 版本 1.27.0。
📊 1. 追踪数据结构全面解析 (OTLP Trace JSON)
追踪数据跟踪单个请求在系统中经过的所有步骤。核心元素是 Span。
{
"resourceSpans": [
{
"resource": {
"attributes": [
{ "key": "service.name", "value": { "stringValue": "checkout-service" } },
{ "key": "service.instance.id", "value": { "stringValue": "627cc493-f310-47de-96bd-71410b7dec09" } },
{ "key": "cloud.provider", "value": { "stringValue": "aws" } },
{ "key": "host.id", "value": { "stringValue": "ip-172-31-12-55" } }
]
},
"scopeSpans": [
{
"scope": {
"name": "io.opentelemetry.instrumentation.http",
"version": "1.27.0"
},
"spans": [
{
"traceId": "4bf92f3577b34da6a3ce929d0e0e4736",
"spanId": "00f067aa0ba902b7",
"name": "HTTP POST /checkout",
"kind": "SPAN_KIND_SERVER",
"startTimeUnixNano": "1729123548123456789",
"endTimeUnixNano": "1729123549223456789",
"attributes": [
{ "key": "http.method", "value": { "stringValue": "POST" } },
{ "key": "http.status_code", "value": { "intValue": 200 } },
{ "key": "net.peer.ip", "value": { "stringValue": "10.10.1.12" } },
{ "key": "user.id", "value": { "stringValue": "abcd-123" } }
],
"events": [
{
"timeUnixNano": "1729123548156789000",
"name": "db.query.start",
"attributes": [
{ "key": "db.statement", "value": { "stringValue": "SELECT * FROM orders WHERE id=42" } }
]
}
],
"links": [
{
"traceId": "4bf92f3577b34da6a3ce929d0e0e4736",
"spanId": "2233445566778899",
"attributes": [
{ "key": "linked.operation", "value": { "stringValue": "payment-processing" } }
]
}
],
"status": { "code": "STATUS_CODE_OK", "message": "completed successfully" }
}
]
}
]
}
]
}
✨ 主要字段详细解读
| 字段 | 说明 | 示例值 |
| — | — | — |
| “traceId” | 识别整个事务的唯一 ID。 | 4bf92f3577b34da6a3ce929d0e0e4736 |
| “spanId” | 识别当前操作步骤的唯一 ID。 | 00f067aa0ba902b7 |
| “name” | Span 所代表的操作名称。 | HTTP POST /checkout |
| “kind” | Span 的类型(服务器、客户端、内部等)。 | SPAN_KIND_SERVER |
| “startTimeUnixNano”, “endTimeUnixNano” | 操作的开始和结束时间(纳秒)。 ⏱️ | 1729123548… |
| “attributes” | 与 Span 相关的额外详细信息(HTTP 方法、状态码、用户 ID 等)。 | http.method: POST |
| “events” | Span 执行期间特定时间点发生的事件记录(日志消息、数据库查询开始等)。 | name: db.query.start |
| “links” | 将此 Span 与其他追踪/Span 连接起来的信息(对分布式追踪很有用)。 🔗 | linked.operation: payment-processing |
| “status” | Span 的执行结果(成功/错误代码和消息)。 | code: STATUS_CODE_OK |
> 示例亮点:显示 checkout-service 处理 HTTP POST 请求 (traceId: 4bf92f…) 期间发生了数据库查询事件 (db.query.start),并最终成功 (STATUS_CODE_OK)。
📈 2. 指标数据结构全面解析 (OTLP Metrics JSON)
指标数据以数值形式表示系统性能或状态随时间的变化。它以各种形式存在,如 Gauge(瞬时值)、Sum(总和)和 Histogram(直方图)。
{
"resourceMetrics": [
{
"resource": {
"attributes": [
{ "key": "service.name", "value": { "stringValue": "checkout-service" } },
{ "key": "service.version", "value": { "stringValue": "1.5.2" } },
{ "key": "host.name", "value": { "stringValue": "ip-172-31-12-55" } }
]
},
"scopeMetrics": [
{
"scope": {
"name": "io.opentelemetry.runtime",
"version": "1.27.0"
},
"metrics": [
{
"name": "request_duration_seconds",
"description": "HTTP request duration",
"unit": "s",
"sum": {
"dataPoints": [
{
"attributes": [
{ "key": "http.method", "value": { "stringValue": "POST" } },
{ "key": "http.status_code", "value": { "intValue": 200 } }
],
"startTimeUnixNano": "1729123548123456000",
"timeUnixNano": "1729123549223466000",
"value": 0.154,
"flags": 1
}
],
"aggregationTemporality": "AGGREGATION_TEMPORALITY_DELTA",
"isMonotonic": false
}
},
{
"name": "system.cpu.utilization",
"description": "CPU usage percentage",
"unit": "%",
"gauge": {
"dataPoints": [
{
"attributes": [
{ "key": "host.id", "value": { "stringValue": "ip-172-31-12-55" } }
],
"timeUnixNano": "1729123549123459999",
"value": 73.4
}
]
}
}
]
}
]
}
]
}
✨ 主要字段详细解读
| 字段 | 说明 | 示例值 |
| — | — | — |
| “name”, “description”, “unit” | 指标的名称、描述和测量单位。 | request_duration_seconds, s |
| “sum”, “gauge” | 指标的类型及其值所在的块。 | sum (累计总和), gauge (瞬时值) |
| “dataPoints” | 实际测量数据值的列表。 | 📝 |
| dataPoints.”attributes” | 该测量值特有的标签/过滤信息(例如:HTTP 方法、状态码)。 | http.status_code: 200 |
| dataPoints.”value” | 测量的实际数值。 | 0.154 (秒), 73.4 (%) |
| dataPoints.”timeUnixNano” | 测量值收集的时间。 ⏰ | 1729123549… |
| sum.”aggregationTemporality” | 总和测量值的聚合方式(增量:与前一间隔的差值,累积:从开始的总和)。 | AGGREGATION_TEMPORALITY_DELTA |
> 示例亮点:显示请求处理时间 (request_duration_seconds) 以总和 (sum) 形式测量为 0.154 秒,系统 CPU 利用率 (system.cpu.utilization) 以瞬时值 (gauge) 形式测量为 73.4%。
📝 3. 日志数据结构全面解析 (OTLP Logs JSON)
日志数据是记录应用程序中发生的事件的基于文本的消息。OTel 通过将追踪信息与日志关联来提高其利用率。
{
"resourceLogs": [
{
"resource": {
"attributes": [
{ "key": "service.name", "value": { "stringValue": "checkout-service" } },
{ "key": "service.namespace", "value": { "stringValue": "web-shop" } },
{ "key": "host.id", "value": { "stringValue": "ip-172-31-12-55" } }
]
},
"scopeLogs": [
{
"scope": {
"name": "io.opentelemetry.logger",
"version": "1.27.0"
},
"logRecords": [
{
"timeUnixNano": "1729123548123456789",
"observedTimeUnixNano": "1729123548125456789",
"severityText": "INFO",
"severityNumber": 9,
"body": { "stringValue": "Order ID 42 successfully processed" },
"attributes": [
{ "key": "order.id", "value": { "intValue": 42 } },
{ "key": "user.id", "value": { "stringValue": "abcd-123" } },
{ "key": "event.name", "value": { "stringValue": "order_completed" } }
],
"traceId": "4bf92f3577b34da6a3ce929d0e0e4736",
"spanId": "00f067aa0ba902b7",
"flags": 1
},
{
"timeUnixNano": "1729123549223456000",
"severityText": "ERROR",
"severityNumber": 17,
"body": { "stringValue": "Payment gateway timeout error" },
"attributes": [
{ "key": "payment.processor", "value": { "stringValue": "stripe" } },
{ "key": "error.code", "value": { "intValue": 504 } }
],
"traceId": "7aa111223344556677889900aabbccdd",
"spanId": "11aabbccddeeff00",
"flags": 1
}
]
}
]
}
]
}
✨ 主要字段详细解读
| 字段 | 说明 | 示例值 |
| — | — | — |
| “timeUnixNano”, “observedTimeUnixNano” | 日志生成时间以及收集器观察到的时间。 | 1729123548… |
| “severityText”, “severityNumber” | 日志的严重性级别(文本和数值)。 | INFO (9), ERROR (17) |
| “body” | 实际日志消息内容。 | Order ID 42 successfully processed |
| “attributes” | 与日志消息相关的额外信息。 | order.id: 42, user.id: abcd-123 |
| “traceId”, “spanId” | 导致此日志的追踪和Span的 ID。(可观测性核心!) 🧩 | 4bf92f35…, 00f067aa… |
> 示例亮点:订单成功日志 (severityText: INFO) 已链接到特定的追踪/Span ID。此外,支付网关错误日志 (severityText: ERROR) 也以严重性级别 17 记录。
💡 总结与结论
OpenTelemetry 的 OTLP JSON 格式将所有可观测数据捆绑成标准化的分层结构,从而实现高效的传输和处理。
- 资源 (Resource): 明确数据的来源(服务、主机信息)。
- 范围 (Scope): 指明用于数据收集的库信息。
- 数据: 包含实际内容,如追踪(Span)、指标(数据点)和日志(日志记录)。
得益于这种清晰详细的结构,使用 OTel 的系统即使在分布式环境中也能轻松收集、分析和可视化数据,从而全面掌握运营状况! 👍
发表回复