Skip to content

Commit 603202d

Browse files
[feat][otel-integration][add optional OpenTelemetry tracing and metrics]
Add OpenTelemetry instrumentation for agent and multi-agent workflow observability. Tracing is disabled by default and activates only when SWARMS_OTEL_ENABLED=true and dependencies are available. Changes: Add swarms/telemetry/otel.py with tracing decorators and metrics. Integrate tracing into Agent.run(), SwarmRouter, SequentialWorkflow, ConcurrentWorkflow. Add optional opentelemetry dependencies. Add documentation, example, and tests. Closes #1199 Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent 64ccdc9 commit 603202d

11 files changed

Lines changed: 1269 additions & 69 deletions

File tree

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
# OpenTelemetry Integration
2+
3+
Swarms provides built-in OpenTelemetry support for distributed tracing and metrics collection across agent and multi-agent workflow executions.
4+
5+
## Installation
6+
7+
OpenTelemetry support is optional. Install the required dependencies:
8+
9+
```bash
10+
# Using pip with extras
11+
pip install swarms[otel]
12+
13+
# Or install packages directly
14+
pip install opentelemetry-api opentelemetry-sdk opentelemetry-exporter-otlp-proto-grpc
15+
```
16+
17+
## Configuration
18+
19+
Enable OpenTelemetry tracing via environment variables:
20+
21+
| Variable | Description | Default |
22+
|----------|-------------|---------|
23+
| `SWARMS_OTEL_ENABLED` | Enable/disable tracing (`true`/`false`) | `false` |
24+
| `OTEL_SERVICE_NAME` | Service name for traces | `swarms` |
25+
| `OTEL_EXPORTER_OTLP_ENDPOINT` | OTLP collector endpoint | None |
26+
| `OTEL_EXPORTER_OTLP_HEADERS` | Headers for OTLP exporter | None |
27+
28+
## Quick Start
29+
30+
```python
31+
import os
32+
33+
# Enable tracing
34+
os.environ["SWARMS_OTEL_ENABLED"] = "true"
35+
os.environ["OTEL_SERVICE_NAME"] = "my-agent-app"
36+
os.environ["OTEL_EXPORTER_OTLP_ENDPOINT"] = "http://localhost:4317"
37+
38+
from swarms import Agent
39+
40+
agent = Agent(
41+
agent_name="research-agent",
42+
model_name="gpt-4o-mini",
43+
max_loops=1,
44+
)
45+
46+
# Traces are automatically created for agent.run()
47+
result = agent.run("What is the capital of France?")
48+
```
49+
50+
## What Gets Traced
51+
52+
### Agent Runs
53+
54+
Each `agent.run()` call creates a span with:
55+
56+
- `agent.name` - Agent's name
57+
- `agent.id` - Agent's unique identifier
58+
- `agent.model` - Model being used
59+
- `agent.max_loops` - Maximum loop configuration
60+
- `run.has_image` - Whether image input was provided
61+
- `run.duration_ms` - Execution time in milliseconds
62+
- `run.status` - `success` or `error`
63+
64+
### Multi-Agent Workflows
65+
66+
SwarmRouter, SequentialWorkflow, and ConcurrentWorkflow executions create spans with:
67+
68+
- `swarm.name` - Workflow name
69+
- `swarm.id` - Workflow identifier
70+
- `swarm.type` - Type of workflow (e.g., `SequentialWorkflow`)
71+
- `swarm.agent_count` - Number of agents in the workflow
72+
- `run.duration_ms` - Total execution time
73+
- `run.status` - `success` or `error`
74+
75+
## Metrics
76+
77+
When enabled, the following metrics are collected:
78+
79+
| Metric | Type | Description |
80+
|--------|------|-------------|
81+
| `swarms.agent.runs` | Counter | Number of agent run invocations |
82+
| `swarms.agent.duration` | Histogram | Duration of agent runs (ms) |
83+
| `swarms.agent.errors` | Counter | Number of agent run errors |
84+
| `swarms.swarm.runs` | Counter | Number of swarm run invocations |
85+
| `swarms.swarm.duration` | Histogram | Duration of swarm runs (ms) |
86+
87+
## Using with Jaeger
88+
89+
```bash
90+
# Start Jaeger
91+
docker run -d --name jaeger \
92+
-p 16686:16686 \
93+
-p 4317:4317 \
94+
jaegertracing/all-in-one:latest
95+
96+
# Configure environment
97+
export SWARMS_OTEL_ENABLED=true
98+
export OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317
99+
100+
# Run your application
101+
python your_app.py
102+
103+
# View traces at http://localhost:16686
104+
```
105+
106+
## Custom Tracing
107+
108+
Use the `trace_context` helper for custom spans:
109+
110+
```python
111+
from swarms.telemetry import trace_context
112+
113+
with trace_context("custom.operation", {"key": "value"}) as span:
114+
# Your code here
115+
result = do_something()
116+
117+
if span:
118+
span.set_attribute("result.count", len(result))
119+
```
120+
121+
## Checking Status
122+
123+
```python
124+
from swarms.telemetry import is_otel_enabled, otel_available
125+
126+
# Check if OTEL packages are installed
127+
print(f"OTEL available: {otel_available()}")
128+
129+
# Check if OTEL is enabled
130+
print(f"OTEL enabled: {is_otel_enabled()}")
131+
```
132+
133+
## Best Practices
134+
135+
1. **Production environments**: Always set `OTEL_EXPORTER_OTLP_ENDPOINT` to send traces to your collector
136+
2. **Sampling**: For high-volume applications, configure sampling in your OTLP collector
137+
3. **Service naming**: Use descriptive `OTEL_SERVICE_NAME` values to identify your application
138+
4. **Error tracking**: Errors are automatically recorded with exception details
139+
140+
## Graceful Degradation
141+
142+
The integration is designed to be non-invasive:
143+
144+
- If OTEL packages are not installed, tracing is silently disabled
145+
- If `SWARMS_OTEL_ENABLED` is not set to `true`, no tracing overhead is added
146+
- All tracing operations are wrapped in try/except to prevent affecting normal execution
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
"""
2+
OpenTelemetry Tracing Example for Swarms
3+
4+
This example demonstrates how to enable OpenTelemetry tracing
5+
for agent and multi-agent workflow executions.
6+
7+
Prerequisites:
8+
pip install swarms[otel]
9+
# or
10+
pip install opentelemetry-api opentelemetry-sdk opentelemetry-exporter-otlp-proto-grpc
11+
12+
Configuration:
13+
Set these environment variables before running:
14+
- SWARMS_OTEL_ENABLED=true # Enable tracing
15+
- OTEL_SERVICE_NAME=my-app # Your service name (default: swarms)
16+
- OTEL_EXPORTER_OTLP_ENDPOINT=... # OTLP endpoint (optional)
17+
18+
Running with Jaeger:
19+
# Start Jaeger
20+
docker run -d --name jaeger \
21+
-p 16686:16686 \
22+
-p 4317:4317 \
23+
jaegertracing/all-in-one:latest
24+
25+
# Set environment and run
26+
export SWARMS_OTEL_ENABLED=true
27+
export OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317
28+
python otel_tracing_example.py
29+
30+
# View traces at http://localhost:16686
31+
"""
32+
33+
import os
34+
35+
os.environ["SWARMS_OTEL_ENABLED"] = "true"
36+
os.environ["OTEL_SERVICE_NAME"] = "swarms-example"
37+
38+
from swarms import Agent
39+
from swarms.structs.swarm_router import SwarmRouter
40+
from swarms.telemetry import is_otel_enabled, otel_available
41+
42+
43+
def main():
44+
print("OpenTelemetry Integration Example")
45+
print("=" * 50)
46+
47+
print(f"OTEL Available: {otel_available()}")
48+
print(f"OTEL Enabled: {is_otel_enabled()}")
49+
print()
50+
51+
if not otel_available():
52+
print(
53+
"OpenTelemetry packages not installed. Install with:"
54+
)
55+
print(" pip install swarms[otel]")
56+
print()
57+
58+
analyst = Agent(
59+
agent_name="Financial-Analyst",
60+
system_prompt="You are a financial analyst. Provide brief, concise analysis.",
61+
model_name="gpt-4o-mini",
62+
max_loops=1,
63+
)
64+
65+
researcher = Agent(
66+
agent_name="Market-Researcher",
67+
system_prompt="You are a market researcher. Provide brief insights.",
68+
model_name="gpt-4o-mini",
69+
max_loops=1,
70+
)
71+
72+
print("Running single agent (traced)...")
73+
result = analyst.run(
74+
"What are the key factors affecting tech stock prices?"
75+
)
76+
print(f"Result: {result[:200]}..." if len(result) > 200 else f"Result: {result}")
77+
print()
78+
79+
print("Running multi-agent workflow (traced)...")
80+
router = SwarmRouter(
81+
name="analysis-team",
82+
agents=[analyst, researcher],
83+
swarm_type="SequentialWorkflow",
84+
max_loops=1,
85+
)
86+
87+
workflow_result = router.run(
88+
"Analyze the current state of AI chip market"
89+
)
90+
print("Workflow completed!")
91+
print()
92+
93+
if is_otel_enabled():
94+
print("Traces have been recorded.")
95+
endpoint = os.getenv("OTEL_EXPORTER_OTLP_ENDPOINT")
96+
if endpoint:
97+
print(f"Check your OTLP backend at: {endpoint}")
98+
else:
99+
print(
100+
"No OTLP endpoint configured - traces stored in memory only."
101+
)
102+
else:
103+
print(
104+
"OTEL not enabled. Set SWARMS_OTEL_ENABLED=true to enable tracing."
105+
)
106+
107+
108+
if __name__ == "__main__":
109+
main()

pyproject.toml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,23 @@ requests = "*"
7474
mcp = "*"
7575
schedule = "*"
7676

77+
[tool.poetry.group.otel]
78+
optional = true
79+
80+
[tool.poetry.group.otel.dependencies]
81+
opentelemetry-api = ">=1.20.0"
82+
opentelemetry-sdk = ">=1.20.0"
83+
opentelemetry-exporter-otlp-proto-grpc = ">=1.20.0"
84+
opentelemetry-semantic-conventions = ">=0.41b0"
85+
86+
[tool.poetry.extras]
87+
otel = [
88+
"opentelemetry-api",
89+
"opentelemetry-sdk",
90+
"opentelemetry-exporter-otlp-proto-grpc",
91+
"opentelemetry-semantic-conventions",
92+
]
93+
7794
[tool.poetry.scripts]
7895
swarms = "swarms.cli.main:main"
7996

0 commit comments

Comments
 (0)