用途:让一个 Python 服务根据应用元数据,将每次被追踪的操作发往各自正确的 Arize space_id 与 project_name。每个操作在第一个 span 开始前必须解析出唯一的 space_id 和 project_name。普通单项目追踪请用 arize-instrumentation;本技能不做导出后重路由、不回填历史 span、不创建 Arize space/project,也不替用户编造元数据映射。
安全规则:不得猜测目标或静默使用其他租户的目标;不得把 API key 写入代码或让用户粘贴到聊天中,从环境变量读取 ARIZE_API_KEY。保留已有非 Arize 导出器与处理器;移除或替换固定目标的 Arize 导出路径,避免路由 span 被复制到旧目的地。路由元数据缺失、无效或不可用时应让业务继续运行但不向 Arize 导出 span,并在全新 OpenTelemetry 上下文中运行以防旧值跨租户泄漏,日志告警不含密钥或敏感元数据。使用一把对所有目标 space 都有权限的 API key,否则停止并报告凭据阻塞。
第一阶段检查与定义契约:确定要改的 Python 服务与入口;找出现有追踪初始化、provider/导出器、instrumentor 与客户端创建顺序;找到拥有目标元数据的请求或 agent 执行边界;确定稳定元数据字段及其现有真实来源,用于解析 space_id 与 project_name;检查可能超出请求上下文的异步任务、线程池、队列或后台 worker;找出测试命令与风格;只检查目标应用配置。范围、字段、映射来源或目标行为不明确时,先提出最小必要问题,不要先装包或改代码。
第二阶段实现:用项目包管理器要求 arize-otel>=0.11.0,不改无关依赖。无现有 provider 时,在 instrumentor 和 LLM 客户端之前调用 register_with_routing(api_key=os.environ["ARIZE_API_KEY"]);已有非 Arize provider 时保留它并添加 ArizeRoutingSpanProcessor(api_key=os.environ["ARIZE_API_KEY"], endpoint=Endpoint.ARIZE, transport=Transport.GRPC),沿用应用现有 endpoint 与 transport,且不要在其他全局 provider 安装后调用 register_with_routing。解析器必须同时返回两个非空值,否则视为无目标;映射数据保留在原有真实来源,不复制进追踪代码。元数据可用时,在最外层边界用 set_routing_context(space_id=target.space_id, project_name=target.project_name) 包裹整个操作;无目标时在全新上下文中执行业务。只捕获解析器预期的查找/配置异常,不隐藏无关失败。路由上下文内自动与手动子 span 会继承 arize.space_id 与 arize.project.name;不要在 span 开始后再设置路由。后台任务需显式传播上下文或在 worker 中重新解析并进入新路由上下文。
验证:对解析器与执行边界跑单测;证明两种元数据产生两组不同 space/project;证明子 span 继承所选对;证明并发不泄漏上下文;证明未知元数据与解析失败会清除继承路由、不导出到任何回退目标且业务继续;证明原有非 Arize 导出器/处理器仍挂载且无固定 Arize 路径;在非生产 space 为每个目标触发唯一命名 trace,并用 arize-trace 与相同凭据确认 trace 只出现在预期目标。短生命周期脚本退出前调用 force_flush() 与 shutdown()。仅通过单测不得声称完成,除非未要求在线验证。
限制:两个路由值必填,缺一即跳过 span;ArizeRoutingSpanProcessor 按唯一 space 创建并缓存处理器,高基数 space ID 需先评估;路由只选择 space 与 project,其他客户元数据仍应放在普通 OpenInference 属性中;若发现 arize-otel 缺少能力,应停止并提出独立 SDK 变更,而非添加兼容 hack。允许值分片、并发、测试与验证细节见 references/REFERENCE.md;相关技能有 arize-instrumentation、arize-trace、arize-admin。