Skip to content

Commit b71ef1e

Browse files
committed
docs: update README and add working example
1 parent 0544cdc commit b71ef1e

File tree

2 files changed

+476
-23
lines changed

2 files changed

+476
-23
lines changed

examples/configs/tracing/README.md

Lines changed: 342 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,354 @@
1-
# README
1+
# NeMo Guardrails Tracing
22

3-
We encourage you to implement a log adapter for the production environment based on your specific requirements.
3+
This guide explains how to set up tracing with NeMo Guardrails to monitor and debug your guardrails interactions.
44

5-
To use the `FileSystem` and `OpenTelemetry` adapters, please install the following dependencies:
5+
## What is Tracing?
6+
7+
Tracing helps you understand what happens inside your guardrails:
8+
9+
- Track which rails are activated
10+
- Monitor LLM calls and responses
11+
- Debug performance issues
12+
- Analyze conversation flows
13+
14+
## Quick Start
15+
16+
### 1. Try the Working Example
17+
18+
The fastest way to see tracing in action:
19+
20+
```bash
21+
pip install nemoguardrails[tracing] opentelemetry-sdk
22+
23+
cd examples/configs/tracing/
24+
python working_example.py
25+
```
26+
27+
This will show traces printed to your console immediately.
28+
29+
### 2. Basic Configuration
30+
31+
Enable tracing in your `config.yml`:
32+
33+
```yaml
34+
tracing:
35+
enabled: true
36+
adapters:
37+
- name: FileSystem
38+
```
39+
40+
Or use OpenTelemetry (requires additional setup):
41+
42+
```yaml
43+
tracing:
44+
enabled: true
45+
adapters:
46+
- name: OpenTelemetry
47+
```
48+
49+
## Available Tracing Adapters
50+
51+
### FileSystem Adapter (Easiest)
52+
53+
Logs traces to local JSON files which is a good option for development and debugging:
54+
55+
```yaml
56+
tracing:
57+
enabled: true
58+
adapters:
59+
- name: FileSystem
60+
filepath: "./logs/traces.jsonl"
61+
```
62+
63+
**When to use**: Development, debugging, simple logging needs.
64+
65+
### OpenTelemetry Adapter
66+
67+
```yaml
68+
tracing:
69+
enabled: true
70+
adapters:
71+
- name: OpenTelemetry
72+
```
73+
74+
**When to use**: Production environments, integration with monitoring systems, distributed applications.
75+
76+
## OpenTelemetry Ecosystem Compatibility
77+
78+
**NeMo Guardrails is compatible with the entire OpenTelemetry ecosystem.** The examples below show common configurations, but you can use any OpenTelemetry compatible:
79+
80+
- **Exporters**: Jaeger, Zipkin, Prometheus, New Relic, Datadog, AWS X-Ray, Google Cloud Trace, and many more
81+
- **Collectors**: OpenTelemetry Collector, Jaeger Collector, custom collectors
82+
- **Backends**: Any system that accepts OpenTelemetry traces
83+
84+
For the complete list of supported exporters, see the [OpenTelemetry Registry](https://opentelemetry.io/ecosystem/registry/).
85+
86+
### Custom Adapter
87+
88+
Implement your own adapter for specific requirements:
89+
90+
```python
91+
from nemoguardrails.tracing.adapters.base import InteractionLogAdapter
92+
93+
class MyCustomAdapter(InteractionLogAdapter):
94+
name = "MyCustomAdapter"
95+
96+
def transform(self, interaction_log):
97+
# your custom logic here
98+
pass
99+
```
100+
101+
## OpenTelemetry Setup
102+
103+
### Understanding the Architecture
104+
105+
- **NeMo Guardrails**: Uses only the OpenTelemetry API (doesn't configure anything)
106+
- **Your Application**: Configures the OpenTelemetry SDK and exporters
107+
108+
This means you must configure OpenTelemetry in your application code.
109+
110+
### Installation
111+
112+
```bash
113+
pip install nemoguardrails[tracing]
114+
115+
# install OpenTelemetry SDK and exporters (required for your application)
116+
pip install opentelemetry-sdk
117+
```
118+
119+
### Configuration Examples
120+
121+
#### Common Examples
122+
123+
**Console Output** (Development/Testing):
124+
125+
Suitable for development which prints traces to your terminal:
126+
127+
```python
128+
from opentelemetry import trace
129+
from opentelemetry.sdk.trace import TracerProvider
130+
from opentelemetry.sdk.trace.export import BatchSpanProcessor, ConsoleSpanExporter
131+
from opentelemetry.sdk.resources import Resource
132+
133+
# configure OpenTelemetry (do this before using NeMo Guardrails)
134+
resource = Resource.create({
135+
"service.name": "my-guardrails-app",
136+
"service.version": "1.0.0",
137+
}, schema_url="https://opentelemetry.io/schemas/1.26.0")
138+
139+
tracer_provider = TracerProvider(resource=resource)
140+
trace.set_tracer_provider(tracer_provider)
141+
142+
# use console exporter (prints to terminal)
143+
console_exporter = ConsoleSpanExporter()
144+
span_processor = BatchSpanProcessor(console_exporter)
145+
tracer_provider.add_span_processor(span_processor)
146+
147+
# now configure NeMo Guardrails
148+
from nemoguardrails import LLMRails, RailsConfig
149+
150+
config = RailsConfig.from_content(
151+
config={
152+
"models": [{"type": "main", "engine": "openai", "model": "gpt-3.5-turbo-instruct"}],
153+
"tracing": {
154+
"enabled": True,
155+
"adapters": [{"name": "OpenTelemetry"}]
156+
}
157+
}
158+
)
159+
160+
rails = LLMRails(config)
161+
response = rails.generate(messages=[{"role": "user", "content": "Hello!"}])
162+
```
163+
164+
**OTLP Exporter** (Production-ready):
165+
166+
For production use with observability platforms:
167+
168+
```bash
169+
# install OTLP exporter
170+
pip install opentelemetry-exporter-otlp
171+
```
172+
173+
```python
174+
from opentelemetry import trace
175+
from opentelemetry.sdk.trace import TracerProvider
176+
from opentelemetry.sdk.trace.export import BatchSpanProcessor
177+
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter
178+
from opentelemetry.sdk.resources import Resource
179+
180+
# configure OpenTelemetry
181+
resource = Resource.create({
182+
"service.name": "my-guardrails-app",
183+
"service.version": "1.0.0",
184+
}, schema_url="https://opentelemetry.io/schemas/1.26.0")
185+
186+
tracer_provider = TracerProvider(resource=resource)
187+
trace.set_tracer_provider(tracer_provider)
188+
189+
# configure OTLP exporter
190+
otlp_exporter = OTLPSpanExporter(
191+
endpoint="http://localhost:4317", # Your OTLP collector endpoint
192+
insecure=True
193+
)
194+
195+
span_processor = BatchSpanProcessor(otlp_exporter)
196+
tracer_provider.add_span_processor(span_processor)
197+
198+
# use with NeMo Guardrails (same as console example)
199+
```
200+
201+
> **Note**: These examples show popular configurations, but OpenTelemetry supports many more exporters and backends. You can integrate with any OpenTelemetry-compatible observability platform by installing the appropriate exporter package and configuring it in your application code.
202+
203+
## Additional Integration Examples
204+
205+
These are just a few examples of the many OpenTelemetry integrations available:
206+
207+
### Zipkin Integration
208+
209+
1. Start Zipkin server:
210+
211+
```bash
212+
docker run -d -p 9411:9411 openzipkin/zipkin
213+
```
214+
215+
2. Install Zipkin exporter:
6216

7217
```bash
8-
pip install opentelemetry-api opentelemetry-sdk aiofiles
218+
pip install opentelemetry-exporter-zipkin
9219
```
10220

11-
If you want to use Zipkin as a backend, you can use the following command to start a Zipkin server:
221+
3. Configure in your application:
222+
223+
```python
224+
from opentelemetry.exporter.zipkin.proto.http import ZipkinExporter
225+
226+
zipkin_exporter = ZipkinExporter(
227+
endpoint="http://localhost:9411/api/v2/spans",
228+
)
229+
span_processor = BatchSpanProcessor(zipkin_exporter)
230+
tracer_provider.add_span_processor(span_processor)
231+
```
12232

13-
1. Install the Zipkin exporter for OpenTelemetry:
233+
### OpenTelemetry Collector
14234

15-
```sh
16-
pip install opentelemetry-exporter-zipkin
17-
```
235+
Create a collector configuration file:
18236

19-
2. Run the `Zipkin` server using Docker:
237+
```yaml
238+
# otel-config.yaml
239+
receivers:
240+
otlp:
241+
protocols:
242+
grpc:
243+
endpoint: 0.0.0.0:4317
244+
http:
245+
endpoint: 0.0.0.0:4318
246+
247+
processors:
248+
batch:
249+
250+
exporters:
251+
logging:
252+
loglevel: debug
253+
254+
service:
255+
pipelines:
256+
traces:
257+
receivers: [otlp]
258+
processors: [batch]
259+
exporters: [logging]
260+
```
261+
262+
Run the collector:
263+
264+
```bash
265+
docker run -p 4317:4317 -p 4318:4318 \
266+
-v $(pwd)/otel-config.yaml:/etc/otel-collector-config.yaml \
267+
otel/opentelemetry-collector:latest \
268+
--config=/etc/otel-collector-config.yaml
269+
```
270+
271+
## Migration Guide
272+
273+
### From Previous Versions
274+
275+
If you were using the old OpenTelemetry configuration:
276+
277+
**❌ no longer supported:**
278+
279+
```yaml
280+
tracing:
281+
enabled: true
282+
adapters:
283+
- name: OpenTelemetry
284+
service_name: "my-service"
285+
exporter: "console"
286+
resource_attributes:
287+
env: "production"
288+
```
289+
290+
**✅ supported:**
291+
292+
```python
293+
# configure OpenTelemetry in your application code
294+
from opentelemetry import trace
295+
from opentelemetry.sdk.trace import TracerProvider
296+
from opentelemetry.sdk.trace.export import BatchSpanProcessor, ConsoleSpanExporter
297+
298+
tracer_provider = TracerProvider()
299+
trace.set_tracer_provider(tracer_provider)
300+
301+
console_exporter = ConsoleSpanExporter()
302+
span_processor = BatchSpanProcessor(console_exporter)
303+
tracer_provider.add_span_processor(span_processor)
304+
305+
config = RailsConfig.from_content(
306+
config={
307+
"tracing": {
308+
"enabled": True,
309+
"adapters": [{"name": "OpenTelemetry"}]
310+
}
311+
}
312+
)
313+
```
314+
315+
### Why the Change?
316+
317+
This change follows OpenTelemetry best practices:
318+
319+
1. **Libraries use only the API**: No configuration conflicts
320+
2. **Applications control observability**: You decide where traces go
321+
3. **Better compatibility**: Works with any OpenTelemetry setup
322+
323+
## Troubleshooting
324+
325+
### Common Issues
326+
327+
**No traces appear:**
328+
329+
- Ensure OpenTelemetry is configured in your application (not just NeMo Guardrails config)
330+
- Check that your exporter is working (try `ConsoleSpanExporter` first)
331+
- Verify tracing is enabled in your config
332+
333+
**Connection errors with OTLP:**
334+
335+
```
336+
WARNING: Transient error StatusCode.UNAVAILABLE encountered while exporting traces to localhost:4317
337+
```
338+
339+
- Make sure your collector/endpoint is running
340+
- Use `ConsoleSpanExporter` for testing without external dependencies
341+
342+
**Import errors:**
343+
344+
```
345+
ImportError: No module named 'opentelemetry'
346+
```
20347

21-
```sh
22-
docker run -d -p 9411:9411 openzipkin/zipkin
23-
```
348+
- Install the tracing dependencies: `pip install nemoguardrails[tracing]`
349+
- For exporters: `pip install opentelemetry-exporter-otlp`
24350

25-
3. Update the `config.yml` to set the exporter to Zipkin:
351+
**Wrong service name in traces:**
26352

27-
```yaml
28-
tracing:
29-
enabled: true
30-
adapters:
31-
- name: OpenTelemetry
32-
service_name: "nemo_guardrails_service"
33-
exporter: "zipkin"
34-
resource_attributes:
35-
env: "production"
353+
- Configure the `Resource` with `SERVICE_NAME` in your application code
354+
- The old `service_name` parameter is no longer used

0 commit comments

Comments
 (0)