日志服务 接入 Spring AI 数据

Spring AI 是 Java 生态中常用的 AI 应用开发框架,Agent 运行时会产生多轮 ReAct 推理、模型调用、工具调用、向量检索和子 Agent 调用等数据。在 Spring AI 应用中引入腾讯云 Agent 可观测 SDK tencentcloud-agentobs-sdk-springai-java 后,只需将 SDK 注册到 Spring AI 使用的 ObservationRegistry 。

相关产品
日志服务 产品页,含版本规格、价格与购买入口。

一、操作场景

接入完成后,你可以在 Agent 可观测控制台查看以下信息:

·每次顶层 ChatClient 调用的完整调用链,以及入口、Agent、推理轮次(Step)、模型调用、工具调用、Embedding 和向量检索之间的父子关系。

·模型调用的请求模型、请求参数(如 temperature、max_tokens)、输入/输出 Token、结束原因(finish_reason)、耗时和输入/输出消息。

·工具名称、调用参数、返回结果、耗时、错误类型和错误信息。

·工具内部嵌套调用的子 Agent,以及多层子 Agent 的嵌套关系。

·.call() 同步调用与 .stream() 流式调用的完整链路,流式调用跨 Reactor 线程时仍归属于同一条 Trace。

·按会话(Session)和用户(User)聚合的多轮请求关联关系。

SDK 具有以下特点:

·无字节码增强:纯 SDK 依赖,不依赖 javaagent,业务代码无需修改。

·无需开启 Spring AI 隐私开关:SDK 直接从 Observation 上下文读取 Prompt、Completion 和工具参数,无需开启 Spring AI 的 include-prompt 配置。

·可与其他 OTel 实现共存:SDK 内置的 OpenTelemetry 依赖已做隔离,可与应用中已有的 APM javaagent 或其他 OpenTelemetry 实现安全共存。

这篇提供以下两种接入方式,你可根据实际情况选择:

接入方式 说明 推荐场景
方式一:通过 Skill 快速接入与分析 使用支持 Skill 的 AI 工具,由 AI 创建或复用日志主题,并完成 SDK 引入、配置和验证。 希望减少手动配置,并在接入后通过自然语言分析 Trace 数据。
方式二:手动配置接入 引入 Maven 依赖,配置 Endpoint、日志主题和访问凭证,并在代码中注册 SDK。 需要精细控制接入参数,或所用工具不支持 Skill。

二、前提条件

接入前,请确认已完成以下准备工作:

·已开通 AgentObs(Agent 可观测)。

·已准备具备 AgentObs。写入权限的访问凭证,例如 CAM 子账号、CAM 角色或临时密钥。云 API 密钥信息请前往 API 密钥管理 获取,密钥需对目标主题有写入权限,权限模板参见 采集 Agent 可观测数据。

·已获取接入所需的地域接入点(Endpoint):即 Agent 应用所在地域的接入点域名,请参见 地域和访问域名。以广州地域为例:

·方式一填写地域:ap-guangzhou。

·方式二填写域名:内网为 ap-guangzhou.cls.tencentyun.com,外网为 ap-guangzhou.cls.tencentcs.com。

·已基于 Spring AI 开发应用,且应用可以正常运行。版本要求如下:

组件 支持版本
JDK 17及以上
Spring AI 1.0.x、2.0.x
Spring Boot 3.x、4.x
Micrometer Observation 跟随应用使用的 Spring Boot 版本

三、方式一:通过 Skill 快速接入与分析

如果你使用支持 Skill 的 AI 工具,可使用 腾讯云 Agent 可观测助手 自动完成接入与分析。该 Skill 可创建或复用日志主题,识别 Spring AI 项目并完成 Maven 依赖引入、配置和验证。

在 AI 工具中输入以下内容:

请使用腾讯云 Agent 可观测助手 Skill:https://skillhub.cn/skills/tencentcloud-cls-agent-obs帮我把当前 Spring AI 项目接入腾讯云 Agent 可观测,地域为 ap-guangzhou。

接入完成后,你还可以直接描述分析需求。例如:

分析这个 Agent 最近 1 小时的运行情况,定位耗时最高、Token 消耗最多和失败最多的模型或工具调用,并给出可能原因。

四、方式二:手动配置接入

如果你需要精细控制 SDK、日志主题或访问凭证等参数,或者所用工具不支持 Skill,请按以下步骤手动完成接入。

五、步骤1:创建 Agent 可观测应用

1. 进入 Agent 可观测 页面。

2. 单击应用接入,根据页面提示创建应用。

3. 在新创建的应用右侧单击编辑,复制 Trace 日志主题 ID。该 ID 用于后续配置中的 CLS_TOPIC_ID。

六、步骤2:引入 SDK 依赖

在 Spring AI 项目的 pom.xml 中添加以下依赖:

<dependency> <groupId>com.tencentcloudapi.observability</groupId> <artifactId>tencentcloud-agentobs-sdk-springai-java</artifactId> <version>1.0.1</version></dependency>

注意:说明:

七、步骤3:配置环境变量

设置 Endpoint、日志主题 ID 和腾讯云访问密钥。以下示例以广州地域外网为例:

macOS / LinuxWindows(PowerShell)export CLS_ENDPOINT=ap-guangzhou.cls.tencentcs.comexport CLS_TOPIC_ID=<Trace 日志主题 ID>export CLS_SECRET_ID=<SecretId>export CLS_SECRET_KEY=<SecretKey>$env:CLS_ENDPOINT = "ap-guangzhou.cls.tencentcs.com"$env:CLS_TOPIC_ID = "<Trace日志主题ID>"$env:CLS_SECRET_ID = "<SecretId>"$env:CLS_SECRET_KEY = "<SecretKey>"

环境变量 是否必填 说明
CLS_ENDPOINT 是 地域接入点域名,须与 Trace 日志主题位于同一地域。未填写协议前缀时,SDK 自动补全 https://。
CLS_TOPIC_ID 是 步骤1中获取的 Trace 日志主题 ID。请勿填写应用 ID。
CLS_SECRET_ID 是 腾讯云访问密钥 ID,需具备目标日志主题的写入权限。请前往 API 密钥管理 获取。
CLS_SECRET_KEY 是 腾讯云访问密钥 Key。

以上4项必填配置缺少任意一项时,SDK 初始化会抛出 IllegalStateException 并列出缺失项。

除环境变量外,你也可以将配置写入 .env 文件。SDK 依次查找应用工作目录下的 ./.env 和 ~/.agentobs-springai/config.env,读取最先找到的一个文件,且不会覆盖已设置的环境变量。

CLS_ENDPOINT=ap-guangzhou.cls.tencentcs.comCLS_TOPIC_ID=<Trace 日志主题 ID>CLS_SECRET_ID=<SecretId>CLS_SECRET_KEY=<SecretKey>

注意:访问凭证属于敏感信息,建议通过环境变量或不提交到代码仓库的 .env 文件注入,并使用最小权限、可轮换的临时凭证,避免将 SecretKey 硬编码到代码中。

八、步骤4:初始化采集

根据应用类型,将 SDK 注册到 Spring AI 使用的 ObservationRegistry 上。原有 ChatClient、ChatModel、@Tool 等业务代码无需修改。

Spring Boot 应用非 Spring Boot 应用新增一个配置类,声明 ClsObservability Bean:import com.tencentcloudapi.observability.springai.ClsObservability;import io.micrometer.observation.ObservationRegistry;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;@Configurationpublic class ClsObservabilityConfig { // 容器关闭时自动上报剩余的 Span @Bean(destroyMethod = "shutdown") public ClsObservability clsObservability(ObservationRegistry observationRegistry) { // 从环境变量或 .env 文件读取 CLS 配置 ClsObservability obs = ClsObservability.install(); // 注册到 Spring AI 实际使用的 ObservationRegistry obs.registerOn(observationRegistry); return obs; }}在应用启动时初始化 SDK,并注册到 ChatClient / ChatModel 所使用的 ObservationRegistry 上:ClsObservability obs = ClsObservability.install();obs.registerOn(registry);// … 原有 Spring AI 业务代码 …obs.flush(); // 可选,立即上报缓冲区中的 Spanobs.shutdown(); // 可选,JVM 退出时 SDK 会自动执行

注意:SDK 必须注册到 Spring AI 实际使用的同一个 ObservationRegistry 实例上,自行通过 ObservationRegistry.create() 新建的实例无法接收 Spring AI 的事件。Spring Boot 应用通常由 spring-boot-starter-actuator 自动装配该 Bean;如果应用未引入 Actuator,可使用 @ConditionalOnMissingBean 声明一个兜底 Bean:

注意:@Bean@ConditionalOnMissingBeanpublic ObservationRegistry observationRegistry() { return ObservationRegistry.create();}

如需在代码中显式指定参数,可以传入 ClsConfig,未填写的字段会回退读取环境变量:

import com.tencentcloudapi.observability.springai.ClsConfig;import com.tencentcloudapi.observability.springai.ClsObservability;ClsObservability obs = ClsObservability.install( ClsConfig.builder() .serviceName("order-assistant") .serviceVersion("2.3.0") .deploymentEnvironment("prod") .customAttribute("project_id", "proj_001") .build()); // 访问凭证仍从环境变量或 .env 文件读取

配置优先级为:ClsConfig 显式传入的值 > 环境变量 > .env 文件 > 默认值。ClsConfig 支持的可选参数如下:

Builder 方法 环境变量 默认值 说明
serviceName CLS_SERVICE_NAME springai-app 服务或应用名称。
serviceVersion CLS_SERVICE_VERSION 无 服务版本。
serviceInstanceId CLS_SERVICE_INSTANCE_ID <主机名>@<进程号> 服务实例 ID。
deploymentEnvironment CLS_DEPLOYMENT_ENVIRONMENT 无 部署环境,例如 prod、test。
source CLS_SOURCE 本机 IP 上报来源 IP。
batchSize CLS_BATCH_SIZE 32 每批上报的 Span 数量,取值范围为1 – 1000。
sampleRatio CLS_SAMPLE_RATIO 1.0 Trace 采样率,取值范围为0.0 – 1.0,详见 Trace 采样。
debug CLS_DEBUG false 是否以 DEBUG 级别输出每个 Observation 的开始和结束日志。
reactorContextPropagation CLS_SPRINGAI_REACTOR_CONTEXT_PROPAGATION true 是否自动开启 Reactor 上下文传播,详见 流式调用。
customAttribute(key, value) CLS_CUSTOM_<KEY> 无 自定义属性,以 agent.custom.<key> 写入 Span,key 自动转为小写。

九、步骤5:关联会话与用户(推荐)

在调用 ChatClient 前,通过 ClsBaggage 设置会话 ID 和用户 ID,即可在 Agent 可观测控制台按会话或用户聚合分析 Trace:

import com.tencentcloudapi.observability.springai.ClsBaggage;@PostMapping("/chat")public String chat(@RequestHeader("X-Session-Id") String sessionId, @RequestHeader("X-User-Id") String userId, @RequestBody String prompt) { ClsBaggage.set(sessionId, userId); // 或 ClsBaggage.set(sessionId, userId, userName) try { return chatClient.prompt().user(prompt).call().content(); } finally { ClsBaggage.clear(); }}

方法 写入的 Span 字段
ClsBaggage.set(sessionId, userId[, userName]) 同时设置会话 ID、用户 ID 和用户名称。
ClsBaggage.setSession(id) gen_ai.session.id
ClsBaggage.setUser(id) gen_ai.user.id
ClsBaggage.setUserName(name) gen_ai.user.name

注意:说明:

十、步骤6:运行 Agent 并验证结果

1. 启动应用,在启动日志中确认出现 installed (service=…, endpoint=…, topic=…, sampleRatio=…),表示 SDK 初始化成功。

2. 运行一次包含模型调用的 Agent 任务。建议同时触发一个工具调用,以便检查完整调用树。

3. 登录 Agent 可观测控制台,进入步骤1创建的应用。

4. 打开调用链页面,选择包含测试请求的时间范围。

5. 打开最新 Trace,检查是否包含 Entry、Agent、Step、Chat、Tool 等 Span。

6. 选择具体 Span,检查其耗时、状态、输入输出、Token 用量和模型请求参数等数据。

十二、Span 层级与采集属性

SDK 将 Spring AI 的 Observation 映射为以下调用树结构:

enter_application ← 入口,每次顶层 ChatClient 调用生成一个└─ invoke_agent main ← 主 Agent ├─ react round_1 ← 第1轮推理 │ ├─ chat <model> ← 模型调用(ChatModel) │ ├─ execute_tool <tool> ← 工具调用(ToolCallback) │ │ └─ invoke_subagent <tool> ← 工具内部嵌套调用的 ChatClient │ │ └─ react round_1 ─ chat / execute_tool … │ ├─ embedding ← 向量化(EmbeddingModel) │ └─ retrieval <store> ← 向量检索(VectorStore) └─ react round_2 .. N ← 每多一轮工具调用,新增一个推理轮次 └─ chat <model> / execute_tool <tool> …

Span 类型(gen_ai.span.kind) 对应操作 主要采集属性
entry 应用入口 会话 ID、轮次 ID、用户 ID、输入/输出消息。Agent 执行出错时,错误状态会传播到该 Span。
agent 主 Agent 或子 Agent Agent 名称、Agent 范围(main 或 subagent)、输入/输出消息。子 Agent 通过 gen_ai.subagent.parent_tool_call.id 关联触发它的工具调用。
step ReAct 推理轮次、Embedding 及其他操作 推理轮次编号、Step ID、结束原因;Embedding 的输入内容、向量数量和向量维度。
chat 模型调用 请求模型、temperature、top_p、max_tokens 等请求参数,结束原因,输入/输出 Token,调用耗时,输入/输出消息。
tool 工具调用 工具名称、调用 ID、调用参数、返回结果、调用耗时,异常时记录错误类型。
retriever 向量检索 检索语句、top_k、返回文档数量、检索耗时。

调用树的识别规则如下:

·ReAct 多轮推理:某次模型调用以 finish_reason=tool_calls 结束后,下一次模型调用会开启新的推理轮次 react round_N。

·子 Agent:工具内部调用的 ChatClient 识别为 invoke_subagent <工具名>,与外层共享会话 ID 和轮次 ID,支持任意嵌套深度,内外层 .call() 与 .stream() 可任意组合。

·多个顶层 ChatClient:同一请求内先后调用多个顶层 ChatClient 时,每次调用生成独立的 Trace。

输入/输出消息采用 OpenAI Chat 格式的 JSON 数组记录,单个字段超过8000字符时截断。Spring AI 原生附带的 Micrometer 标签也会一并写入对应 Span。完整字段定义请参见 Agent Trace 字段定义说明。

十三、Trace 采样

SDK 默认全量上报 Trace。如需降低上报量和存储成本,可调低采样率:

环境变量代码配置# 大约每 10 轮对话保留 1 轮export CLS_SAMPLE_RATIO=0.1ClsObservability.install( ClsConfig.builder() .sampleRatio(0.1) .build());

采样率配置优先级为:ClsConfig 显式传入的值 > JVM 参数 -Dcls.springai.sample-ratio > 环境变量 CLS_SAMPLE_RATIO > .env 文件 > 默认值 1.0。超出0.0 – 1.0范围的值会被修正为边界值,无法解析的值按 1.0 处理。

十四、流式调用

ChatClient.stream() 会将 Spring AI 内部的 Observation 派发到 Reactor 调度线程。为确保流式调用的 Span 归属于同一条 Trace,SDK 初始化时会自动开启 Reactor 自动上下文传播(Hooks.enableAutomaticContextPropagation())。该设置对 JVM 全局生效且可重复调用;应用中未引入 Reactor 时不执行任何操作。

如果应用已自行开启该设置,可通过以下任一方式关闭 SDK 的自动开启:

·代码配置:ClsConfig.builder().reactorContextPropagation(false)

·JVM 参数:-Dcls.springai.reactor-context-propagation=false(优先于环境变量)

·环境变量:CLS_SPRINGAI_REACTOR_CONTEXT_PROPAGATION=false

十六、启动时报错 IllegalStateException: CLS configuration incomplete

缺少必填配置。请检查 CLS_ENDPOINT、CLS_TOPIC_ID、CLS_SECRET_ID、CLS_SECRET_KEY 是否已通过环境变量、.env 文件或 ClsConfig 全部配置,报错信息中会列出缺失项。

十七、AgentObs 中没有 Trace 数据

请按以下顺序检查:

1. 确认 registerOn() 传入的是 Spring AI 实际使用的 ObservationRegistry,而不是自行新建的实例。

2. 查看启动日志中的 installed (service=…, endpoint=…, topic=…, sampleRatio=…),确认 Endpoint、日志主题 ID 和采样率是否正确。

3. 确认 CLS_ENDPOINT 与 Trace 日志主题位于同一地域。

4. 确认 CLS_TOPIC_ID 为 Trace 日志主题 ID,而不是 Agent 可观测应用 ID。

5. 确认访问密钥具备目标日志主题的写入权限。

6. 确认运行环境能够访问所配置的 Endpoint。使用内网域名时,需确保应用运行在同地域的腾讯云内网环境中。

7. 完成测试任务后,等待至少一个刷新周期再查询数据。

如仍无法定位,可设置 CLS_DEBUG=true,并将 com.tencentcloudapi.observability 的日志级别调整为 DEBUG,查看 onStart TURN session=… turn=… traceId=… 等 SDK 日志。

十八、AgentObs 中只有部分对话的 Trace

可能已开启 Trace 采样。请查看启动日志中的 sampleRatio 取值,如需全量上报,请设置 CLS_SAMPLE_RATIO=1.0。

十九、流式调用的 Span 被拆分为多条 Trace

Reactor 上下文传播被关闭或开启失败。请检查启动日志中是否有 enabled Reactor automatic context propagation,并确认未 reactorContextPropagation 设置为 false。

20、Trace 中的会话 ID 显示为 sess-xxx

未设置会话信息。请在调用 ChatClient 前调用 ClsBaggage.set(…) 传入业务会话 ID 和用户 ID,详见步骤5。

21、Spring AI 原生的 gen_ai.prompt 字段为空

Spring AI 的 include-prompt 配置默认关闭,因此原生字段为空。SDK 会直接读取对话内容并写入 gen_ai.input.messages 和 gen_ai.output.messages 字段,请查看这两个字段。

22、Trace 中缺少 Token 或部分模型属性

Token 用量、结束原因等数据来自模型服务的返回结果。如果模型服务或对应的 Spring AI 模型集成未返回 Usage、结束原因等字段,SDK 无法采集。

23、应用中已使用 APM javaagent 或其他 OpenTelemetry 实现,是否冲突

不冲突。SDK 内置的 OpenTelemetry 依赖已重定位到独立包名,APM javaagent 的字节码增强不会作用于 SDK 的 Tracer;SDK 也不会注册全局 GlobalOpenTelemetry 实例,不会影响应用已有的 OpenTelemetry 配置。

如果某个工作线程上同时存在 APM 注入的父上下文和上一次流式调用的残留状态,SDK 会以独立的根上下文开启新一轮对话,以确保 AgentObs 中的 Trace 完整独立,此时该请求与 APM 链路的关联会丢失。

24、相关文档

·选择接入方式

·Agent 可观测应用详情

·Agent Trace 字段定义说明

·Spring AI SDK GitHub 仓库

赞 (0)
上一篇 5天前
下一篇 5天前