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
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
> Use [this search for a list of all CHANGELOG.md files in this repo](https://github.com/search?q=repo%3Aalibaba%2Floongsuite-python-agent+path%3A**%2FCHANGELOG.md&type=code).

## Unreleased

### Added

- **loongsuite-instrumentation-google-adk**: Add initial support for Google Agent Development Kit (ADK) #35
1 change: 1 addition & 0 deletions instrumentation-loongsuite/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@
| [loongsuite-instrumentation-agentscope](./loongsuite-instrumentation-agentscope) | agentscope >= 0.1.5.dev0 | No | development
| [loongsuite-instrumentation-agno](./loongsuite-instrumentation-agno) | agno >= 1.5.0 | No | development
| [loongsuite-instrumentation-dify](./loongsuite-instrumentation-dify) | dify | No | development
| [loongsuite-instrumentation-google-adk](./loongsuite-instrumentation-google-adk) | google-adk >= 0.1.0 | Yes | experimental
| [loongsuite-instrumentation-langchain](./loongsuite-instrumentation-langchain) | langchain_core >= 0.1.0 | Yes | development
| [loongsuite-instrumentation-mcp](./loongsuite-instrumentation-mcp) | mcp>=1.3.0 | Yes | development
Original file line number Diff line number Diff line change
@@ -0,0 +1,331 @@
# OpenTelemetry Google ADK Instrumentation

[![OpenTelemetry](https://img.shields.io/badge/OpenTelemetry-GenAI_Semantic_Conventions-blue)](https://github.com/open-telemetry/semantic-conventions/blob/main/docs/gen-ai/)

Google ADK (Agent Development Kit) Python Agent provides comprehensive observability for Google ADK applications using OpenTelemetry.

## Features

- ✅ **Automatic Instrumentation**: Zero-code integration via `opentelemetry-instrument`
- ✅ **Manual Instrumentation**: Programmatic control via `GoogleAdkInstrumentor`
- ✅ **GenAI Semantic Conventions**: Full compliance with OpenTelemetry GenAI standards
- ✅ **Comprehensive Spans**: `invoke_agent`, `chat`, `execute_tool`
- ✅ **Standard Metrics**: Operation duration and token usage
- ✅ **Content Capture**: Optional message and response content capture
- ✅ **Google ADK native instrumentation Compatible**: Works seamlessly with ADK native instrumentation

## Quick Start

```bash
# Install
pip install google-adk litellm
pip install ./instrumentation-loongsuite/loongsuite-instrumentation-google-adk

# Configure
export DASHSCOPE_API_KEY=your-api-key

# Run with auto instrumentation
opentelemetry-instrument \
--traces_exporter console \
--service_name my-adk-app \
python your_app.py
```

For details on LoongSuite and Jaeger setup, refer to [LoongSuite Documentation](https://github.com/alibaba/loongsuite-python-agent/blob/main/README.md).

## Installing Google ADK Instrumentation

```shell
# OpenTelemetry Core
pip install opentelemetry-distro opentelemetry-exporter-otlp
opentelemetry-bootstrap -a install

# Google ADK and LLM Dependencies
pip install google-adk>=0.1.0
pip install litellm

# Demo Application Dependencies (optional, only if running examples)
pip install fastapi uvicorn pydantic

# GoogleAdkInstrumentor
git clone https://github.com/alibaba/loongsuite-python-agent.git
cd loongsuite-python-agent
pip install ./instrumentation-loongsuite/loongsuite-instrumentation-google-adk
```

## Collect Data

Here's a simple demonstration of Google ADK instrumentation. The demo uses:

- A [Google ADK application](examples/main.py) that demonstrates agent interactions with multiple tools

### Running the Demo

> **Note**: The demo uses DashScope (Alibaba Cloud LLM service) by default. You need to set the `DASHSCOPE_API_KEY` environment variable.

#### Option 1: Using OpenTelemetry Auto Instrumentation

```bash
# Set your DashScope API key
export DASHSCOPE_API_KEY=your-dashscope-api-key

# Enable content capture (optional, for debugging)
export OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT=true

# Run with auto instrumentation
opentelemetry-instrument \
--traces_exporter console \
--service_name demo-google-adk \
python examples/main.py
```

#### Option 2: Using Loongsuite

```bash
# Set your DashScope API key
export DASHSCOPE_API_KEY=your-dashscope-api-key

# Enable content capture (optional, for debugging)
export OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT=true

# Run with loongsuite instrumentation
loongsuite-instrument \
--traces_exporter console \
--service_name demo-google-adk \
python examples/main.py
```

#### Option 3: Export to Jaeger

```bash
# Set your DashScope API key
export DASHSCOPE_API_KEY=your-dashscope-api-key

# Configure OTLP exporter
export OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT=true
export OTEL_TRACES_EXPORTER=otlp
export OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317
export OTEL_EXPORTER_OTLP_PROTOCOL=grpc

# Run the application
opentelemetry-instrument \
--service_name demo-google-adk \
python examples/main.py
```

### Expected Results

The instrumentation will generate traces showing the Google ADK operations:

#### Tool Execution Span Example

```json
{
"name": "execute_tool get_current_time",
"context": {
"trace_id": "xxx",
"span_id": "xxx",
"trace_state": "[]"
},
"kind": "SpanKind.INTERNAL",
"parent_id": "xxx",
"start_time": "2025-10-23T06:36:33.858459Z",
"end_time": "2025-10-23T06:36:33.858779Z",
"status": {
"status_code": "UNSET"
},
"attributes": {
"gen_ai.operation.name": "execute_tool",
"gen_ai.tool.name": "get_current_time",
"gen_ai.tool.description": "xxx",
"input.value": "{xxx}",
"output.value": "{xxx}"
},
"events": [],
"links": [],
"resource": {
"attributes": {
"telemetry.sdk.language": "python",
"telemetry.sdk.name": "opentelemetry",
"telemetry.sdk.version": "1.37.0",
"service.name": "demo-google-adk"
},
"schema_url": ""
}
}
```

#### LLM Chat Span Example

```json
{
"name": "chat qwen-max",
"kind": "SpanKind.CLIENT",
"attributes": {
"gen_ai.operation.name": "chat",
"gen_ai.request.model": "qwen-max",
"gen_ai.response.model": "qwen-max",
"gen_ai.usage.input_tokens": 150,
"gen_ai.usage.output_tokens": 45
}
}
```

#### Agent Invocation Span Example

```json
{
"name": "invoke_agent ToolAgent",
"kind": "SpanKind.CLIENT",
"attributes": {
"gen_ai.operation.name": "invoke_agent",
"gen_ai.agent.name": "ToolAgent",
"input.value": "[{\"role\": \"user\", \"parts\": [{\"type\": \"text\", \"content\": \"现在几点了?\"}]}]",
"output.value": "[{\"role\": \"assistant\", \"parts\": [{\"type\": \"text\", \"content\": \"当前时间是 2025-11-27 14:36:33\"}]}]"
}
}
```

### Viewing in Jaeger

After [setting up Jaeger](https://www.jaegertracing.io/docs/latest/getting-started/), you can visualize the complete trace hierarchy in the Jaeger UI, showing the relationships between Runner, Agent, LLM, and Tool spans

## Configuration

### Environment Variables

The following environment variables can be used to configure the Google ADK instrumentation:

| Variable | Description | Default |
|----------|-------------|---------|
| `OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT` | Capture message content in traces | `false` |
| `DASHSCOPE_API_KEY` | DashScope API key (required for demo) | - |

### Programmatic Configuration

You can also configure the instrumentation programmatically:

```python
from opentelemetry.instrumentation.google_adk import GoogleAdkInstrumentor

# Configure the instrumentor
instrumentor = GoogleAdkInstrumentor()

# Enable instrumentation with custom configuration
instrumentor.instrument(
tracer_provider=your_tracer_provider,
meter_provider=your_meter_provider
)
```

## Supported Features

### Traces

The Google ADK instrumentation automatically creates traces for:

- **Agent Runs**: Complete agent execution cycles
- **Tool Calls**: Individual tool invocations
- **Model Interactions**: LLM requests and responses
- **Session Management**: User session tracking
- **Error Handling**: Exception and error tracking

### Metrics

The instrumentation follows the [OpenTelemetry GenAI Semantic Conventions for Metrics](https://github.com/open-telemetry/semantic-conventions/blob/main/docs/gen-ai/gen-ai-metrics.md) and provides the following **standard client metrics**:

#### 1. `gen_ai.client.operation.duration` (Histogram)

Records the duration of GenAI operations in seconds.

**Instrument Type**: Histogram
**Unit**: `s` (seconds)
**Status**: Development

**Required Attributes**:
- `gen_ai.operation.name`: Operation being performed (e.g., `chat`, `invoke_agent`, `execute_tool`)
- `gen_ai.provider.name`: Provider name (e.g., `google_adk`)

**Conditionally Required Attributes**:
- `error.type`: Error type (only if operation ended in error)
- `gen_ai.request.model`: Model name (if available)

**Recommended Attributes**:
- `gen_ai.response.model`: Response model name
- `server.address`: Server address
- `server.port`: Server port

**Example Values**:
- LLM operation: `gen_ai.operation.name="chat"`, `gen_ai.request.model="gemini-pro"`, `duration=1.5s`
- Agent operation: `gen_ai.operation.name="invoke_agent"`, `gen_ai.request.model="math_tutor"`, `duration=2.3s`
- Tool operation: `gen_ai.operation.name="execute_tool"`, `gen_ai.request.model="calculator"`, `duration=0.5s`

#### 2. `gen_ai.client.token.usage` (Histogram)

Records the number of tokens used in GenAI operations.

**Instrument Type**: Histogram
**Unit**: `{token}`
**Status**: Development

**Required Attributes**:
- `gen_ai.operation.name`: Operation being performed
- `gen_ai.provider.name`: Provider name
- `gen_ai.token.type`: Token type (`input` or `output`)

**Conditionally Required Attributes**:
- `gen_ai.request.model`: Model name (if available)

**Recommended Attributes**:
- `gen_ai.response.model`: Response model name
- `server.address`: Server address
- `server.port`: Server port

**Example Values**:
- Input tokens: `gen_ai.token.type="input"`, `gen_ai.request.model="gemini-pro"`, `count=100`
- Output tokens: `gen_ai.token.type="output"`, `gen_ai.request.model="gemini-pro"`, `count=50`

**Note**: These metrics use **Histogram** instrument type (not Counter) and follow the standard OpenTelemetry GenAI semantic conventions. All other metrics (like `genai.agent.runs.count`, etc.) are non-standard and have been removed to ensure compliance with the latest OTel specifications.

### Semantic Conventions

This instrumentation follows the OpenTelemetry GenAI semantic conventions:

- [GenAI Spans](https://github.com/open-telemetry/semantic-conventions/blob/main/docs/gen-ai/gen-ai-spans.md)
- [GenAI Agent Spans](https://github.com/open-telemetry/semantic-conventions/blob/main/docs/gen-ai/gen-ai-agent-spans.md)
- [GenAI Metrics](https://github.com/open-telemetry/semantic-conventions/blob/main/docs/gen-ai/gen-ai-metrics.md)



## Troubleshooting

### Common Issues

1. **Module Import Error**: If you encounter `No module named 'google.adk.runners'`, ensure that `google-adk` is properly installed:
```bash
pip install google-adk>=0.1.0
```

2. **DashScope API Error**: If you see authentication errors, verify your API key is correctly set:
```bash
export DASHSCOPE_API_KEY=your-api-key
# Verify it's set
echo $DASHSCOPE_API_KEY
```

3. **Instrumentation Not Working**:
- Check that the instrumentation is enabled and the Google ADK application is using the `Runner` class
- Verify you see the log message: `Plugin 'opentelemetry_adk_observability' registered`
- For manual instrumentation, ensure you call `GoogleAdkInstrumentor().instrument()` before creating the Runner

4. **Missing Traces**:
- Verify that the OpenTelemetry exporters are properly configured
- Check the `OTEL_TRACES_EXPORTER` environment variable is set (e.g., `console`, `otlp`)
- For OTLP exporter, ensure the endpoint is reachable


## References

- [OpenTelemetry Project](https://opentelemetry.io/)
- [Google ADK Documentation](https://google.github.io/adk-docs/)
- [GenAI Semantic Conventions](https://github.com/open-telemetry/semantic-conventions/blob/main/docs/gen-ai/)
Loading