@crossdelta/telemetry
v0.5.2
Published
OpenTelemetry instrumentation for CrossDelta services
Maintainers
Readme
@crossdelta/telemetry
Zero-config OpenTelemetry instrumentation for TypeScript services.
Import once, get automatic tracing, metrics, and logs — configured entirely via environment variables.
┌─────────────────┐ OTLP/HTTP ┌──────────────────┐
│ Your Service │ ───── traces ───► │ Grafana Cloud │
│ │ ───── metrics ──► │ Better Stack │
│ │ ───── logs ─────► │ Jaeger, etc. │
└─────────────────┘ └──────────────────┘Why this library?
Setting up OpenTelemetry is tedious: SDK initialization, exporter configuration, instrumentation setup, graceful shutdown handling...
| Feature | Benefit |
|---------|---------|
| 🚀 Zero config | Just import — reads OTEL_* env vars automatically |
| 🔌 Selective instrumentation | HTTP, Express, and Pino instrumented under Node.js |
| 📊 Traces + Metrics + Logs | All three signals configured in one import |
| 📝 Pino log forwarding | Pino logs automatically sent to OTLP via PinoInstrumentation (Node.js) |
| 💬 Console capture | console.log/warn/error forwarded as OTEL LogRecords (all runtimes) |
| 🛑 Graceful shutdown | Flushes telemetry on SIGTERM/SIGINT |
| 🏃 Multi-runtime | Node.js (full instrumentation) and Bun (console log forwarding) |
Installation
bun add @crossdelta/telemetry
# or
npm install @crossdelta/telemetryGetting Started
1. Add the import (first line!)
// src/index.ts
import '@crossdelta/telemetry' // ← MUST be first!
import { Hono } from 'hono'
// ... rest of your code⚠️ Important: The import must come before any other imports to properly patch modules (especially Pino).
2. Set environment variables
# Service identification
OTEL_SERVICE_NAME=my-service
OTEL_RESOURCE_ATTRIBUTES=service.name=my-service,deployment.environment=production
# Traces endpoint
OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=https://otlp-gateway.grafana.net/otlp/v1/traces
# Metrics endpoint (optional)
OTEL_EXPORTER_OTLP_METRICS_ENDPOINT=https://otlp-gateway.grafana.net/otlp/v1/metrics
# Logs endpoint (optional — enables pino + console forwarding)
OTEL_EXPORTER_OTLP_LOGS_ENDPOINT=https://otlp-gateway.grafana.net/otlp/v1/logs
# Shared auth header for all signals
OTEL_EXPORTER_OTLP_HEADERS=Authorization=Basic base64(instanceId:apiKey)3. That's it!
Your service now exports traces, metrics, and logs. You'll see:
✅ OpenTelemetry initialized for my-serviceIf no OTEL_EXPORTER_OTLP_TRACES_ENDPOINT or OTEL_EXPORTER_OTLP_LOGS_ENDPOINT is set, telemetry is disabled:
ℹ️ OpenTelemetry not configured (no OTEL_EXPORTER_OTLP_TRACES_ENDPOINT)How Logs Work
Logs are captured through two mechanisms:
Pino (Node.js services via
nestjs-pino):@opentelemetry/instrumentation-pinointercepts pino's output viapino.multistreamand sends log records to the OTEL Logs API. Logs still appear on stdout as usual.Console (all runtimes):
console.log/info/warn/error/debugare patched to emit OTEL LogRecords alongside their normal stdout output.
Both paths use BatchLogRecordProcessor → OTLPLogExporter → your configured logs endpoint.
Runtime Support
| Feature | Node.js | Bun | |---------|---------|-----| | Console log forwarding | ✅ | ✅ | | Pino log forwarding | ✅ | ❌ (no require hooks) | | HTTP tracing | ✅ | ❌ (no require hooks) | | Express/NestJS tracing | ✅ | ❌ (no require hooks) | | Metrics export | ✅ | ✅ | | Graceful shutdown | ✅ | ✅ |
Bun services (Hono) get log forwarding and metrics. Full instrumentation (traces, pino) requires Node.js.
Instrumentations (Node.js only)
| Package | What it captures |
|---------|-----------------|
| @opentelemetry/instrumentation-http | Incoming/outgoing HTTP requests |
| @opentelemetry/instrumentation-express | Express/NestJS route spans |
| @opentelemetry/instrumentation-pino | Pino log records → OTEL Logs API |
Advanced Usage
For custom configuration, use initTelemetry() instead of the side-effect import:
import { initTelemetry } from '@crossdelta/telemetry'
initTelemetry({
// Custom metrics export interval (default: 60s)
metricsIntervalMs: 30_000,
// Custom shutdown handler
onShutdown: async () => {
await myDatabase.close()
},
})Supported Backends
Any OTLP-compatible backend works:
- Grafana Cloud (Tempo, Mimir, Loki)
- Better Stack
- Jaeger
- Honeycomb
- Datadog
- New Relic
API Reference
initTelemetry(config?)
Initialize the OpenTelemetry SDK manually.
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| metricsIntervalMs | number | 60000 | Metrics export interval |
| onShutdown | () => Promise<void> | - | Custom shutdown handler |
Returns true if initialized, false if already initialized or not configured.
getSDK()
Returns the current NodeSDK instance (or null if not initialized).
shutdownTelemetry()
Flush all pending telemetry data and shut down the SDK.
Infrastructure
OTEL environment variables are automatically injected by @crossdelta/infrastructure via buildOtelEnv(). See the infra config for endpoint configuration (Pulumi secrets).
License
MIT © crossdelta
