助手
扣子 AI 帮助与支持
你好,我是 扣子 文档问答助手 🎉 你在阅读当前文档的过程中,无论对文档概念的解释,还是文档内容方面的疑问,都可以随时向我提问,我会全力为你解答
推荐问题
如何快速了解这个空间的核心内容?
有哪些近期更新的重点文档?
我应该从哪些文档开始阅读?
文档反馈

Spring AI

更新于: 2026-06-24 15:45:09

本文介绍如何通过 Spring AI 上报 Trace 数据到扣子罗盘。

功能介绍

Spring AI 是一个强大的框架,通过与 OpenTelemetry 的集成,能够自动捕获应用程序中的关键操作和性能指标,并将这些数据作为 Trace 信息上报到扣子罗盘。Spring AI 的自动化功能可以大大简化集成过程。

配置 OpenTelemetry

Maven 配置

在通过 Spring AI 上报 Trace 前,需要先添加 Maven 依赖,包括 Spring AI 的模型调用库、OpenTelemetry 检测库、Micrometer 到 OpenTelemetry 的连接器以及 OpenTelemetry 导出器。
本示例使用的是 Spring AI 应用程序调用 OpenAI 模型的 pom.xml 文件,如需使用 Gradle 工具,配置类似。

说明

  • 如果你需要调用其他不支持 OpenAI 协议的模型,可以将下面示例中的 spring-ai-openai-spring-boot-starter 替换为对应模型的依赖。
  • 本示例以 Spring AI 1.0.0-M8 版本为例。具体说明,请参考Spring AI 版本须知
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-parent</artifactId>
       <version>3.4.5</version>
       <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>ai-openai-helloworld</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>ai-openai-helloworld</name>
    <description>Simple AI Application using OpenAPI Service</description>
    <properties>
       <java.version>17</java.version>
    </properties>

    <dependencyManagement>
       <dependencies>
          <dependency>
             <groupId>org.springframework.ai</groupId>
             <artifactId>spring-ai-bom</artifactId>
             <version>1.0.0-M8</version>
             <type>pom</type>
             <scope>import</scope>
          </dependency>
          <dependency>
             <groupId>io.opentelemetry.instrumentation</groupId>
             <artifactId>opentelemetry-instrumentation-bom</artifactId>
             <version>2.13.2</version>
             <type>pom</type>
             <scope>import</scope>
          </dependency>
       </dependencies>
    </dependencyManagement>

    <dependencies>
       <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter</artifactId>
       </dependency>

       <dependency>
          <groupId>org.springframework.ai</groupId>
          <artifactId>spring-ai-starter-model-openai</artifactId>
       </dependency>

       <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-web</artifactId>
       </dependency>

       <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-actuator</artifactId>
       </dependency>

       <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-test</artifactId>
          <scope>test</scope>
       </dependency>

       <dependency>
          <groupId>io.opentelemetry.instrumentation</groupId>
          <artifactId>opentelemetry-spring-boot-starter</artifactId>
       </dependency>

       <dependency>
          <groupId>io.micrometer</groupId>
          <artifactId>micrometer-tracing-bridge-otel</artifactId>
       </dependency>

       <dependency>
          <groupId>io.opentelemetry</groupId>
          <artifactId>opentelemetry-exporter-otlp</artifactId>
          <version>1.47.0</version>
       </dependency>
    </dependencies>

    <build>
       <plugins>
          <plugin>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-maven-plugin</artifactId>
          </plugin>
       </plugins>
    </build>

</project>

导出配置

下述代码是一个调用方舟模型的 application.yaml 配置示例,用于设置 Spring AI 针对 Span 导出的相关开关。

spring:
  application:
    name: spring-ai-demo # 服务名称,自定义。
  ai:
    chat:
      observations:
        include-prompt: true  # 是否上报模型输入,默认关闭。
        include-completion: true # 是否上报模型输出,默认关闭。
    openai: # 使用 OpenAI 协议的模型接口,在此配置。
      api-key: "*********" # 填写你的大模型 API_KEY。
      chat:
        base-url: "https://ark.cn-beijing.volces.com"
        completions-path: "/api/v3/chat/completions"
management:
  tracing:
    sampling:
      probability: 1.0  # 采样率,1.0是100%采样,全量Span上报。

以上配置完成了 Spring AI 服务的 Opentelemetry 自动检测配置,服务内部的模型执行过程将被记录到 Span。

环境变量配置

在上报 Trace 数据前,你需要正确配置 OpenTelemetry 的环境变量 OTEL_EXPORTER_OTLP_HEADERSOTEL_EXPORTER_OTLP_TRACES_ENDPOINT,用于指定上报数据时所需的扣子罗盘空间 ID,访问令牌和上报地址,以确保数据能够正确发送到指定的扣子罗盘空间中。环境变量配置格式及说明如下:

OTEL_EXPORTER_OTLP_HEADERS: cozeloop-workspace-id={CozeLoop空间ID},Authorization=Bearer {个人访问令牌或服务访问令牌}
OTEL_EXPORTER_OTLP_TRACES_ENDPOINT: https://api.coze.cn/v1/loop/opentelemetry/v1/traces

环境变量

说明

OTEL_EXPORTER_OTLP_HEADERS

设置上报数据时所需的认证信息和工作空间标识。包括:

OTEL_EXPORTER_OTLP_TRACES_ENDPOINT

用于指定 OpenTelemetry 数据的上报地址,固定为 https://api.coze.cn/v1/loop/opentelemetry/v1/traces

上报 Trace 及验证结果

示例 1:​使用 Toolcall 增强模型

本示例展示了一个基于 Spring AI 框架搭建的应用程序,如何集成豆包大模型实现智能交互,并上报 Trace 数据到扣子罗盘。通过定义 DateTimeTools 类提供获取当前日期时间和天气信息的工具方法,供大模型在需要时调用。使用 ChatClient 构建器配置豆包模型,支持非流式和流式两种响应模式。

package spring.ai.example.spring_ai_demo;

import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.ai.model.tool.DefaultToolCallingChatOptions;
import org.springframework.ai.tool.annotation.Tool;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.context.i18n.LocaleContextHolder;
import reactor.core.publisher.Flux;
import java.time.LocalDateTime;



@SpringBootApplication
public class Application_tool {
    public static void main(String[] args) {
        SpringApplication app = new SpringApplication(Application_tool.class);
        app.run(args);
    }

    static class DateTimeTools {
        @Tool(description = "Get the current date and time in the user's timezone")
        String getCurrentDateTime() {
            return LocalDateTime.now().atZone(LocaleContextHolder.getTimeZone().toZoneId()).toString();
        }

        @Tool(description = "Get the current weather in the given location")
        String getCurrentWeather() {
            return "今天上海多云转晴,温度25摄氏度";
        }
    }

    @Bean
    CommandLineRunner cli_tool(ChatClient.Builder builder) {
        return args -> {
            invokeAI(builder);
        };
    }

    private void invokeAI(ChatClient.Builder builder) {
        var chat = builder.build();
        var prompt = new Prompt("你是一个专业的沟通师,可以根据用户的问题给出准确的回答",
                DefaultToolCallingChatOptions.builder().model("doubao-1-5-pro-256k-250115").build());
// 非流式
        System.out.println(chat.prompt(prompt).user("今天的日期是什么?")
                .tools(new DateTimeTools())
                .call()
                .content());
// 流式
//        Flux<String> stream = chat.prompt(prompt).user("今天的日期是什么?")
//                .tools(new DateTimeTools())
//                .stream()
//                .content();
//        stream.subscribe(
//                System.out::print, // 处理每个响应部分
//                error -> System.err.println("Error: " + error.getMessage()), // 处理错误
//                System.out::println // 处理完成事件
//        );

    }
}

上报 Trace 数据后,你可以在扣子罗盘Trace 页面,找到并单击目标 Span,查看上报的 Trace 数据。
Image

示例 2:关联用户ID、会话ID

本示例展示了如何在 Spring AI 中借助 OpenTelemetry 实现 Span 与用户 ID、会话 ID 的关联,将用户和会话信息添加到 Trace 数据中。示例首先展示了 OpenTelemetry 的初始化配置、工具类定义、追踪上下文管理及 AI 交互逻辑。然后在此基础上,创建 Tracer 和根 Span,通过设置 user.id 与 session.id 绑定用户与会话标识。

package spring.ai.example.spring_ai_demo;

import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.ai.model.tool.DefaultToolCallingChatOptions;
import org.springframework.ai.tool.annotation.Tool;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.context.i18n.LocaleContextHolder;

import io.opentelemetry.exporter.otlp.http.trace.OtlpHttpSpanExporter;
import io.opentelemetry.sdk.trace.export.BatchSpanProcessor;
import io.opentelemetry.api.GlobalOpenTelemetry;
import io.opentelemetry.api.trace.Span;
import io.opentelemetry.api.trace.Tracer;
import io.opentelemetry.context.Scope;
import io.opentelemetry.sdk.OpenTelemetrySdk;
import io.opentelemetry.sdk.trace.SdkTracerProvider;
import reactor.core.publisher.Flux;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Supplier;



@SpringBootApplication
public class Application {
    public static void initOpenTelemetry() {
        // 创建一个 OTLP HTTP 导出器
        Supplier<Map<String, String>> headersSupplier = () -> {
            Map<String, String> headers = new HashMap<>();
            headers.put("cozeloop-workspace-id", "750894316061025****");
            headers.put("Authorization", "Bearer pat_AyJcG40P6TeIQLJENe6QpVuGs3SiJ3t****");
            return headers;
        };
        OtlpHttpSpanExporter otlpExporter = OtlpHttpSpanExporter.builder()
                .setEndpoint("https://api.coze.cn/v1/loop/opentelemetry/v1/traces") // 设置你的 OTLP 接收器的 URL
                .setHeaders(headersSupplier)
                .build();

        // 创建 TracerProvider 并添加批量处理器
        SdkTracerProvider tracerProvider = SdkTracerProvider.builder()
                .addSpanProcessor(BatchSpanProcessor.builder(otlpExporter).build())
                .build();

        // 创建 OpenTelemetrySdk 实例
        OpenTelemetrySdk openTelemetrySdk = OpenTelemetrySdk.builder()
                .setTracerProvider(tracerProvider)
                .buildAndRegisterGlobal();
    }

    public static void main(String[] args) {
        SpringApplication app = new SpringApplication(Application.class);
        app.run(args);
    }

    static class DateTimeTools {

        @Tool(description = "Get the current date and time in the user's timezone")
        String getCurrentDateTime() {
            return LocalDateTime.now().atZone(LocaleContextHolder.getTimeZone().toZoneId()).toString();
        }

        @Tool(description = "Get the current weather in the given location")
        String getCurrentWeather() {
            return "今天上海多云转晴,温度25摄氏度";
        }

    }

    @Bean
    CommandLineRunner cli(ChatClient.Builder builder) {
        return args -> {
            // 初始化 OpenTelemetry, 供自定义节点使用
            initOpenTelemetry();

            // 创建一个 Tracer
            Tracer tracer = GlobalOpenTelemetry.getTracer("exampleTracer");
            // 创建根节点,存储userID和sessionID
            Span span = tracer.spanBuilder("root-span")
                    .setAttribute("user.id", "user-123456")
                    .setAttribute("session.id", "session-123456")
                    .startSpan();

            try (Scope ignored = span.makeCurrent()) {
                invokeAI(builder);
            } finally {
                span.end();
            }
        };
    }

    private void invokeAI(ChatClient.Builder builder) {
        var chat = builder.build();
        var prompt = new Prompt("你是一个专业的沟通师,可以根据用户的问题给出准确的回答",
                DefaultToolCallingChatOptions.builder().model("doubao-1-5-pro-256k-250115").build());

// 非流式
        System.out.println(chat.prompt(prompt).user("今天是周几?")
                .tools(new DateTimeTools())
                .call()
                .content());

// 流式
//        Flux<String> stream = chat.prompt(prompt).user("What day is today?")
//                .tools(new DateTimeTools())
//                .stream()
//                .content();
//        stream.subscribe(
//                System.out::print, // 处理每个响应部分
//                error -> System.err.println("Error: " + error.getMessage()), // 处理错误
//                System.out::println // 处理完成事件
//        );

    }
}

上报 Trace 数据后,你可以在扣子罗盘Trace 页面,找到并单击目标 Span,查看上报的 Trace 数据。
Image

参考信息

Spring AI 版本须知

1.0.0-M版本(如1.0.0-M8)

  • 模型节点:支持上报模型的输入、输出到 Trace,对应 application.yaml 文件中的配置字段分别为 spring.ai.chat.observations.include-promptspring.ai.chat.observations.include-completion,值为 true,表示打开状态。
  • Tool 节点:不支持上报。

1.0.0-RC1、1.0.0-SNAPSHOT、1.1.0-SNAPSHOT

  • 模型节点:不支持上报模型的输入、输出到 Trace,只支持通过本地日志打印模型的输入、输出,对应 application.yaml 文件中的配置字段分别为 spring.ai.chat.observations.log-promptspring.ai.chat.observations.log-completion,值为 true,表示打开状态。
  • Tool 节点:支持上报,也支持控制 Tool 的输入、输出,对应 application.yaml 文件中的配置字段为spring.ai.tools.observations.include-content,值为 true,表示打开状态,具体数据将展示在 Metadata 里展示。