Spring AI Alibaba 1.x 系列【80】可观测集成

文章目录

  • [1. 项目概述](#1. 项目概述)
  • [2. 架构原理](#2. 架构原理)
    • [2.1 观测数据流](#2.1 观测数据流)
    • [2.2 三个观测层级](#2.2 三个观测层级)
  • [3. 环境准备](#3. 环境准备)
    • [3.1 前置条件](#3.1 前置条件)
    • [3.2 依赖说明](#3.2 依赖说明)
  • [4. 自动配置](#4. 自动配置)
    • [4.1 自动配置类](#4.1 自动配置类)
    • [4.2 自动配置源码逻辑](#4.2 自动配置源码逻辑)
    • [4.3 如何使用自动配置的 Bean](#4.3 如何使用自动配置的 Bean)
    • [4.4 配置属性](#4.4 配置属性)
  • [5. 应用配置](#5. 应用配置)
    • [5.1 application.yml 关键配置](#5.1 application.yml 关键配置)
    • [5.2 logback-spring.xml](#5.2 logback-spring.xml)
  • [6. 核心代码实现](#6. 核心代码实现)
    • [6.1 启动类](#6.1 启动类)
    • [6.2 StateGraph + 观测](#6.2 StateGraph + 观测)
    • [6.3 ReactAgent + 观测](#6.3 ReactAgent + 观测)
    • [6.4 OtlpLoggingConfig](#6.4 OtlpLoggingConfig)
    • [6.5 ObservationFilterConfig](#6.5 ObservationFilterConfig)
  • [7. 观测指标(Metrics)](#7. 观测指标(Metrics))
    • [7.1 自动采集的指标](#7.1 自动采集的指标)
    • [7.2 查看指标](#7.2 查看指标)
  • [8. 观测拦截器示例](#8. 观测拦截器示例)
    • [8.1 Bean 注册 Hook](#8.1 Bean 注册 Hook)
    • [8.2 树型 Span 结构](#8.2 树型 Span 结构)
  • [9. API 端点](#9. API 端点)

1. 项目概述

本案例演示如何为 Spring AI AlibabaReactAgentStateGraph 接入完整的可观测性方案,覆盖:

  • 图执行观测Graph / Node / Edge 三级生命周期的 TraceMetrics
  • 模型调用观测ChatClient / ChatModel 的调用耗时、Token 用量、Prompt/Response 日志
  • OTLP 导出Trace + Metrics + Logs 通过 OTLP/gRPC 统一导出到 SkyWalking OAP
  • Prometheus + GrafanaMetrics 通过 /actuator/prometheus 暴露

2. 架构原理

2.1 观测数据流

复制代码
┌──────────────────────────────────────────────────────────────┐
│                      应用层                                   │
│  ReactAgent / StateGraph ↔ ChatClient ↔ ChatModel            │
│         │                      │               │              │
│         ▼                      ▼               ▼              │
│  GraphObservation        ChatClient       ChatModel          │
│  LifecycleListener       Observation      Observation        │
│         │                      │               │              │
│         └──────────────────────┼───────────────┘              │
│                                ▼                              │
│                     Micrometer Observation API                │
│                   (ObservationRegistry)                       │
│                    │          │          │                     │
│                    ▼          ▼          ▼                     │
│               Metrics     Tracing      Logging               │
│                    │          │          │                     │
│                    ▼          ▼          ▼                     │
│             OTLP/gRPC   OTLP/gRPC   OTLP/gRPC                │
└────────────────────┬─────────┬─────────┬────────────────────┘
                     │         │         │
                     ▼         ▼         ▼
              ┌──────────────────────────────────┐
              │       SkyWalking OAP              │
              │  (192.168.1.111:4319 / 12800)    │
              └──────────────┬───────────────────┘
                             │
              ┌──────────────┴───────────────────┐
              │        Prometheus + Grafana       │
              └──────────────────────────────────┘

2.2 三个观测层级

层级 范围 数据 来源
Graph 级 StateGraph 整体执行 执行次数、耗时、成功率、每个节点生命周期 GraphObservationLifecycleListener
Chat 级 每次 LLM 调用 调用耗时、Token 用量(input/output/total) Spring AI ChatModelObservation
HTTP 级 REST API 请求 请求量、延迟、错误率 Spring Boot Actuator

3. 环境准备

3.1 前置条件

  • JDK 17+
  • Maven 3.6+
  • 阿里云 DashScope API Key
  • SkyWalking OAP(已部署在 192.168.1.111:4319

3.2 依赖说明

xml 复制代码
<!-- 核心:Agent Framework -->
<dependency>
    <groupId>com.alibaba.cloud.ai</groupId>
    <artifactId>spring-ai-alibaba-agent-framework</artifactId>
    <version>1.1.2.2</version>
</dependency>

<!-- 自动配置:Graph Observation(一键启用图执行观测) -->
<dependency>
    <groupId>com.alibaba.cloud.ai</groupId>
    <artifactId>spring-ai-alibaba-starter-graph-observation</artifactId>
    <version>1.1.2.2</version>
</dependency>

<!-- 观测基础设施 -->
<dependency>
    <groupId>io.micrometer</groupId>
    <artifactId>micrometer-tracing</artifactId>            <!-- Trace 抽象 -->
</dependency>
<dependency>
    <groupId>io.micrometer</groupId>
    <artifactId>micrometer-tracing-bridge-otel</artifactId> <!-- Micrometer → OTel 桥接 -->
</dependency>
<dependency>
    <groupId>io.micrometer</groupId>
    <artifactId>micrometer-registry-otlp</artifactId>      <!-- Metrics OTLP 导出 -->
</dependency>
<dependency>
    <groupId>io.opentelemetry</groupId>
    <artifactId>opentelemetry-exporter-otlp</artifactId>   <!-- Trace OTLP 导出 -->
</dependency>
<dependency>
    <groupId>io.opentelemetry.instrumentation</groupId>
    <artifactId>opentelemetry-logback-appender-1.0</artifactId> <!-- Logs OTLP 导出 -->
    <version>2.14.0-alpha</version>
</dependency>

4. 自动配置

spring-ai-alibaba-starter-graph-observation 通过 GraphObservationAutoConfiguration 提供一键自动装配。

4.1 自动配置类

类名com.alibaba.cloud.ai.autoconfigure.graph.GraphObservationAutoConfiguration

触发条件

  • @ConditionalOnClass 检测到 ObservationRegistryGraphObservationLifecycleListener
  • spring.ai.alibaba.graph.observation.enabled=true(默认就是 true

自动注册的 Bean

Bean 名称 类型 作用
observationGraphCompileConfig CompileConfig 预配置了 ObservationRegistry + GraphObservationLifecycleListener,Graph 编译时直接传入
graphObservationLifecycleListener GraphObservationLifecycleListener 监听 Graph 执行全生命周期,在 Node/Edge 级别创建 Span
graphObservationHandler GraphObservationHandler Graph 级别的 Span 创建和属性填充
graphNodeObservationHandler GraphNodeObservationHandler Node 级别的 Span 创建
graphEdgeObservationHandler GraphEdgeObservationHandler Edge 路由级别的 Span 创建

4.2 自动配置源码逻辑

GraphObservationAutoConfiguration 的核心装配逻辑等价于:

java 复制代码
@Configuration
@ConditionalOnClass({ObservationRegistry.class, GraphObservationLifecycleListener.class})
@EnableConfigurationProperties(GraphObservationProperties.class)
public class GraphObservationAutoConfiguration {

    @Bean
    public CompileConfig observationGraphCompileConfig(
            ObjectProvider<ObservationRegistry> observationRegistry,
            ObjectProvider<GraphObservationLifecycleListener> listeners) {

        CompileConfig.Builder builder = CompileConfig.builder();
        observationRegistry.ifUnique(builder::observationRegistry);
        listeners.ifUnique(builder::withLifecycleListener);
        return builder.build();
    }

    @Bean
    public GraphObservationLifecycleListener graphObservationLifecycleListener(
            ObservationRegistry observationRegistry,
            ObjectProvider<GraphObservationConvention> convention,
            ObjectProvider<GraphNodeObservationConvention> nodeConvention,
            ObjectProvider<GraphEdgeObservationConvention> edgeConvention) {

        return new GraphObservationLifecycleListener(
                observationRegistry,
                convention.getIfUnique(),
                nodeConvention.getIfUnique(),
                edgeConvention.getIfUnique()
        );
    }

    // GraphObservationHandler, GraphNodeObservationHandler, GraphEdgeObservationHandler ...
}

4.3 如何使用自动配置的 Bean

在自己的 Config 中直接注入 observationGraphCompileConfig

java 复制代码
@Bean
public CompiledGraph myGraph(
        @Qualifier("observationGraphCompileConfig") CompileConfig observationConfig) {

    StateGraph graph = new StateGraph();
    // ... 添加节点和边
    return graph.compile(observationConfig);  // ← 传入即可启用观测
}

@Bean
public ReactAgent myAgent(
        ObservationRegistry observationRegistry,
        @Qualifier("observationGraphCompileConfig") CompileConfig observationConfig) {

    return ReactAgent.builder()
            .model(chatModel)
            .observationRegistry(observationRegistry)   // ← ChatModel 层观测
            .compileConfig(observationConfig)            // ← Graph 层观测
            .build();
}

4.4 配置属性

spring-ai-alibaba-starter-graph-observation 提供的 GraphObservationProperties

yaml 复制代码
spring.ai.alibaba.graph.observation:
  enabled: true    # 是否启用 Graph 观测(默认 true)

Spring AI 自带的 ChatClient/ChatModel 观测配置:

yaml 复制代码
spring.ai.chat.client.observations:
  log-prompt: true        # 日志中记录 Prompt
  log-completion: true    # 日志中记录 Response

spring.ai.chat.observations:
  log-prompt: true
  log-completion: true
  include-error-logging: true  # 记录异常日志

spring.ai.tools.observations:
  include-content: true        # Span 中包含工具调用入参和返回值

5. 应用配置

5.1 application.yml 关键配置

yaml 复制代码
server.port: 8080
spring.application.name: spring-ai-alibaba-observation

# DashScope 模型
spring.ai.dashscope:
  api-key: ${DASHSCOPE_API_KEY}
  chat.options:
    model: qwen-plus

# Graph 观测开关
spring.ai.alibaba.graph.observation.enabled: true

# Chat 观测配置
spring.ai:
  tools.observations.include-content: true
  chat.client.observations:
    log-prompt: true
    log-completion: true
  chat.observations:
    log-prompt: true
    log-completion: true
    include-error-logging: true

# OTLP 导出到 SkyWalking
management:
  tracing:
    enabled: true
    sampling.probability: 1.0
  otlp:
    tracing:
      endpoint: http://192.168.1.111:4319
      transport: grpc
      export.enabled: true
    logging:
      endpoint: http://192.168.1.111:4319
      transport: grpc
      export.enabled: true
  endpoints.web.exposure.include: health,metrics,info

# 日志格式(带上 traceId / spanId)
logging:
  pattern:
    level: "%5p [${spring.application.name:},%X{traceId:-},%X{spanId:-}]"

5.2 logback-spring.xml

xml 复制代码
<configuration>
    <property name="CONSOLE_LOG_PATTERN"
        value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level [%mdc{traceId:-N/A}] [%mdc{spanId:-N/A}] %logger{36} - %msg%n"/>

    <include resource="org/springframework/boot/logging/logback/defaults.xml"/>
    <include resource="org/springframework/boot/logging/logback/console-appender.xml"/>

    <!-- OTLP 日志 Appender:日志也通过 OTLP 上报到 SkyWalking -->
    <appender name="OTLP"
        class="io.opentelemetry.instrumentation.logback.appender.v1_0.OpenTelemetryAppender">
        <captureExperimentalAttributes>true</captureExperimentalAttributes>
        <captureCodeAttributes>true</captureCodeAttributes>
        <captureMdcAttributes>traceId,spanId</captureMdcAttributes>
    </appender>

    <root level="INFO">
        <appender-ref ref="CONSOLE"/>
        <appender-ref ref="OTLP"/>
    </root>
</configuration>

6. 核心代码实现

6.1 启动类

java 复制代码
@SpringBootApplication
public class ObservationDemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(ObservationDemoApplication.class, args);
    }
}

只需 @SpringBootApplication------starter-graph-observation 的自动配置会自动生效。

6.2 StateGraph + 观测

通过注入自动配置的 observationGraphCompileConfig,一行代码启用:

java 复制代码
@Bean("observedTextProcessGraph")
public CompiledGraph observedTextProcessGraph(
        ChatModel chatModel,
        @Qualifier("observationGraphCompileConfig") CompileConfig observationConfig) {

    StateGraph graph = new StateGraph();
    graph.addNode("parse_input", node_async(state -> { ... }))
         .addNode("analyze_text", node_async(state -> {
             String result = ChatClient.builder(chatModel).build()
                     .prompt().user("Analyze: " + text).call().content();
             return Map.of("analysis", result);
         }))
         .addNode("format_output", node_async(state -> { ... }))
         .addEdge(START, "parse_input")
         .addEdge("parse_input", "analyze_text")
         .addEdge("analyze_text", "format_output")
         .addEdge("format_output", END);

    return graph.compile(observationConfig);  // ← 关键:传入观测 Config
}

效果:每个 Node 执行自动创建 SpanGraph 级别的 total duration 自动记录为 Metric

6.3 ReactAgent + 观测

双层次观测:.observationRegistry() + .compileConfig()

java 复制代码
@Bean("observedWeatherAgent")
public ReactAgent observedWeatherAgent(
        ChatModel chatModel,
        ObservationRegistry observationRegistry,
        @Qualifier("observationGraphCompileConfig") CompileConfig observationConfig) {

    return ReactAgent.builder()
            .name("weather-assistant")
            .model(chatModel)
            .instruction("You are a helpful weather assistant.")
            .methodTools(new WeatherTool())
            .observationRegistry(observationRegistry)   // ChatModel 层观测
            .compileConfig(observationConfig)            // Graph 层观测
            .enableLogging(true)
            .build();
}

6.4 OtlpLoggingConfig

Spring Boot 默认不自动装配 LoggerProvider,需手动安装 OpenTelemetryAppender

java 复制代码
@Component
public class OtlpLoggingConfig implements InitializingBean {
    private final OpenTelemetry openTelemetry;

    @Override
    public void afterPropertiesSet() {
        OpenTelemetryAppender.install(openTelemetry);
    }
}

6.5 ObservationFilterConfig

Spring Boot 3.4+ 移除了 management.observations.http.server.requests.ignored-uris,改用编程方式过滤:

java 复制代码
@Bean
ObservationPredicate onlyBusinessApiObservations() {
    return (observationName, context) -> {
        if (context instanceof ServerRequestObservationContext server) {
            String uri = server.getCarrier().getRequestURI();
            return uri.startsWith("/api/") && !uri.startsWith("/api/proxy/");
        }
        return true;
    };
}

7. 观测指标(Metrics)

7.1 自动采集的指标

指标名 类型 说明
spring.ai.alibaba.graph.execution Timer Graph 执行耗时
spring.ai.alibaba.graph.node.execution Timer 单个 Node 执行耗时
spring.ai.alibaba.graph.edge.execution Timer Edge 路由耗时
gen_ai.client.operation.duration Histogram LLM 操作耗时(GenAI 语义约定)
gen_ai.client.token.usage Histogram Token 用量(input/output/total)

7.2 查看指标

bash 复制代码
# 查看所有 Graph 相关指标
curl http://localhost:8080/actuator/metrics | jq '.names[]' | grep graph

# 查看特定指标详情
curl http://localhost:8080/actuator/metrics/spring.ai.alibaba.graph.execution

# 查看观测状态
curl http://localhost:8080/api/observation/status

8. 观测拦截器示例

8.1 Bean 注册 Hook

GraphObservationLifecycleListener 作为 LifecycleHook 挂载在 Bean 生命周期的 afterPropertiesSet 时自动注册到 HookManager,全局生效,无需每个 Graph 手动注册:

java 复制代码
// 源码:GraphObservationLifecycleListener
@Override
public void afterPropertiesSet() {
    HookManager.register(this);  // ← 全局注册,所有 Graph 编译时自动包含
}

8.2 树型 Span 结构

复制代码
Graph Execution Span
├── Node: parse_input Span
│   └── (ChatClient Span)
│       └── (ChatModel Span)
├── Node: analyze_text Span
│   └── (ChatClient Span)
│       └── (ChatModel Span)
│           ├── gen_ai.token.usage (input=156, output=89, total=245)
│           └── gen_ai.operation.duration (1.2s)
├── Edge: analyze_text -> transform_text Span
├── Node: transform_text Span
├── Edge: transform_text -> format_output Span
├── Node: format_output Span
└── Edge: format_output -> END Span

9. API 端点

bash 复制代码
# StateGraph 同步
GET http://localhost:8080/api/graph/text-process?text=hello

# StateGraph 流式(SSE)
GET http://localhost:8080/api/graph/text-process/stream?text=hello

# ReactAgent 同步
GET http://localhost:8080/api/agent/weather?query=Beijing

# ReactAgent 流式(SSE)
GET http://localhost:8080/api/agent/weather/stream?query=Beijing

# 观测状态查询
GET http://localhost:8080/api/observation/status

前端页面:

路径 功能
/index.html 仪表盘首页
/ai-chat.html AI 对话界面
/trace-viewer.html Trace 链路查看器
/ai-metrics.html AI 指标监控面板
/log-viewer.html 日志查看器

相关推荐
TPBoreas1 小时前
spring3.5的本质改变
spring
渡码桑1 小时前
STM32 TinyML实战2026:3步在单片机上跑通AI推理——从TensorFlow到Edge Impulse的嵌入式进化
人工智能·stm32·单片机
chian-ocean1 小时前
突破纯文字交互:基于魔珐星云端到端技术,赋能国产大模型构建数字人智能体
人工智能·交互·语音识别
暗夜猎手-大魔王1 小时前
hermes源码学习8--Gateway 内部机制
人工智能·gateway
console.log('npc')1 小时前
将 Figma 接入 Codex MCP:从 `/plugins` 到本地插件配置的完整教程
前端·人工智能·python·figma·code·codex·mcp
俊哥V1 小时前
每日 AI 研究简报 · 2026-06-11
人工智能·ai
Rain5091 小时前
1.1 理解AI Agent与自动化数据分析
人工智能·ai·数据分析·自动化·ai编程
吴佳浩 Alben1 小时前
pytorch 你不学?_EP01_环境准备与安装验证
人工智能·pytorch·python
葡萄城技术团队1 小时前
从NL2SQL到AI智能问数:企业数据分析的下一步在哪里
人工智能·数据挖掘·数据分析