Skip to main content
LangSmith 支持基于 OpenTelemetry 的追踪,允许您从任何兼容 OpenTelemetry 的应用程序发送追踪数据。本指南涵盖了 LangChain 应用程序的自动检测以及其他框架的手动检测。 了解如何使用 OpenTelemetry 与 LangSmith 追踪您的 LLM 应用程序。
对于自托管安装或区域 SaaS,请在下面的请求中相应地更新 LangSmith URL:欧盟 (GCP) 使用 eu.api.smith.langchain.com;AWS 托管的美国 SaaS 使用 aws.api.smith.langchain.com

追踪 LangChain 应用程序

如果您使用 LangChain 或 LangGraph,请使用内置集成来追踪您的应用程序:
  1. 安装支持 OpenTelemetry 的 LangSmith 包:
    pip install "langsmith[otel]"
    pip install langchain
    
    需要 Python SDK 版本 langsmith>=0.3.18。我们推荐 langsmith>=0.4.25 以获得重要的 OpenTelemetry 修复。
  2. 在您的 LangChain/LangGraph 应用程序中,通过设置 LANGSMITH_OTEL_ENABLED 环境变量启用 OpenTelemetry 集成:
    LANGSMITH_OTEL_ENABLED=true
    LANGSMITH_TRACING=true
    LANGSMITH_ENDPOINT=https://api.smith.langchain.com
    LANGSMITH_API_KEY=<your_langsmith_api_key>
    # 对于链接到多个工作区的 LangSmith API 密钥,请设置 LANGSMITH_WORKSPACE_ID 环境变量以指定使用哪个工作区。
    
  3. 创建一个带有追踪功能的 LangChain 应用程序。例如:
    import os
    from langchain_openai import ChatOpenAI
    from langchain_core.prompts import ChatPromptTemplate
    
    # 创建一个链
    prompt = ChatPromptTemplate.from_template("Tell me a joke about {topic}")
    model = ChatOpenAI()
    chain = prompt | model
    
    # 运行链
    result = chain.invoke({"topic": "programming"})
    print(result.content)
    
  4. 应用程序运行后,在 LangSmith 仪表板中查看追踪数据(示例)。

追踪非 LangChain 应用程序

对于非 LangChain 应用程序或自定义检测,您可以使用标准的 OpenTelemetry 客户端在 LangSmith 中追踪您的应用程序。(我们推荐 langsmith ≥ 0.4.25。)
  1. 安装 OpenTelemetry SDK、OpenTelemetry 导出器包以及 OpenAI 包:
    pip install openai
    pip install opentelemetry-sdk
    pip install opentelemetry-exporter-otlp
    
  2. 设置端点的环境变量,替换为您特定的值:
    OTEL_EXPORTER_OTLP_ENDPOINT=https://api.smith.langchain.com/otel
    OTEL_EXPORTER_OTLP_HEADERS="x-api-key=<your langsmith api key>"
    
    根据您的 otel 导出器的配置方式,如果您只发送追踪数据,可能需要将 /v1/traces 附加到端点。
    如果您是自托管 LangSmith,请将基础端点替换为您的 LangSmith API 端点并附加 /api/v1。例如:OTEL_EXPORTER_OTLP_ENDPOINT=https://ai-company.com/api/v1/otel
    可选:指定一个不同于 “default” 的自定义项目名称:
    OTEL_EXPORTER_OTLP_ENDPOINT=https://api.smith.langchain.com/otel
    OTEL_EXPORTER_OTLP_HEADERS="x-api-key=<your langsmith api key>,Langsmith-Project=<project name>"
    
  3. 记录一个追踪。 此代码设置一个 OTEL 追踪器和导出器,用于将追踪数据发送到 LangSmith。然后调用 OpenAI 并发送所需的 OpenTelemetry 属性。
    from openai import OpenAI
    from opentelemetry import trace
    from opentelemetry.sdk.trace import TracerProvider
    from opentelemetry.sdk.trace.export import (
        BatchSpanProcessor,
    )
    from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
    
    client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
    
    otlp_exporter = OTLPSpanExporter(
        timeout=10,
    )
    
    trace.set_tracer_provider(TracerProvider())
    trace.get_tracer_provider().add_span_processor(
        BatchSpanProcessor(otlp_exporter)
    )
    
    tracer = trace.get_tracer(__name__)
    
    def call_openai():
        model = "gpt-5.4-mini"
        with tracer.start_as_current_span("call_open_ai") as span:
            span.set_attribute("langsmith.span.kind", "LLM")
            span.set_attribute("langsmith.metadata.user_id", "user_123")
            span.set_attribute("gen_ai.system", "OpenAI")
            span.set_attribute("gen_ai.request.model", model)
            span.set_attribute("llm.request.type", "chat")
    
            messages = [
                {"role": "system", "content": "You are a helpful assistant."},
                {
                    "role": "user",
                    "content": "Write a haiku about recursion in programming."
                }
            ]
    
            for i, message in enumerate(messages):
                span.set_attribute(f"gen_ai.prompt.{i}.content", str(message["content"]))
                span.set_attribute(f"gen_ai.prompt.{i}.role", str(message["role"]))
    
            completion = client.chat.completions.create(
                model=model,
                messages=messages
            )
    
            span.set_attribute("gen_ai.response.model", completion.model)
            span.set_attribute("gen_ai.completion.0.content", str(completion.choices[0].message.content))
            span.set_attribute("gen_ai.completion.0.role", "assistant")
            span.set_attribute("gen_ai.usage.prompt_tokens", completion.usage.prompt_tokens)
            span.set_attribute("gen_ai.usage.completion_tokens", completion.usage.completion_tokens)
            span.set_attribute("gen_ai.usage.total_tokens", completion.usage.total_tokens)
    
            return completion.choices[0].message
    
    if __name__ == "__main__":
        call_openai()
    
  4. 在 LangSmith 仪表板中查看追踪数据(示例)。

将追踪发送到备用提供商

虽然 LangSmith 是 OpenTelemetry 追踪的默认目标,但您也可以配置 OpenTelemetry 将追踪发送到其他可观测性平台。
在 LangSmith Python SDK ≥ 0.4.1 中可用。我们推荐 ≥ 0.4.25,其中包含改进 OTEL 导出和混合扇出稳定性的修复。

使用环境变量进行全局配置

默认情况下,LangSmith OpenTelemetry 导出器会将数据发送到 LangSmith API OTEL 端点,但可以通过设置标准 OTEL 环境变量来自定义:
OTEL_EXPORTER_OTLP_ENDPOINT: 覆盖端点 URL
OTEL_EXPORTER_OTLP_HEADERS: 添加自定义头(LangSmith API 密钥和项目会自动添加)
OTEL_SERVICE_NAME: 设置自定义服务名称(默认为 "langsmith")
LangSmith 默认使用 HTTP 追踪导出器。如果您想使用自己的追踪提供程序,可以:
  1. 如上所示设置 OTEL 环境变量,或者
  2. 在初始化 LangChain 组件之前设置全局追踪提供程序,LangSmith 将检测并使用它,而不是创建自己的。

配置备用 OTLP 端点

要将追踪发送到不同的提供程序,请使用提供程序的端点配置 OTLP 导出器:
import os

from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI
from opentelemetry import trace
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor

# 为 LangChain 设置环境变量
os.environ["LANGSMITH_OTEL_ENABLED"] = "true"
os.environ["LANGSMITH_TRACING"] = "true"

# 为您的自定义端点配置 OTLP 导出器
provider = TracerProvider()
otlp_exporter = OTLPSpanExporter(
    # 更改为您的提供程序端点
    endpoint="https://otel.your-provider.com/v1/traces",
    # 添加任何所需的认证头
    headers={"api-key": "your-api-key"},
)
processor = BatchSpanProcessor(otlp_exporter)
provider.add_span_processor(processor)
trace.set_tracer_provider(provider)

# 创建并运行 LangChain 应用程序
prompt = ChatPromptTemplate.from_template("Tell me a joke about {topic}")
model = ChatOpenAI()
chain = prompt | model
result = chain.invoke({"topic": "programming"})
print(result.content)
混合追踪在版本 ≥ 0.4.1 中可用。要将追踪发送到您的 OTEL 端点,请设置:LANGSMITH_OTEL_ONLY="true" (推荐:使用 langsmith ≥ 0.4.25。)

支持的 OpenTelemetry 属性和事件映射

通过 OpenTelemetry 将追踪发送到 LangSmith 时,以下属性会映射到 LangSmith 字段:

核心 LangSmith 属性

OpenTelemetry 属性LangSmith 字段备注
langsmith.trace.name运行名称覆盖运行的 span 名称
langsmith.span.kind运行类型值:llmchaintoolretrieverembeddingpromptparser
langsmith.trace.session_id会话 ID相关追踪的会话标识符
langsmith.trace.session_name会话名称会话的名称
langsmith.span.tags标签附加到 span 的自定义标签(逗号分隔)
langsmith.metadata.{key}metadata.{key}带有 langsmith 前缀的自定义元数据

GenAI 标准属性

OpenTelemetry 属性LangSmith 字段备注
gen_ai.systemmetadata.ls_providerGenAI 系统(例如 “openai”、“anthropic”)
gen_ai.operation.name运行类型将 “chat”/“completion” 映射为 “llm”,“embedding” 映射为 “embedding”
gen_ai.promptinputs发送给模型的输入提示
gen_ai.completionoutputs模型生成的输出
gen_ai.prompt.{n}.roleinputs.messages[n].role第 n 个输入消息的角色
gen_ai.prompt.{n}.contentinputs.messages[n].content第 n 个输入消息的内容
gen_ai.prompt.{n}.message.roleinputs.messages[n].role角色的替代格式
gen_ai.prompt.{n}.message.contentinputs.messages[n].content内容的替代格式
gen_ai.completion.{n}.roleoutputs.messages[n].role第 n 个输出消息的角色
gen_ai.completion.{n}.contentoutputs.messages[n].content第 n 个输出消息的内容
gen_ai.completion.{n}.message.roleoutputs.messages[n].role角色的替代格式
gen_ai.completion.{n}.message.contentoutputs.messages[n].content内容的替代格式
gen_ai.input.messagesinputs.messages输入消息数组
gen_ai.output.messagesoutputs.messages输出消息数组
gen_ai.tool.nameinvocation_params.tool_name工具名称,同时将运行类型设置为 “tool”

GenAI 请求参数

OpenTelemetry 属性LangSmith 字段备注
gen_ai.request.modelinvocation_params.model用于请求的模型名称
gen_ai.response.modelinvocation_params.model响应中返回的模型名称
gen_ai.request.temperatureinvocation_params.temperature温度设置
gen_ai.request.top_pinvocation_params.top_pTop-p 采样设置
gen_ai.request.max_tokensinvocation_params.max_tokens最大 token 数设置
gen_ai.request.frequency_penaltyinvocation_params.frequency_penalty频率惩罚设置
gen_ai.request.presence_penaltyinvocation_params.presence_penalty存在惩罚设置
gen_ai.request.seedinvocation_params.seed用于生成的随机种子
gen_ai.request.stop_sequencesinvocation_params.stop停止生成的序列
gen_ai.request.top_kinvocation_params.top_kTop-k 采样参数
gen_ai.request.encoding_formatsinvocation_params.encoding_formats输出编码格式

GenAI 使用指标

OpenTelemetry 属性LangSmith 字段备注
gen_ai.usage.input_tokensusage_metadata.input_tokens使用的输入 token 数
gen_ai.usage.output_tokensusage_metadata.output_tokens使用的输出 token 数
gen_ai.usage.total_tokensusage_metadata.total_tokens使用的总 token 数
gen_ai.usage.prompt_tokensusage_metadata.input_tokens使用的输入 token 数(已弃用)
gen_ai.usage.completion_tokensusage_metadata.output_tokens使用的输出 token 数(已弃用)
gen_ai.usage.details.reasoning_tokensusage_metadata.reasoning_tokens使用的推理 token 数

TraceLoop 属性

OpenTelemetry 属性LangSmith 字段备注
traceloop.entity.inputinputs来自 TraceLoop 的完整输入值
traceloop.entity.outputoutputs来自 TraceLoop 的完整输出值
traceloop.entity.name运行名称来自 TraceLoop 的实体名称
traceloop.span.kind运行类型映射到 LangSmith 运行类型
traceloop.llm.request.type运行类型”embedding” 映射为 “embedding”,其他映射为 “llm”
traceloop.association.properties.{key}metadata.{key}带有 traceloop 前缀的自定义元数据

OpenInference 属性

OpenTelemetry 属性LangSmith 字段备注
input.valueinputs完整输入值,可以是字符串或 JSON
output.valueoutputs完整输出值,可以是字符串或 JSON
openinference.span.kind运行类型将各种类型映射到 LangSmith 运行类型
llm.systemmetadata.ls_providerLLM 系统提供程序
llm.model_namemetadata.ls_model_name来自 OpenInference 的模型名称
tool.name运行名称当 span 类型为 “TOOL” 时的工具名称
metadatametadata.*要合并的元数据的 JSON 字符串

LLM 属性

OpenTelemetry 属性LangSmith 字段备注
llm.input_messagesinputs.messages输入消息
llm.output_messagesoutputs.messages输出消息
llm.token_count.promptusage_metadata.input_tokens提示 token 计数
llm.token_count.completionusage_metadata.output_tokens完成 token 计数
llm.token_count.totalusage_metadata.total_tokens总 token 计数
llm.usage.total_tokensusage_metadata.total_tokens替代的总 token 计数
llm.invocation_parametersinvocation_params.*调用参数的 JSON 字符串
llm.presence_penaltyinvocation_params.presence_penalty存在惩罚
llm.frequency_penaltyinvocation_params.frequency_penalty频率惩罚
llm.request.functionsinvocation_params.functions函数定义

提示模板属性

OpenTelemetry 属性LangSmith 字段备注
llm.prompt_template.variables运行类型将运行类型设置为 “prompt”,与 input.value 一起使用

检索器属性

OpenTelemetry 属性LangSmith 字段备注
retrieval.documents.{n}.document.contentoutputs.documents[n].page_content第 n 个检索文档的内容
retrieval.documents.{n}.document.metadataoutputs.documents[n].metadata第 n 个检索文档的元数据(JSON)

工具属性

OpenTelemetry 属性LangSmith 字段备注
toolsinvocation_params.tools工具定义数组
tool_argumentsinvocation_params.tool_arguments工具参数,作为 JSON 或键值对

Logfire 属性

OpenTelemetry 属性LangSmith 字段备注
promptinputsLogfire 提示输入
all_messages_eventsoutputsLogfire 消息事件输出
eventsinputs/outputsLogfire 事件数组,分割输入/选择事件

OpenTelemetry 事件映射

事件名称LangSmith 字段备注
gen_ai.content.promptinputs从事件属性中提取提示内容
gen_ai.content.completionoutputs从事件属性中提取完成内容
gen_ai.system.messageinputs.messages[]对话中的系统消息
gen_ai.user.messageinputs.messages[]对话中的用户消息
gen_ai.assistant.messageoutputs.messages[]对话中的助手消息
gen_ai.tool.messageoutputs.messages[]工具响应消息
gen_ai.choiceoutputs带有完成原因的模型选择/响应
exceptionstatus, error将状态设置为 “error” 并提取异常消息/堆栈跟踪

事件属性提取

对于消息事件,提取以下属性:
  • content → 消息内容
  • role → 消息角色
  • id → tool_call_id(用于工具消息)
  • gen_ai.event.content → 完整消息 JSON
对于选择事件:
  • finish_reason → 选择完成原因
  • message.content → 选择消息内容
  • message.role → 选择消息角色
  • tool_calls.{n}.id → 工具调用 ID
  • tool_calls.{n}.function.name → 工具函数名称
  • tool_calls.{n}.function.arguments → 工具函数参数
  • tool_calls.{n}.type → 工具调用类型
对于异常事件:
  • exception.message → 错误消息
  • exception.stacktrace → 错误堆栈跟踪(附加到消息)

实现示例

使用 LangSmith SDK 进行追踪

使用 LangSmith SDK 的 OpenTelemetry 辅助工具配置导出。以下示例追踪一个 Google ADK 代理
import asyncio
from langsmith.integrations.otel import configure
from google.adk import Runner
from google.adk.agents import LlmAgent
from google.adk.sessions import InMemorySessionService
from google.genai import types

# 配置 LangSmith OpenTelemetry 导出(无需 OTEL 环境变量或头)
configure(project_name="adk-otel-demo")


async def main():
    agent = LlmAgent(
        name="travel_assistant",
        model="gemini-2.5-flash-lite",
        instruction="You are a helpful travel assistant.",
    )

    session_service = InMemorySessionService()
    runner = Runner(app_name="travel_app", agent=agent, session_service=session_service)

    user_id = "user_123"
    session_id = "session_abc"
    await session_service.create_session(app_name="travel_app", user_id=user_id, session_id=session_id)

    new_message = types.Content(parts=[types.Part(text="Hi! Recommend a weekend trip to Paris.")], role="user")

    for event in runner.run(user_id=user_id, session_id=session_id, new_message=new_message):
        print(event)


if __name__ == "__main__":
    asyncio.run(main())
您无需设置 OTEL 环境变量或导出器。configure() 会自动为 LangSmith 配置它们;检测器(如 GoogleADKInstrumentor)创建 span。
这是在 LangSmith 中生成的追踪数据的示例

向追踪添加附件

LangSmith 支持向追踪附加文件。这在构建具有多模态输入或输出的代理时非常有用。使用 OpenTelemetry 追踪时也支持附件。 下面的示例追踪一个 Google ADK 代理并向追踪添加附件。它结合使用了 LangSmith 的 OtelSpanProcessor 和一个自定义的 AttachmentSpanProcessor,后者使用 on_end() 向父 span 添加图像附件。
import asyncio
import base64
import json
from pathlib import Path
from dotenv import load_dotenv
from google.adk import Runner
from google.adk.agents import LlmAgent
from google.adk.sessions import InMemorySessionService
from google.genai import types
from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider, SpanProcessor
from langsmith.integrations.otel import OtelSpanProcessor


class AttachmentSpanProcessor(SpanProcessor):
    """自定义 SpanProcessor,用于向调用 span 添加附件。"""

    def __init__(self):
        self.attachment_data = None

    def set_attachment(self, attachment_data):
        self.attachment_data = attachment_data

    def on_end(self, span):
        if span.name == "invocation" and self.attachment_data:
            attachments_json = json.dumps([self.attachment_data])
            span._attributes["langsmith.attachments"] = attachments_json

load_dotenv()

# 手动设置 TracerProvider
provider = TracerProvider()
trace.set_tracer_provider(provider)

# 首先添加附件处理器(在 LangSmith 处理器之前运行)
attachment_processor = AttachmentSpanProcessor()
provider.add_span_processor(attachment_processor)

# 其次添加 LangSmith 处理器(接收已修改的 span)
langsmith_processor = OtelSpanProcessor(project="travel-assistant")
provider.add_span_processor(langsmith_processor)

def get_flight_info(destination: str, departure_date: str) -> dict:
    """获取目的地的航班信息。"""
    return {
        "destination": destination,
        "departure_date": departure_date,
        "price": "$450",
        "duration": "5h 30m",
        "airline": "Example Airways"
    }

def get_hotel_recommendations(city: str, check_in: str) -> dict:
    """获取城市的酒店推荐。"""
    return {
        "city": city,
        "check_in": check_in,
        "hotels": [
            {"name": "Grand Plaza Hotel", "rating": 4.5, "price": "$120/night"},
            {"name": "City Center Inn", "rating": 4.2, "price": "$95/night"}
        ]
    }

async def main():
    # 准备附件
    receipt_path = Path("receipt-template-example.png")
    with open(receipt_path, "rb") as img_file:
        image_bytes = img_file.read()
        image_base64 = base64.b64encode(image_bytes).decode("ascii")

    attachment_data = {
        "name": "receipt-template-example",
        "content": image_base64,
        "mime_type": "image/jpeg",
    }

    attachment_processor.set_attachment(attachment_data)

    # 创建 ADK 代理
    agent = LlmAgent(
        name="travel_assistant",
        tools=[get_flight_info, get_hotel_recommendations],
        model="gemini-2.0-flash-exp",
        instruction="You are a helpful travel assistant that can help with flights and hotels.",
    )

    # 设置会话和运行器
    session_service = InMemorySessionService()
    runner = Runner(
        app_name="travel_app",
        agent=agent,
        session_service=session_service
    )

    await session_service.create_session(
        app_name="travel_app",
        user_id="traveler_456",
        session_id="session_789"
    )

    # 向代理发送消息
    new_message = types.Content(
        parts=[types.Part(text="I need to book a flight to Paris for March 15th and find a good hotel.")],
        role="user",
    )

    # 运行代理并处理事件
    events = runner.run(
        user_id="traveler_456",
        session_id="session_789",
        new_message=new_message,
    )

    for event in events:
        print(event)

if __name__ == "__main__":
    asyncio.run(main())
这是在 LangSmith 中生成的追踪数据的示例

高级配置

使用 OpenTelemetry collector 进行扇出

当您需要 OTEL 扇出时,请使用 LANGSMITH_OTEL_ENABLED=true。配置您的应用程序发出一次 OTEL span,然后使用 OpenTelemetry Collector 将它们路由到 LangSmith 和任何其他可观测性后端。 当您正在追踪应用程序并希望进行多目标路由时,请使用此方法。如果您正在操作 LangSmith 平台基础设施遥测(来自 Kubernetes 上自托管 LangSmith 服务的日志、指标、追踪),请改用为 LangSmith 遥测配置您的 collector 指南。 对于更高级的场景,您可以使用 OpenTelemetry Collector 将您的遥测数据扇出到多个目标。这比在应用程序代码中配置多个导出器更具可扩展性。
  1. 为您的环境安装 OpenTelemetry Collector
  2. 创建一个配置文件(例如 otel-collector-config.yaml),导出到多个目标:
    receivers:
      otlp:
        protocols:
          grpc:
            endpoint: 0.0.0.0:4317
          http:
            endpoint: 0.0.0.0:4318
    
    processors:
      batch:
    
    exporters:
      otlphttp/langsmith:
        endpoint: https://api.smith.langchain.com/otel/v1/traces
        headers:
          x-api-key: ${env:LANGSMITH_API_KEY}
          Langsmith-Project: my_project
      otlphttp/other_provider:
        endpoint: https://otel.your-provider.com/v1/traces
        headers:
          api-key: ${env:OTHER_PROVIDER_API_KEY}
    
    service:
      pipelines:
        traces:
          receivers: [otlp]
          processors: [batch]
          exporters: [otlphttp/langsmith, otlphttp/other_provider]
    
  3. 配置您的应用程序发送到 collector:
    import os
    from opentelemetry import trace
    from opentelemetry.sdk.trace import TracerProvider
    from opentelemetry.sdk.trace.export import BatchSpanProcessor
    from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
    from langchain_openai import ChatOpenAI
    from langchain_core.prompts import ChatPromptTemplate
    
    # 指向您的本地 OpenTelemetry Collector
    otlp_exporter = OTLPSpanExporter(
        endpoint="http://localhost:4318/v1/traces"
    )
    provider = TracerProvider()
    processor = BatchSpanProcessor(otlp_exporter)
    provider.add_span_processor(processor)
    trace.set_tracer_provider(provider)
    
    # 为 LangChain 设置环境变量
    os.environ["LANGSMITH_OTEL_ENABLED"] = "true"
    os.environ["LANGSMITH_TRACING"] = "true"
    
    # 创建并运行 LangChain 应用程序
    prompt = ChatPromptTemplate.from_template("Tell me a joke about {topic}")
    model = ChatOpenAI()
    chain = prompt | model
    result = chain.invoke({"topic": "programming"})
    print(result.content)
    
此方法具有以下几个优点:
  • 所有遥测目标的集中配置
  • 减少应用程序代码中的开销
  • 更好的可扩展性和弹性
  • 无需更改应用程序代码即可添加或删除目标

使用 LangChain 和 OpenTelemetry 进行分布式追踪

当您的 LLM 应用程序跨越多个服务或进程时,分布式追踪至关重要。OpenTelemetry 的上下文传播功能确保追踪在服务边界之间保持连接。

分布式追踪中的上下文传播

在分布式系统中,上下文传播在服务之间传递追踪元数据,以便将相关的 span 链接到同一追踪:
  • Trace ID:整个追踪的唯一标识符
  • Span ID:当前 span 的唯一标识符
  • 采样决策:指示是否应采样此追踪

使用 LangChain 设置分布式追踪

要启用跨多个服务的分布式追踪:
import os
from opentelemetry import trace
from opentelemetry.propagate import inject, extract
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
import requests
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate

# 设置 OpenTelemetry 追踪提供程序
provider = TracerProvider()
otlp_exporter = OTLPSpanExporter(
    endpoint="https://api.smith.langchain.com/otel/v1/traces",
    headers={"x-api-key": os.getenv("LANGSMITH_API_KEY"), "Langsmith-Project": "my_project"}
)
processor = BatchSpanProcessor(otlp_exporter)
provider.add_span_processor(processor)
trace.set_tracer_provider(provider)
tracer = trace.get_tracer(__name__)

# 服务 A:创建一个 span 并将上下文传播到服务 B
def service_a():
    with tracer.start_as_current_span("service_a_operation") as span:
        # 创建一个链
        prompt = ChatPromptTemplate.from_template("Summarize: {text}")
        model = ChatOpenAI()
        chain = prompt | model

        # 运行链
        result = chain.invoke({"text": "OpenTelemetry is an observability framework"})

        # 将上下文传播到服务 B
        headers = {}
        inject(headers)  # 将追踪上下文注入到头中

        # 使用追踪上下文调用服务 B
        response = requests.post(
            "http://service-b.example.com/process",
            headers=headers,
            json={"summary": result.content}
        )
        return response.json()

# 服务 B:提取上下文并继续追踪
from flask import Flask, request, jsonify

app = Flask(__name__)

@app.route("/process", methods=["POST"])
def service_b_endpoint():
    # 从请求头中提取追踪上下文
    context = extract(request.headers)
    with tracer.start_as_current_span("service_b_operation", context=context) as span:
        data = request.json
        summary = data.get("summary", "")

        # 使用另一个 LLM 链处理摘要
        prompt = ChatPromptTemplate.from_template("Analyze the sentiment of: {text}")
        model = ChatOpenAI()
        chain = prompt | model
        result = chain.invoke({"text": summary})

        return jsonify({"analysis": result.content})

if __name__ == "__main__":
    app.run(port=5000)