Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@

**Developer note:** use the AlloyDB proxy to run from your own development environment - [instructions](data/Database.md)

### Traceability
* OpenTelemetry Setup - [Configuration and setup instructions](opentelemetry-setup.md)

### Dependent Services
* MCP Servers
* MCP Weather Server - [Deployment instructions](mcp/mcp-weather-server/README.md)
Expand Down Expand Up @@ -72,5 +75,3 @@ gcloud run deploy agentic-rag --image us-central1-docker.pkg.dev/<Your Project>/
--memory 2Gi --cpu 2 --cpu-boost --execution-environment=gen2 \
--set-env-vars="SERVER_PORT=8080,GCP_PROJECT_ID=<project>,GCP_LOCATION=us-central1,GCP_PROJECT_NUM=<project_number>,ALLOY_DB_URL=<URL>,ALLOY_DB_USERNAME=<user>,GEMMA_URL=<optional>,MCP_WEATHER_SERVER=<MCP-Server-URL>,MCP_FILE_SERVER=<MCP-Server-URL>,GCP_TEXTEMBEDDING_MODEL=textembedding-005" \
--set-secrets="ALLOY_DB_PASSWORD=ALLOY_DB_SECRET:latest,TAVILY_API_KEY=TAVILY_API_KEY:latest"


4 changes: 2 additions & 2 deletions data/Database.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,5 @@ select capital, country

# describe tables
\d public.capitals
\d public. continents
``
\d public.continents
```
6 changes: 5 additions & 1 deletion data/tables.ddl
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ DROP TABLE IF EXISTS continents;
DROP TABLE IF EXISTS capitals;
DROP TYPE IF EXISTS embed_type;

-- Install the vector and alloydb_scann extensions:
CREATE EXTENSION IF NOT EXISTS vector;
CREATE EXTENSION IF NOT EXISTS alloydb_scann;

-- Create enum type for embedding types
CREATE TYPE embed_type AS ENUM ('hierarchical', 'hypothetical', 'contextual', 'late');

Expand Down Expand Up @@ -73,7 +77,7 @@ VALUES
((SELECT capital_id FROM capitals WHERE capital = 'Ankara'),
'hypothetical', 'Geographical content about Ankara...', 'Ankara is located in central Anatolia and has a continental climate...'),
((SELECT capital_id FROM capitals WHERE capital = 'Ankara'),
'contextual', 'Cultural content about Ankara...', 'The culture of Ankara reflects its position as Turkey's capital...');
'contextual', 'Cultural content about Ankara...', 'The culture of Ankara reflects its position as Turkey''s capital...');

-- Example SELECT to retrieve a capital with all its chunks and continents
SELECT
Expand Down
Binary file added images/TraceExample.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions mcp/mcp-file-server/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ The server supports two transport modes:

### WebMVC SSE Mode (Default)
```bash
java -jar target/mcp-weather-server-0.0.1.jar
java -jar target/mcp-file-server-0.0.1.jar
```

## Configuration
Expand All @@ -33,7 +33,7 @@ Configure the server through `application.properties`:

```properties
# Server identification
spring.ai.mcp.server.name=my-weather-server
spring.ai.mcp.server.name=my-file-server
spring.ai.mcp.server.version=0.0.1

# Server type (SYNC/ASYNC)
Expand Down
120 changes: 120 additions & 0 deletions opentelemetry-setup.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
# OpenTelemetry Setup for Google Cloud Trace

This document explains how OpenTelemetry has been integrated into the AI Patterns UI application to send end-to-end trace data to Google Cloud Trace.

## Overview

OpenTelemetry is configured to automatically instrument the Spring Boot application and send trace data to Google Cloud Trace. This provides visibility into the application's performance and helps identify bottlenecks.

## Dependencies Added

The following dependencies were added to `pom.xml`:

```xml
<!-- OpenTelemetry Dependencies -->
<dependency>
<groupId>io.opentelemetry.instrumentation</groupId>
<artifactId>opentelemetry-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>com.google.cloud.opentelemetry</groupId>
<artifactId>exporter-trace</artifactId>
<version>0.34.0</version>
</dependency>
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-exporter-otlp</artifactId>
</dependency>
```

Additionally, the OpenTelemetry BOM was added to dependency management:

```xml
<dependency>
<groupId>io.opentelemetry.instrumentation</groupId>
<artifactId>opentelemetry-instrumentation-bom</artifactId>
<version>2.10.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
```

## Configuration

### Application Properties

The following properties were added to `application.properties`:

```properties
# OpenTelemetry Configuration
opentelemetry.traces.enabled=true
opentelemetry.logs.export.enabled=false
opentelemetry.metrics.export.enabled=false

# Google Cloud Trace Configuration
otel.traces.exporter=google_cloud_trace
otel.exporter.otlp.protocol=grpc
otel.resource.attributes=service.name=${spring.application.name},service.version=1.0.0

# GCP Project Configuration
gcp.project.id=${GCP_PROJECT_ID}
```

### OpenTelemetry Configuration Class

A configuration class `OpenTelemetryConfig` was created to set up the Google Cloud Trace exporter:

- Located at: `src/main/java/com/xiao/ai/patterns/config/OpenTelemetryConfig.java`
- Creates a `TraceExporter` for Google Cloud Trace
- Configures the `SdkTracerProvider` with resource attributes
- Provides a `Tracer` bean for manual instrumentation

## Manual Instrumentation

Key services have been instrumented with custom spans:

### AgenticRAGService

- **callAgent** method: Creates spans with attributes for chat ID and model
- **stream** method: Creates spans for streaming operations with proper lifecycle management

### ChatService

- **chat** method: Basic span creation with tool usage tracking
- **stream** method: Comprehensive instrumentation including:
- RAG operations tracking
- Query compression events
- HyDE (Hypothetical Document Embedding) events
- Guardrails/moderation tracking
- Reranking operations

## Span Attributes and Events

The instrumentation captures:

- **Attributes**: chat.id, chat.model, streaming, rag.enabled, tools.enabled, guardrails.enabled
- **Events**: Building AI Assistant, Starting stream, Query compression, HyDE operations, RAG retrieval, Reranking
- **Metrics**: response.length, rag.items.retrieved

## Running with OpenTelemetry

1. Ensure the `GCP_PROJECT_ID` environment variable is set
2. Ensure Google Cloud credentials are configured
3. Run the application normally - traces will be automatically sent to Google Cloud Trace

## Viewing Traces

Traces can be viewed in the Google Cloud Console:
1. Navigate to the Trace section
2. Filter by service name (matches `spring.application.name`)
3. View detailed trace timelines and span attributes

![Trace Example](images/TraceExample.png)

## Disabling OpenTelemetry

To disable OpenTelemetry, set the following property:

```properties
opentelemetry.traces.enabled=false
```
22 changes: 22 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,21 @@
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

<!-- OpenTelemetry Dependencies -->
<dependency>
<groupId>io.opentelemetry.instrumentation</groupId>
<artifactId>opentelemetry-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>com.google.cloud.opentelemetry</groupId>
<artifactId>exporter-trace</artifactId>
<version>0.34.0</version>
</dependency>
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-exporter-otlp</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jdbc</artifactId>
Expand Down Expand Up @@ -303,6 +318,13 @@
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>io.opentelemetry.instrumentation</groupId>
<artifactId>opentelemetry-instrumentation-bom</artifactId>
<version>2.10.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>

Expand Down
2 changes: 1 addition & 1 deletion src/main/frontend/views/@index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import ChatOptionsModel from "Frontend/generated/ai/patterns/utils/ChatUtils/Cha
import {Checkbox, ComboBox, TextArea, RadioGroup, RadioButton, Button, Icon, Tooltip} from "@vaadin/react-components";

const models = [
'gemini-2.5-pro-preview-03-25',
'gemini-2.5-pro',
'gemini-2.0-flash-001',
'gemini-1.5-pro-002'
];
Expand Down
52 changes: 52 additions & 0 deletions src/main/java/ai/patterns/config/OpenTelemetryConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package ai.patterns.config;

import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.api.trace.Tracer;
import io.opentelemetry.sdk.OpenTelemetrySdk;
import io.opentelemetry.sdk.trace.SdkTracerProvider;
import io.opentelemetry.sdk.trace.export.BatchSpanProcessor;
import io.opentelemetry.sdk.resources.Resource;
import io.opentelemetry.api.common.AttributeKey;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;

import java.io.IOException;

@Configuration
@ConditionalOnProperty(value = "opentelemetry.traces.enabled", havingValue = "true", matchIfMissing = true)
public class OpenTelemetryConfig {

@Value("${spring.application.name:ai-patterns-ui}")
private String applicationName;

@Value("${gcp.project.id:}")
private String projectId;

@Bean
public OpenTelemetry openTelemetry() throws IOException {
Resource resource = Resource.getDefault().toBuilder()
.put(AttributeKey.stringKey("service.name"), applicationName)
.put(AttributeKey.stringKey("service.version"), "1.0.0")
.build();

// Create Google Cloud Trace exporter
io.opentelemetry.sdk.trace.export.SpanExporter googleCloudTraceExporter =
com.google.cloud.opentelemetry.trace.TraceExporter.createWithDefaultConfiguration();

SdkTracerProvider tracerProvider = SdkTracerProvider.builder()
.setResource(resource)
.addSpanProcessor(BatchSpanProcessor.builder(googleCloudTraceExporter).build())
.build();

return OpenTelemetrySdk.builder()
.setTracerProvider(tracerProvider)
.buildAndRegisterGlobal();
}

@Bean
public Tracer tracer(OpenTelemetry openTelemetry) {
return openTelemetry.getTracer(applicationName);
}
}
Loading