GenAI應(yīng)用語義層監(jiān)控與根因分析)
如果你正在開發(fā)或維護(hù)一個基于大語言模型GenAI的應(yīng)用那么下面這個場景你一定不陌生你部署了一個智能客服機(jī)器人用戶反饋時好時壞。有時它回答得精準(zhǔn)流暢有時卻答非所問甚至“胡言亂語”。你想定位問題卻發(fā)現(xiàn)傳統(tǒng)的監(jiān)控指標(biāo)如請求延遲、QPS完全不夠用。你無法回答一些核心問題用戶的哪些問題容易導(dǎo)致模型“幻覺”不同提示詞Prompt模板的成功率差異有多大模型響應(yīng)的質(zhì)量如相關(guān)性、毒性如何量化傳統(tǒng)的 APM 和日志工具在這里失靈了。你面對的是一個“黑盒”輸入是自然語言輸出也是自然語言。沒有固定的狀態(tài)碼沒有標(biāo)準(zhǔn)的錯誤類型。你只能靠人工抽查或者開發(fā)復(fù)雜的后處理腳本來分析日志效率低下且難以規(guī)模化。今天要介紹的開源項目正是為了解決這個痛點。它不是一個全新的監(jiān)控平臺而是一個巧妙的“連接器”——將 OpenTelemetryOtel的鏈路追蹤Traces數(shù)據(jù)與你最關(guān)心的 GenAI 質(zhì)量指標(biāo)Metrics和原始提示詞Raw Prompts關(guān)聯(lián)起來。它的核心價值在于讓你能用成熟的、云原生的可觀測性技術(shù)棧Prometheus, Grafana等來監(jiān)控和洞察 GenAI 應(yīng)用的內(nèi)部狀態(tài)與質(zhì)量。你不再需要為 GenAI 特制一套孤立的監(jiān)控系統(tǒng)。本文將深入解析這個項目的設(shè)計思路、核心原理并提供一個從零開始的完整實戰(zhàn)教程。你會學(xué)到為什么 GenAI 應(yīng)用需要新的可觀測性范式——傳統(tǒng)監(jiān)控的盲區(qū)在哪里。如何利用 OpenTelemetry 的靈活性捕獲 GenAI 特有的語義信息。如何將非結(jié)構(gòu)化的 LLM 交互提示詞、響應(yīng)轉(zhuǎn)化為結(jié)構(gòu)化的、可告警的指標(biāo)。通過一個完整的示例應(yīng)用手把手搭建從數(shù)據(jù)采集、處理到可視化的全鏈路監(jiān)控。無論你是正在將 AI 功能集成到現(xiàn)有產(chǎn)品中的工程師還是負(fù)責(zé)維護(hù) AI 服務(wù)穩(wěn)定性的 SRE這篇文章都將為你提供一套立即可用的解決方案。1. 這篇文章真正要解決的問題從“黑盒猜測”到“白盒度量”在深入代碼之前我們必須先厘清 GenAI 應(yīng)用監(jiān)控的獨特挑戰(zhàn)。傳統(tǒng)的 Web 服務(wù)監(jiān)控建立在可預(yù)測的輸入輸出之上HTTP 狀態(tài)碼、數(shù)據(jù)庫查詢耗時、異常堆棧。這些信號是結(jié)構(gòu)化的、離散的。GenAI 應(yīng)用則完全不同輸入非結(jié)構(gòu)化用戶的提問Prompt千變?nèi)f化長度、意圖、復(fù)雜度各異。輸出非結(jié)構(gòu)化模型的回答是一段自然文本沒有對錯只有“好壞”或“相關(guān)與否”?!板e誤”定義模糊一個 HTTP 500 是明確的錯誤但一個回答了錯誤信息的模型響應(yīng)即“幻覺”在協(xié)議層可能是完全成功的HTTP 200。成本敏感每一次 API 調(diào)用都直接產(chǎn)生費用Token 消耗低質(zhì)量的交互意味著資源的浪費。因此監(jiān)控 GenAI 應(yīng)用核心是監(jiān)控其“語義層”的質(zhì)量和成本。你需要回答這些問題質(zhì)量維度響應(yīng)的相關(guān)性、準(zhǔn)確性、完整性、毒性toxicity如何成本維度每次對話消耗了多少 Token哪些類型的 Prompt 導(dǎo)致 Token 消耗激增性能維度不同模型提供商如 OpenAI, Anthropic或不同模型版本如 gpt-4o vs gpt-3.5-turbo的延遲和成功率對比如何根因分析當(dāng)發(fā)現(xiàn)質(zhì)量下降時能否快速回溯到導(dǎo)致問題的具體用戶提問和當(dāng)時的完整對話上下文現(xiàn)有的方案往往是割裂的用 Datadog/NewRelic 看基礎(chǔ)指標(biāo)用 LangSmith/Arize 等 AI 專用平臺看質(zhì)量再自己寫腳本算成本。這帶來了數(shù)據(jù)孤島、運維復(fù)雜和成本高昂的問題。本項目的核心思路是利用 OpenTelemetry 作為統(tǒng)一的數(shù)據(jù)采集和傳輸層在其強大的鏈路追蹤Trace能力基礎(chǔ)上附著 GenAI 特有的語義信息原始 Prompt、響應(yīng)、評估分?jǐn)?shù)等然后通過一個處理層將這些信息聚合、計算成標(biāo)準(zhǔn)的指標(biāo)Metrics并最終接入通用的監(jiān)控告警體系。簡單說它讓 GenAI 應(yīng)用變得“可觀測”而不僅僅是“可監(jiān)控”。2. 核心概念與架構(gòu)拆解在動手之前我們需要理解幾個關(guān)鍵概念以及它們是如何協(xié)同工作的。2.1 OpenTelemetry (Otel) 與 TracesOpenTelemetry 是一個云原生計算基金會CNCF下的項目旨在提供一套統(tǒng)一的標(biāo)準(zhǔn)來收集、生成遙測數(shù)據(jù)包括鏈路追蹤 Traces、指標(biāo) Metrics、日志 Logs。對于本文我們主要關(guān)注Traces。一個Trace代表一個完整的事務(wù)或工作流例如一次用戶請求。它由一個唯一的TraceId標(biāo)識。一個 Trace 由多個Span組成每個 Span 代表事務(wù)中的一個具體操作例如“調(diào)用 OpenAI API”、“解析用戶意圖”。Span 之間具有父子關(guān)系形成調(diào)用鏈。關(guān)鍵點每個 Span 可以攜帶豐富的Attributes屬性這些是鍵值對可以記錄任何你想附加的上下文信息例如user.idhttp.status_code 或者對我們至關(guān)重要的genai.promptgenai.response。2.2 GenAI 的語義信息附著項目通過在 Otel Span 上添加特定的 Attributes來標(biāo)記 GenAI 交互。這通常在你的應(yīng)用代碼中完成。例如genai.operation: “completion” 或 “chat”genai.prompt: 用戶發(fā)送的原始文本。genai.response: 模型返回的完整文本。genai.model: “gpt-4”genai.total_tokens: 本次調(diào)用消耗的總 Token 數(shù)。genai.evaluation.score.relevance: 一個后評估模型給本次回答的相關(guān)性打分0-1。2.3 從 Traces 到 Metrics 的轉(zhuǎn)換這是項目的核心處理層。一個獨立的處理器例如一個 Otel Collector 的處理器或一個獨立的 Fluentd/Pipeline 服務(wù)會消費這些包含 GenAI 屬性的 Trace 數(shù)據(jù)。它的工作流程是過濾識別出包含genai.*屬性的 Span。提取與計算從這些 Span 的屬性中提取數(shù)值如total_tokens,evaluation.score并可能進(jìn)行一些計算如計算平均分、分桶統(tǒng)計。聚合按照特定的維度Dimensions進(jìn)行聚合例如按genai.model、service.name、genai.operation分組。輸出指標(biāo)將聚合結(jié)果生成為標(biāo)準(zhǔn)的指標(biāo)數(shù)據(jù)格式如 Prometheus 的genai_token_usage_total,genai_response_relevance_score并推送到指標(biāo)后端如 Prometheus。2.4 原始提示詞Raw Prompts的存儲與檢索指標(biāo)是聚合后的、用于告警和趨勢分析的數(shù)據(jù)。但當(dāng)告警觸發(fā)時運維人員需要查看導(dǎo)致問題的具體案例。這就是存儲原始提示詞和響應(yīng)的意義。項目通常會將原始的、非結(jié)構(gòu)化的genai.prompt和genai.response存儲到一個支持全文檢索的數(shù)據(jù)庫中如 Elasticsearch。同時會保留這些數(shù)據(jù)與 TraceId 的關(guān)聯(lián)。這樣在 Grafana 儀表板上看到一個異常的指標(biāo)例如某個模型的平均相關(guān)性分?jǐn)?shù)驟降你可以直接點擊數(shù)據(jù)點通過 TraceId 查詢到對應(yīng)的原始對話進(jìn)行根因分析。架構(gòu)全景圖[你的 GenAI 應(yīng)用] --(嵌入 Otel SDK生成帶有 genai.* 屬性的 Traces)-- [Otel Collector] | |-- (處理器提取 genai 屬性生成 Metrics) -- [Prometheus] -- [Grafana 看板] | |-- (處理器將原始 Prompt/Response 寫入) -- [Elasticsearch] -- [根因分析界面]3. 環(huán)境準(zhǔn)備與前置條件我們將通過一個簡單的 Python Flask 應(yīng)用來模擬一個 GenAI 服務(wù)并搭建完整的監(jiān)控棧。所需環(huán)境操作系統(tǒng)Linux / macOS / WSL2 (Windows)Docker Docker Compose用于一鍵部署后端組件Otel Collector, Prometheus, Grafana, Elasticsearch, Kibana。請確保已安裝。Python 3.9用于編寫示例應(yīng)用。基礎(chǔ)的命令行操作知識。組件版本說明以 Docker 鏡像最新穩(wěn)定版為準(zhǔn)具體版本可能隨時間更新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項目結(jié)構(gòu)預(yù)覽genai-observability-demo/ ├── docker-compose.yml # 定義所有后端服務(wù) ├── collector-config.yaml # Otel Collector 配置 ├── prometheus.yml # Prometheus 配置 ├── app/ # Python 示例應(yīng)用 │ ├── app.py │ ├── requirements.txt │ └── Dockerfile └── README.md4. 搭建可觀測性后端基礎(chǔ)設(shè)施我們首先使用 Docker Compose 啟動所有支撐服務(wù)。創(chuàng)建docker-compose.yml文件version: 3.8 services: # OpenTelemetry Collector - 接收、處理、導(dǎo)出遙測數(shù)據(jù) 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 # 健康檢查/指標(biāo)端口 networks: - observability-net depends_on: - prometheus - elasticsearch # Prometheus - 抓取并存儲指標(biāo) 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 - 指標(biāo)可視化 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 - 存儲原始提示詞和響應(yīng) 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。創(chuàng)建collector-config.yamlreceivers: otlp: protocols: grpc: endpoint: 0.0.0.0:4317 http: endpoint: 0.0.0.0:4318 processors: # 批處理處理器優(yōu)化性能 batch: timeout: 1s send_batch_size: 1024 # 這是一個關(guān)鍵處理器它從 Traces 中提取 GenAI 屬性并生成 Metrics。 # 注意這是一個示例性的配置實際項目中可能需要自定義開發(fā)或使用社區(qū)貢獻(xiàn)的處理器。 # 這里我們用 attributes 處理器模擬提取動作真正的指標(biāo)生成邏輯通常在導(dǎo)出器中定義或通過自定義處理器實現(xiàn)。 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 # 嘗試轉(zhuǎn)換為整型用于后續(xù)指標(biāo)計算 converted_type: int exporters: # 將指標(biāo)導(dǎo)出到 Prometheus prometheus: endpoint: 0.0.0.0:8889 namespace: genai const_labels: environment: demo # 將包含原始提示詞的 Trace 數(shù)據(jù)導(dǎo)出到 Elasticsearch 進(jìn)行存儲 elasticsearch: endpoints: [http://elasticsearch:9200] logs_index: genai-traces traces_index: genai-traces # 調(diào)試用將日志打印到控制臺 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 暴露的指標(biāo)。創(chuàng)建prometheus.ymlglobal: scrape_interval: 15s evaluation_interval: 15s scrape_configs: - job_name: otel-collector static_configs: - targets: [otel-collector:8889] # 注意這里使用 Docker 服務(wù)名現(xiàn)在啟動所有后端服務(wù)docker-compose up -d等待幾分鐘然后訪問以下服務(wù)確認(rèn)啟動成功Grafana:http://localhost:3000(用戶名admin, 密碼admin)Prometheus:http://localhost:9090Kibana:http://localhost:5601Elasticsearch:http://localhost:9200(返回 JSON 信息)5. 編寫并集成示例 GenAI 應(yīng)用我們的示例應(yīng)用是一個簡單的 Flask API它模擬調(diào)用大語言模型。為了簡化我們用一個隨機(jī)函數(shù)來模擬模型響應(yīng)和評估分?jǐn)?shù)并集成 OpenTelemetry SDK 來發(fā)送帶有 GenAI 屬性的 Traces。創(chuàng)建應(yīng)用目錄app/和requirements.txtFlask2.3.3 opentelemetry-api1.21.0 opentelemetry-sdk1.21.0 opentelemetry-exporter-otlp1.21.0 opentelemetry-instrumentation-flask0.41b0創(chuàng)建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. 設(shè)置 TracerProvider trace.set_tracer_provider(TracerProvider()) # 2. 創(chuàng)建 OTLP Exporter指向我們運行的 Collector otlp_exporter OTLPSpanExporter(endpointhttp://localhost:4317, insecureTrue) # 3. 創(chuàng)建 BatchSpanProcessor 并添加到 TracerProvider span_processor BatchSpanProcessor(otlp_exporter) trace.get_tracer_provider().add_span_processor(span_processor) # 4. 初始化 Flask 應(yīng)用并自動注入儀表 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): 模擬調(diào)用 LLM API并生成一些模擬的 GenAI 屬性 # 模擬網(wǎng)絡(luò)延遲 time.sleep(random.uniform(0.1, 0.5)) # 模擬響應(yīng)文本 mock_responses [ f這是一個關(guān)于{prompt[:20]}...的模擬回答。, 根據(jù)我的知識庫您的問題涉及多個方面。, 抱歉我無法回答這個問題。, 您能提供更多上下文信息嗎 ] response random.choice(mock_responses) # 模擬 Token 消耗 (假設(shè) prompt 長度影響) prompt_tokens len(prompt) // 4 completion_tokens len(response) // 4 total_tokens prompt_tokens completion_tokens # 模擬一個評估分?jǐn)?shù) (例如相關(guān)性) 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) # 為本次請求創(chuàng)建一個 Span with tracer.start_as_current_span(genai_chat_completion) as span: # 將 GenAI 相關(guān)的語義信息作為屬性添加到 Span 上 # 這是將非結(jié)構(gòu)化數(shù)據(jù)接入可觀測性體系的關(guān)鍵一步 span.set_attribute(genai.operation, chat) span.set_attribute(genai.model, model) span.set_attribute(genai.prompt, user_prompt) # 原始提示詞 # 注意在生產(chǎn)環(huán)境中需注意隱私和長度可能需要對長文本進(jìn)行采樣或哈希處理。 # 模擬調(diào)用 LLM response, total_tokens, relevance_score call_mock_llm(user_prompt, model) # 將響應(yīng)和計算結(jié)果也作為屬性記錄 span.set_attribute(genai.response, response) # 原始響應(yīng) span.set_attribute(genai.total_tokens, total_tokens) span.set_attribute(genai.evaluation.score.relevance, relevance_score) span.set_attribute(http.status_code, 200) # 返回結(jié)果給用戶 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)創(chuàng)建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部分添加我們的應(yīng)用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現(xiàn)在重新啟動所有服務(wù)包括新應(yīng)用docker-compose down docker-compose up -d --build6. 生成數(shù)據(jù)與驗證流水線應(yīng)用啟動后我們可以發(fā)送一些請求來生成數(shù)據(jù)。使用curl或 Postman 發(fā)送請求# 發(fā)送一個聊天請求 curl -X POST http://localhost:5000/chat \ -H Content-Type: application/json \ -d {prompt: 請解釋一下量子計算的基本原理。, model: gpt-4} # 發(fā)送另一個請求 curl -X POST http://localhost:5000/chat \ -H Content-Type: application/json \ -d {prompt: 今天的天氣怎么樣, model: gpt-3.5-turbo}多發(fā)送幾個不同model和prompt的請求以生成多樣化的數(shù)據(jù)。驗證數(shù)據(jù)流檢查 Collector 日志查看是否有數(shù)據(jù)被接收和處理。docker logs otel-collector --tail 20你應(yīng)該能看到類似“TracesExporter”和“MetricsExporter”的日志條目。檢查 Prometheus 指標(biāo)訪問http://localhost:9090在表達(dá)式輸入框中輸入genai_Prometheus 應(yīng)該能自動補全出以genai_開頭的指標(biāo)例如genai_total_tokens。如果能看到說明指標(biāo)已成功生成并導(dǎo)出。檢查 Elasticsearch 數(shù)據(jù)訪問http://localhost:5601進(jìn)入 Kibana。首次進(jìn)入需要創(chuàng)建索引模式。進(jìn)入Management Stack Management Index Patterns。創(chuàng)建索引模式genai-traces*。然后進(jìn)入Analytics Discover選擇genai-traces*索引模式你應(yīng)該能看到包含genai.prompt和genai.response字段的文檔記錄。7. 配置 Grafana 儀表板進(jìn)行可視化現(xiàn)在數(shù)據(jù)已經(jīng)流入 Prometheus 和 Elasticsearch我們可以在 Grafana 中創(chuàng)建儀表板來洞察我們的 GenAI 應(yīng)用。添加數(shù)據(jù)源登錄 Grafana (http://localhost:3000admin/admin)。進(jìn)入Configuration Data Sources。點擊Add data source選擇Prometheus。URL 填寫http://prometheus:9090注意使用 Docker 服務(wù)名點擊Save Test應(yīng)顯示成功。同樣方式添加Elasticsearch數(shù)據(jù)源URL 填寫http://elasticsearch:9200Index name 填寫genai-traces*。創(chuàng)建指標(biāo)儀表板新建一個 Dashboard。添加一個 Panel查詢 Prometheus 指標(biāo)例如總 Token 消耗趨勢sum(genai_total_tokens) by (genai_model)平均響應(yīng)相關(guān)性分?jǐn)?shù)avg(genai_evaluation_score_relevance) by (genai_model)請求速率rate(genai_request_duration_seconds_count[5m])(需要先定義該指標(biāo))利用 Grafana 的圖表類型時間序列圖、柱狀圖、儀表盤進(jìn)行可視化。關(guān)聯(lián)原始數(shù)據(jù)高級這是體現(xiàn)“Bounded”價值的關(guān)鍵——將指標(biāo)與原始提示詞關(guān)聯(lián)。在指標(biāo)圖表上可以添加一個 “Drilldown” 鏈接。鏈接指向 Kibana Discover 頁面并攜帶時間范圍過濾和可能的trace.id參數(shù)如果我們在 Span 中記錄了它。這樣當(dāng)你在 Grafana 上看到一個異常峰值時點擊它就能直接跳轉(zhuǎn)到 Kibana查看在那個時間點導(dǎo)致問題的具體用戶提問和模型回答。示例 Grafana 查詢用于 Token 消耗 假設(shè)我們的處理器將genai.total_tokens屬性轉(zhuǎn)換為了一個名為genai_token_usage_total的計數(shù)器Counter指標(biāo)。我們可以這樣查詢每秒的 Token 消耗速率sum(rate(genai_token_usage_total[5m])) by (genai_model)8. 常見問題與排查思路問題現(xiàn)象可能原因排查方式解決方案應(yīng)用啟動失敗無法連接 Collector1. Collector 服務(wù)未運行。2. 網(wǎng)絡(luò)配置錯誤應(yīng)用容器無法訪問otel-collector:4317。3. 端口映射錯誤。1.docker ps檢查otel-collector容器狀態(tài)。2. 在應(yīng)用容器內(nèi)執(zhí)行nc -zv otel-collector 4317。3. 檢查docker-compose.yml中網(wǎng)絡(luò)配置和端口映射。1. 確保docker-compose up -d成功。2. 確認(rèn)所有服務(wù)在同一個自定義網(wǎng)絡(luò)如observability-net下。3. 檢查應(yīng)用環(huán)境變量OTEL_EXPORTER_OTLP_ENDPOINT是否正確。Prometheus 中查詢不到genai_開頭的指標(biāo)1. Collector 的 Prometheus exporter 配置錯誤或未啟動。2. 處理器未能正確從 Traces 生成 Metrics。3. 應(yīng)用沒有發(fā)送帶有g(shù)enai.*屬性的 Span。1. 訪問http://localhost:8889/metrics查看 Collector 自身暴露的指標(biāo)確認(rèn)是否有 GenAI 相關(guān)指標(biāo)。2. 檢查 Collector 日志查看prometheusexporter 是否有錯誤。3. 檢查應(yīng)用代碼確認(rèn)span.set_attribute被正確調(diào)用。1. 核對collector-config.yaml中exporters.prometheus的配置和service.pipelines.metrics的組成。2. 確保處理器如attributes/genai在tracespipeline 中并且屬性被成功提取和轉(zhuǎn)換。3. 在應(yīng)用中使用debugexporter 或打印日志確認(rèn) Span 屬性已設(shè)置。Kibana 中查不到 Trace 數(shù)據(jù)1. Elasticsearch exporter 配置錯誤。2. Elasticsearch 索引創(chuàng)建失敗或名稱不匹配。3. 數(shù)據(jù)格式不符合 Elasticsearch 要求。1. 檢查 Collector 日志中elasticsearchexporter 的相關(guān)信息。2. 直接訪問http://localhost:9200/_cat/indices?v查看是否存在genai-traces索引。3. 訪問http://localhost:9200/genai-traces/_search?pretty嘗試查詢數(shù)據(jù)。1. 核對collector-config.yaml中exporters.elasticsearch的endpoints和index配置。2. 確保 Elasticsearch 服務(wù)健康運行且版本兼容。3. 考慮在 exporter 中增加flush相關(guān)配置或檢查是否有字段映射沖突。Grafana 圖表顯示 “No Data”1. Prometheus 數(shù)據(jù)源配置錯誤。2. 查詢的指標(biāo)名稱不正確。3. 時間范圍選擇不當(dāng)尚無數(shù)據(jù)。1. 在 Grafana 數(shù)據(jù)源配置頁面點擊Save Test。2. 前往 Prometheus UI (http://localhost:9090)在 Graph 頁面的指標(biāo)下拉框中查找正確的指標(biāo)名。3. 擴(kuò)大 Grafana 儀表板的時間范圍。1. 確保 Prometheus 數(shù)據(jù)源的 URL 指向正確的地址在 Docker 網(wǎng)絡(luò)內(nèi)使用服務(wù)名。2. 使用 Prometheus 的表達(dá)式瀏覽器驗證指標(biāo)查詢語句。3. 確認(rèn)應(yīng)用已產(chǎn)生數(shù)據(jù)且數(shù)據(jù)流已到達(dá) Prometheus。原始提示詞字段過長導(dǎo)致 ES 寫入失敗Elasticsearch 默認(rèn)對字符串字段長度有限制ignore_above。查看 Collector 或 Elasticsearch 日志尋找max_bytes_length_exceeded或類似的錯誤。1. 在應(yīng)用側(cè)對過長的 Prompt 進(jìn)行截斷或采樣。2. 在 Elasticsearch 中為該索引的特定字段設(shè)置更大的ignore_above值或使用text類型而非keyword。9. 生產(chǎn)環(huán)境最佳實踐與進(jìn)階建議將這套方案用于生產(chǎn)環(huán)境需要考慮更多因素采樣策略Sampling全量收集所有 Prompt 和 Response 對存儲和網(wǎng)絡(luò)壓力巨大。必須實施采樣。頭部采樣Head-based在入口處決定是否記錄整個 Trace??梢曰诟怕嗜?10%或基于規(guī)則如只記錄錯誤請求、慢請求、或特定用戶群的請求。尾部采樣Tail-based先收集所有數(shù)據(jù)在 Collector 端根據(jù)最終結(jié)果例如響應(yīng)包含錯誤、評估分?jǐn)?shù)過低決定是否保留。這更精準(zhǔn)但更復(fù)雜。Otel Collector 提供了tail_sampling處理器。隱私與合規(guī)PII原始 Prompt 和 Response 可能包含用戶個人信息、敏感商業(yè)數(shù)據(jù)。脫敏在應(yīng)用 SDK 或 Collector 處理器中對特定字段如郵箱、手機(jī)號、身份證號進(jìn)行掩碼或哈希處理。訪問控制確保 Kibana 或存儲原始數(shù)據(jù)的數(shù)據(jù)庫有嚴(yán)格的權(quán)限控制僅限授權(quán)人員訪問。數(shù)據(jù)保留策略為 Elasticsearch 索引設(shè)置合理的 TTL生存時間自動刪除過期數(shù)據(jù)。自定義指標(biāo)與評估本文示例使用了簡單的隨機(jī)分?jǐn)?shù)。在實際中你需要定義對業(yè)務(wù)有意義的評估維度。業(yè)務(wù)指標(biāo)例如對于客服機(jī)器人可以定義“問題解決率”、“轉(zhuǎn)人工率”。自動化評估集成一個評估服務(wù)可以是另一個 LLM 調(diào)用或規(guī)則引擎對每次響應(yīng)自動打分相關(guān)性、安全性、事實準(zhǔn)確性等并將分?jǐn)?shù)作為屬性記錄。成本指標(biāo)除了總 Token 數(shù)可以計算每次請求的成本根據(jù)模型定價并聚合為每日/每用戶成本。性能與擴(kuò)展性Collector 部署在生產(chǎn)中Otel Collector 應(yīng)以 DaemonSetK8s或 Sidecar 形式部署靠近應(yīng)用以減少網(wǎng)絡(luò)延遲和單點故障。緩沖與重試配置 Collector 的batch處理器和導(dǎo)出器的隊列、重試策略以應(yīng)對后端存儲如 Prometheus, ES的臨時不可用。指標(biāo)基數(shù)控制避免使用高基數(shù)的屬性如user_id作為指標(biāo)的標(biāo)簽Label這會導(dǎo)致 Prometheus 指標(biāo)爆炸。這類高基數(shù)維度應(yīng)留在 Trace 或 Log 中用于下鉆分析。告警規(guī)則基于生成的指標(biāo)在 Prometheus Alertmanager 或 Grafana 中設(shè)置有意義的告警。質(zhì)量告警avg(genai_evaluation_score_relevance) 0.7持續(xù) 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 應(yīng)用的語義層信息相結(jié)合我們構(gòu)建了一套統(tǒng)一、強大且可擴(kuò)展的可觀測性方案。它打破了傳統(tǒng)監(jiān)控對 GenAI “黑盒”的無力感讓開發(fā)者能夠像監(jiān)控任何關(guān)鍵業(yè)務(wù)服務(wù)一樣監(jiān)控 AI 模型的質(zhì)量、性能和成本。這套方案的核心優(yōu)勢在于其標(biāo)準(zhǔn)化和可集成性——你無需拋棄現(xiàn)有的 Prometheus、Grafana、Elasticsearch 技術(shù)棧而是通過 Otel 這一 CNCF 標(biāo)準(zhǔn)優(yōu)雅地將其擴(kuò)展到了 AI 時代。你可以從本文的示例出發(fā)根據(jù)實際業(yè)務(wù)需求定制需要收集的屬性、定義關(guān)鍵指標(biāo)、設(shè)計評估維度并構(gòu)建起真正服務(wù)于你業(yè)務(wù)的 GenAI 可觀測性體系。當(dāng)你的下一個 AI 功能出現(xiàn)效果波動時你將不再只能猜測而是可以精準(zhǔn)地定位到問題源頭。