OTLP Export
Export traces to any OpenTelemetry-compatible backend with zero additional dependencies.
Overview
The OpenTelemetry Protocol (OTLP) is the standard wire format for sending telemetry data to observability backends. Vestig ships a built-in OTLP exporter that:
- Zero dependencies — uses native
fetch()instead of the heavy@opentelemetry/exporter-trace-otlp-httpSDK - Batches and retries — automatically buffers spans and retries with exponential backoff
- Edge-compatible — works on Cloudflare Workers, Vercel Edge Functions, and any runtime with
fetch() - Universal backend support — Jaeger, Honeycomb, Grafana Cloud, Vercel, Datadog, Axiom, and any OTLP-compatible collector
Quick Start
Configuration Reference
| Option | Type | Default | Description |
|---|---|---|---|
endpoint |
string |
Required | OTLP endpoint URL for traces |
serviceName |
string |
Required | Service name, maps to service.name resource attribute |
serviceVersion |
string |
-- | Service version, maps to service.version |
environment |
string |
-- | Deployment environment, maps to deployment.environment |
headers |
Record<string, string> |
-- | Custom HTTP headers for authentication |
resourceAttributes |
Record<string, unknown> |
-- | Additional OTLP resource attributes |
batchSize |
number |
100 |
Max spans to batch before sending |
flushInterval |
number |
5000 |
Interval in ms between automatic flushes |
timeout |
number |
30000 |
Request timeout in ms |
maxRetries |
number |
3 |
Maximum retry attempts on failure |
retryDelay |
number |
1000 |
Initial retry delay in ms (doubles each attempt) |
enabled |
boolean |
true |
Enable/disable the exporter |
The exporter also sets the following resource attributes automatically:
telemetry.sdk.name—vestigtelemetry.sdk.version— current Vestig versiontelemetry.sdk.language—javascript
Backend-Specific Setup
Jaeger
Local development with Jaeger (default OTLP HTTP port):
Honeycomb
Grafana Cloud
Vercel
Vercel sets standard OpenTelemetry environment variables automatically:
Datadog
Axiom
SpanProcessor Interface
The OTLPExporter implements the SpanProcessor interface, which is how Vestig notifies external systems about span lifecycle events.
onStart— called when a span begins (optional, used for real-time streaming)onEnd— called when a span finishes (required, this is where batching exporters collect spans)forceFlush— send all buffered data immediatelyshutdown— flush remaining data and release resources
Creating a Custom Processor
Management Functions
Vestig provides global functions for managing all registered processors:
| Function | Description |
|---|---|
registerSpanProcessor(processor) |
Register a processor globally |
unregisterSpanProcessor(processor) |
Remove a registered processor |
getSpanProcessors() |
List all registered processors |
flushSpanProcessors() |
Flush all processors (send buffered data) |
shutdownSpanProcessors() |
Shutdown all processors (flush and release) |
All management functions are importable from vestig or vestig/otlp.
Graceful Shutdown
Always flush pending spans before your process exits. Undelivered spans in the buffer are lost if the process terminates without flushing.
For Next.js apps, place this in your instrumentation.ts:
Error Handling
Export failures throw OTLPExportError, which provides structured error details:
Properties
| Property | Type | Description |
|---|---|---|
statusCode |
number |
HTTP status code (0 for network errors) |
responseBody |
string | undefined |
Response body from the backend, if available |
cause |
Error | undefined |
Underlying error (e.g., network failure) |
Helper Getters
| Getter | Returns true when |
|---|---|
isNetworkError |
Status code is 0 (fetch failed entirely) |
isTimeout |
Status code is 408 (request timed out) |
isClientError |
Status code is 4xx (bad request, auth failure) |
isServerError |
Status code is 5xx (backend unavailable) |
isRetryable |
Network error, timeout, or server error |
The exporter automatically retries on retryable errors (network, timeout, 5xx) with exponential backoff. Client errors (4xx) are not retried since they indicate a configuration problem.
Advanced
Conversion Utilities
For advanced use cases, Vestig exports the low-level conversion functions used internally by the exporter:
toOTLPSpan(span, epochStartMs)— convert a Vestig Span to the OTLP wire formattoOTLPAttributes(attrs)— convert aRecord<string, unknown>to OTLP key-value pairstoOTLPAttributeValue(value)— convert a single value to an OTLP attribute valuetoOTLPStatusCode(status)— convert a Vestig span status to an OTLP status codemsToNano(ms)— convert milliseconds to nanosecond string (OTLP timestamp format)isoToNano(isoString)— convert an ISO date string to nanosecond string
OTLP Enums
Standard OTLP enums are available for building custom payloads:
Edge Compatibility
The OTLP exporter works on Edge runtimes — Cloudflare Workers, Vercel Edge Functions, Deno Deploy — because it relies solely on the fetch() API rather than Node.js-specific modules like http or net.
For Edge environments, consider smaller batch sizes and shorter flush intervals since Edge functions have shorter execution windows:
Related
- Tracing Overview — How tracing works in Vestig
- Spans — Deep dive into the Span API
- Context Propagation — AsyncLocalStorage-based context flow
- Instrumentation — Unified Next.js setup with registerVestig()
- Cloudflare & Edge — Edge runtime deployment guide