Adapters
OTLP Adapter
Send logs via OpenTelemetry Protocol (OTLP) to Grafana, Datadog, Honeycomb, and any compatible backend. Supports gRPC and HTTP transports.
The OTLP (OpenTelemetry Protocol) adapter sends logs in the standard OpenTelemetry format. This works with any OTLP-compatible backend including:
- Grafana Cloud (Loki)
- Datadog
- Honeycomb
- Jaeger
- Splunk
- New Relic
- Self-hosted OpenTelemetry Collector
Installation
The OTLP adapter comes bundled with evlog:
server/plugins/evlog-drain.ts
import { createOTLPDrain } from 'evlog/otlp'
Quick Start
1. Set your OTLP endpoint
.env
NUXT_OTLP_ENDPOINT=http://localhost:4318
2. Create the drain plugin
server/plugins/evlog-drain.ts
import { createOTLPDrain } from 'evlog/otlp'
export default defineNitroPlugin((nitroApp) => {
nitroApp.hooks.hook('evlog:drain', createOTLPDrain())
})
Configuration
The adapter reads configuration from multiple sources (highest priority first):
- Overrides passed to
createOTLPDrain() - Runtime config at
runtimeConfig.evlog.otlp - Runtime config at
runtimeConfig.otlp - Environment variables (
NUXT_OTLP_*orOTEL_*)
Environment Variables
| Variable | Description |
|---|---|
NUXT_OTLP_ENDPOINT | OTLP HTTP endpoint (e.g., http://localhost:4318) |
NUXT_OTLP_SERVICE_NAME | Override service name |
NUXT_OTLP_HEADERS | Custom headers (format: Key=Value,Key2=Value2) |
NUXT_OTLP_AUTH | Shortcut for Authorization header |
Standard OpenTelemetry variables are also supported:
| Variable | Description |
|---|---|
OTEL_EXPORTER_OTLP_ENDPOINT | OTLP endpoint (fallback) |
OTEL_EXPORTER_OTLP_HEADERS | Headers in OTEL format |
OTEL_SERVICE_NAME | Service name (fallback) |
Runtime Config
nuxt.config.ts
export default defineNuxtConfig({
runtimeConfig: {
otlp: {
endpoint: '', // Set via NUXT_OTLP_ENDPOINT
},
},
})
Override Options
server/plugins/evlog-drain.ts
import { createOTLPDrain } from 'evlog/otlp'
export default defineNitroPlugin((nitroApp) => {
nitroApp.hooks.hook('evlog:drain', createOTLPDrain({
endpoint: 'http://localhost:4318',
serviceName: 'my-api',
headers: {
'Authorization': 'Bearer xxx',
},
resourceAttributes: {
'deployment.environment': 'staging',
},
}))
})
Full Configuration Reference
| Option | Type | Default | Description |
|---|---|---|---|
endpoint | string | - | OTLP HTTP endpoint (required) |
serviceName | string | From event | Override service.name resource attribute |
headers | object | - | Custom HTTP headers for authentication |
resourceAttributes | object | - | Additional OTLP resource attributes |
timeout | number | 5000 | Request timeout in milliseconds |
Provider-Specific Setup
Grafana Cloud
- Go to your Grafana Cloud portal
- Navigate to Connections > Collector > OpenTelemetry
- Copy your OTLP endpoint and generate credentials
.env
NUXT_OTLP_ENDPOINT=https://otlp-gateway-prod-us-central-0.grafana.net/otlp
OTEL_EXPORTER_OTLP_HEADERS=Authorization=Basic%20base64-encoded-credentials
Grafana uses URL-encoded headers. The
%20 is a space character. The adapter automatically decodes this format.Datadog
.env
NUXT_OTLP_ENDPOINT=https://http-intake.logs.datadoghq.com
NUXT_OTLP_HEADERS=DD-API-KEY=your-api-key
Local OpenTelemetry Collector
For development and testing, run a local collector:
otel-collector.yaml
receivers:
otlp:
protocols:
http:
endpoint: 0.0.0.0:4318
exporters:
debug:
verbosity: detailed
service:
pipelines:
logs:
receivers: [otlp]
exporters: [debug]
docker run --rm -p 4318:4318 \
-v $(pwd)/otel-collector.yaml:/etc/otelcol/config.yaml \
otel/opentelemetry-collector:latest
.env
NUXT_OTLP_ENDPOINT=http://localhost:4318
OTLP Log Format
evlog maps wide events to the OTLP log format:
| evlog Field | OTLP Field |
|---|---|
level | severityNumber / severityText |
timestamp | timeUnixNano |
service | Resource attribute service.name |
environment | Resource attribute deployment.environment |
version | Resource attribute service.version |
region | Resource attribute cloud.region |
traceId | traceId |
spanId | spanId |
| All other fields | Log attributes |
Severity Mapping
| evlog Level | OTLP Severity Number | OTLP Severity Text |
|---|---|---|
debug | 5 | DEBUG |
info | 9 | INFO |
warn | 13 | WARN |
error | 17 | ERROR |
Troubleshooting
Missing endpoint error
[evlog/otlp] Missing endpoint. Set NUXT_OTLP_ENDPOINT or OTEL_EXPORTER_OTLP_ENDPOINT
Make sure your endpoint environment variable is set and the server was restarted.
401 Unauthorized
Your authentication headers may be missing or incorrect. Check:
- The
OTEL_EXPORTER_OTLP_HEADERSformat is correct - Credentials are valid and not expired
- The endpoint URL is correct
404 Not Found
The adapter sends to /v1/logs. Make sure your endpoint:
- Supports OTLP HTTP (not gRPC)
- Is the base URL without
/v1/logssuffix
Logs not appearing
- Check the server console for
[evlog/otlp]error messages - Test with a local collector first to verify the format
- Check your backend's ingestion delay (some have 1-2 minute delays)
Direct API Usage
For advanced use cases:
server/utils/otlp.ts
import { sendToOTLP, sendBatchToOTLP, toOTLPLogRecord } from 'evlog/otlp'
// Send a single event
await sendToOTLP(event, {
endpoint: 'http://localhost:4318',
})
// Send multiple events
await sendBatchToOTLP(events, {
endpoint: 'http://localhost:4318',
})
// Convert event to OTLP format (for inspection)
const otlpRecord = toOTLPLogRecord(event)
Next Steps
- Axiom Adapter - Send logs to Axiom
- PostHog Adapter - Send logs to PostHog
- Custom Adapters - Build your own adapter
- Best Practices - Security and production tips