Netra uses the OpenTelemetry Protocol (OTLP) to export traces, making it compatible with any OTLP-compliant backend. This guide covers how to configure custom endpoints, authentication, and self-hosted setups.
OTLP Endpoint Configuration
Netra Cloud
By default, traces are sent to Netra’s cloud backend. Configure the endpoint and API key:
import os
from netra import Netra
Netra.init(
app_name="my-ai-app",
headers=f"x-api-key={os.getenv('NETRA_API_KEY')}",
)
Or via environment variables:
export NETRA_API_KEY="your-api-key"
export NETRA_OTLP_ENDPOINT="https://api.getnetra.ai/telemetry"
Regional Endpoints
Netra provides regional endpoints for data residency requirements:
| Region | Location | Endpoint |
|---|
| US | N. Virginia (us-east-1) | https://api.getnetra.ai/telemetry |
| EU | Frankfurt (eu-central-1) | https://api.eu.getnetra.ai/telemetry |
Regions are strictly separated, and no data is shared across regions. Choosing a region close to you can help improve speed and comply with local data residency laws and privacy regulations.
# US region
export NETRA_OTLP_ENDPOINT="https://api.getnetra.ai/telemetry"
# EU region
export NETRA_OTLP_ENDPOINT="https://api.eu.getnetra.ai/telemetry"
Custom Backend Configuration
Setting a Custom Endpoint
Point Netra to any OTLP-compatible backend:
import os
from netra import Netra
# Set custom endpoint via environment variable
os.environ["NETRA_OTLP_ENDPOINT"] = "https://otel-collector.internal.company.com"
Netra.init(
app_name="my-ai-app",
headers="Authorization=Bearer your-token",
)
Via environment variables:
export NETRA_OTLP_ENDPOINT="https://otel-collector.internal.company.com"
export NETRA_HEADERS="Authorization=Bearer your-token"
Netra automatically formats the endpoint URL:
- If the URL doesn’t end with
/v1/traces, it’s appended automatically
- Base URLs like
https://collector.example.com become https://collector.example.com/v1/traces
# These are equivalent:
export NETRA_OTLP_ENDPOINT="https://collector.example.com"
export NETRA_OTLP_ENDPOINT="https://collector.example.com/v1/traces"
Authentication Methods
API Key Authentication (Netra Cloud)
For Netra cloud endpoints, use the x-api-key header:
Netra.init(
app_name="my-ai-app",
headers=f"x-api-key={os.getenv('NETRA_API_KEY')}",
)
Bearer Token Authentication
For custom backends that use Bearer tokens:
Netra.init(
app_name="my-ai-app",
headers=f"Authorization=Bearer {os.getenv('OTEL_TOKEN')}",
)
Pass multiple headers using comma separation (W3C Correlation-Context format):
Netra.init(
app_name="my-ai-app",
headers="Authorization=Bearer token123,x-custom-header=value",
)
Automatic Authentication Detection
Netra automatically determines the authentication method based on the endpoint:
| Endpoint Contains | Authentication Header |
|---|
getnetra | x-api-key: {value} |
| Other | Authorization: Bearer {value} |
This means for Netra cloud, you only need to provide the API key value:
# For Netra cloud - uses x-api-key header automatically
export NETRA_API_KEY="ntr_abc123"
# For custom backends - uses Authorization: Bearer header
export NETRA_HEADERS="Authorization=Bearer custom-token"
Self-Hosted OpenTelemetry Collector
Basic Collector Setup
Deploy an OpenTelemetry Collector to receive traces from Netra:
# otel-collector-config.yaml
receivers:
otlp:
protocols:
http:
endpoint: "0.0.0.0:4318"
grpc:
endpoint: "0.0.0.0:4317"
processors:
batch:
timeout: 1s
send_batch_size: 1024
exporters:
# Export to Jaeger
jaeger:
endpoint: "jaeger:14250"
tls:
insecure: true
# Export to logging (for debugging)
logging:
loglevel: debug
service:
pipelines:
traces:
receivers: [otlp]
processors: [batch]
exporters: [jaeger, logging]
Configure Netra to send to the collector:
export NETRA_OTLP_ENDPOINT="http://otel-collector:4318"
Docker Compose Example
# docker-compose.yml
version: '3.8'
services:
app:
build: .
environment:
- NETRA_APP_NAME=my-ai-app
- NETRA_OTLP_ENDPOINT=http://otel-collector:4318
- NETRA_ENV=development
otel-collector:
image: otel/opentelemetry-collector-contrib:latest
command: ["--config=/etc/otel-collector-config.yaml"]
volumes:
- ./otel-collector-config.yaml:/etc/otel-collector-config.yaml
ports:
- "4317:4317" # OTLP gRPC
- "4318:4318" # OTLP HTTP
jaeger:
image: jaegertracing/all-in-one:latest
ports:
- "16686:16686" # Jaeger UI
- "14250:14250" # Jaeger gRPC
Kubernetes Deployment
# otel-collector-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: otel-collector
spec:
replicas: 1
selector:
matchLabels:
app: otel-collector
template:
metadata:
labels:
app: otel-collector
spec:
containers:
- name: otel-collector
image: otel/opentelemetry-collector-contrib:latest
args:
- --config=/etc/otel/config.yaml
ports:
- containerPort: 4317
- containerPort: 4318
volumeMounts:
- name: config
mountPath: /etc/otel
volumes:
- name: config
configMap:
name: otel-collector-config
---
apiVersion: v1
kind: Service
metadata:
name: otel-collector
spec:
selector:
app: otel-collector
ports:
- name: otlp-grpc
port: 4317
- name: otlp-http
port: 4318
Popular Backend Integrations
Jaeger
# otel-collector-config.yaml
exporters:
jaeger:
endpoint: "jaeger-collector:14250"
tls:
insecure: true
export NETRA_OTLP_ENDPOINT="http://otel-collector:4318"
Grafana Tempo
# otel-collector-config.yaml
exporters:
otlp:
endpoint: "tempo:4317"
tls:
insecure: true
Datadog
# otel-collector-config.yaml
exporters:
datadog:
api:
key: ${DD_API_KEY}
site: datadoghq.com
New Relic
# otel-collector-config.yaml
exporters:
otlp:
endpoint: "https://otlp.nr-data.net:4317"
headers:
api-key: ${NEW_RELIC_LICENSE_KEY}
Honeycomb
# otel-collector-config.yaml
exporters:
otlp:
endpoint: "api.honeycomb.io:443"
headers:
x-honeycomb-team: ${HONEYCOMB_API_KEY}
Dual Export Setup
Send traces to both Netra and a custom backend:
# otel-collector-config.yaml
receivers:
otlp:
protocols:
http:
endpoint: "0.0.0.0:4318"
exporters:
# Forward to Netra (use endpoint matching your region)
# US: https://api.getnetra.ai/telemetry/v1/traces
# EU: https://api.eu.getnetra.ai/telemetry/v1/traces
otlp/netra:
endpoint: "https://api.getnetra.ai/telemetry/v1/traces"
headers:
x-api-key: ${NETRA_API_KEY}
# Also export to Jaeger
jaeger:
endpoint: "jaeger:14250"
tls:
insecure: true
service:
pipelines:
traces:
receivers: [otlp]
processors: [batch]
exporters: [otlp/netra, jaeger]
Configure your application to send to the local collector:
export NETRA_OTLP_ENDPOINT="http://localhost:4318"
Troubleshooting
Connection Issues
-
Verify endpoint reachability
curl -v https://your-endpoint/v1/traces
-
Check authentication
- Ensure API key or token is correct
- Verify header format matches backend expectations
-
Enable debug mode
Netra.init(app_name="my-app", debug_mode=True)
Traces Not Appearing
-
Disable batching for debugging
Netra.init(app_name="my-app", disable_batch=True)
-
Check collector logs
docker logs otel-collector
-
Verify OTLP endpoint format
- Ensure the endpoint accepts HTTP/protobuf
- Check if
/v1/traces path is correct
TLS/SSL Errors
For self-signed certificates in development:
# otel-collector-config.yaml
exporters:
otlp:
endpoint: "https://internal-backend:4317"
tls:
insecure: true # Only for development!
Never use insecure: true in production. Configure proper TLS certificates instead.
Best Practices
-
Use environment variables - Keep endpoints and credentials out of code.
-
Deploy a collector - For production, use an OpenTelemetry Collector as a gateway rather than sending directly from applications.
-
Enable batching - Keep
disable_batch=False (default) for better performance.
-
Monitor collector health - Set up health checks and metrics for your collector.
-
Use regional endpoints - Choose the Netra endpoint closest to your infrastructure.
Next Steps