CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-org-springframework-ai--spring-ai-vector-store

Common vector store functionality for Spring AI providing a portable abstraction layer for integrating vector databases with comprehensive filtering, similarity search, and observability support.

Overview
Eval results
Files

observability.mddocs/guides/

Observability Guide

Learn how to monitor and trace your vector store operations with Micrometer.

Overview

Spring AI Vector Store includes built-in observability support through Micrometer, providing:

  • Metrics: Operation duration, counts, and performance
  • Distributed Tracing: End-to-end request visibility
  • Custom Observations: Tailored monitoring for your needs

All vector store operations (add, delete, query) are automatically observed when observability is configured.

Quick Start

Step 1: Add Dependencies

<!-- Micrometer for metrics -->
<dependency>
    <groupId>io.micrometer</groupId>
    <artifactId>micrometer-core</artifactId>
</dependency>

<!-- Prometheus export (optional) -->
<dependency>
    <groupId>io.micrometer</groupId>
    <artifactId>micrometer-registry-prometheus</artifactId>
</dependency>

<!-- Tracing (optional) -->
<dependency>
    <groupId>io.micrometer</groupId>
    <artifactId>micrometer-tracing-bridge-brave</artifactId>
</dependency>

Step 2: Configure Vector Store with Observability

import io.micrometer.observation.ObservationRegistry;
import org.springframework.ai.vectorstore.SimpleVectorStore;
import org.springframework.ai.vectorstore.observation.DefaultVectorStoreObservationConvention;

@Configuration
public class VectorStoreConfig {
    
    @Bean
    public VectorStore vectorStore(
            EmbeddingModel embeddingModel,
            ObservationRegistry observationRegistry) {
        
        return SimpleVectorStore.builder(embeddingModel)
            .observationRegistry(observationRegistry)
            .customObservationConvention(new DefaultVectorStoreObservationConvention())
            .build();
    }
}

Step 3: Operations Are Automatically Tracked

// These operations are automatically observed
vectorStore.add(documents);                    // Tracked: add operation
vectorStore.similaritySearch(request);         // Tracked: query operation
vectorStore.delete(ids);                       // Tracked: delete operation

Spring Boot Integration

Configuration

Add to application.yml:

management:
  metrics:
    export:
      prometheus:
        enabled: true
  tracing:
    sampling:
      probability: 1.0  # Sample 100% in dev (reduce in prod)
  observations:
    key-values:
      application: my-vector-app
      environment: ${SPRING_PROFILES_ACTIVE:dev}

Or application.properties:

management.metrics.export.prometheus.enabled=true
management.tracing.sampling.probability=1.0
management.observations.key-values.application=my-vector-app
management.observations.key-values.environment=${spring.profiles.active:dev}

Spring Boot Actuator

Add Spring Boot Actuator for metrics endpoints:

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

Access metrics at: http://localhost:8080/actuator/prometheus

Metrics

Available Metrics

When observability is configured, the following metrics are collected:

Metric NameTypeDescription
db.vector.client.operationTimerDuration of vector store operations
db.vector.client.operation.activeGaugeCurrently active operations
db.vector.client.operation.maxGaugeMaximum operation duration

Metric Tags (Low Cardinality)

TagExample ValuesDescription
db.systemsimple, pinecone, chromaVector store type
db.operation.nameadd, delete, queryOperation type
db.vector.similarity.metriccosine, euclideanSimilarity metric

Metric Tags (High Cardinality)

TagDescription
db.collection.nameCollection/index name
db.vector.dimension_countEmbedding dimensions
db.vector.query.top_kNumber of results requested
db.vector.query.similarity_thresholdSimilarity threshold
db.vector.query.response.documents.countNumber of results returned

Example Metrics Output

# HELP db_vector_client_operation_seconds
# TYPE db_vector_client_operation_seconds summary
db_vector_client_operation_seconds_count{db_operation_name="query",db_system="simple"} 50.0
db_vector_client_operation_seconds_sum{db_operation_name="query",db_system="simple"} 1.234

db_vector_client_operation_seconds_count{db_operation_name="add",db_system="simple"} 10.0
db_vector_client_operation_seconds_sum{db_operation_name="add",db_system="simple"} 0.523

Distributed Tracing

Setup Zipkin

Add dependency:

<dependency>
    <groupId>io.zipkin.reporter2</groupId>
    <artifactId>zipkin-reporter-brave</artifactId>
</dependency>

Configure in application.yml:

management:
  tracing:
    sampling:
      probability: 1.0
  zipkin:
    tracing:
      endpoint: http://localhost:9411/api/v2/spans

Start Zipkin

docker run -d -p 9411:9411 openzipkin/zipkin

Access UI at: http://localhost:9411

Trace Example

Trace: user-request-12345
├─ HTTP GET /search
│  └─ db.vector.client.operation (query documents)
│     ├─ Span ID: abc123
│     ├─ Duration: 45ms
│     ├─ Tags:
│     │  ├─ db.system: simple
│     │  ├─ db.operation.name: query
│     │  ├─ db.vector.query.top_k: 10
│     │  └─ db.vector.query.response.documents.count: 8
│     └─ Events:
│        ├─ query.start
│        └─ query.complete

Custom Observation Conventions

Create a custom convention to customize metric names and tags:

import org.springframework.ai.vectorstore.observation.VectorStoreObservationConvention;
import org.springframework.ai.vectorstore.observation.VectorStoreObservationContext;
import io.micrometer.common.KeyValue;
import io.micrometer.common.KeyValues;

public class CustomObservationConvention implements VectorStoreObservationConvention {
    
    @Override
    public String getName() {
        return "custom.vector.operation";  // Custom metric name
    }
    
    @Override
    public String getContextualName(VectorStoreObservationContext context) {
        return context.getOperationName() + " on " + context.getCollectionName();
    }
    
    @Override
    public KeyValues getLowCardinalityKeyValues(VectorStoreObservationContext context) {
        return KeyValues.of(
            KeyValue.of("db.type", context.getDatabaseSystem()),
            KeyValue.of("operation", context.getOperationName()),
            KeyValue.of("environment", System.getenv("ENV"))  // Custom tag
        );
    }
    
    @Override
    public KeyValues getHighCardinalityKeyValues(VectorStoreObservationContext context) {
        return KeyValues.of(
            KeyValue.of("collection", context.getCollectionName() != null ?
                context.getCollectionName() : "unknown")
        );
    }
}

// Use in configuration
@Bean
public VectorStore vectorStore(
        EmbeddingModel embeddingModel,
        ObservationRegistry observationRegistry) {
    return SimpleVectorStore.builder(embeddingModel)
        .observationRegistry(observationRegistry)
        .customObservationConvention(new CustomObservationConvention())
        .build();
}

Grafana Dashboard

Setup Grafana

docker run -d -p 3000:3000 grafana/grafana

Add Prometheus Data Source

  1. Go to http://localhost:3000 (admin/admin)
  2. Add Prometheus data source: http://localhost:9090

Example Queries

Query Duration:

rate(db_vector_client_operation_seconds_sum[5m]) / 
rate(db_vector_client_operation_seconds_count[5m])

Operations Per Second:

rate(db_vector_client_operation_seconds_count[5m])

Operation Count by Type:

sum by (db_operation_name) (db_vector_client_operation_seconds_count)

Monitoring Best Practices

1. Sample Traces in Production

Don't trace every request in production:

# Development: 100%
management.tracing.sampling.probability=1.0

# Production: 10%
management.tracing.sampling.probability=0.1

2. Set Alerts

Example Prometheus alert:

groups:
  - name: vector_store
    rules:
      - alert: VectorStoreHighLatency
        expr: |
          rate(db_vector_client_operation_seconds_sum[5m]) / 
          rate(db_vector_client_operation_seconds_count[5m]) > 1
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "Vector store operations taking > 1s"

3. Monitor Key Metrics

Track these metrics:

  • Query duration: Should be < 100ms for most use cases
  • Operations per second: Monitor throughput
  • Error rate: Track failed operations
  • Document counts: Track data growth

4. Use Tags Wisely

Low cardinality (limited values):

  • Operation type (add/delete/query)
  • Store type (simple/pinecone/etc)
  • Environment (dev/staging/prod)

High cardinality (many values):

  • Collection names
  • Query details
  • Document IDs (be careful with cardinality explosion)

Complete Example

import org.springframework.ai.vectorstore.SimpleVectorStore;
import org.springframework.ai.vectorstore.observation.DefaultVectorStoreObservationConvention;
import io.micrometer.observation.ObservationRegistry;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.simple.SimpleMeterRegistry;

public class ObservabilityExample {
    
    public static void main(String[] args) {
        // 1. Create meter registry
        MeterRegistry meterRegistry = new SimpleMeterRegistry();
        
        // 2. Create observation registry
        ObservationRegistry observationRegistry = ObservationRegistry.create();
        observationRegistry.observationConfig()
            .observationHandler(new DefaultMeterObservationHandler(meterRegistry));
        
        // 3. Create vector store with observability
        SimpleVectorStore vectorStore = SimpleVectorStore.builder(embeddingModel)
            .observationRegistry(observationRegistry)
            .customObservationConvention(new DefaultVectorStoreObservationConvention())
            .build();
        
        // 4. Perform operations (automatically tracked)
        vectorStore.add(documents);
        List<Document> results = vectorStore.similaritySearch(request);
        
        // 5. View metrics
        meterRegistry.getMeters().forEach(meter -> {
            System.out.println("Metric: " + meter.getId());
            System.out.println("Measurements: " + meter.measure());
        });
    }
}

Production Configuration

application-prod.yml

spring:
  ai:
    vectorstore:
      initialize-schema: false

# Metrics export
management:
  metrics:
    export:
      prometheus:
        enabled: true
        step: 1m
      datadog:
        enabled: true
        api-key: ${DATADOG_API_KEY}
        step: 1m
  
  # Distributed tracing
  tracing:
    sampling:
      probability: 0.1  # 10% sampling
  
  # Custom tags
  observations:
    key-values:
      application: vector-store-app
      environment: production
      datacenter: ${DATACENTER:us-east-1}
      version: ${APP_VERSION:unknown}
  
  # Endpoints
  endpoints:
    web:
      exposure:
        include: health,prometheus,metrics
  
  # Health checks
  health:
    defaults:
      enabled: true

# Logging
logging:
  level:
    org.springframework.ai.vectorstore: INFO
    io.micrometer.observation: INFO

Troubleshooting

No Metrics Appearing

Check:

  1. ObservationRegistry is configured
  2. MeterRegistry is bound to ObservationRegistry
  3. Actuator endpoints are exposed
  4. Operations are being called
// Verify registry is working
@Autowired
private ObservationRegistry observationRegistry;

@PostConstruct
public void verify() {
    logger.info("ObservationRegistry: {}", observationRegistry.getClass());
}

High Cardinality Warnings

Solution: Reduce high-cardinality tags

// BAD: Document IDs create too many unique metrics
KeyValue.of("document.id", doc.getId())

// GOOD: Use counts instead
KeyValue.of("document.count", String.valueOf(docs.size()))

Missing Trace Context

Solution: Ensure tracing is configured

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

Next Steps

  • See Examples: Check Real-World Scenarios for monitoring patterns
  • API Reference: See Observation API for complete details
  • Production Guide: See Configuration API for production setup

Reference

  • Observation API - Complete API documentation
  • Configuration API - Configuration options
  • Micrometer Documentation - Official Micrometer docs

Install with Tessl CLI

npx tessl i tessl/maven-org-springframework-ai--spring-ai-vector-store

docs

index.md

tile.json