主题
使用 OpenTelemetry Gateway 架构脱敏敏感数据
使用 OpenTelemetry collector 在追踪进入 LangSmith 之前对敏感数据进行脱敏。
LangChain、LangGraph 和 Deep Agents 应用支持基于 OpenTelemetry 的追踪。你可以不将追踪直接发送到 LangSmith,而是让其经过你控制的 OpenTelemetry collector,应用脱敏规则去除敏感字段,再将脱敏后的追踪转发到 LangSmith。
追踪通过 OTLP/HTTP 从你的应用流向 collector。collector 运行一个 transform processor,在将脱敏后的 span 转发到 LangSmith API 之前,对敏感 span 属性(例如提示词输入和模型补全)进行脱敏。
flowchart TD
A["Application<br/>(LangChain / LangGraph / Deep Agents)"]
subgraph collector[":4318"]
B["Receiver<br/>OTLP/HTTP"]
C["Transform Processor<br/>PII Redaction<br/>(email, phone, SSN, CC)"]
D["OTLP/HTTP Exporter"]
B --> C --> D
end
E["LangSmith API<br/>api.smith.langchain.com"]
A -->|"OTLP/HTTP"| B
D -->|"OTLP/HTTP"| E
前置条件
以下两种方法都需要设置以下环境变量。将 OTEL_EXPORTER_OTLP_ENDPOINT 设置为 collector 的地址:
bash
LANGSMITH_OTEL_ENABLED="true"
LANGSMITH_TRACING="true"
LANGSMITH_OTEL_ONLY="true"
LANGSMITH_PROJECT="my-project"
OTEL_EXPORTER_OTLP_ENDPOINT="http://<my-otel-collector-endpoint>:4318"有关 LANGSMITH_PROJECT 的更多信息,请参阅将追踪记录到指定项目。
配置 collector
两种方法还都需要一个 OpenTelemetry collector 作为应用与 LangSmith 之间的中介运行。以下配置会设置监听端口 4318 的 OTLP receiver、一个对 gen_ai.prompt 和 gen_ai.completion span 属性进行脱敏的 transform processor,以及一个将脱敏后的追踪转发到 LangSmith API 的 exporter:
yaml
receivers:
otlp:
protocols:
http:
endpoint: 0.0.0.0:4318
processors:
transform/redact:
error_mode: ignore
trace_statements:
- context: span
statements:
- replace_pattern(attributes["gen_ai.completion"], "[\\s\\S]*", "[REDACTED]")
- replace_pattern(attributes["gen_ai.prompt"], "[\\s\\S]*", "[REDACTED]")
exporters:
otlphttp/langsmith:
traces_endpoint: "https://api.smith.langchain.com/otel/v1/traces"
headers:
x-api-key: "${env:LANGSMITH_API_KEY}"
Langsmith-Project: "${env:LANGSMITH_PROJECT}"
x-Tenant-Id: "${env:LANGSMITH_TENANT_ID}" # Required if API key is not scoped to a specific workspace
service:
pipelines:
traces:
receivers: [otlp]
processors: [transform/redact]
exporters: [otlphttp/langsmith]使用 LangChain、LangGraph 或 Deep Agents 追踪
如果你的应用已经使用 LangChain、LangGraph 或 Deep Agents,请使用此方法。追踪集成会根据你的环境变量自动处理 span 创建,因此无需额外的 instrumentation 代码:
python
from langchain.agents import create_agent
from langchain.tools import tool
from langchain_openai import ChatOpenAI
@tool
def tell_joke(topic: str) -> str:
llm = ChatOpenAI()
response = llm.invoke(f"Tell me a short, funny joke about {topic}.")
return response.content
agent = create_agent(
model=ChatOpenAI(),
tools=[tell_joke],
system_prompt="When the user asks for jokes, use the tell_joke tool for each topic.",
)
topics = ["programming", "python", "kubernetes", "machine learning"]
result = agent.invoke(
{"messages": [{"role": "user", "content": f"Tell me jokes about these topics: {', '.join(topics)}"}]}
)
print(result["messages"][-1].content)直接使用 OpenTelemetry SDK 追踪
如果你需要以编程方式控制 tracer provider 和 exporter(例如在运行时为每个请求设置项目名称或配置自定义请求头),请使用此方法。你需要在代码中显式配置 provider,而不是仅依赖环境变量:
python
import os
from langchain.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
project_name = os.environ["LANGSMITH_PROJECT"]
otlp_endpoint = os.environ["OTEL_EXPORTER_OTLP_ENDPOINT"]
provider = TracerProvider()
provider.add_span_processor(
BatchSpanProcessor(
OTLPSpanExporter(
endpoint=otlp_endpoint+"/v1/traces",
headers={"Langsmith-Project": project_name},
)
)
)
trace.set_tracer_provider(provider)
chain = ChatPromptTemplate.from_template("Tell me a joke about {topic}") | ChatOpenAI()
for topic in ["programming", "python", "databases", "kubernetes", "machine learning"]:
print(f"Asking about {topic}...")
result = chain.invoke({"topic": topic})
print(f" {result.content[:100]}\n")
provider.force_flush()
provider.shutdown()NOTE
如果你希望不经过 collector 直接对敏感数据脱敏,请参阅防止在追踪中记录敏感数据。