手把手教你为 AI 应用接入专有的可观测平台,追踪每一次模型调用、Token 消耗与成本。

写在前面

在前文中,我们分别介绍了 ARMS(阿里云商业方案,需挂载 Java Agent)和 Zipkin(开源通用链路追踪,基于 Micrometer + Brave)。这两个方案都能帮我们“看到” AI 应用内部发生了什么,但它们并不是为 AI 场景量身定做的——比如,你无法直接看到某次对话消耗了多少 Token、花了多少钱。

本篇文章的主角 LangFuse,正是为解决 AI 应用观测痛点而生的开源平台。我们将通过一个完整的 Spring AI Alibaba 示例项目,带你理解它背后的原理,并亲手将它跑起来。

🔖 本文适合:正在使用 Spring AI Alibaba 开发 LLM 应用的开发者,希望获得比普通链路追踪更深入的 AI 调用分析。


一、 AI 专用可观测性

在传统微服务中,我们关心的是:

  • 请求耗时
  • 错误率
  • 调用链关系

在 AI 应用中,还需要关注

  • 每次对话的 Token 输入/输出数量
  • 不同模型(如 qwen-max、gpt-4)的 单次与累计成本
  • Prompt 和 Completion 的 真实内容(用于调试和审计)
  • 工具调用(Tool Calling)的 参数与结果

通用链路追踪系统(如 Zipkin、Jaeger)并不解析 LLM 请求体,自然无法提供上述信息。而 LangFuse 在 OpenTelemetry 标准之上,额外解析了 AI 调用的语义字段,从而生成 Token 统计、成本分析等报表。


二、LangFuse 整体架构(含 Mermaid 图)

下图展示了用户请求进入 Spring Boot 应用,经过 OpenTelemetry 埋点,最终上报到 LangFuse 的完整数据流:

Spring Boot 应用

方法调用被拦截

创建/结束 Span

每隔几秒导出

OTLP/HTTP + Protobuf

解析 AI 语义

展示

HTTP 请求

用户 / 客户端

AI Controller
Chat / Image / Embedding

Spring AI Bean
如 ChatClient, ImageModel

OpenTelemetry Instrumentation
自动拦截 AI 调用

OpenTelemetry SDK
生成 Span + Metrics

OtlpHttpExporter
批量上报

LangFuse OTLP Collector
https://cloud.langfuse.com/api/public/otel

LangFuse 存储

LangFuse 控制台
Traces / Analytics / Prompts

开发者 / 运维

原理说明

  1. Spring AI 内部已集成 Micrometer Observation API。当调用 ChatClientImageModel 等方法时,会自动生成一个 Observation(观测上下文)。
  2. 项目中加入 opentelemetry-spring-boot-starter 后,Micrometer 的 Observation 会被桥接到 OpenTelemetry 的 Span
  3. OpenTelemetry SDK 负责采样、合并 Span,并通过 OtlpHttpExporter 定期将数据以 Protobuf 格式发送到配置好的 OTLP Endpoint。
  4. LangFuse 的 OTLP 接收器不仅存储通用 Span,还会识别 gen_ai. 开头的属性(如 gen_ai.request.modelgen_ai.usage.input_tokens),从而生成 AI 专用的可视化面板。

三、十分钟快速体验:从零到看见 Trace

3.1 准备环境

确保你的电脑上有:

  • JDK 17+(推荐 Eclipse Temurin 或 Oracle OpenJDK)
  • Maven 3.8+
  • Git
java -version
mvn -version
git --version

3.2 注册 LangFuse 云端账号(免费)

LangFuse 提供免费云端版,非常适合测试——不需要自己维护数据库。

  1. 访问 https://cloud.langfuse.com,点击 Sign up(可用 GitHub 登录)。
  2. 验证邮箱后登录,点击 + New Project,取名 spring-ai-demo,环境选 Development
  3. 进入左下角 Settings → API Keys,点击 Create API Key。你会得到:
    • Public Key(形如 pk-lf-xxxxxxxx
    • Secret Key(形如 sk-lf-xxxxxxxx
      ⚠️ 密钥只显示一次,请妥善保存。

3.3 生成 Base64 认证头

LangFuse 的 OTLP 端点使用 HTTP Basic Auth,用户名 = Public Key,密码 = Secret Key。我们需要将它们 base64 编码后放在 Authorization: Basic 头中。

在终端执行(替换成你真实的 Key):

echo -n "pk-lf-xxxxxx:sk-lf-xxxxxx" | base64
# 输出类似:cGstbGYtbnVsbDpzay1sZi1udWxs

记下这个 Base64 字符串,稍后要用。

3.4 获取通义千问 API Key

访问 阿里云百炼平台控制台,创建 API Key(形如 sk-xxxx)。

3.5 下载并配置示例项目

git clone https://github.com/alibaba/spring-ai-alibaba.git
cd spring-ai-alibaba/spring-ai-alibaba-observability-example/observability-langfuse-example

编辑 src/main/resources/application.yml,或通过环境变量配置。推荐使用环境变量(避免硬编码密钥):

export AI_DASHSCOPE_API_KEY="sk-你的通义千问Key"
export LANGFUSE_BASE64_AUTH="你的Base64字符串"

如果希望直接修改 application.yml,找到下面片段并替换:

exporter:
  otlp:
    endpoint: "https://cloud.langfuse.com/api/public/otel"
    headers:
      Authorization: "Basic ${LANGFUSE_BASE64_AUTH}"   # 注意这里会读取环境变量

3.6 启动应用

mvn clean spring-boot:run

看见 Tomcat started on port 8080 即成功。

3.7 发起测试请求并查看观测数据

打开另一个终端,执行:

# 1. 普通对话
curl "http://localhost:8080/observability/chat?prompt=你好,请介绍自己"

# 2. 向量化(embedding)
curl "http://localhost:8080/observability/embedding"

# 3. 生成图片(会下载png)
curl "http://localhost:8080/observability/image/generate" -o test.png

# 4. 工具调用(天气)
curl "http://localhost:8080/observability/tools?prompt=杭州天气如何"

然后登录 LangFuse 控制台,点击 Traces,你会看到每条请求对应一条 Trace,点进去可以查看:

  • 模型名称(qwen-max)
  • 输入 Prompt 内容
  • 输出 Completion 内容
  • Token 用量(输入/输出)
  • 耗时与 Metadata

切换到 Analytics 页面,还能看到 Token 趋势图和成本估算。


四、核心依赖与原理详解

很多开发者困惑:为什么只加了几行依赖,AI 调用就能自动上报?下面我们来剖析 pom.xml 中关键的几个模块。

<!-- Spring AI 观测自动配置(关键!) -->
<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-autoconfigure-model-chat-observation</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-autoconfigure-model-embedding-observation</artifactId>
</dependency>
<!-- 图片、向量存储等类似,不一一列举 -->

<!-- OpenTelemetry Spring Boot Starter -->
<dependency>
    <groupId>io.opentelemetry.instrumentation</groupId>
    <artifactId>opentelemetry-spring-boot-starter</artifactId>
    <version>2.9.0</version>
</dependency>

<!-- Micrometer 到 OpenTelemetry 的桥接 -->
<dependency>
    <groupId>io.micrometer</groupId>
    <artifactId>micrometer-tracing-bridge-otel</artifactId>
</dependency>

<!-- OTLP 导出器 -->
<dependency>
    <groupId>io.opentelemetry</groupId>
    <artifactId>opentelemetry-exporter-otlp</artifactId>
</dependency>

原理详解

组件 职责
spring-ai-autoconfigure-*-observation 为每个 AI 模型(Chat、Embedding、Image)定义 Observation 约定:何时开始、结束、记录哪些字段(prompt、completion、token 用量等)。
opentelemetry-spring-boot-starter 自动配置 OpenTelemetry SDK,并开启对常见框架(WebClient、RestTemplate、数据源)的埋点。它会读取 otel.* 配置。
micrometer-tracing-bridge-otel 关键桥接层:使 Micrometer 的 Observation 与 OpenTelemetry 的 Span 互通。Spring AI 发出 Observation 事件 → 桥接器自动创建/结束 OpenTelemetry Span。
opentelemetry-exporter-otlp 将 OpenTelemetry Span 和 Metrics 通过 OTLP 协议(HTTP/gRPC)发送到远端 Collector。LangFuse 正是扮演了 OTLP Collector 的角色。

💡 通俗比喻:Observation 是“事件日记本”,桥接器是“翻译官”,OTLP 导出器是“快递员”,LangFuse 是“AI 专项仓库”。


五、配置的常见困惑与最佳实践

原示例中存在两处 observations 配置,容易混淆。我们梳理出清晰、推荐的配置结构:

spring:
  application:
    name: observability-langfuse-demo
  ai:
    dashscope:
      api-key: ${AI_DASHSCOPE_API_KEY}
    # 统一的 AI 观测开关
    observations:
      log-prompt: true          # 在日志中打印 prompt
      log-completion: true      # 在日志中打印 completion
      include-error-logging: true

# OpenTelemetry 相关配置
otel:
  service:
    name: ${spring.application.name}
  traces:
    sampler:
      always_on                # 100% 采样(生产环境可改为概率采样)
  exporter:
    otlp:
      endpoint: "https://cloud.langfuse.com/api/public/otel"
      headers:
        Authorization: "Basic ${LANGFUSE_BASE64_AUTH}"
  logs:
    exporter: none              # LangFuse 暂时不支持日志导出,避免报错

注意

  • spring.ai.observations.* 控制 Spring AI 内部的观测行为(是否记录详细内容)。
  • otel.* 控制 OpenTelemetry SDK 的导出行为。
  • 原文档中有 chat.client.observations 和顶层 observations,它们是不同作用的配置(一个针对 ChatClient 的特定配置,另一个被误用),建议统一使用 spring.ai.observations

六、代码走读:四个 Controller 分别展示了什么?

项目中有四个控制器,对应 AI 能力的观测演示。

6.1 ChatModelController – 对话流式输出

@GetMapping
public Flux<String> chat(@RequestParam(defaultValue = "hello!") String prompt) {
    return chatClient.prompt(prompt).stream().content();
}

当执行这个请求时,Spring AI 的 ChatClient 内部会触发 chat.observation,OpenTelemetry 会记录:

  • gen_ai.request.model(从配置自动获取)
  • gen_ai.request.prompt(如果开启 log-prompt)
  • gen_ai.response.completion
  • gen_ai.usage.input_tokens / output_tokens

6.2 ImageModelController – 图片生成并直接返回

ImageResponse imageResponse = imageModel.call(new ImagePrompt(DEFAULT_PROMPT));
String imageUrl = imageResponse.getResult().getOutput().getUrl();
// ... 代理输出图片流

图片生成也会产生一个独立的 Observation,记录生成参数(如尺寸、质量)和结果 URL。

6.3 EmbeddingModelController – 文本向量化

嵌入模型调用一般用于 RAG 检索,LangFuse 会记录向量维度(1536 等)和耗时。

6.4 ToolCallingController – 工具调用(天气查询)

Spring AI 的工具调用会被拆分为多个 Span:一个主 Chat Span + 每个 tool call 的子 Span。LangFuse 能清晰展示模型先决定调用工具,工具返回结果后模型再最终回答的过程。


七、生产环境部署与调优

7.1 打包与运行

mvn clean package -DskipTests
java -jar target/observability-langfuse-example-1.0.0-SNAPSHOT.jar

7.2 Docker 化

创建 Dockerfile

FROM eclipse-temurin:17-jre-alpine
WORKDIR /app
COPY target/*.jar app.jar
ENTRYPOINT ["java", "-jar", "app.jar"]

构建并运行:

docker build -t spring-ai-langfuse .
docker run -p 8080:8080 -e AI_DASHSCOPE_API_KEY="xxx" -e LANGFUSE_BASE64_AUTH="xxx" spring-ai-langfuse

7.3 成本控制与采样

生产环境若流量很大,建议降低采样率,同时保留错误请求的 100% 采样。

otel:
  traces:
    sampler:
      type: traceidratio
      ratio: 0.05   # 5% 采样

更高级的方案:使用 parentbased_traceidratio 保证已采样链路的完整性。

7.4 自建 LangFuse(数据不出网)

当你对数据隐私有要求时,可通过 Docker 自建:

git clone https://github.com/langfuse/langfuse.git
cd langfuse/infrastructure/docker
docker-compose up -d

然后修改 application.yml 中的 OTLP endpoint 为 http://your-server:3000/api/public/otel


八、常见问题解决(真·有效)

8.1 认证失败:401 Unauthorized

原因:Base64 凭证错误,或未正确设置 Authorization 头。

解决方法

# 重新生成 base64(注意 -n 参数防止换行)
echo -n "你的公钥:你的私钥" | base64
# 复制输出的字符串,确保没有多余空格

8.2 控制台看不到任何 Trace

排查步骤

  1. 检查采样率:确认 otel.traces.sampler.always_on 生效。
  2. 开启 OpenTelemetry 调试日志:
    logging.level.io.opentelemetry: DEBUG
    
    重启后若看到 Exporting 1 spans... 说明数据已发送。
  3. 确认网络:curl https://cloud.langfuse.com/api/public/otel 能通。
  4. 等待 10~30 秒:LangFuse 控制台有缓存延迟。

8.3 编译报错 “Name for argument not present”

原因:Maven 缺少 -parameters 编译参数,导致一些 Spring 参数名反射失败。

解决:在 pom.xmlmaven-compiler-plugin 中加入:

<compilerArgs>
    <arg>-parameters</arg>
</compilerArgs>

九、LangFuse vs Zipkin vs ARMS 最终选型建议

维度 Zipkin LangFuse ARMS
Token/成本分析 ✅ 专精 ✅ 需购买
自建难度 低(单一 jar) 中(需 Postgres+ClickHouse) 不可自建
免费额度 无限制 每月 10k 事件免费 有限免费额度
LLM 调试体验 一般 极好(展示完整对话) 好(阿里云控制台)
推荐场景 简单链路 + 不想付费 AI 应用首选 企业级全栈 + 已有阿里云

一句话总结

  • 如果你是个人开发者或创业团队,做 AI 应用 → LangFuse 免费版性价比最高。
  • 如果你公司已有阿里云全套服务,且需要基础设施统一监控 → ARMS
  • 如果你只关心调用链是否存在断点,不关心 Token → Zipkin

十、总结与扩展

通过本文,你已经学会:

  • 为什么 AI 应用需要 LangFuse 这类专用观测平台。
  • OpenTelemetry 与 Spring AI 观测如何协作。
  • 完整搭建一个从配置到运行再到分析的示例项目。
  • 解决接入过程中 90% 的常见问题。

下一步可以做的

  1. 给应用增加 RAG 链路(如向量数据库检索),LangFuse 会自动记录检索耗时和返回文档数。
  2. 利用 LangFuse 的 Prompt Management 功能,将 prompt 版本与调用 trace 关联。
  3. 设置 评分与反馈(用户点赞点踩),LangFuse 支持关联到具体 trace,用于评估模型表现。

如果你在实操中遇到任何问题,欢迎在评论区留言。🚀

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐