OpenTelemetry#
Distributed tracing with per-request spans following HTTP semantic conventions. All telemetry dependencies are lazily imported — zero startup cost until the plugin is installed.
Installation#
bash
bun add @opentelemetry/apiQuick Start#
typescript
import { otelPlugin } from "@buntok/core/plugins/opentelemetry";
app.plugin(otelPlugin({
serviceName: "my-api",
exporter: "console", // logs traces to console
}));Options#
| Option | Type | Default | Description |
|---|---|---|---|
| serviceName | string | — | Required. Service name for trace identification. |
| serviceVersion | string | — | Service version. |
| exporter | "console" | "otlp" | "console" | Trace exporter. |
| otlpEndpoint | string | "http://localhost:4318" | OTLP endpoint URL (only for "otlp"). |
| sampler | "alwaysOn" | "alwaysOff" | "traceIdRatioBased" | "alwaysOn" | Sampling strategy. |
| sampleRate | number | 1 | Sample ratio (0–1), only for "traceIdRatioBased". |
What It Does#
- Initializes OpenTelemetry SDK with your service name
- Registers global middleware that creates a span per request
- Records HTTP semantic attributes:
http.request.method(GET, POST, etc.)url.full(full request URL)http.response.status_code(200, 404, etc.)
- Sets span status OK/Error based on response status (2xx = OK, 4xx/5xx = ERROR)
- Records exceptions on error (stack trace captured)
- Graceful shutdown on
SIGTERM/SIGINT— flushes remaining spans
OTLP Exporter (Production)#
For production, send traces to a collector (Jaeger, Grafana Tempo, Honeycomb, etc.):
typescript
app.plugin(otelPlugin({
serviceName: "my-api",
exporter: "otlp",
otlpEndpoint: "http://localhost:4318",
sampler: "traceIdRatioBased",
sampleRate: 0.1, // sample 10% of requests
}));Console Exporter (Development)#
Logs traces to console — useful for debugging:
typescript
app.plugin(otelPlugin({
serviceName: "my-api",
exporter: "console",
}));Sampling Strategies#
| Strategy | Description | Use Case |
|---|---|---|
| "alwaysOn" | Record all requests | Development, low traffic |
| "alwaysOff" | Record no requests | Disable tracing |
| "traceIdRatioBased" | Sample sampleRate % of requests | Production (reduce overhead) |
Span Lifecycle#
typescript
Request arrives
→ span starts (method, url)
→ handler runs
→ response sent
→ span ends (status code, duration)
→ span exported to collectorWhat Gets Traced#
- Every HTTP request to any route
- Request method and URL
- Response status code
- Duration (start → end)
- Errors and exceptions
Info
Dependencies are lazily imported. No
@opentelemetry/api code runs until the plugin is installed via app.plugin().