使用 OpenTelemetry 跟踪 LangChain
LangSmith Python SDK 提供了内置的 OpenTelemetry 集成,使您能够使用 OpenTelemetry 标准追踪 LangChain 和 LangGraph 应用,并将这些追踪数据发送至任何兼容 OTel 的平台。
1. 安装
需要 Python SDK 版本 langsmith>=0.3.18。
安装支持 OpenTelemetry 的 LangSmith 包:
pip install "langsmith[otel]"
pip install langchain
2. 启用 OpenTelemetry 集成
您可以通过设置 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>
3. 创建一个支持追踪功能的 LangChain 应用
以下是一个简单示例,展示如何在 LangChain 中使用 OpenTelemetry 集成:
import os
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
# LangChain will automatically use OpenTelemetry to send traces to LangSmith
# because the LANGSMITH_OTEL_ENABLED environment variable is set
# Create a chain
prompt = ChatPromptTemplate.from_template("Tell me a joke about {topic}")
model = ChatOpenAI()
chain = prompt | model
# Run the chain
result = chain.invoke({"topic": "programming"})
print(result.content)
4. 在 LangSmith 中查看追踪记录
当您的应用程序运行后,您将在 LangSmith 仪表板中看到追踪记录 ,如下所示。
使用 LangChain 和 OpenTelemetry 进行分布式追踪
分布式追踪在您的大语言模型(LLM)应用跨越多个服务或进程时至关重要。OpenTelemetry 的上下文传播能力可确保追踪在服务边界之间保持连贯。
分布式追踪中的上下文传播
在分布式系统中,上下文传播会在服务之间传递跟踪元数据,从而将相关的跨度(spans)关联到同一跟踪(trace)中:
- 追踪ID:整个追踪的唯一标识符
- Span ID(跨度标识符):当前跨度的唯一标识符
- 采样决策:指示此追踪是否应被采样
使用 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
# Set up OpenTelemetry trace provider
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__)
# Service A: Create a span and propagate context to Service B
def service_a():
with tracer.start_as_current_span("service_a_operation") as span:
# Create a chain
prompt = ChatPromptTemplate.from_template("Summarize: {text}")
model = ChatOpenAI()
chain = prompt | model
# Run the chain
result = chain.invoke({"text": "OpenTelemetry is an observability framework"})
# Propagate context to Service B
headers = {}
inject(headers) # Inject trace context into headers
# Call Service B with the trace context
response = requests.post(
"http://service-b.example.com/process",
headers=headers,
json={"summary": result.content}
)
return response.json()
# Service B: Extract the context and continue the trace
from flask import Flask, request, jsonify
app = Flask(__name__)
@app.route("/process", methods=["POST"])
def service_b_endpoint():
# Extract the trace context from the request headers
context = extract(request.headers)
with tracer.start_as_current_span("service_b_operation", context=context) as span:
data = request.json
summary = data.get("summary", "")
# Process the summary with another LLM chain
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)
向其他提供商发送追踪数据
虽然 LangSmith 是 OpenTelemetry 追踪数据的默认接收目的地,但您也可以配置 OpenTelemetry,将追踪数据发送至其他可观测性平台。
使用环境变量或全局配置
默认情况下,LangSmith OpenTelemetry 导出器会将数据发送至 LangSmith API 的 OTEL 端点,但您可通过设置标准的 OTEL 环境变量来自定义此行为:
OTEL_EXPORTER_OTLP_ENDPOINT: Override the endpoint URL
OTEL_EXPORTER_OTLP_HEADERS: Add custom headers (LangSmith API keys and Project are added automatically)
OTEL_SERVICE_NAME: Set a custom service name (defaults to "langsmith")
LangSmith 默认使用 HTTP 追踪导出器。如果您希望使用自己的追踪服务提供商,可以执行以下任一操作:
- 按上述方式设置 OTEL 环境变量,或
- 在初始化 LangChain 组件之前,设置一个全局 trace 提供程序,LangSmith 将检测并使用该提供程序,而非自行创建。
配置备用OTLP端点
要将追踪数据发送到其他提供商,请使用该提供商的端点来配置 OTLP 导出器:
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
# Set environment variables for LangChain
os.environ["LANGSMITH_OTEL_ENABLED"] = "true"
os.environ["LANGSMITH_TRACING"] = "true"
# Configure the OTLP exporter for your custom endpoint
provider = TracerProvider()
otlp_exporter = OTLPSpanExporter(
# Change to your provider's endpoint
endpoint="https://otel.your-provider.com/v1/traces",
# Add any required headers for authentication
headers={"api-key": "your-api-key"}
)
processor = BatchSpanProcessor(otlp_exporter)
provider.add_span_processor(processor)
trace.set_tracer_provider(provider)
# Create and run a LangChain application
prompt = ChatPromptTemplate.from_template("Tell me a joke about {topic}")
model = ChatOpenAI()
chain = prompt | model
result = chain.invoke({"topic": "programming"})
print(result.content)
使用 OpenTelemetry Collector 实现扇出
对于更高级的场景,您可以使用 OpenTelemetry Collector 将遥测数据分发至多个目标。相比在应用程序代码中配置多个导出器,这是一种更具可扩展性的方法。
-
安装 OpenTelemetry Collector: 请遵循针对您环境的 官方安装说明。
-
配置采集器: 创建一个配置文件(例如
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]
- 配置您的应用程序以向采集器发送数据:
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
# Point to your local 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)
# Set environment variables for LangChain
os.environ["LANGSMITH_OTEL_ENABLED"] = "true"
os.environ["LANGSMITH_TRACING"] = "true"
# Create and run a LangChain application
prompt = ChatPromptTemplate.from_template("Tell me a joke about {topic}")
model = ChatOpenAI()
chain = prompt | model
result = chain.invoke({"topic": "programming"})
print(result.content)
这种方法具有多项优势:
- 所有遥测目标的集中化配置
- 降低了应用程序代码的开销
- 更佳的可扩展性和弹性
- 无需修改应用程序代码即可添加或移除目标地址