Langfuse 详解:大模型应用可观测性与链路追踪实践

发布时间:2026/8/27 2:00:07
Langfuse 详解:大模型应用可观测性与链路追踪实践 最近在做基于大模型的应用时我发现最麻烦的不是写代码而是出了问题以后不知道该怎么排查。用户的同一句提问有时候模型回答正常有时候又答非所问你说它没调用吧Token 费用涨得飞快你说它调用了吧又找不到具体是哪个环节慢、哪个环节错。为了把这类问题彻底看清楚我把 Langfuse 完整研究了一遍从本机部署到项目接入全流程跑通。这篇教程就是这次落地的整理内容包括 Langfuse 是什么、为什么需要它、如何部署、如何接入 Python 与 Spring Boot 项目、常见报错怎么解决争取让你看完就能直接上手做大模型监控。1. 为什么需要 Langfuse大模型应用的可观测性痛点1.1 传统日志监控解决不了 LLM 问题在传统后端开发中我们有非常成熟的监控体系接口日志、错误码、链路追踪、指标告警。一个请求发出去哪个服务慢、哪个 SQL 有问题、哪个下游接口报错通过 SkyWalking、Pinpoint、Zipkin 这类工具基本都能查清楚。但到了 LLM 应用里情况发生了变化。大模型应用往往不是“请求-响应”这么简单而是一整条链路用户输入经过 Prompt 模板组装进入模型调用可能还会触发工具调用、检索知识库、多轮上下文拼接最后才生成回复。这条链路里的每一个环节都在消耗 Token、都在产生延迟而且大模型本身的输出还有很强的随机性。传统日志只能记录“调用了哪个接口”却很难回答下面这些问题这个请求发送给模型的 Prompt 到底是什么模型返回的完整内容是什么本次调用消耗了多少 Token、费用是多少请求慢在模型调用阶段还是慢在知识库检索阶段用户多轮对话的上下文是如何拼接和演变的Agent 在哪个步骤选择了哪个工具这些问题不解决大模型应用基本上就是“黑盒”。用户说回答不对你连模型看到了什么都不知道。1.2 Langfuse 是什么Langfuse 是一个开源的 LLM 可观测性与分析平台用来追踪、调试和评估大模型应用。你可以把它理解为“大模型应用的链路追踪系统 审计日志 成本分析工具”的组合体。它解决的核心问题就是让大模型应用里的每一次模型调用、每一步 Agent 决策、每一轮对话上下文都变得可见。从开发环境调接口到生产环境做效果分析Langfuse 都能派上用场。Langfuse 的核心能力包括Trace 可视化把一次完整请求展开成树状结构每一步耗时、输入输出、Token 消耗一目了然。会话级追踪支持把多轮对话聚合到同一个 Session 下方便观察上下文演变。成本统计自动聚合 Token 消耗与费用按项目、用户、模型维度查看开销。Prompt 版本管理支持在平台上管理 Prompt 模板并关联到具体 Trace。在线评估支持人工打分、标注也可以接入自动化评估逻辑。数据集与测试可以沉淀测试集回归验证 Prompt 变更效果。1.3 Langfuse 与普通日志监控的区别很多同学会问我在代码里用 log.info 打印 Prompt 和返回结果再加个数据库表存起来是不是一样的短期内能用但工程化程度差很多。Langfuse 与普通日志方案的本质区别在于它围绕 LLM 调用语义建立了数据模型而不是简单地记录字符串。对比维度普通日志方案Langfuse数据组织一行行文本Trace、Span、Generation 的树状结构上下文关联靠 requestId 手动拼自动关联父子节点Token 统计需要自己算自动统计模型调用消耗多轮会话很难表达原生 Session 概念效果评估需要自建支持打标、评分、数据集回归检索体验grep 日志可视化筛选与查询简单说普通日志是“一串记录”Langfuse 是“一棵有逻辑的追踪树”。这也是为什么现在越来越多的 LLM 项目会引入 Langfuse。2. 环境准备与部署方式选择在接入 Langfuse 之前我们需要先把服务部署起来。Langfuse 支持多种部署方式你先根据自己的场景选一种。2.1 部署方式对比部署方式适合场景说明Docker Compose 自托管本地开发、公司内网、数据敏感场景完全掌控数据推荐优先尝试官方云服务不想维护基础设施上手最快但要考虑数据出域问题Kubernetes Helm 部署生产环境、已有 K8s 集群适合规模化运维Railway / Render 等 PaaS快速演示配置简单但网络访问可能需要额外处理如果你只是体验功能官方云服务是最快的如果你打算在项目里深度使用我更推荐第一种也就是通过 Docker Compose 在自己服务器或本机部署。毕竟大模型应用的业务数据往往涉及用户输入内容放在自己环境里心里更有底。2.2 通过 Docker Compose 部署 Langfuse本文的部署环境以 Linux 服务器或安装了 Docker Desktop 的本地电脑为例。你需要提前准备好Docker 与 Docker Compose 插件建议 Docker 版本不低于 20.10可用的 3000 端口Langfuse 默认 Web 端口一定的磁盘空间用于存放数据库数据这里我们使用一个最小可运行的 Docker Compose 配置。Langfuse 依赖 PostgreSQL 作为主数据库Redis 用于缓存与队列Web 服务自身负责提供控制台和 API。不同版本的 Langfuse 对依赖项要求略有差异请以你自己的实际版本为准这里重点演示配置思路。# 文件路径docker-compose.yml version: 3.9 services: langfuse: image: langfuse/langfuse:latest restart: always depends_on: - db - redis ports: - 3000:3000 environment: - NEXTAUTH_URLhttp://localhost:3000 - NEXTAUTH_SECRETplease-generate-a-random-secret - ENCRYPTION_KEYplease-generate-a-random-encryption-key - SALTplease-generate-a-random-salt - DATABASE_URLpostgresql://postgres:postgresdb:5432/langfuse - REDIS_URLredis://redis:6379 - NODE_ENVproduction db: image: postgres:16 restart: always environment: - POSTGRES_USERpostgres - POSTGRES_PASSWORDpostgres - POSTGRES_DBlangfuse volumes: - langfuse-db-data:/var/lib/postgresql/data healthcheck: test: [CMD-SHELL, pg_isready -U postgres] interval: 5s timeout: 5s retries: 5 redis: image: redis:7 restart: always volumes: - langfuse-redis-data:/data volumes: langfuse-db-data: langfuse-redis-data:配置里面有几个环境变量需要特别说明NEXTAUTH_URLLangfuse 控制台的对外访问地址。如果你用 IP 访问就改成http://你的服务器IP:3000如果是域名访问就改成对应的域名。NEXTAUTH_SECRET用于会话加密的密钥越随机越好。ENCRYPTION_KEY用于对敏感配置比如 Prompt 模板内容进行加密的密钥。SALT密码哈希盐值同样需要随机生成。DATABASE_URLPostgreSQL 连接字符串。REDIS_URLRedis 连接字符串。其中 ENCRYPTION_KEY 和 SALT 至少需要 16 字节建议用下面的命令生成openssl rand -base64 32 openssl rand -base64 16生成结果形如a3Bq...把它填到对应的环境变量里即可。注意每次部署只要配置过后续迁移环境时务必保持一致否则历史加密数据会无法解密。配置完成后在 docker-compose.yml 所在目录执行docker compose up -d首次启动会拉取镜像需要等待一段时间。启动完成后访问http://localhost:3000你应该能看到 Langfuse 的注册页面。在继续下面的内容之前进到注册页面创建一个本地账号并登录。登录后系统会自动创建一个默认项目你也可以在项目列表里新建项目。2.3 创建项目和 API KeyLangfuse 的应用访问不是直接用账号密码而是通过 API Key 来鉴权。这是因为项目代码通常运行在服务端不能把浏览器登录态的 Cookie 用于接口调用。操作步骤很简单登录 Langfuse 控制台。在页面左上角进入项目。打开左侧菜单中的“Settings”找到“API Keys”。点击新建 API Key系统会生成一对公钥和私钥。注意私钥只在创建时完整展示一次关闭页面后就看不到了。你可以把它理解成支付密钥需要妥善保存在环境变量或密钥管理系统中。公钥也是敏感信息同样不要硬编码在前端代码里。这一对 Key 会用在后续所有代码接入中。为了便于区分不同环境建议分别为开发环境、测试环境、生产环境创建独立的项目并生成各自独立的 API Key。这样即使某个环境的 Key 泄漏也可以快速单独撤销不影响其他环境。3. Langfuse 核心概念与数据模型在写代码之前花几分钟理解 Langfuse 的数据模型非常重要。因为这些概念会直接出现在 SDK 的 API 命名里也决定了你后续怎么设计自己的埋点。3.1 Trace 与 ObservationTrace 是 Langfuse 中最顶层的概念。一次业务请求对应一个 Trace比如“用户问了一个问题”“Agent 执行了一次完整任务”。一个 Trace 可以包含多个子节点这些子节点统称为 Observation。Observation 是“可观测对象”的统称下面又细分为 Span、Generation、Event 三种。你可以把 Trace 看作是整棵树的根Observation 是树干和树叶。在实际请求中一次完整的 LLM 应用调用可能是这样的Trace用户提问 ├── Span知识库检索 │ └── GenerationEmbedding 模型调用 ├── SpanPrompt 组装 └── Generation大模型回答这个结构非常直观哪个环节慢、哪个环节在调用模型、哪个环节出现异常一眼就能看出来。3.2 Span、Generation 与 EventSpan 用于表示一段有时间跨度的操作比如“查数据库”“调用外部 API”“执行一段本地逻辑”。它强调的是“耗时操作”不一定涉及模型调用。Generation 是特殊的 Span 或者说 Observation专门用来表示一次模型生成调用。无论是 OpenAI 的 Chat Completions、开源模型的本地推理还是 Embedding 调用都可以用 Generation 表示。Langfuse 会自动解析模型名、输入输出、Token 消耗、延迟等指标。Event 则是一个瞬间发生的事件比如“用户点击了某个按钮”“发生了某个异常”。它没有时间跨度只表示某个时间点发生了什么。按我的使用经验绝大多数场景下你只需要关心 Trace 和 Generation。手动创建 Span 的场景一般是在你的代码里有比较耗时的非模型操作比如检索数据库、调用外部搜索 API这些操作对问题排查也很有价值。3.3 Session 与 UserSession 用于把多个 Trace 聚合到一个多轮会话中。聊天机器人场景里用户连续提问多轮每轮请求是一个 Trace但它们都属于同一个 Session。Langfuse 会帮你把 Session 里的所有 Trace 按时间线展示方便观察整个对话的上下文演变。User 则是更上层的维度。如果你的系统有登录用户体系可以把用户 ID 关联到 Trace 或 Session 上。这样后续做数据分析时就可以按用户维度查看成本、调用次数、响应延迟。Session 和 User 的关系可以类比为“一次客服工单”和“客户姓名”。一个 Session 对应一个完整交互周期一个 User 可以创建多个 Session。3.4 数据上报链路Langfuse 的数据上报链路比较简单你的应用代码 ↓ SDK / HTTP API Langfuse Web 服务 ↓ PostgreSQL业务数据 Redis队列Python SDK 会将 trace 数据批量异步发送到 Langfuse 服务。发送失败时数据会暂存在内存队列中SDK 会根据配置重试或丢弃。因此在需要保证数据不丢失的生产场景建议评估一下网络抖动对上报链路的影响必要时可以增加本地缓冲或日志兜底。理解完这些概念下面进入实战环节。4. Python SDK 快速接入实战Langfuse 对 Python 生态支持得最完善官方提供了langfusePython 包同时支持原生 OpenAI 客户端、LangChain、LlamaIndex 等框架的回调接入。下面从最基础的用法开始讲。4.1 安装与初始化在项目虚拟环境中安装 SDKpip install langfuse然后把 API Key 和地址放到环境变量中。推荐使用.env文件管理避免把密钥写进代码仓库# 文件路径.env LANGFUSE_PUBLIC_KEYpk-lf-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx LANGFUSE_SECRET_KEYsk-lf-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx LANGFUSE_HOSThttp://localhost:3000其中LANGFUSE_HOST是你部署 Langfuse 的地址。如果应用与 Langfuse 在同一台服务器写http://localhost:3000即可如果跨服务器要写内网或公网可访问的地址。接下来初始化客户端# 文件路径langfuse_client.py import os from langfuse import Langfuse # SDK 会自动读取 LANGFUSE_PUBLIC_KEY、LANGFUSE_SECRET_KEY、LANGFUSE_HOST langfuse Langfuse()如果你不想使用环境变量也可以在创建对象时显式传入langfuse Langfuse( public_keypk-lf-xxx, secret_keysk-lf-xxx, hosthttp://localhost:3000, )这里的host参数在旧版本 SDK 中可能是base_url不同版本命名有差异请以你安装版本的实际参数名为准。4.2 使用装饰器自动追踪Langfuse 的observe装饰器可以自动包装函数把函数调用记录为一个 Observation。这是最省事的接入方式很适合先跑通链路。# 文件路径quickstart.py from langfuse.decorators import observe, langfuse_context from openai import OpenAI client OpenAI() observe() def generate_answer(question: str) - str: # 这里调用了 OpenAI 的 Chat Completions 接口 response client.chat.completions.create( modelgpt-4o-mini, messages[ {role: system, content: 你是一个乐于助人的助手。}, {role: user, content: question}, ], temperature0.7, ) answer response.choices[0].message.content # 将调用信息关联到当前 trace langfuse_context.update_current_trace( inputquestion, outputanswer, ) return answer if __name__ __main__: print(generate_answer(给我讲一个笑话))运行之后登录 Langfuse 控制台在 Traces 页面应该能看到一条新的 trace 记录。点进去可以看到函数名generate_answer、输入参数、OpenAI 模型调用记录和输出结果。需要注意是observe装饰器默认只记录函数级信息并不会自动捕获函数内部的 OpenAI 调用。如果你想让 Langfuse 自动追踪 OpenAI 请求需要结合 OpenAI 的 callback 能力或者手动创建 Generation下面的示例会演示。4.3 手动创建 Trace 与 Generation手动创建的优势是控制粒度更细。你可以给一个 Trace 添加多个 Generation、Span、Event精确描述每一步做了什么。# 文件路径manual_trace.py from langfuse import Langfuse langfuse Langfuse() def main(): trace langfuse.trace( name用户提问链路, user_iduser_12345, session_idsession_abc, input{question: 请介绍一下 Python 的 GIL}, ) # 记录一次 Embedding 调用 embedding_generation trace.generation( nameembedding-query, modeltext-embedding-3-small, input请介绍一下 Python 的 GIL, model_parameters{type: embedding}, ) # 模拟调用结果 embedding_vector [0.1, 0.2, 0.3] embedding_generation.end(output{vector: embedding_vector}) # 记录一次大模型调用 llm_generation trace.generation( namechat-completion, modelgpt-4o-mini, input{ messages: [ {role: system, content: 你是 Python 技术专家}, {role: user, content: 请介绍一下 Python 的 GIL}, ] }, model_parameters{temperature: 0.7}, ) # 模拟调用结果 answer GIL 是 Python 解释器中的一个全局锁…… llm_generation.end( output{content: answer}, usage{ input: 40, output: 120, total: 160, unit: TOKENS, }, ) trace.update(output{answer: answer}) # 确保数据发送到服务端 langfuse.flush() if __name__ __main__: main()这里有两个容易踩的坑。第一个trace.generation()返回的是一个 generation 对象调用它并不会立即上报必须调用end()标记结束。如果你创建了 generation 但忘记调用end()Langfuse 上会看到一条没有结束时间的记录。第二个langfuse.flush()很重要。SDK 默认是异步批量上报程序正常退出时如果你不主动 flush可能会丢失最后几条尚未发送的数据。在 Web 服务里这种问题不明显因为进程长时间存活但脚本类程序运行完就退出最后如果不 flush数据就悄无声息丢了。这是一个非常隐蔽的问题我在调试时花了不少时间才定位到。4.4 接入 OpenAI 和 LangChain如果你的项目直接用 OpenAI SDK可以在请求时通过langfuse_openai扩展自动埋点。官方推荐使用langfuse.openai模块中的openai客户端# 文件路径openai_trace.py from langfuse.openai import openai # 这个客户端会自动上报 trace 信息 response openai.chat.completions.create( modelgpt-4o-mini, messages[ {role: user, content: 用一句话解释什么是数据库索引} ], ) print(response.choices[0].message.content)如果你使用的是 LangChain可以通过 Langfuse 提供的 CallbackHandler 一键接入# 文件路径langchain_trace.py from langchain_openai import ChatOpenAI from langfuse.callback import CallbackHandler # Langfuse 回调处理器 langfuse_handler CallbackHandler() llm ChatOpenAI(modelgpt-4o-mini, temperature0.7) result llm.invoke( 讲一个程序员加班的笑话, config{callbacks: [langfuse_handler]}, ) print(result.content)接入完成后只要在 Langchain 的调用配置里带上回调Langfuse 会自动把链路上的模型调用、中间步骤、Token 消耗记录下来。它内部会将 LangChain 的 Chain、LLM、Tool 等组件映射为对应的 Observation 类型所以在控制台上看到的是结构化的追踪树而不是一堆堆的原始日志。需要提醒的是LangChain 和 Langfuse 都在快速迭代CallbackHandler 的具体位置和导入方式可能因版本而异。如果出现导入错误优先去查你所安装版本的官方文档或者在 GitHub 仓库的 examples 目录里找示例。5. Spring Boot 集成 Langfuse 的思路很多公司后端是 Java 技术栈那么 Java/Spring Boot 项目怎么接入 Langfuse这里要说明一点Langfuse 对 Java 生态的 SDK 支持不如 Python 那么完善但我们可以通过 Langfuse 的公开 HTTP API 实现上报。这个思路通用性很强不依赖特定语言。5.1 Java 生态的接入方式Langfuse 在前后端交互时控制台本身也是通过一组 REST API 来读写数据的。这组 API 使用 Basic Auth鉴权信息就是你在上一步创建的公钥和私钥。所以 Java 项目接入本质上就两步构造 Trace 数据按 Langfuse API 要求的 JSON 结构组装。使用 HttpClient、RestTemplate 或 OpenFeign 发起 HTTP 请求将数据提交到/api/public/traces接口。由于不同版本的 API 路径存在微调你在实际开发时先到 Langfuse 的 OpenAPI 页面确认一下当前版本的接口定义再按接口文档调整 JSON 字段。5.2 上报 Trace 的最小实现下面给出一个用 RestTemplate 上报 Trace 的示例。这里只演示核心思路实际项目中需要把 URL、认证信息放到配置中心或环境变量中。先添加依赖dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency然后写一个简单的服务类// 文件路径src/main/java/com/example/langfuse/LangfuseClient.java package com.example.langfuse; import org.springframework.beans.factory.annotation.Value; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.stereotype.Component; import org.springframework.web.client.RestTemplate; Component public class LangfuseClient { private final RestTemplate restTemplate; Value(${langfuse.api-url:http://localhost:3000}) private String apiUrl; Value(${langfuse.public-key}) private String publicKey; Value(${langfuse.secret-key}) private String secretKey; public LangfuseClient(RestTemplate restTemplate) { this.restTemplate restTemplate; } public void sendTrace(String traceJson) { String url apiUrl /api/public/traces; HttpHeaders headers new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); headers.setBasicAuth(publicKey, secretKey); HttpEntityString entity new HttpEntity(traceJson, headers); restTemplate.postForEntity(url, entity, String.class); } }对应的配置项# 文件路径src/main/resources/application.properties langfuse.api-urlhttp://localhost:3000 langfuse.public-keypk-lf-xxxxxxxx langfuse.secret-keysk-lf-xxxxxxxx然后在业务代码中调用// 文件路径src/main/java/com/example/langfuse/ChatService.java package com.example.langfuse; import org.springframework.stereotype.Service; Service public class ChatService { private final LangfuseClient langfuseClient; public ChatService(LangfuseClient langfuseClient) { this.langfuseClient langfuseClient; } public String chat(String question) { // 业务逻辑组装 prompt调用模型 String answer callLLM(question); // 构造 trace JSON String traceJson { name: spring-boot-chat, timestamp: 2026-01-01T00:00:00.000Z, input: %s, output: %s } .formatted(escapeJson(question), escapeJson(answer)); langfuseClient.sendTrace(traceJson); return answer; } private String callLLM(String question) { // 这里放你实际的模型调用代码 return 这是模拟的模型回答; } private String escapeJson(String text) { if (text null) { return ; } return text.replace(\\, \\\\) .replace(\, \\\) .replace(\n, \\n); } }这个例子简单但已经能完成最基本的 Trace 上报。如果想记录 Generation 或 Span只需要往 JSON 里增加对应字段。字段结构以上述 API 文档为准我不在这里硬列避免版本不一致误导你。5.3 与 LLM 网关结合如果你所在团队已经建设了 LLM 网关LLM Gateway比如用 Spring Cloud Gateway 统一转发模型请求那么 Langfuse 埋点放在网关层会非常合适。这样不需要每个业务服务都单独接入只要网关统一封装模型调用就能在整个公司层面形成统一的模型监控视图。在网关层接入时需要注意一个问题Trace ID 的透传。网关生成 Trace ID 后要把它放到请求头传给下游服务下游服务在处理业务逻辑时产生的日志、调用信息最好也带上这个 Trace ID。这样当整体链路异常时你可以从 Langfuse 控制台一直追到具体业务日志排查效率会高很多。6. 常见问题与排查思路接入 Langfuse 的过程中我整理了一些高频问题按现象、原因、解决思路分列如下问题现象常见原因解决思路浏览器访问 3000 端口无法打开容器未启动、端口被占用、安全组未放行查看docker compose ps检查日志确认端口与防火墙创建 API Key 后代码仍返回 401公钥或私钥配置错误、密钥复制多了空格检查环境变量重新生成 Key注意私钥只在创建时显示一次代码执行成功但控制台看不到 Trace没有调用flush()、上报地址不通、异步发送失败脚本类程序末尾调用flush()查看请求是否返回 401/404Trace 显示出来了但没有模型调用记录使用observe时未接入 OpenAI/LangChain 回调改用手动创建 Generation或使用官方封装客户端Generation 一直显示未结束创建了对象但没调用end()在模型调用完成后调用end()并传入输出内容Token 消耗显示为 0手动创建 Generation 时未传usage参数在end()中传入usage包括 input、output、total、unit多轮对话无法聚合没有给 Trace 指定session_id创建 Trace 时传入统一生成的 session_id服务器重启后历史数据丢失未挂载数据卷容器数据存在容器层配置volumes持久化 PostgreSQL 和 Redis 数据部署升级后登录报错环境变量密钥与之前不一致检查并保持NEXTAUTH_SECRET、ENCRYPTION_KEY、SALT不变排查的时候建议按这个顺序走先看 Langfuse 服务端日志确认请求有没有进来。再看应用侧日志确认 SDK 是否成功发送。最后看 Langfuse API 返回状态码确认鉴权是否通过。这套顺序能定位绝大多数问题。7. 最佳实践与工程建议接入 Langfuse 只是第一步把工具用好才是关键。这一节分享一些实际项目中值得注意的实践建议。7.1 Trace 命名要有清晰规范Trace 的name字段会出现在控制台的会话列表中建议用“业务模块-动作类型”的格式命名例如chat-send-messageagent-execute-taskrag-retrieve-docsembedding-generate命名清晰之后你在控制台里搜索、过滤、统计时都会省力很多。如果所有 Trace 都叫同一个名字后续做成本分析和性能分析时根本无法区分业务来源。7.2 控制敏感信息避免数据泄露大模型应用的 Trace 里往往包含了用户输入的原文、Prompt 模板、模型输出。这些内容会长期存储在 Langfuse 的数据库中如果其中包含手机号、身份证号、公司机密等敏感信息就会有数据泄露风险。建议在接入时就做好脱敏策略用户输入中的手机号可以打码密钥、Token 不要拼进 Prompt模型输出中也不要记录完整的个人身份信息。如果确实需要记录敏感字段用于调试可以考虑只记录哈希值或截断后的内容。7.3 使用 Session 聚合多轮对话聊天类应用一定记得传session_id。没有 Session 聚合你看到的是一堆孤立的 Trace无法按用户对话链路分析问题。有 Session 聚合后你可以在 Langfuse 控制台查看一次完整的多轮交互过程包括每轮之间上下文是怎么拼接的、用户在哪里开始绕圈、模型在哪里开始答错。7.4 只追踪关键链路深度观察核心场景Trace 也不是越细越好。如果你的项目调用链路特别复杂每一层都塞大量的 Span 和 Event最终会让控制台页面变得非常拥挤反而影响排查效率。我的建议是核心业务场景做完整深度追踪包含每步 Span、Generation、Token 消耗。边缘场景或辅助逻辑只记录必要的输入输出。Event 用于关键异常和分支决策不要把所有普通日志都塞进来。7.5 生产环境注意抽样采集与数据保留在业务量较大的生产环境中所有请求都做全量深追踪数据量会非常可观。这时候需要结合业务诉求做取舍按比例抽样比如 10% 的请求记录全量 trace。对高优先级用户或 VIP 用户全量记录。对异常场景全量记录正常场景抽样。同时Langfuse 底层使用 PostgreSQL 存储数据量过大后需要关注数据库性能。建议提前规划数据保留周期定期清理过期数据或者把历史数据归档到数仓。控制台里的项目设置若支持数据保留配置按业务需求设置即可。7.6 环境隔离与密钥管理就像前面说的开发、测试、生产环境尽量使用不同的 Langfuse 项目甚至不同的部署实例。环境隔离能避免测试数据污染生产环境的监控分析结果。API Key 的保管也要重视。把 Key 放在环境变量、K8s Secret 或配置中心里不要硬编码到代码仓库。如果 Key 意外泄漏及时去控制台撤销并重新生成。8. 从一个小例子开始这篇教程从 Langfuse 的概念讲起到 Docker Compose 部署、Python SDK 接入、Spring Boot 上报思路、常见问题排查和工程实践核心链路已经完整覆盖。你可以先把第一节提到的部署流程跑通然后照着第四节的 Python 示例写一个最小可运行案例观察 Trace 在控制台上的展示形态再逐步扩展到自己的业务代码里。在大模型应用开发中模型效果和系统稳定性同样重要。有了 Langfuse 这类工具至少当模型回答错误、Token 费用异常、链路延迟变高的时候你有机会看清问题的全貌而不是靠猜。建议先把这篇文章收藏备用等真正接入 Langfuse 时照着配置一步步操作即可。

相关新闻