Prhub

#21254 feat: add OpenTelemetry tracing to DiffGenerator

原始 PR 作者 jh-nv 合并时间 2026-04-24 00:25 文件变更 19 提交数 27 评论 32 代码增减 +978 / -259

执行摘要

为 DiffGenerator 添加 OpenTelemetry 追踪基础设施

PR描述指出需要为diffusion/multimodal generation子系统启用OpenTelemetry追踪,以实现与SRT运行时的功能对等。下游消费者(如Dynamo)需要diffusion路径中的追踪支持,因此希望尽早落地基础架构。

此PR值得精读,尤其关注:1)如何将OTel追踪集成到多进程架构中(worker进程独立初始化);2)通过上下文管理器封装复用追踪逻辑;3)跨分解角色传播追踪上下文的序列化方案;4)轻量级进程内OTLP收集器的实现(替代Docker依赖)。

讨论亮点
  1. 将手动span操作重构为上下文管理器

    sufeng-buaa: "Could we implement this using a context manager and put the related implementations in one place, for example in python/sglang/multimodal_gen/runtime/utils/trace_wrapper.py? Then this can be rewritten as with trace_slice(req.trace_ctx, DiffStag.GPU_FORWARD):"
    作者接受并实现,创建了trace_wrapper.pyDiffStageConfig/DiffStage

  2. 定义DiffStageConfig为冻结数据类而非枚举

    sufeng-buaa: "I think defining it this way is better, since we wouldn't need to pass the level every time." 建议使用冻结数据类,作者采纳。

  3. 避免延迟导入

    mickqian: "please avoid lazy imports as it introduce runtime overhead and hide possible exceptions." 作者移除所有延迟导入。

  4. 测试集成与CI

    sufeng-buaa: "I recently submitted a PR to integrate tracing into the ci(#21740)... After my PR is merged, you can add test cases directly and start up the sglang server for real testing." 作者等待后添加了集成测试,并将LightweightOtlpCollector提取到公共工具。

  5. 关于是否拆分为两个PR的讨论

    mickqian: "if this is not related to sglang-diffusion, please split into two PRs" 针对test/registered/observability/test_tracing.py的修改。最终保留在一个PR中。

实现拆解

  1. 服务端配置与进程级初始化
    - 修改python/sglang/multimodal_gen/runtime/server_args.py,新增--enable-trace--otlp-traces-endpointCLI标志,镜像SRT的配置。
    - 在DiffGenerator.from_server_args()中初始化OTel导出器,服务名sglang-diffusion,线程标签DiffGenerator
    - GPU worker进程(gpu_worker.py)中为每个worker初始化追踪,线程标签DiffWorker_rank{N}
    - launch_server.py将追踪配置传递给worker进程。

  2. 请求级追踪上下文
    - 在python/sglang/multimodal_gen/runtime/entrypoints/utils.pyprepare_request中,当追踪启用时创建TraceReqContext,并链接外部W3C追踪头。
    - python/sglang/multimodal_gen/runtime/schedule_batch.pyReq类新增trace_ctx字段,默认使用无操作的TraceNullContext
    - 在OpenAI兼容的image/video API端点(image_api.pyvideo_api.py)中提取traceparent/tracestate请求头。

  3. 跨度(Span)插装
    - 引入python/sglang/multimodal_gen/runtime/utils/trace_wrapper.py,提供DiffStage命名常量(scheduler_dispatchgpu_forward)和上下文管理器trace_reqtrace_slice,简化跨度生命周期管理。
    - managers/scheduler.pyscheduler_dispatch跨度包裹forward调度。
    - managers/gpu_worker.pygpu_forward跨度包裹pipeline前向调用。
    - diffusion_generator.pyfinally块中调用trace_req_finish()关闭跨度。
    - 所有导入延迟,避免追踪禁用时的依赖膨胀。

  4. 分解角色间的追踪上下文传播
    - 修改python/sglang/multimodal_gen/runtime/disaggregation/scheduler_mixin.py,在extract_transfer_fields中将TraceReqContext序列化为JSON安全的_trace_state(W3C载体)通过标量字段传递,接收方在_build_disagg_req中通过__setstate__重建上下文。
    - 新增_disagg_trace_dispatch辅助函数包裹执行前向,确保跨度在分解角色中正确嵌套。

  5. 测试覆盖
    - 新增python/sglang/test/otel_collector.py:轻量级进程内OTLP收集器,替代Docker-based otel-collector,用于测试断言。
    - 新增python/sglang/multimodal_gen/test/unit/test_disagg_trace.py:单元测试验证分解追踪传播的序列化/反序列化契约。
    - 新增python/sglang/multimodal_gen/test/server/test_tracing.py:集成测试,启动带追踪的扩散服务器,发送请求并验证期望跨度被导出。
    - 修改test/registered/observability/test_tracing.py:移除重复的收集器实现,导入共享的LightweightOtlpCollector

代码示例:trace_wrapper.py核心逻辑

代码示例:分解标量字段中的追踪状态序列化

已知限制(后续跟进)

  • trace_req_finish()尚未附加跨度属性(模型名、生成参数、延迟分解)。
  • /set_trace_level端点用于动态追踪详细级别控制。
  • Mesh API未插装。
文件 模块 状态 重要度
python/sglang/multimodal_gen/runtime/utils/trace_wrapper.py 追踪工具 added 8.58
python/sglang/test/otel_collector.py 测试工具 added 8.05
python/sglang/multimodal_gen/runtime/disaggregation/scheduler_mixin.py 分解调度 modified 7.76
python/sglang/multimodal_gen/test/server/test_tracing.py 追踪测试 added 7.89
python/sglang/multimodal_gen/test/unit/test_disagg_trace.py 分解追踪测试 added 7.63
test/registered/observability/test_tracing.py 追踪测试 modified 7.24
python/sglang/multimodal_gen/runtime/entrypoints/openai/image_api.py API 入口 modified 6.31
python/sglang/multimodal_gen/runtime/managers/scheduler.py 调度器 modified 6.18
python/sglang/multimodal_gen/runtime/entrypoints/utils.py 请求处理 modified 6.11
python/sglang/multimodal_gen/runtime/entrypoints/diffusion_generator.py 生成器 modified 6.08
python/sglang/multimodal_gen/runtime/managers/gpu_worker.py GPU worker modified 6.05

关键符号

DiffStageConfig.__init__ DiffStage.SCHEDULER_DISPATCH DiffStage.GPU_FORWARD trace_req trace_slice LightweightOtlpCollector.__init__ LightweightOtlpCollector._try_grpc_server LightweightOtlpCollector._handle_trace_request SchedulerDisaggMixin._disagg_trace_dispatch extract_transfer_fields _build_disagg_req prepare_request test_spans_exported test_spans_without_traceparent test_batch_requests TestDisaggTracePropagation.test_tracing_disabled_omits_trace_state TestDisaggTracePropagation.test_tracing_enabled_state_roundtrip TestDisaggTracePropagation.test_build_disagg_req_installs_rebuilt_ctx TestDisaggTracePropagation.test_build_disagg_req_falls_back_when_tracing_off

关键源码片段

python/sglang/multimodal_gen/runtime/disaggregation/scheduler_mixin.py dependency-wiring

修改分解调度器 mixin,实现追踪上下文在编码器 / 去噪器 / 解码器角色间的 JSON 安全传播。

# 导出追踪状态到标量字段
trace_ctx = getattr(req, "trace_ctx", None)
if trace_ctx is not None and getattr(trace_ctx, "tracing_enable", False):
    try:
        trace_state = trace_ctx.__getstate__()
        if trace_state and trace_state.get("tracing_enable"):
            scalar_fields["_trace_state"] = trace_state
    except Exception as e:
        logger.debug("Failed to export trace state: %s", e)# 接收方重建追踪上下文
trace_state = scalar_fields.pop("_trace_state", None)
if trace_state is not None:
    try:
        rebuilt_ctx = object.__new__(TraceReqContext)
        rebuilt_ctx.__setstate__(trace_state)
        req.trace_ctx = rebuilt_ctx
    except Exception as e:
        logger.debug("Failed to rebuild trace context: %s", e)# 使用 _disagg_trace_dispatch 包装前向执行
with self._disagg_trace_dispatch(req):
    self.worker.execute_forward([req], return_req=True)

评论区精华

使用上下文管理器重构 Span 操作 设计

sufeng-buaa 建议将手动 trace_slice_start/end 替换为上下文管理器,并集中到 trace_wrapper.py。

结论:作者采纳建议,创建了 trace_req 和 trace_slice 上下文管理器,以及 DiffStageConfig 数据类。 · 已解决

DiffStageConfig 的定义方式 设计

sufeng-buaa 建议使用冻结数据类代替枚举,避免每次传递 level。

结论:作者采纳,将枚举改为数据类 DiffStageConfig。 · 已解决

避免延迟导入 性能

mickqian 指出延迟导入引入运行时开销并隐藏异常。

结论:作者移除所有延迟导入,改为模块级别导入。 · 已解决

测试集成与 CI 测试

sufeng-buaa 提到 PR #21740 将追踪集成到 CI,建议等待后添加集成测试。

结论:作者等待 PR 合并后添加了集成测试,并提取公共收集器。 · 已解决

是否拆分 PR other

mickqian 建议将对 test/registered/observability/test_tracing.py 的修改拆分为单独 PR,因为不直接相关。

结论:作者和 sufeng-buaa 均认为提取公共基础设施有助于减少重复,最终保留在一个 PR 中。 · 已解决

风险与影响

  • 默认关闭,零运行时影响--enable-trace为opt-in,且导入使用延迟加载(最终移除),禁用时无任何追踪代码执行。
  • 分解序列化风险_trace_state序列化/反序列化有异常保护,测试覆盖了禁用和启用场景以及JSON往返。
  • 测试基础设施共享LightweightOtlpCollectortest/registered/observability/test_tracing.py提取至python/sglang/test/otel_collector.py,原有测试导入更新,风险低。
  • 跨进程跨度关联:通过W3C traceparent传递,保证正确性依赖于OTel SDK的一致性。
  • 用户影响:启用追踪后,diffusion请求将产生OTel跨度,可被标准OTel收集器消费,便于调试和监控。默认关闭,无影响。
  • 系统影响:新增依赖(opentelemetry-api和opentelemetry-sdk)仅在启用追踪时加载。测试框架新增共享收集器,减少依赖。
  • 团队影响:为后续细粒度跨度属性、动态追踪级别控制提供了基础。
新增追踪基础设施 跨进程序列化 测试覆盖依赖 CI 默认关闭零风险

关联 Issue

未识别关联 Issue

当前没有检测到明确关联的 Issue 链接,后续同步到相关引用后会出现在这里。

完整报告

参与讨论