这是什么
Langfuse 是一个开源的 LLM 可观测性平台,用于追踪、监控和调试 AI 应用的请求链路。 千手大师通过 OpenTelemetry (OTel) 桥接层把它接入查询流程,实现三类观测:
- LLM 调用追踪:记录每次 API 请求的模型、Provider、输入 / 输出与 Token 用量(含缓存读写拆分)。
- 工具执行追踪:记录每个工具调用的名称、输入、输出、耗时与错误标记。
- 多 Agent 追踪:主 Agent 与
AgentTool启动的子 Agent 各自拥有独立 Trace。
启用开关由 isLangfuseEnabled() 判定:同时存在
LANGFUSE_PUBLIC_KEY 与 LANGFUSE_SECRET_KEY 时开启,
否则全部追踪函数直接返回 null 或跳过,等价于零开销。
生命周期在启动流程内完成:src/entrypoints/init.ts 启动时调用
initLangfuse() 创建 LangfuseSpanProcessor 与
BasicTracerProvider,并通过 registerCleanup(shutdownLangfuse)
在进程退出时强制 flush 并关闭。依赖库为
@langfuse/otel、@langfuse/tracing 与
@opentelemetry/sdk-trace-base。
前置条件
-
一个 Langfuse 实例:可以在自己的 Docker / Kubernetes 上自部署,也可以使用官方
Langfuse Cloud(
https://cloud.langfuse.com,提供免费测试额度)。 -
一对 API 密钥:在实例的 Project Settings → API Keys 页面获取
Public Key(pk-...)与Secret Key(sk-...)。 两个都要提供,只配置其一会保持 no-op。 -
服务地址:默认指向 Langfuse Cloud;自部署时需要把
LANGFUSE_BASE_URL指向你的实例。 - 网络出口可达:运行环境需能访问所配置的 Langfuse 主机。
安装 / 启用
无需安装任何 CLI 插件,配置环境变量即可启用。
-
获取 Public Key 与 Secret Key
在 Langfuse 实例的 Project Settings → API Keys 页面创建密钥对,记录公钥与密钥。
-
设置环境变量
两个密钥必须同时存在。可在真实 shell 环境中导出,或写入用户级
~/.claude/settings.json的env字段(受信任源,启动早期注入), 也可写入~/.claude.json。LANGFUSE_PUBLIC_KEY=pk-xxx \ LANGFUSE_SECRET_KEY=sk-xxx \ LANGFUSE_BASE_URL=https://cloud.langfuse.com \ qsdashi -
验证生效
启动后会创建 Processor(debug 日志输出
[langfuse] Initialized with LangfuseSpanProcessor), 每轮对话创建 Trace([langfuse] Trace created: ...), 在 Langfuse 面板即可看到对应 Track / Session。
Langfuse 在启动早期初始化,早于「信任建立后」的完整 settings 环境注入。
放在项目级 .claude/settings.json 的 env 会太晚,
当轮不生效。请使用真实 shell 环境变量、~/.claude/settings.json 的
env(userSettings 属受信任源,早期注入)或 ~/.claude.json。
配置
全部通过环境变量控制,均无对应的 CLI 子命令。
| 环境变量 | 默认值 | 说明 |
|---|---|---|
LANGFUSE_PUBLIC_KEY |
无(必填) | Langfuse 公钥,缺失则不启用 |
LANGFUSE_SECRET_KEY |
无(必填) | Langfuse 密钥,缺失则不启用 |
LANGFUSE_BASE_URL |
https://cloud.langfuse.com |
服务地址,自部署时改为你的实例地址 |
LANGFUSE_TRACING_ENVIRONMENT |
development |
环境标签,用于面板筛选 |
LANGFUSE_FLUSH_AT |
20 |
批量发送的 span 数量阈值 |
LANGFUSE_FLUSH_INTERVAL |
10 |
定时刷新间隔(秒) |
LANGFUSE_EXPORT_MODE |
batched |
导出模式:batched(批量)或 immediate(即时) |
LANGFUSE_TIMEOUT |
5 |
请求超时(秒) |
LANGFUSE_USER_ID |
无 |
指定 Trace 的用户标识,用于面板按用户聚合;解析顺序为
显式 username > LANGFUSE_USER_ID > 账号邮箱 > 设备 ID
|
Processor 的 release 字段取自构建常量 MACRO.VERSION,
无需手动配置,用于在面板中按版本对比。
追踪层级与脱敏
数据流从一个根 Trace 展开,子节点为 LLM generation 与 tool span:
Trace (Agent Span) <- createTrace() / createSubagentTrace()
├── Generation (LLM 调用) <- recordLLMObservation()
├── tools (批量工具 span) <- createToolBatchSpan() / endToolBatchSpan()
│ ├── Tool Observation <- recordToolObservation()
│ └── Tool Observation
└── ...
主 Agent 每次 query() 调用(即用户一次对话 turn)创建一个 agent
类型的根 Span,名称为 agent-run 或 agent-run:<querySource>,
元数据含 provider、model、agentType: "main",
并携带 Session ID 以支持按会话聚合。子 Agent 通过 createSubagentTrace()
创建独立 Trace,名称为 agent:<agentType>。
LLM generation 名称按 Provider 映射:
| Provider | Generation 名称 |
|---|---|
firstParty | ChatAnthropic |
bedrock | ChatBedrockAnthropic |
vertex | ChatVertexAnthropic |
foundry | ChatFoundry |
openai | ChatOpenAI |
gemini | ChatGoogleGenerativeAI |
grok | ChatXAI |
每个工具调用记录为 tool 类型的 Span,名称为工具名(如
FileEditTool、BashTool),元数据含 toolUseId 与
isError;失败时附加 level: ERROR。Trace 结束时若状态为
interrupted 或 error,会分别标记 WARNING / ERROR。
所有上传数据在发送前经 sanitize.ts 处理:
| 范围 | 脱敏策略 |
|---|---|
| 敏感字段(全局) |
匹配 api_key / token / secret /
password / credential / auth_header
等关键字的字段值替换为 [REDACTED]
|
| Home 路径 |
将 /Users/xxx、C:\Users\xxx 等替换为 ~
(同时覆盖 file_path / path / directory)
|
FileReadTool / FileWriteTool / FileEditTool |
内容整体遮蔽,仅保留字符数:[file content redacted, N chars] |
BashTool / PowerShellTool |
输出截断至 500 字符,超出追加 [truncated] |
ConfigTool / MCPTool |
输出完全遮蔽 |
| 其他工具 | 原样保留(仍经过全局字段与路径脱敏) |
convert.ts 另将内部 Message 类型转换为 Langfuse 期望的 OpenAI 兼容格式:
text → text part、thinking → thinking part、
tool_use → tool call、tool_result → tool 消息,
图片与文档退化为 [image] / [document: name] 占位标记。
常用命令与参数
Langfuse 集成没有独立的 CLI 子命令,启用与调参完全依赖环境变量。相关「参数」为追踪 命名的行为约定与关键调用函数:
| 项 | 说明 |
|---|---|
initLangfuse() |
启动时调用,创建 Processor 与 Provider;已有实例则直接返回 |
isLangfuseEnabled() |
检查双密钥是否齐备;各追踪函数据此快速短路 |
flushLangfuse() |
强制 flush 当前队列(如 Trace 结束、进程退出前调用) |
shutdownLangfuse() |
flush 后关闭 Processor,经 cleanup 钩子在退出时执行 |
agent-run[:source] |
主 Agent 根 Trace 名称 |
agent:<agentType> |
子 Agent 独立 Trace 名称 |
tools |
并发工具批次的父 span 名称,元数据含 toolNames / toolCount / batchIndex |
批量模式下(默认 batched),span 达到 LANGFUSE_FLUSH_AT 数量或
经过 LANGFUSE_FLUSH_INTERVAL 秒才发送。每次对话 turn 结束时会主动
flushLangfuse(),进程退出时也会强制 flush,因此不会丢失尾部数据。
实战示例
写入用户级 settings.json 长期生效(受信任源,启动早期注入):
{
"env": {
"LANGFUSE_PUBLIC_KEY": "pk-xxx",
"LANGFUSE_SECRET_KEY": "sk-xxx",
"LANGFUSE_BASE_URL": "https://cloud.langfuse.com",
"LANGFUSE_TRACING_ENVIRONMENT": "production"
}
}
即时模式(每个 span 立即发送,适合调试,吞吐略低):
LANGFUSE_EXPORT_MODE=immediate qsdashi
自部署 Langfuse(Docker 方式仅供参考,实际部署请对照 Langfuse 官方文档):
docker run -d \
--name langfuse \
-p 3000:3000 \
-e DATABASE_URL=postgresql://... \
langfuse/langfuse:latest
# 随后把 LANGFUSE_BASE_URL 指向该实例
LANGFUSE_BASE_URL=http://localhost:3000 qsdashi
把一次 Trace 保存为数据集(Dataset)是 Langfuse 平台侧的能力,需要在 Langfuse 界面中操作。千手大师只负责把链路数据上报上去,不提供对应的命令行子命令。
常见问题排错
最常见原因是把密钥写进了项目级 .claude/settings.json:该来源的
env 在信任建立后才完全注入,而 Langfuse 已在启动早期初始化,当轮不会生效。
改用真实 shell 环境变量、~/.claude/settings.json 或 ~/.claude.json。
isLangfuseEnabled() 要求
LANGFUSE_PUBLIC_KEY 与 LANGFUSE_SECRET_KEY 同时存在。
任一缺失时追踪函数直接短路,日志会提示 No keys configured, running in no-op mode。
默认导出模式为 batched,按 LANGFUSE_FLUSH_AT(默认 20 个 span)
或 LANGFUSE_FLUSH_INTERVAL(默认 10 秒)触发。需要实时观看时改为
LANGFUSE_EXPORT_MODE=immediate,或调低刷新阈值与间隔。
确认 LANGFUSE_BASE_URL 指向的地址从运行环境可达,且协议(http / https)与端口正确;
超时由 LANGFUSE_TIMEOUT(默认 5 秒)控制,网络不通时会看到
[langfuse] Init failed 或 Flush error 日志,不影响主流程。
上传前统一经过脱敏:文件读写内容整体遮蔽只留字符数、Shell 输出截断 500 字符、
Config / MCP 输出完全遮蔽、敏感字段替换为 [REDACTED]、Home 路径替换为 ~。
但仍建议自部署实例并限制网络出口,避免把密钥交给不可信服务。