news 2026/4/7 15:25:14

OTLP Trace数据结构

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
OTLP Trace数据结构

根据你的问题,OTLP(OpenTelemetry Protocol)是OpenTelemetry项目原生的数据传输协议,其数据模型基于ProtoBuf(Protocol Buffers)定义。你可以直接使用OpenTelemetry官方提供的Java类库来处理其Trace数据,无需从零开始手动定义。

📦 核心数据结构与Java类

OTLP的Trace数据是一个层次化的结构,其核心的Java类定义在 opentelemetry-proto 依赖中。主要类的层次关系如下:

· ExportTraceServiceRequest
· 描述:最顶层的请求容器,代表一次上报的所有数据。
· 核心字段:repeated ResourceSpans resource_spans
· ResourceSpans
· 描述:代表来自同一“资源”(如一个微服务实例)的所有Trace数据。
· 核心字段:
· Resource resource:描述数据源的属性(如服务名、主机名、K8s Pod信息)。
· repeated ScopeSpans scope_spans
· ScopeSpans (旧称 InstrumentationLibrarySpans)
· 描述:代表同一“检测库”(如某个特定版本的SDK或框架)产生的Span集合。
· 核心字段:
· InstrumentationScope scope:描述检测库的信息(名称、版本)。
· repeated Span spans
· Span
· 描述:单个跨度(Span),是Trace数据的最小单元,代表一个具体的工作单元(如一次函数调用、一次HTTP请求)。
· 核心字段:
· bytes trace_id:Trace的唯一标识,16字节。
· bytes span_id:Span的唯一标识,8字节。
· bytes parent_span_id:父Span的ID,用于构建调用链。
· string name:Span的名称(如接口路径、方法名)。
· SpanKind kind:Span类型(如 SERVER、CLIENT)。
· fixed64 start_time_unix_nano:开始时间戳(纳秒)。
· fixed64 end_time_unix_nano:结束时间戳(纳秒)。
· repeated KeyValue attributes:键值对属性(如 http.status_code=200)。
· Status status:状态(OK, ERROR)。
· repeated Span.Link links:指向其他相关Span的链接。
· repeated Event events:Span期间发生的事件(日志)。

🔧 如何使用这些类

1. 添加Maven依赖
要在项目中使用这些预生成的类,你需要在pom.xml 中添加以下依赖:

```xml
<dependency>
<groupId>io.opentelemetry.proto</groupId>
<artifactId>opentelemetry-proto</artifactId>
<version>1.1.0</version> <!-- 请检查并使用最新版本 -->
</dependency>
```

2. 构建和序列化数据示例
以下代码展示了如何使用这些类构建一个简单的Span,并将其序列化为Protobuf格式的字节数组,以便通过OTLP协议(如HTTP)发送:

```java
import com.google.protobuf.ByteString;
import io.opentelemetry.proto.collector.trace.v1.ExportTraceServiceRequest;
import io.opentelemetry.proto.common.v1.AnyValue;
import io.opentelemetry.proto.common.v1.KeyValue;
import io.opentelemetry.proto.resource.v1.Resource;
import io.opentelemetry.proto.trace.v1.ScopeSpans;
import io.opentelemetry.proto.trace.v1.Span;
import io.opentelemetry.proto.trace.v1.Status;

public class OtlpTraceBuilder {

public static byte[] buildTraceRequest() {
// 1. 创建一个 Span
Span span = Span.newBuilder()
.setTraceId(ByteString.copyFromUtf8("1234567890abcdef1234567890abcdef")) // 16字节的十六进制字符串
.setSpanId(ByteString.copyFromUtf8("1234567890abcdef")) // 8字节的十六进制字符串
.setName("/api/user/login")
.setKind(Span.SpanKind.SPAN_KIND_SERVER)
.setStartTimeUnixNano(System.nanoTime())
.setEndTimeUnixNano(System.nanoTime() + 1_000_000L) // 假设持续1毫秒
.addAttributes(KeyValue.newBuilder()
.setKey("http.method")
.setValue(AnyValue.newBuilder().setStringValue("GET").build())
.build())
.addAttributes(KeyValue.newBuilder()
.setKey("http.status_code")
.setValue(AnyValue.newBuilder().setIntValue(200).build())
.build())
.setStatus(Status.newBuilder().setCode(Status.StatusCode.STATUS_CODE_OK).build())
.build();

// 2. 将 Span 放入 ScopeSpans 和 ResourceSpans
ScopeSpans scopeSpans = ScopeSpans.newBuilder().addSpans(span).build();
io.opentelemetry.proto.trace.v1.ResourceSpans resourceSpans =
io.opentelemetry.proto.trace.v1.ResourceSpans.newBuilder()
.setResource(Resource.newBuilder()
.addAttributes(KeyValue.newBuilder()
.setKey("service.name")
.setValue(AnyValue.newBuilder().setStringValue("user-service").build())
.build())
.build())
.addScopeSpans(scopeSpans)
.build();

// 3. 构建最终的导出请求
ExportTraceServiceRequest request = ExportTraceServiceRequest.newBuilder()
.addResourceSpans(resourceSpans)
.build();

// 4. 序列化为字节数组 (可通过HTTP/gRPC发送)
return request.toByteArray();
}
}
```

💡 关键细节与注意事项

· ID格式:trace_id 和 span_id 在协议层是字节数组(ByteString),但通常用十六进制字符串表示和传递。示例中为了直观使用了字符串,实际生产环境需确保正确的字节转换。
· 时间单位:所有时间戳(start_time_unix_nano)的单位是纳秒。
· 状态码:Span的状态码 (status.code) 是 STATUS_CODE_UNSET、STATUS_CODE_OK 或 STATUS_CODE_ERROR。
· 传输方式:序列化后的Protobuf数据可以通过OTLP协议发送,常见端口是gRPC的 4317 或HTTP的 4318(端点通常为 /v1/traces)。

📚 扩展学习

如果你需要实现一个接收端(Collector)来解析OTLP数据,可以参考以下基于Spring Boot的控制器代码片段:

```java
import io.opentelemetry.proto.collector.trace.v1.ExportTraceServiceRequest;
import com.google.protobuf.InvalidProtocolBufferException;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/v1/traces")
public class OtlpTraceController {
@PostMapping(consumes = "application/x-protobuf")
public String receiveTrace(@RequestBody byte[] body) {
try {
ExportTraceServiceRequest request = ExportTraceServiceRequest.parseFrom(body);
// 处理 request 中的 trace 数据
System.out.println("Received trace data.");
return "OK";
} catch (InvalidProtocolBufferException e) {
return "Invalid Protobuf data";
}
}
}
```

要运行此控制器,你需要在Spring配置中添加对Protobuf消息转换器的支持。

如果你想进一步了解某个特定类(如 Span 或 Resource)的完整字段定义,或者需要查看更复杂的示例(例如包含 links 或 events 的Span),我可以为你提供更详细的说明。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/3/25 9:38:10

Dify平台适配主流大模型:灵活调用Token资源的最佳实践

Dify平台适配主流大模型&#xff1a;灵活调用Token资源的最佳实践 在企业加速拥抱AI的今天&#xff0c;一个现实问题摆在面前&#xff1a;如何让大模型真正落地业务场景&#xff0c;而不是停留在技术演示或实验原型中&#xff1f;我们见过太多团队投入大量人力开发智能客服、知…

作者头像 李华
网站建设 2026/3/28 14:19:20

AUTOSAR网络管理编译与移植技术指南

AUTOSAR网络管理实战&#xff1a;从配置到移植的全链路解析一场“休眠”引发的系统性思考在一次车身控制器&#xff08;BCM&#xff09;项目调试中&#xff0c;团队遇到了一个典型问题&#xff1a;车辆熄火后&#xff0c;CAN总线始终无法进入低功耗状态&#xff0c;导致静态电流…

作者头像 李华
网站建设 2026/4/7 11:02:05

深入浅出讲解UDS协议NRC错误响应逻辑

深入理解UDS协议中的NRC错误响应机制&#xff1a;从原理到实战你有没有遇到过这样的场景&#xff1f;诊断仪发了一个读数据请求&#xff0c;ECU却只回了个“7F 22 XX”——三字节的否定响应&#xff0c;像一道谜题横在面前。这时候&#xff0c;是反复重试&#xff1f;还是抓耳挠…

作者头像 李华
网站建设 2026/4/4 0:34:33

如何制作一个 RAG 系统以获取对您数据的强大访问权限

原文&#xff1a;towardsdatascience.com/how-to-make-a-rag-system-to-gain-powerful-access-to-your-data-caf4bb9186ea RAG 系统是一种创新的信息检索方法。它结合了传统的信息检索方法&#xff0c;如向量相似度搜索&#xff0c;以及最先进的大语言模型技术。结合这些技术&a…

作者头像 李华
网站建设 2026/4/3 8:31:40

Dify平台的冷启动优化策略研究

Dify平台的冷启动优化策略研究 在大模型技术迅猛发展的今天&#xff0c;越来越多企业试图将LLM&#xff08;大语言模型&#xff09;融入实际业务场景。然而现实却常常令人沮丧&#xff1a;一个看似简单的智能客服或知识问答系统&#xff0c;从构思到可演示原型往往需要数周甚至…

作者头像 李华
网站建设 2026/4/5 4:51:41

Dify平台如何保障长时间运行任务的稳定性?

Dify平台如何保障长时间运行任务的稳定性&#xff1f; 在当今企业级AI应用日益复杂的背景下&#xff0c;一个常被忽视但至关重要的问题浮出水面&#xff1a;当AI系统需要持续运行数小时甚至跨天交互时&#xff0c;如何确保它不会“断片”、不会丢状态、不会因一次网络抖动而前功…

作者头像 李华