Skip to content

refactor(metrics): 解耦 Portal 指标打点与 Exporter - #814

Open
feng-95 wants to merge 5 commits into
volcengine:mainfrom
feng-95:refactor/apmplus-meter-uploader
Open

refactor(metrics): 解耦 Portal 指标打点与 Exporter#814
feng-95 wants to merge 5 commits into
volcengine:mainfrom
feng-95:refactor/apmplus-meter-uploader

Conversation

@feng-95

@feng-95 feng-95 commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

改动说明

本次改造将 VeADK Portal 指标的“执行打点”和“创建导出链路”拆分为两项独立职责:

  • 在 VeADK Portal 遥测 Hook 已安装的前提下,LLM、Tool、Skill 指标执行打点时不再检查 ENABLE_APMPLUSAPMPlusExporter 或其他 Exporter 是否存在;
  • PortalMetricRecorder 直接通过 OpenTelemetry Global MeterProvider 创建测量工具并记录;
  • APMPlusExporter 不再创建或注册指标记录器,只在当前仍为 _ProxyMeterProvider 时兜底创建带 APMPlus Reader 的 Global MeterProvider
  • 已有真实 Global MeterProvider 时,APMPlus 不替换 Provider、不追加 Reader,也不接管其生命周期;
  • 删除基于 Exporter 激活的 MetricUploaderRegistry,进程内只保留一份 portal_metrics.portal_metric_recorder

修改原因

旧实现把 Portal 指标是否打点绑定在 APMPlus Exporter 注册流程上,会产生两个问题:

  1. 已安装 Portal 遥测 Hook 且业务已经配置 Global MeterProvider、但没有启用 APMPlus 时,VeADK 指标不会执行打点;
  2. 指标记录器同时承担 Provider、Reader 和 Exporter 创建职责,埋点逻辑与导出配置互相耦合。

改造后,VeADK 的指标记录不再根据 Exporter 做开关判断;由业务配置、自动埋点或 APMPlus 兜底创建的 Global MeterProvider 决定是否以及向哪里导出。

运行规则

当前状态 VeADK 打点行为 APMPlus 行为 外部输出
已安装 Hook,未启用 APMPlus,未配置真实 Provider 调用代理测量工具 不创建 Provider 无;默认代理直接丢弃
已安装 Hook,未启用 APMPlus,已有真实 Provider 指标进入已有 Provider 不参与 由已有 Reader / Exporter 决定
启用 APMPlus,当前为 _ProxyMeterProvider 指标进入后续安装的 Provider 创建 APMPlus Provider、Reader 和 Exporter APMPlus
启用 APMPlus,已有真实 Provider 指标进入已有 Provider 不替换、不追加 Reader 由已有 Reader / Exporter 决定
只有 Global MeterProvider,没有 OpentelemetryTracer 或任何 VeADK Exporter 当前不会安装 Portal Hook,因此不会产生 VeADK Portal 指标 不参与 只输出其他组件自身产生的指标

OpenTelemetry 1.37.0 会在安装真实 Provider 后,将已有代理测量工具绑定到真实 Provider。安装前发生的打点不会缓存或补报。

Portal Hook 的当前边界

本 MR 解耦的是“指标记录”与“Exporter / Provider 创建”,没有调整 Portal 遥测 Hook 的安装时机:

  • Portal Hook 通过 OpentelemetryTracer.model_post_init() 中的 patch_google_adk_telemetry() 安装;
  • 手动配置 OpentelemetryTracer,或通过 ENABLE_APMPLUSENABLE_COZELOOPENABLE_TLS 创建 Tracer 时,Hook 会安装;
  • 单独启动 opentelemetry-instrument 不等于安装 VeADK Portal Hook;自动埋点与 ENABLE_APMPLUS=true 同时使用时,会因为 VeADK 创建 OpentelemetryTracer 而安装 Hook;
  • 如果业务只配置 Global MeterProvider,但没有创建 OpentelemetryTracer 或启用任何 VeADK Exporter,当前只会上报其他组件自身产生的指标,不会产生 VeADK Portal 指标;
  • 该行为是本 MR 当前接受的边界,本次不继续调整。若后续需要做到“只要创建 Agent 就始终安装 Portal Hook”,应作为独立改造处理。

与 Trace 的关系

Provider 和导出链路保持独立:

  • 已有 Global TracerProvider 时,沿用 fix(tracing): trust preconfigured provider for APMPlus #813 的规则,跳过 APMPlus Span Processor 注册,避免 Trace 重复上报;
  • Portal 指标是否导出由 Global MeterProvider 决定,不依赖 APMPlus Span Processor 是否注册;
  • Portal Hook 的安装目前仍依赖 OpentelemetryTracer 初始化,边界见上一节;
  • 已有 Global MeterProvider 时,指标交给该 Provider。

E2E 验证

场景 APMPlus Exporter 数量 Global Provider / Reader 云端 span / 唯一 span 云端 gen_ai_chat_count
未启用 APMPlus,未配置全局 Provider 0 _ProxyMeterProvider / 0 0 / 0 0 条时序
未启用 APMPlus,代码预配置全局 Provider,并显式创建 OpentelemetryTracer 0 MeterProvider / 1 4 / 4 1
环境变量启用 APMPlus,无预配置 Provider 1 MeterProvider / 1 4 / 4 1
手动传入 APMPlusExporter(),无预配置 Provider 1 MeterProvider / 1 4 / 4 1
环境变量启用 APMPlus,代码预配置全局 Provider 1 MeterProvider / 1 4 / 4 1
手动传入 APMPlusExporter(),代码预配置全局 Provider 1 MeterProvider / 1 4 / 4 1
环境变量与手动 Exporter 同时启用,代码预配置全局 Provider 1 MeterProvider / 1 4 / 4 1
opentelemetry-instrument 自动埋点并启用 APMPlus(命令行 Agent) 1 MeterProvider / 1 5 / 5 1

7 个存在导出链路的 gen_ai_chat_count 查询都只有 1 条时序,且 current=min=max=1。所有云端 Trace 的 span 总数与唯一 span 数一致,错误 span 为 0。

最新服务级 E2E

场景 服务名 启动方式 云端 span / 唯一 span gen_ai_chat_count Token
非自动埋点 feng_local_test_no_auto 普通 Python 启动 FastAPI 4 / 4 1 输入 17 / 输出 3
自动埋点并启用 APMPlus feng_local_test_auto opentelemetry-instrument 启动 FastAPI 11 / 11 1 输入 19 / 输出 5

自动埋点场景多出的 Span 来自 FastAPI、HTTP 和 Jinja2 自动埋点,11 个 Span ID 全部不同,不属于重复上报。自动埋点场景使用更新后的 APMPlus appkey,MR 和测试报告不记录明文。

gen_ai.client.token.usage 同时存在 gen_ai_operation_name=generate_contentgen_ai_operation_name=chat 两套属性维度;自动埋点与非自动埋点场景均存在,因此不是重复 Exporter 导出。查询 Token 时需要按指标来源或 gen_ai_operation_name 区分,避免宽泛聚合造成重复计算。

自动化检查

  • pytest -q tests/test_agent.py tests/test_portal_metrics.py tests/test_tracing.py tests/test_tracing_content.py:49 项通过;
  • Ruff 0.11.12 检查和格式检查:通过;
  • git diff --check:通过;
  • GitHub Actions 的 Python 3.10 / 3.12 Unit Tests、pre-commit、License Header Check 均通过;
  • 当前 HEAD 的 Secret Scan 仍为失败状态,需要在合入前复查具体扫描结果;
  • 本地完整 pre-commit 在安装 gitleaks 环境时被旧 Go 工具链阻塞;GitHub pre-commit 已通过。

测试报告

@feng-95
feng-95 force-pushed the refactor/apmplus-meter-uploader branch from 2d60db9 to 1e6c1aa Compare August 4, 2026 16:02
@feng-95
feng-95 force-pushed the refactor/apmplus-meter-uploader branch from 15fa31d to e064701 Compare August 5, 2026 08:01
@feng-95 feng-95 changed the title refactor(metrics): decouple APMPlus meter uploader refactor(metrics): 解耦 Portal 指标打点与 Exporter Aug 5, 2026
@feng-95
feng-95 force-pushed the refactor/apmplus-meter-uploader branch from e064701 to 064ba19 Compare August 11, 2026 12:51
@feng-95
feng-95 marked this pull request as ready for review August 11, 2026 13:21
@feng-95
feng-95 force-pushed the refactor/apmplus-meter-uploader branch from 064ba19 to ac889d3 Compare August 11, 2026 14:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant