基于OpenTelemetry实现GenAI应用语义层监控与根因分析

基于OpenTelemetry实现GenAI应用语义层监控与根因分析 如果你正在开发或维护一个基于大语言模型GenAI的应用那么下面这个场景你一定不陌生你部署了一个智能客服机器人用户反馈时好时坏。有时它回答得精准流畅有时却答非所问甚至“胡言乱语”。你想定位问题却发现传统的监控指标如请求延迟、QPS完全不够用。你无法回答一些核心问题用户的哪些问题容易导致模型“幻觉”不同提示词Prompt模板的成功率差异有多大模型响应的质量如相关性、毒性如何量化传统的 APM 和日志工具在这里失灵了。你面对的是一个“黑盒”输入是自然语言输出也是自然语言。没有固定的状态码没有标准的错误类型。你只能靠人工抽查或者开发复杂的后处理脚本来分析日志效率低下且难以规模化。今天要介绍的开源项目正是为了解决这个痛点。它不是一个全新的监控平台而是一个巧妙的“连接器”——将 OpenTelemetryOtel的链路追踪Traces数据与你最关心的 GenAI 质量指标Metrics和原始提示词Raw Prompts关联起来。它的核心价值在于让你能用成熟的、云原生的可观测性技术栈Prometheus, Grafana等来监控和洞察 GenAI 应用的内部状态与质量。你不再需要为 GenAI 特制一套孤立的监控系统。本文将深入解析这个项目的设计思路、核心原理并提供一个从零开始的完整实战教程。你会学到为什么 GenAI 应用需要新的可观测性范式——传统监控的盲区在哪里。如何利用 OpenTelemetry 的灵活性捕获 GenAI 特有的语义信息。如何将非结构化的 LLM 交互提示词、响应转化为结构化的、可告警的指标。通过一个完整的示例应用手把手搭建从数据采集、处理到可视化的全链路监控。无论你是正在将 AI 功能集成到现有产品中的工程师还是负责维护 AI 服务稳定性的 SRE这篇文章都将为你提供一套立即可用的解决方案。1. 这篇文章真正要解决的问题从“黑盒猜测”到“白盒度量”在深入代码之前我们必须先厘清 GenAI 应用监控的独特挑战。传统的 Web 服务监控建立在可预测的输入输出之上HTTP 状态码、数据库查询耗时、异常堆栈。这些信号是结构化的、离散的。GenAI 应用则完全不同输入非结构化用户的提问Prompt千变万化长度、意图、复杂度各异。输出非结构化模型的回答是一段自然文本没有对错只有“好坏”或“相关与否”。“错误”定义模糊一个 HTTP 500 是明确的错误但一个回答了错误信息的模型响应即“幻觉”在协议层可能是完全成功的HTTP 200。成本敏感每一次 API 调用都直接产生费用Token 消耗低质量的交互意味着资源的浪费。因此监控 GenAI 应用核心是监控其“语义层”的质量和成本。你需要回答这些问题质量维度响应的相关性、准确性、完整性、毒性toxicity如何成本维度每次对话消耗了多少 Token哪些类型的 Prompt 导致 Token 消耗激增性能维度不同模型提供商如 OpenAI, Anthropic或不同模型版本如 gpt-4o vs gpt-3.5-turbo的延迟和成功率对比如何根因分析当发现质量下降时能否快速回溯到导致问题的具体用户提问和当时的完整对话上下文现有的方案往往是割裂的用 Datadog/NewRelic 看基础指标用 LangSmith/Arize 等 AI 专用平台看质量再自己写脚本算成本。这带来了数据孤岛、运维复杂和成本高昂的问题。本项目的核心思路是利用 OpenTelemetry 作为统一的数据采集和传输层在其强大的链路追踪Trace能力基础上附着 GenAI 特有的语义信息原始 Prompt、响应、评估分数等然后通过一个处理层将这些信息聚合、计算成标准的指标Metrics并最终接入通用的监控告警体系。简单说它让 GenAI 应用变得“可观测”而不仅仅是“可监控”。2. 核心概念与架构拆解在动手之前我们需要理解几个关键概念以及它们是如何协同工作的。2.1 OpenTelemetry (Otel) 与 TracesOpenTelemetry 是一个云原生计算基金会CNCF下的项目旨在提供一套统一的标准来收集、生成遥测数据包括链路追踪 Traces、指标 Metrics、日志 Logs。对于本文我们主要关注Traces。一个Trace代表一个完整的事务或工作流例如一次用户请求。它由一个唯一的TraceId标识。一个 Trace 由多个Span组成每个 Span 代表事务中的一个具体操作例如“调用 OpenAI API”、“解析用户意图”。Span 之间具有父子关系形成调用链。关键点每个 Span 可以携带丰富的Attributes属性这些是键值对可以记录任何你想附加的上下文信息例如user.idhttp.status_code 或者对我们至关重要的genai.promptgenai.response。2.2 GenAI 的语义信息附着项目通过在 Otel Span 上添加特定的 Attributes来标记 GenAI 交互。这通常在你的应用代码中完成。例如genai.operation: “completion” 或 “chat”genai.prompt: 用户发送的原始文本。genai.response: 模型返回的完整文本。genai.model: “gpt-4”genai.total_tokens: 本次调用消耗的总 Token 数。genai.evaluation.score.relevance: 一个后评估模型给本次回答的相关性打分0-1。2.3 从 Traces 到 Metrics 的转换这是项目的核心处理层。一个独立的处理器例如一个 Otel Collector 的处理器或一个独立的 Fluentd/Pipeline 服务会消费这些包含 GenAI 属性的 Trace 数据。它的工作流程是过滤识别出包含genai.*属性的 Span。提取与计算从这些 Span 的属性中提取数值如total_tokens,evaluation.score并可能进行一些计算如计算平均分、分桶统计。聚合按照特定的维度Dimensions进行聚合例如按genai.model、service.name、genai.operation分组。输出指标将聚合结果生成为标准的指标数据格式如 Prometheus 的genai_token_usage_total,genai_response_relevance_score并推送到指标后端如 Prometheus。2.4 原始提示词Raw Prompts的存储与检索指标是聚合后的、用于告警和趋势分析的数据。但当告警触发时运维人员需要查看导致问题的具体案例。这就是存储原始提示词和响应的意义。项目通常会将原始的、非结构化的genai.prompt和genai.response存储到一个支持全文检索的数据库中如 Elasticsearch。同时会保留这些数据与 TraceId 的关联。这样在 Grafana 仪表板上看到一个异常的指标例如某个模型的平均相关性分数骤降你可以直接点击数据点通过 TraceId 查询到对应的原始对话进行根因分析。架构全景图[你的 GenAI 应用] --(嵌入 Otel SDK生成带有 genai.* 属性的 Traces)-- [Otel Collector] | |-- (处理器提取 genai 属性生成 Metrics) -- [Prometheus] -- [Grafana 看板] | |-- (处理器将原始 Prompt/Response 写入) -- [Elasticsearch] -- [根因分析界面]3. 环境准备与前置条件我们将通过一个简单的 Python Flask 应用来模拟一个 GenAI 服务并搭建完整的监控栈。所需环境操作系统Linux / macOS / WSL2 (Windows)Docker Docker Compose用于一键部署后端组件Otel Collector, Prometheus, Grafana, Elasticsearch, Kibana。请确保已安装。Python 3.9用于编写示例应用。基础的命令行操作知识。组件版本说明以 Docker 镜像最新稳定版为准具体版本可能随时间更新OpenTelemetry Collector:otel/opentelemetry-collector-contrib:latestPrometheus:prom/prometheus:latestGrafana:grafana/grafana-oss:latestElasticsearch Kibana:docker.elastic.co/elasticsearch/elasticsearch:8.11.0,docker.elastic.co/kibana/kibana:8.11.0项目结构预览genai-observability-demo/ ├── docker-compose.yml # 定义所有后端服务 ├── collector-config.yaml # Otel Collector 配置 ├── prometheus.yml # Prometheus 配置 ├── app/ # Python 示例应用 │ ├── app.py │ ├── requirements.txt │ └── Dockerfile └── README.md4. 搭建可观测性后端基础设施我们首先使用 Docker Compose 启动所有支撑服务。创建docker-compose.yml文件version: 3.8 services: # OpenTelemetry Collector - 接收、处理、导出遥测数据 otel-collector: image: otel/opentelemetry-collector-contrib:latest container_name: otel-collector command: [--config/etc/otel-collector-config.yaml] volumes: - ./collector-config.yaml:/etc/otel-collector-config.yaml ports: - 4317:4317 # OTLP gRPC 接收端口 - 4318:4318 # OTLP HTTP 接收端口 - 8889:8889 # 健康检查/指标端口 networks: - observability-net depends_on: - prometheus - elasticsearch # Prometheus - 抓取并存储指标 prometheus: image: prom/prometheus:latest container_name: prometheus volumes: - ./prometheus.yml:/etc/prometheus/prometheus.yml - prometheus_data:/prometheus command: - --config.file/etc/prometheus/prometheus.yml - --storage.tsdb.path/prometheus - --web.console.libraries/etc/prometheus/console_libraries - --web.console.templates/etc/prometheus/console_templates - --storage.tsdb.retention.time200h - --web.enable-lifecycle ports: - 9090:9090 networks: - observability-net # Grafana - 指标可视化 grafana: image: grafana/grafana-oss:latest container_name: grafana volumes: - grafana_data:/var/lib/grafana environment: - GF_SECURITY_ADMIN_PASSWORDadmin ports: - 3000:3000 networks: - observability-net depends_on: - prometheus # Elasticsearch - 存储原始提示词和响应 elasticsearch: image: docker.elastic.co/elasticsearch/elasticsearch:8.11.0 container_name: elasticsearch environment: - discovery.typesingle-node - xpack.security.enabledfalse - ES_JAVA_OPTS-Xms512m -Xmx512m volumes: - elasticsearch_data:/usr/share/elasticsearch/data ports: - 9200:9200 networks: - observability-net # Kibana - Elasticsearch 的可视化界面 kibana: image: docker.elastic.co/kibana/kibana:8.11.0 container_name: kibana environment: - ELASTICSEARCH_HOSTShttp://elasticsearch:9200 ports: - 5601:5601 networks: - observability-net depends_on: - elasticsearch networks: observability-net: driver: bridge volumes: prometheus_data: grafana_data: elasticsearch_data:接下来配置 Otel Collector。创建collector-config.yamlreceivers: otlp: protocols: grpc: endpoint: 0.0.0.0:4317 http: endpoint: 0.0.0.0:4318 processors: # 批处理处理器优化性能 batch: timeout: 1s send_batch_size: 1024 # 这是一个关键处理器它从 Traces 中提取 GenAI 属性并生成 Metrics。 # 注意这是一个示例性的配置实际项目中可能需要自定义开发或使用社区贡献的处理器。 # 这里我们用 attributes 处理器模拟提取动作真正的指标生成逻辑通常在导出器中定义或通过自定义处理器实现。 attributes/genai: actions: - key: genai.operation action: insert from_attribute: genai.operation - key: genai.model action: insert from_attribute: genai.model - key: genai.total_tokens action: insert from_attribute: genai.total_tokens # 尝试转换为整型用于后续指标计算 converted_type: int exporters: # 将指标导出到 Prometheus prometheus: endpoint: 0.0.0.0:8889 namespace: genai const_labels: environment: demo # 将包含原始提示词的 Trace 数据导出到 Elasticsearch 进行存储 elasticsearch: endpoints: [http://elasticsearch:9200] logs_index: genai-traces traces_index: genai-traces # 调试用将日志打印到控制台 debug: verbosity: detailed service: pipelines: traces: receivers: [otlp] processors: [batch, attributes/genai] exporters: [elasticsearch, debug] metrics: receivers: [otlp] processors: [batch] exporters: [prometheus, debug]最后配置 Prometheus 来抓取 Collector 暴露的指标。创建prometheus.ymlglobal: scrape_interval: 15s evaluation_interval: 15s scrape_configs: - job_name: otel-collector static_configs: - targets: [otel-collector:8889] # 注意这里使用 Docker 服务名现在启动所有后端服务docker-compose up -d等待几分钟然后访问以下服务确认启动成功Grafana:http://localhost:3000(用户名admin, 密码admin)Prometheus:http://localhost:9090Kibana:http://localhost:5601Elasticsearch:http://localhost:9200(返回 JSON 信息)5. 编写并集成示例 GenAI 应用我们的示例应用是一个简单的 Flask API它模拟调用大语言模型。为了简化我们用一个随机函数来模拟模型响应和评估分数并集成 OpenTelemetry SDK 来发送带有 GenAI 属性的 Traces。创建应用目录app/和requirements.txtFlask2.3.3 opentelemetry-api1.21.0 opentelemetry-sdk1.21.0 opentelemetry-exporter-otlp1.21.0 opentelemetry-instrumentation-flask0.41b0创建app.pyimport random import time from flask import Flask, request, jsonify from opentelemetry import trace from opentelemetry.sdk.trace import TracerProvider from opentelemetry.sdk.trace.export import BatchSpanProcessor from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter from opentelemetry.instrumentation.flask import FlaskInstrumentor # 1. 设置 TracerProvider trace.set_tracer_provider(TracerProvider()) # 2. 创建 OTLP Exporter指向我们运行的 Collector otlp_exporter OTLPSpanExporter(endpointhttp://localhost:4317, insecureTrue) # 3. 创建 BatchSpanProcessor 并添加到 TracerProvider span_processor BatchSpanProcessor(otlp_exporter) trace.get_tracer_provider().add_span_processor(span_processor) # 4. 初始化 Flask 应用并自动注入仪表 app Flask(__name__) FlaskInstrumentor().instrument_app(app) # 获取一个 Tracer tracer trace.get_tracer(__name__) def call_mock_llm(prompt: str, model: str gpt-3.5-turbo): 模拟调用 LLM API并生成一些模拟的 GenAI 属性 # 模拟网络延迟 time.sleep(random.uniform(0.1, 0.5)) # 模拟响应文本 mock_responses [ f这是一个关于{prompt[:20]}...的模拟回答。, 根据我的知识库您的问题涉及多个方面。, 抱歉我无法回答这个问题。, 您能提供更多上下文信息吗 ] response random.choice(mock_responses) # 模拟 Token 消耗 (假设 prompt 长度影响) prompt_tokens len(prompt) // 4 completion_tokens len(response) // 4 total_tokens prompt_tokens completion_tokens # 模拟一个评估分数 (例如相关性) relevance_score random.uniform(0.5, 1.0) # 0.5 到 1.0 之间 return response, total_tokens, relevance_score app.route(/chat, methods[POST]) def chat_completion(): 处理聊天请求的端点 data request.get_json() user_prompt data.get(prompt, ) model data.get(model, gpt-3.5-turbo) # 为本次请求创建一个 Span with tracer.start_as_current_span(genai_chat_completion) as span: # 将 GenAI 相关的语义信息作为属性添加到 Span 上 # 这是将非结构化数据接入可观测性体系的关键一步 span.set_attribute(genai.operation, chat) span.set_attribute(genai.model, model) span.set_attribute(genai.prompt, user_prompt) # 原始提示词 # 注意在生产环境中需注意隐私和长度可能需要对长文本进行采样或哈希处理。 # 模拟调用 LLM response, total_tokens, relevance_score call_mock_llm(user_prompt, model) # 将响应和计算结果也作为属性记录 span.set_attribute(genai.response, response) # 原始响应 span.set_attribute(genai.total_tokens, total_tokens) span.set_attribute(genai.evaluation.score.relevance, relevance_score) span.set_attribute(http.status_code, 200) # 返回结果给用户 return jsonify({ model: model, response: response, usage: {total_tokens: total_tokens}, evaluation: {relevance: round(relevance_score, 2)} }) app.route(/health, methods[GET]) def health(): return jsonify({status: healthy}) if __name__ __main__: app.run(host0.0.0.0, port5000, debugFalse)创建Dockerfile以便容器化运行FROM python:3.9-slim WORKDIR /app COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt COPY . . CMD [python, app.py]更新docker-compose.yml在services部分添加我们的应用genai-app: build: ./app container_name: genai-app ports: - 5000:5000 environment: - OTEL_EXPORTER_OTLP_ENDPOINThttp://otel-collector:4317 networks: - observability-net depends_on: - otel-collector现在重新启动所有服务包括新应用docker-compose down docker-compose up -d --build6. 生成数据与验证流水线应用启动后我们可以发送一些请求来生成数据。使用curl或 Postman 发送请求# 发送一个聊天请求 curl -X POST http://localhost:5000/chat \ -H Content-Type: application/json \ -d {prompt: 请解释一下量子计算的基本原理。, model: gpt-4} # 发送另一个请求 curl -X POST http://localhost:5000/chat \ -H Content-Type: application/json \ -d {prompt: 今天的天气怎么样, model: gpt-3.5-turbo}多发送几个不同model和prompt的请求以生成多样化的数据。验证数据流检查 Collector 日志查看是否有数据被接收和处理。docker logs otel-collector --tail 20你应该能看到类似“TracesExporter”和“MetricsExporter”的日志条目。检查 Prometheus 指标访问http://localhost:9090在表达式输入框中输入genai_Prometheus 应该能自动补全出以genai_开头的指标例如genai_total_tokens。如果能看到说明指标已成功生成并导出。检查 Elasticsearch 数据访问http://localhost:5601进入 Kibana。首次进入需要创建索引模式。进入Management Stack Management Index Patterns。创建索引模式genai-traces*。然后进入Analytics Discover选择genai-traces*索引模式你应该能看到包含genai.prompt和genai.response字段的文档记录。7. 配置 Grafana 仪表板进行可视化现在数据已经流入 Prometheus 和 Elasticsearch我们可以在 Grafana 中创建仪表板来洞察我们的 GenAI 应用。添加数据源登录 Grafana (http://localhost:3000admin/admin)。进入Configuration Data Sources。点击Add data source选择Prometheus。URL 填写http://prometheus:9090注意使用 Docker 服务名点击Save Test应显示成功。同样方式添加Elasticsearch数据源URL 填写http://elasticsearch:9200Index name 填写genai-traces*。创建指标仪表板新建一个 Dashboard。添加一个 Panel查询 Prometheus 指标例如总 Token 消耗趋势sum(genai_total_tokens) by (genai_model)平均响应相关性分数avg(genai_evaluation_score_relevance) by (genai_model)请求速率rate(genai_request_duration_seconds_count[5m])(需要先定义该指标)利用 Grafana 的图表类型时间序列图、柱状图、仪表盘进行可视化。关联原始数据高级这是体现“Bounded”价值的关键——将指标与原始提示词关联。在指标图表上可以添加一个 “Drilldown” 链接。链接指向 Kibana Discover 页面并携带时间范围过滤和可能的trace.id参数如果我们在 Span 中记录了它。这样当你在 Grafana 上看到一个异常峰值时点击它就能直接跳转到 Kibana查看在那个时间点导致问题的具体用户提问和模型回答。示例 Grafana 查询用于 Token 消耗 假设我们的处理器将genai.total_tokens属性转换为了一个名为genai_token_usage_total的计数器Counter指标。我们可以这样查询每秒的 Token 消耗速率sum(rate(genai_token_usage_total[5m])) by (genai_model)8. 常见问题与排查思路问题现象可能原因排查方式解决方案应用启动失败无法连接 Collector1. Collector 服务未运行。2. 网络配置错误应用容器无法访问otel-collector:4317。3. 端口映射错误。1.docker ps检查otel-collector容器状态。2. 在应用容器内执行nc -zv otel-collector 4317。3. 检查docker-compose.yml中网络配置和端口映射。1. 确保docker-compose up -d成功。2. 确认所有服务在同一个自定义网络如observability-net下。3. 检查应用环境变量OTEL_EXPORTER_OTLP_ENDPOINT是否正确。Prometheus 中查询不到genai_开头的指标1. Collector 的 Prometheus exporter 配置错误或未启动。2. 处理器未能正确从 Traces 生成 Metrics。3. 应用没有发送带有genai.*属性的 Span。1. 访问http://localhost:8889/metrics查看 Collector 自身暴露的指标确认是否有 GenAI 相关指标。2. 检查 Collector 日志查看prometheusexporter 是否有错误。3. 检查应用代码确认span.set_attribute被正确调用。1. 核对collector-config.yaml中exporters.prometheus的配置和service.pipelines.metrics的组成。2. 确保处理器如attributes/genai在tracespipeline 中并且属性被成功提取和转换。3. 在应用中使用debugexporter 或打印日志确认 Span 属性已设置。Kibana 中查不到 Trace 数据1. Elasticsearch exporter 配置错误。2. Elasticsearch 索引创建失败或名称不匹配。3. 数据格式不符合 Elasticsearch 要求。1. 检查 Collector 日志中elasticsearchexporter 的相关信息。2. 直接访问http://localhost:9200/_cat/indices?v查看是否存在genai-traces索引。3. 访问http://localhost:9200/genai-traces/_search?pretty尝试查询数据。1. 核对collector-config.yaml中exporters.elasticsearch的endpoints和index配置。2. 确保 Elasticsearch 服务健康运行且版本兼容。3. 考虑在 exporter 中增加flush相关配置或检查是否有字段映射冲突。Grafana 图表显示 “No Data”1. Prometheus 数据源配置错误。2. 查询的指标名称不正确。3. 时间范围选择不当尚无数据。1. 在 Grafana 数据源配置页面点击Save Test。2. 前往 Prometheus UI (http://localhost:9090)在 Graph 页面的指标下拉框中查找正确的指标名。3. 扩大 Grafana 仪表板的时间范围。1. 确保 Prometheus 数据源的 URL 指向正确的地址在 Docker 网络内使用服务名。2. 使用 Prometheus 的表达式浏览器验证指标查询语句。3. 确认应用已产生数据且数据流已到达 Prometheus。原始提示词字段过长导致 ES 写入失败Elasticsearch 默认对字符串字段长度有限制ignore_above。查看 Collector 或 Elasticsearch 日志寻找max_bytes_length_exceeded或类似的错误。1. 在应用侧对过长的 Prompt 进行截断或采样。2. 在 Elasticsearch 中为该索引的特定字段设置更大的ignore_above值或使用text类型而非keyword。9. 生产环境最佳实践与进阶建议将这套方案用于生产环境需要考虑更多因素采样策略Sampling全量收集所有 Prompt 和 Response 对存储和网络压力巨大。必须实施采样。头部采样Head-based在入口处决定是否记录整个 Trace。可以基于概率如 10%或基于规则如只记录错误请求、慢请求、或特定用户群的请求。尾部采样Tail-based先收集所有数据在 Collector 端根据最终结果例如响应包含错误、评估分数过低决定是否保留。这更精准但更复杂。Otel Collector 提供了tail_sampling处理器。隐私与合规PII原始 Prompt 和 Response 可能包含用户个人信息、敏感商业数据。脱敏在应用 SDK 或 Collector 处理器中对特定字段如邮箱、手机号、身份证号进行掩码或哈希处理。访问控制确保 Kibana 或存储原始数据的数据库有严格的权限控制仅限授权人员访问。数据保留策略为 Elasticsearch 索引设置合理的 TTL生存时间自动删除过期数据。自定义指标与评估本文示例使用了简单的随机分数。在实际中你需要定义对业务有意义的评估维度。业务指标例如对于客服机器人可以定义“问题解决率”、“转人工率”。自动化评估集成一个评估服务可以是另一个 LLM 调用或规则引擎对每次响应自动打分相关性、安全性、事实准确性等并将分数作为属性记录。成本指标除了总 Token 数可以计算每次请求的成本根据模型定价并聚合为每日/每用户成本。性能与扩展性Collector 部署在生产中Otel Collector 应以 DaemonSetK8s或 Sidecar 形式部署靠近应用以减少网络延迟和单点故障。缓冲与重试配置 Collector 的batch处理器和导出器的队列、重试策略以应对后端存储如 Prometheus, ES的临时不可用。指标基数控制避免使用高基数的属性如user_id作为指标的标签Label这会导致 Prometheus 指标爆炸。这类高基数维度应留在 Trace 或 Log 中用于下钻分析。告警规则基于生成的指标在 Prometheus Alertmanager 或 Grafana 中设置有意义的告警。质量告警avg(genai_evaluation_score_relevance) 0.7持续 5 分钟。成本告警sum(rate(genai_token_usage_total[1h])) 100000每小时 Token 消耗超 10万。错误率告警rate(genai_request_failures_total[5m]) / rate(genai_requests_total[5m]) 0.05失败率超过 5%。通过将 OpenTelemetry 的链路追踪能力与 GenAI 应用的语义层信息相结合我们构建了一套统一、强大且可扩展的可观测性方案。它打破了传统监控对 GenAI “黑盒”的无力感让开发者能够像监控任何关键业务服务一样监控 AI 模型的质量、性能和成本。这套方案的核心优势在于其标准化和可集成性——你无需抛弃现有的 Prometheus、Grafana、Elasticsearch 技术栈而是通过 Otel 这一 CNCF 标准优雅地将其扩展到了 AI 时代。你可以从本文的示例出发根据实际业务需求定制需要收集的属性、定义关键指标、设计评估维度并构建起真正服务于你业务的 GenAI 可观测性体系。当你的下一个 AI 功能出现效果波动时你将不再只能猜测而是可以精准地定位到问题源头。