使用 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 应用程序
这是一个简单的示例,展示了如何将 OpenTelemetry 集成与 LangChain 一起使用
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 的上下文传播功能确保追踪在服务边界之间保持连接。
分布式追踪中的上下文传播
在分布式系统中,上下文传播在服务之间传递追踪元数据,以便将相关的 Span 链接到相同的追踪
- 追踪 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
# 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 组件之前设置全局追踪提供商,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:按照适用于您环境的官方安装说明进行操作。
-
配置 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]
- 配置您的应用程序以发送到 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
# Point to your local OpenTelemetry Collector
otlp_exporter = OTLPSpanExporter(
endpoint="https://#: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)
这种方法提供了几个优点
- 所有遥测目标的集中配置
- 减少应用程序代码中的开销
- 更好的可扩展性和弹性
- 无需更改应用程序代码即可添加或删除目标