news 2026/9/13 1:30:51

MLflow 仓库内 OpenTelemetry Protobuf 定义:最小化 Vendor 机制、数据模型与更新维护指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
MLflow 仓库内 OpenTelemetry Protobuf 定义:最小化 Vendor 机制、数据模型与更新维护指南

MLflow 仓库内 OpenTelemetry Protobuf 定义:最小化 Vendor 机制、数据模型与更新维护指南

【免费下载链接】mlflowThe open source AI engineering platform for agents, LLMs, and ML models. MLflow enables teams of all sizes to debug, evaluate, monitor, and optimize production-quality AI applications while controlling costs and managing access to models and data.项目地址: https://gitcode.com/GitHub_Trending/ml/mlflow

本文聚焦 MLflow 开源仓库中mlflow/protos/opentelemetry/目录下的 OpenTelemetry Protocol Buffer(protobuf)规范定义。MLflow 的 AI Tracing 能力以 OpenTelemetry 数据模型为底层格式,但并未全量引入上游规范,而是只 vendor 了一个"最小够用"的子集。读完本文,你将掌握这三个 proto 文件各自承担的数据建模职责、它们如何被 MLflow 的 tracing 链路(OTLP 导出、trace 归档、Databricks 服务对接)实际消费,以及如何通过update.sh安全地升级这批定义。

为什么 MLflow 需要内置 OpenTelemetry Proto 定义

MLflow 的 Tracing 模块 采用 OpenTelemetry 的 Span 模型来记录一次 LLM/Agent 调用链路的输入、输出、耗时与中间事件。为了保证生成的 trace 能够:

  • 通过标准的 OTLP(OpenTelemetry Protocol)导出到任意兼容后端;
  • TracesData结构上与 OpenTelemetry 生态直接互换;
  • 与 Databricks tracking server 的 trace 存储协议保持字节级兼容;

MLflow 的 Python 包必须在运行时拥有对应的 protobuf 消息类。这些类的定义不能依赖用户环境是否安装了完整的opentelemetry-proto包,因此 MLflow 选择将所需的最小集合直接 vendor 进仓库,随 mlflow 包本体 一起分发。

目录结构与包含内容

mlflow/protos/opentelemetry/ ├── README.md # 本文所述的说明文档 ├── update.sh # 上游同步脚本 └── proto/ ├── common/ │ └── v1/ │ └── common.proto # 通用数据类型 ├── resource/ │ └── v1/ │ └── resource.proto # 资源属性 └── trace/ └── v1/ └── trace.proto # Trace 数据模型

README 明确说明这是一个刻意的最小子集:MLflow 只需要 trace(追踪)能力,因此仅引入了上表中的三个文件。对比上游opentelemetry-proto的完整集(还包括 metrics、logs、profiles、experimental 等大量目录),这套 vendor 只保留了 3 个.proto源文件,显著降低了仓库体积与生成代码量。

数据模型详解:trace.proto

trace.proto 是整个 vendor 子集的核心,声明了package opentelemetry.proto.trace.v1,并 import 了common.protoresource.proto两个姊妹文件。

三层嵌套结构:TracesData → ResourceSpans → ScopeSpans

从源码结构看(trace.proto#L38-L83),OTLP 的 trace 数据采用三层容器嵌套:

消息关键字段语义
TracesDatarepeated ResourceSpans resource_spans顶层数据包,可批量携带来自多个资源的 span 集合
ResourceSpansResource resourcerepeated ScopeSpans scope_spansstring schema_url归属于同一 Resource 的 span 集合;schema_url标识资源数据遵循的 schema 版本
ScopeSpansInstrumentationScope scoperepeated Span spansstring schema_url归属于同一插桩作用域(如某个 SDK/flavor)的 span 列表

ResourceSpansScopeSpans各带独立的schema_url字段,分别约束 resource 数据与 span 数据遵循的 schema 版本(见 trace.proto#L58-L64 与 L77-L82 的注释说明)。中间转发节点可将多个来源的 span 批量合并进同一个TracesData,这也是 OTLP 导出路径的天然形态。

Span 消息:一次操作的最小单元

Span消息(trace.proto#L88-L302)描述了系统中单个组件执行的一次操作,其核心字段如下:

字段类型说明
trace_idbytes(16 字节)所属 trace 的唯一标识,同一条 trace 的所有 span 共享;全零或非 16 字节视为非法,必填
span_idbytes(8 字节)本 span 在 trace 内的唯一标识,创建时分配,必填
parent_span_idbytes(8 字节)父 span 的 ID;根 span 此字段必须为空
trace_statestringW3C Trace Context 格式的 trace 状态
namestring操作描述(如"qualified method name + 行号"),语义上必须非空,必填
kindSpanKind枚举span 类型(见下文)
start_time_unix_nano/end_time_unix_nanofixed64以纳秒计的 Unix 时间戳,语义上要求end_time >= start_time
attributesrepeated KeyValue键值对属性集合,键必须唯一
eventsrepeated Event带时间戳的注解事件(time_unix_nano+name+attributes
linksrepeated Link指向同 trace 或跨 trace 其他 span 的引用(如批处理场景)
statusStatus最终状态(见下文)
flagsfixed32位标志字段(见下文)
dropped_*_countuint32因超长或超量被丢弃的 attributes / events / links 计数

EventLink内嵌消息同样以KeyValue携带属性,且各自维护dropped_attributes_count用于记录截断损耗——这保证了消费者能感知到数据缺失,而不会被静默误导。

SpanKind:区分调用语义

SpanKind枚举(trace.proto#L152-L178)用于在父子关系之外补充描述 span 的语义角色:

  • SPAN_KIND_INTERNAL(默认):应用内部操作,非边界调用;
  • SPAN_KIND_SERVER:服务端处理某个 RPC/远程请求;
  • SPAN_KIND_CLIENT:向远程服务发起的请求;
  • SPAN_KIND_PRODUCER/SPAN_KIND_CONSUMER:消息队列的投递与消费,生产者与消费者之间通常不存在直接的关键路径时延关系。

Status:错误模型

Status消息(trace.proto#L306-L326)由message(人类可读错误信息)与StatusCode枚举构成:STATUS_CODE_UNSET(默认)、STATUS_CODE_OK(开发者确认成功)、STATUS_CODE_ERROR(span 包含错误)。未显式设置 status 时按UNSET处理。

SpanFlags:trace 标志位的位掩码约定

SpanFlags枚举(trace.proto#L342-L357)定义了Span.flags位字段的解读方式:

  • 第 0-7 位:W3C Trace Context 的 trace flags,读取用flags & SPAN_FLAGS_TRACE_FLAGS_MASK
  • 第 8 位(SPAN_FLAGS_CONTEXT_HAS_IS_REMOTE_MASK):父 span/link 是否 remote 的信息是否已知;
  • 第 9 位(SPAN_FLAGS_CONTEXT_IS_REMOTE_MASK):父 span/link 是否为 remote;
  • 第 10-31 位:保留。

该枚举与flags字段均为 OpenTelemetry 协议 1.1 引入的增量特性,旧生产者不会设置该字段,因此消费者不能依据某标志位的缺失反推功能缺失。

common.proto:通用值类型

common.proto 定义了一组被 trace、resource 反复复用的基础类型,声明package opentelemetry.proto.common.v1

  • AnyValue(common.proto#L28-L40):属性值的统一容器,通过oneof承载string_valuebool_valueint_valuedouble_valuearray_valuekvlist_valuebytes_value七种取值,支持嵌套的数组与键值列表;
  • ArrayValuerepeated AnyValue values,因 protobuf 的oneof不允许repeated字段,所以单独拆成消息;
  • KeyValueList:键值对列表的包装,键必须唯一;而像Span.attributes这种高频场景直接使用repeated KeyValue以避免多余包装层(见 common.proto#L49-L53 的注释),两种方式语义等价;
  • KeyValuestring key+AnyValue value,是 attribute 的最小单元;
  • InstrumentationScope(common.proto#L71-L81):插桩作用域信息,含name(空名视为未知)、version及可选 attributes,用于区分不同 SDK/flavor 产生的 span;
  • EntityRef(common.proto#L87-L115):对实体(如 service、host)的引用描述,包含type、标识性属性键id_keys与描述性属性键description_keys,目前标注为 Development 状态。

resource.proto:资源属性

resource.proto 定义了Resource消息(resource.proto#L28-L43),用于描述产生遥测数据的资源实体:

  • attributes:描述资源的属性集合,键必须唯一,通常承载 service.name、service.version、host 信息等全局属性;
  • dropped_attributes_count:被丢弃的属性数量;
  • entity_refs:参与该资源的实体引用列表(Development 状态)。

在 OTLP 层级中,Resource挂载在ResourceSpans.resource上,与ScopeSpans中的 span 数据解耦,实现"一份资源属性复用多条 span"的高效打包。

这些 Proto 在 MLflow 源码中的实际消费

vendor 进来的定义不是摆设,它们在 MLflow 的 tracing 链路上被多处直接引用:

  • Databricks trace 服务协议databricks_tracing.proto在第 13 行import "opentelemetry/proto/trace/v1/trace.proto",并在Trace消息中直接以repeated opentelemetry.proto.trace.v1.Span spans承载 span 数据(databricks_tracing.proto#L516-L519)。这意味着与 Databricks tracking server 交互时,trace 的线上序列化格式就是 OpenTelemetry 的 Span 结构;
  • OTLP 导出器:otlp.py 从opentelemetry.proto.common.v1.common_pb2opentelemetry.proto.resource.v1.resource_pb2导入AnyValueArrayValueKeyValueListResource(otlp.py#L7-L8),并实现_set_otel_proto_anyvalue/_decode_otel_proto_anyvalue在 Python 值与 OTel proto 值之间互转;同文件还定义了 OTLP 的/v1/traces/v1/metrics路径及 gRPC / HTTP-protobuf 两种导出协议选择;
  • Trace 归档与恢复:otel_archival.py 从opentelemetry.proto.trace.v1.trace_pb2导入TracesData(otel_archival.py#L10),将 span 编码为 OTLPTracesData落盘,读取归档时再经Span.from_otel_proto还原。

这也解释了为什么三个文件一个都不能少:trace.proto提供结构,common.proto提供值类型,resource.proto提供资源上下文,三者通过 import 关系形成完整闭环。

更新流程:update.sh逐步解析

README 给出的升级步骤为:修改update.sh中的COMMIT_SHA→ 执行脚本。结合脚本源码(update.sh),完整流程如下:

  1. 锁定上游版本COMMIT_SHA="8654ab7a5a43ca25fe8046e59dcd6935c3f76de0"(update.sh#L13)对应 opentelemetry-proto 的 v1.7.0 版本,脚本以 commit 级别的 tar 包为唯一事实来源,确保可复现;
  2. 定位脚本目录SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"cd进入,保证脚本可以从仓库任意位置调用;
  3. 清理旧文件rm -rf proto删除现有 vendor 目录,避免残留文件造成新旧混用;
  4. 下载并解压curl -fsSL "$ARCHIVE_URL" | tar -xzf - -C "$TEMP_DIR",使用mktemp -d临时目录,并以trap ... EXIT保证退出时清理,兼容 macOS BSD tar 与 GNU tar;
  5. 选择性拷贝:仅拷贝三个目标文件到proto/trace/v1proto/common/v1proto/resource/v1(update.sh#L33-L36),其余上游文件一律不引入。

执行方式(从仓库根目录):

./mlflow/protos/opentelemetry/update.sh

维护注意事项与扩展建议

  • 保持最小子集原则:README 强调,若未来需要 metrics、logs 等能力,应先扩展update.sh的提取列表再运行脚本,而不是手动复制文件——否则下次同步会被rm -rf proto清掉;
  • 校验 import 链:三个文件之间存在 import 依赖(trace.proto依赖common.protoresource.proto),新增文件时务必连同其 import 链一并提取;
  • 版本一致性COMMIT_SHA锁定的是 opentelemetry-proto 的 commit 而非发行 tag,升级后应关注SpanFlags等增量字段、schema_url语义变化及EntityRef等 Development 状态消息的演进;
  • 生成代码同步.proto仅是源定义,MLflow 包内实际加载的是编译后的_pb2类(如opentelemetry.proto.trace.v1.trace_pb2)。替换 proto 后需重新生成对应的 Python 绑定代码,并运行 tracing 相关测试 验证序列化兼容性。

相关源码指引

  • 定义文件:trace.proto、common.proto、resource.proto、update.sh
  • 消费方:databricks_tracing.proto、otlp.py、otel_archival.py
  • 上层 tracing 模块:mlflow/tracing
  • 测试:tests/tracing

【免费下载链接】mlflowThe open source AI engineering platform for agents, LLMs, and ML models. MLflow enables teams of all sizes to debug, evaluate, monitor, and optimize production-quality AI applications while controlling costs and managing access to models and data.项目地址: https://gitcode.com/GitHub_Trending/ml/mlflow

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

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

Claude与OpenAI大模型API核心技术对比与工程实践

1. 核心能力对比:Claude与OpenAI的基因差异Claude和OpenAI虽然都是当前领先的大模型API服务,但两者的技术路线和擅长领域存在显著差异。经过半年多的生产环境实测,我发现这种差异会直接影响开发效率和应用效果。1.1 文本处理能力的实测对比在…

作者头像 李华
网站建设 2026/9/13 1:26:27

Python+Django构建高并发校园食堂点餐系统

1. 项目背景与核心价值校园食堂点餐系统是每个高校信息化建设中不可或缺的一环。传统的人工排队点餐方式存在诸多痛点:高峰时段排队时间长、人工结算效率低、菜品信息不透明、订单管理混乱等。这套基于PythonDjango的解决方案,正是为了解决这些实际问题而…

作者头像 李华
网站建设 2026/9/13 1:26:17

有机婴幼儿食品品牌Once Upon a Farm的成功案例分析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/13 1:24:04

告别逆向破解:合规路径下的点赞数据分析实战指南

做内容运营这几年,我有个特别深的体会:点赞数据是判断流量质量最直接的指标之一,但真想把它分析透的时候,第一步就容易卡住——打开抓包工具一看,抖音这类App的每个请求后面都挂着一串加密参数,abogus、as、…

作者头像 李华