mcpField
D
dt-setup-genai

dt-setup-genai

github.com/dynatrace云与 DevOps17112 次安装2 天前更新
代码仓库

关于 dt-setup-genai

这套流程指导如何为 Python 和 TypeScript GenAI 应用接入 Dynatrace 遥测,涵盖路径选择、跨度补充和结果验证,并明确敏感操作的审批边界。

主要功能

  1. 01选择原生 OTel 或备用路径
  2. 02检测 SDK 与现有埋点
  3. 03补充跨度的会话上下文
  4. 04使用 dtctl 验证遥测
  5. 05指导消息内容捕获设置

适用场景

  1. 01为新的 Python 或 TypeScript GenAI 应用添加埋点
  2. 02为未覆盖的 SDK 选择实现方案
  3. 03检查跨度是否符合 Dynatrace 要求

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/dynatrace/dynatrace-for-ai --skill dt-setup-genai

安装后在 Claude Code 中输入/dt-setup-genai确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
enhance-existing.md
enrich-normalization.md
examples-index.md
multi-sdk-apps.md
no-native-instrumentation.md
validate-contract.md

详细介绍

为 Dynatrace 监控 GenAI 应用

这是 dynatrace-oss/dynatrace-ai-agent-instrumentation-examples 中各框架配方背后的通用决策流程。下文将其简称为 示例仓库。我们将此流程提取出来,使其适用于该仓库尚未覆盖的 SDK。它会告诉你应该采用哪种配方形式,以及原因;无论使用哪种 SDK 或语言,都能据此判断何时算是“完成”。有了持续传输的 span 后,加载 dt-obs-genai 来分析它们。

以下情况不应使用此技能

  • 已经完成监控,现在想要查询或调试 GenAI 遥测数据 → dt-obs-genai。
  • 已经了解该 SDK 的配方,只想复制粘贴代码 → 直接前往示例仓库;此技能用于判断适用哪种配方形式,而不是替代配方。
  • 应用不是 Python 或 TypeScript → 不在此技能的适用范围内。

此技能必须暂停并征求同意的情况

  • 对客户应用代码的任何修改——先展示差异并征得同意。
  • 凭据——由客户创建 Dynatrace 令牌和提供商密钥。切勿打印、记录或存储令牌值;只能通过环境变量或密钥存储来引用。
  • 向其租户部署 OpenPipeline 管道。
  • 此技能无法推断的提供商配置——Azure 部署名称/API 版本、Ollama 模型标签、Bedrock 区域/配置文件。
  • 向其运行时添加采集器——不在适用范围内;这是基础设施问题,而非配置问题。
  • 启用消息内容捕获——默认关闭;只有在用户提出要求时才启用。 提示词/补全内容可能包含 PII 或敏感数据,而且控制项因 SDK 而异: 某些监控器使用 OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT=true;其他监控器使用环境变量无法控制的框架原生标志,而且该标志可能默认开启(例如 pydantic-ai 的 InstrumentationSettings(include_content=...));OpenInference 默认会捕获内容;而 Traceloop/OpenLLMetry 的 opentelemetry-instrumentation-<sdk> 软件包会读取 TRACELOOP_TRACE_CONTENT,默认值为 ON,并忽略 OTel 标准变量。请检查 SDK 实际使用的开关,避免在未注意到的情况下启用内容捕获;如有需要,请商定脱敏方案。

四个步骤

detect ─▶ instrument ─▶ enrich ─▶ validate
  │                                  │
  └──────────── feedback loop ───────┘
   (validate failure → fix in enrich or instrument)
1. 检测

在改动任何代码之前,先弄清楚要为什么添加监测。

输入:

  • 依赖清单(pyproject.toml / requirements.txt / package.json)——当前有哪些 LLM SDK、Agent 框架或可观测性 SDK(OpenAI、Anthropic、Bedrock、LangChain/LangGraph、CrewAI、MCP 服务/客户端、Langfuse,……)。应用可能依赖多个 SDK——请参阅 references/multi-sdk-apps.md。
  • 主机是否已运行 Dynatrace OneAgent(是否存在 oneagent 进程/软件包)——如果已运行,OneAgent 会自动监测常见的 HTTP/SDK 调用,无需更改代码,这会彻底改变后续流程。
  • 应用是否已经接入任何 OTel——例如已有全局 TracerProvider、已有 Traceloop.init()/instrumentor 调用,或已有自定义 span 代码。

输出:针对每个 SDK,确定一个路由键 (框架/SDK, 现有监测状态)(如果有多个 SDK,请参阅 references/multi-sdk-apps.md)、一个分支决策(见下文),以及一个是否使用原生 OTel的决策(第 2 步)。

如何在原生 OTel 与回退方案之间做出选择:****优先选择具有纯 OTel 路径的 SDK(原生 gen_ai.*)。没有原生路径的 SDK 则回退到 OpenInference——只有在其发出 gen_ai.*(Python 语义约定双写,第 2 步)时,才能走完整个流程;否则流程会停在规范化关卡。按以下顺序检查,遇到首个符合项时停止:

  1. 在 references/examples-index.md 中查找该 SDK。如果列出了 opentelemetry/ 配方,这是最快的路径——使用它。
  2. 如果未列出该 SDK,请查看 OpenTelemetry 注册表和厂商 SDK 自身的文档,确认是否支持原生 OTel/gen_ai.*(例如,otel 扩展、span_exporter/tracer provider 钩子,或内置语义约定属性)。 找到后 → 对其进行监测(第 2 步)。
  3. 没有原生 OTel 路径 → 使用 OpenInference。 根据 examples-repo 配方,使用匹配的 openinference-instrumentation-<sdk> 软件包进行监测;如果连这样的软件包都没有,则手动编写 gen_ai.* spans (references/no-native-instrumentation.md)。 只有在发出 gen_ai.* 时,OpenInference 才能走完整个流程——即启用了语义约定双写的 Python instrumentor(第 2 步)。否则(TS/node、旧版本或未设置),spans 会保持为 llm.*/openinference.*,该技能会停在规范化关卡 (references/enrich-normalization.md),然后再继续。
2. 添加监测

接入 span 发出功能。优先选择纯 OTel 路径;只有不存在原生 OTel 路径时,才回退到 OpenInference。只有在该回退方案发出 gen_ai.*(下文的语义约定双写)时,才能走完整个流程;否则会在验证前停在规范化关卡。

  • 纯 OTel(首选,端到端受支持)。 使用原生 OTel 插桩包,或框架自身的 OTel 集成,直接发出 gen_ai.*——直接导出到 Dynatrace OTLP 端点(主机和范围规则见下方的通用形式),或通过采集器导出。许多 Agent 框架和供应商 SDK 都提供了这类集成(或接受自定义 span_exporter);当前列表位于示例仓库,而非本文档中。⚠️ 优先选择由 OTel 正式发布的插桩包,而非 Traceloop/OpenLLMetry 插桩包——据报告,Traceloop/OpenLLMetry 上游已停止维护,因此不要将其用于新的插桩(如果应用已在使用,应按增强现有配置/迁移处理)。它还默认启用消息内容采集;要使用哪个包以及如何路由,请参阅 references/examples-index.md §1a。
  • 回退方案 = OpenInference。 没有原生 OTel 路径 → 使用示例仓库配方中与之匹配的 openinference-instrumentation-<sdk> 包(OpenAIInstrumentor、AnthropicInstrumentor 等)。初始化前,必须使用该 SDK 文档说明的设置,明确禁用其默认开启的消息内容采集;不要依赖 OTel 标准环境变量。如果无法禁用采集,请停止并在运行请求前询问。 Python 插桩包可以双写;验证方式与原生 OTel 相同。其他情况(TS/node、旧版或未设置)下,跨度会保留为 llm.*/openinference.*,技能会在 Validate 前停止,直到用户应用规范化处理器(references/enrich-normalization.md)。如果也没有 OpenInference 包 → 手动编写跨度(references/no-native-instrumentation.md)。
  • 存在 OneAgent: 跳过此步骤——无需更改代码,OneAgent 会自动插桩。只需为应用/服务设置唯一标题(例如 FastAPI(title=...)),这样 Smartscape 才会创建独立实体,而不是将其与其他应用合并。

通用形式,适用于绿地模式(不使用 OneAgent 时): 与应用现有的包管理器保持一致;若从头创建(Python),默认使用 uv。

  1. 构建一个至少包含 service.name 的 Resource,并基于它创建 TracerProvider。gen_ai.agent.name 和其他 Agent 身份属性属于跨度级别,而非 Resource 级别——GenAI 视图和 Agent 快速筛选器会从跨度中读取这些属性,因此应在创建跨度时或在跨度处理器中设置(见 Enrich),而不要设置在 Resource 上。
  2. 添加跨度处理器和 OTLP 导出器,目标设为 Dynatrace 直连,或在 Enrich 需要先转换数据时设为本地 OTel Collector(http://localhost:4318)。端点形式取决于导出器——两者不能互换:
    • 采集器的 otlphttp 导出器使用基础路径($DT_ENDPOINT/api/v2/otlp),并自行追加 /v1/<signal>。
    • SDK 原生导出器(例如 Python 的 OTLPSpanExporter(endpoint=...)、Node 的 OTLPTraceExporter)会将端点原样用作 POST URL——传入完整的 $DT_ENDPOINT/api/v2/otlp/v1/traces(或 /v1/metrics、/v1/logs),否则会返回 404。 请求头:Authorization: Api-Token $DT_API_TOKEN,令牌范围为 openTelemetryTrace.ingest,如有需要,还需 metrics.ingest/logs.ingest。切勿打印、记录或存储令牌值。
  3. 在应用首次调用 LLM 前调用插桩包/SDK 初始化,而不要等到请求处理程序内部才初始化;并包装该调用,以便附加会话/对话关联信息(见 Enrich)。

输入: 路由键 + 步骤 1 中的原生 OTel 决策;DT_ENDPOINT/DT_API_TOKEN 或采集器端点;服务名称。 输出: 运行中的应用发出跨度——直接发出 gen_ai.*(纯 OTel),或发出 llm.*/openinference.*,等待用户端的规范化处理器(回退方案)。

3. 丰富数据

让跨度符合完整的 gen_ai.* 语义约定,并添加跨领域上下文。

无论采用哪种路径,都必须执行:

  • 将指标导出设置为差量时间性(OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE=delta)——Dynatrace 会以 400 错误拒绝累积指标。
  • 捕获消息内容(OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT=SPAN_ONLY 或 SPAN_AND_EVENT、框架原生标志,或 OpenInference 默认启用的捕获)属于必须暂停并征求同意的决定——见上文。获得批准后,确认 gen_ai.input.messages / gen_ai.output.messages 已写入。
  • 为每次对话设置一个稳定的对话 ID,不能每次请求都重新生成,目标属性为 gen_ai.conversation.id。优先使用框架原生机制(如果有),例如 pydantic-ai 会通过其检测功能,从运行/消息历史中推导出 gen_ai.conversation.id;否则,如果在调用位置自行创建跨度,则使用语言特定的跨度修改 API(Python 中的 set_attribute,或 Node 中的 setAttribute——例如没有原生检测功能时的手动跨度路径);对于会在内部创建跨度、且调用位置无法获取跨度句柄的自动检测基准包,则注册语言特定的跨度处理器钩子(Python 中的 on_start,Node 中的 onStart),并在跨度导出前设置属性——应用能够提供的检测器所遗漏的任何属性也都可以采用相同机制。 在多 Agent 应用中,将同一个 ID 传递给每次 Agent/子 Agent 调用——否则每次运行都会生成自己的 ID,对话就会碎片化,只共享一个 trace.id。 OpenInference 用户请注意:using_attributes(session_id=...) 输出的是 session.id,而不是 gen_ai.conversation.id,因此请确认 规范化规则确实会映射该属性。
  • 对于 Agent 框架,应预期出现嵌套跨度(crew/工作流 → Agent → 任务/工具); 应根据跨度名称/跨度类型推导时长指标,而不是根据 gen_ai.operation.name——CrewAI 会在所有三个层级同时将该属性设为 invoke_agent,从而将它们合并到一个直方图中。

回退路径(OpenInference)——用户侧规范化关卡:当无法进行 semconv 双写(TS/node、旧版本)时,跨度会以 llm.*/openinference.* 的形式到达,而不是 gen_ai.*,因此在完成规范化前,Validate 无法通过——且该技能无法替用户执行此步骤。提供示例规范化器配置(collector gen_ai_normalizer 或 OpenPipeline——见 references/enrich-normalization.md),仅在用户确认已应用后再继续 Validate。

**输入:**步骤 2 的原始跨度——gen_ai.*(纯 OTel),或等待用户侧规范化的 llm.*/openinference.*(回退路径)。 **输出:**符合 gen_ai.* 规范的跨度,带有对话关联信息,以及推导出的 Agent/工作流时长或令牌用量指标。

4. 验证

针对已知契约确认整个流水线端到端正常运行——不要凭目测判断。 **dtctl 是主要验证循环:**它会查询 Dynatrace 中已发出的 span,让断言具备机械性且可重复。完整流程、契约固定版本和严重性规则见 references/validate-contract.md。

**输入:**步骤 2–3 中运行且已插桩的应用。在 OpenInference 回退路径中,只有在用户确认其标准化器已应用(Enrich 门控)后,才能开始 Validate——否则,下面所有检查都会因 llm.* span 从未映射而失败。 步骤:

  1. 通过应用发送真实请求。
  2. 检查是否已安装 dtctl(dtctl version);如果没有,请先从 dtctl README 安装,再继续。
  3. 使用 dtctl 查询生成的 span,并按 service.name 筛选——请参阅 references/validate-contract.md 中现成的 dtctl query。 (如果 dtctl 不可用,可手动回退:在 AI Observability 应用的 Explorer / Distributed Tracing 应用中运行相同的 fetch spans DQL——加载 dt-dql-essentials 了解查询语法——但这样会失去 dtctl 提供的可重复断言。)
  4. 根据与应用提供方匹配的契约配置文件,断言其中声明的必需字段和指标——至少需要 gen_ai.provider.name/gen_ai.system(二选一;优先发出 gen_ai.provider.name)。除非所选配置文件/场景将 gen_ai.operation.name 标记为必需字段,否则应将其视为推荐字段;仅当配置文件规定适用时,才应用推理/提供方特定字段。严重性(失败还是警告)及各提供方的配置文件见:references/validate-contract.md。 **输出:**相对于契约的通过/失败结果。如果失败,应在 Enrich 中修复(属性映射缺失/错误),或在 Instrument 中修复(SDK/收集器配置错误)——不要在 Validate 本身修复;Validate 只负责检测,不会修补。修复后,重新运行相同的 dtctl 查询予以确认。

**OneAgent 路径:**步骤 1–4 不变——仍使用 dtctl 查询——但失败时没有 Instrument/Enrich 步骤可供处理:要么是无法修复的 OneAgent 版本差异(报告此问题),要么是步骤 2 中实体标题不唯一(修复标题)。Validate 通过后,加载 dt-obs-genai 进行分析。

从零构建与增强现有项目

两条路径都执行相同的四个步骤——区别在于 Detect 会发现什么,以及 Instrument 可以修改什么。默认选择增强现有项目;从零构建仅适用于少数例外情况。

增强现有项目——任务针对的是一个现有仓库、应用、模板、示例集合、工作流或配置,**即使要求添加的特定文件或示例目前尚不存在也一样。必须保留既有契约——例如同级实现、插桩设置、构建/依赖约定、测试框架或部署配置——因此应遵循现有约定,不要另行创建一套。**从零构建中的“常见结构”不适合直接照搬:全新的 Resource/TracerProvider 会静默替换现有对象,可能导致应用依赖的 span 丢失。有关各类情况的详细说明及服务命名冲突规则,请参阅 references/enhance-existing.md。

从零构建——仅当没有需要保留的现有仓库契约、同级实现、插桩设置、构建约定、测试框架或部署配置时才适用。只有在这种情况下,Instrument 才能创建全新的 Resource/TracerProvider/exporter,而不会有覆盖任何现有内容的风险。如有疑问,就按增强现有项目处理——遵循现有做法,而不是搭建新结构。

参考资料

评论

支持 Markdown