@provide-io/telemetry
v0.3.0
Published
Structured logging, OTEL traces/metrics for TypeScript frontends — parity with provide.telemetry Python package
Downloads
504
Maintainers
Readme
@provide-io/telemetry
Structured logging + OpenTelemetry traces and metrics for TypeScript — feature parity with the provide-telemetry Python package.
Install
npm install @provide-io/telemetryOptional OTEL peer dependencies
To export traces and metrics to an OTLP endpoint (e.g. OpenObserve, Jaeger, Tempo):
npm install \
@opentelemetry/sdk-trace-base \
@opentelemetry/sdk-metrics \
@opentelemetry/resources \
@opentelemetry/exporter-trace-otlp-http \
@opentelemetry/exporter-metrics-otlp-httpAll five are optional — the library degrades gracefully to no-op providers when they are absent.
Quick start
import { setupTelemetry, getConfig, getLogger, registerOtelProviders, shutdownTelemetry } from '@provide-io/telemetry';
// Call once at app startup.
setupTelemetry({
serviceName: 'my-app',
environment: 'production',
version: '1.0.0',
logLevel: 'info',
logFormat: 'json',
otelEnabled: true,
otlpEndpoint: 'http://localhost:4318',
otlpHeaders: { Authorization: 'Basic ...' },
});
// Activate OTLP exporters (requires peer deps above).
await registerOtelProviders(getConfig());
const log = getLogger('api');
log.info({ event: 'request.received.ok', method: 'GET', path: '/health', status: 200 });
// On shutdown — flushes and drains all OTel providers.
await shutdownTelemetry();API reference
Setup
| Export | Description |
|--------|-------------|
| setupTelemetry(config) | Configure the library. Idempotent — safe to call multiple times. |
| getConfig() | Return the current TelemetryConfig. |
| configFromEnv() | Build config from environment variables (see Configuration). |
| registerOtelProviders(cfg) | Wire OTLP trace + metrics exporters. Call after setupTelemetry. |
| shutdownTelemetry() | Flush and shut down all registered OTel providers. |
Logging
import { getLogger } from '@provide-io/telemetry';
const log = getLogger('my-module');
log.debug({ event: 'cache.miss.ok', key: 'user:42' });
log.info({ event: 'request.complete.ok', status: 200, duration_ms: 14 });
log.warn({ event: 'retry.attempt.warn', attempt: 2 });
log.error({ event: 'db.query.error', error: err.message });Event names follow the DA(R)S pattern: 3 segments (domain.action.status) or 4 segments (domain.action.resource.status).
Tracing
import { withTrace, getActiveTraceIds, setTraceContext } from '@provide-io/telemetry';
const result = await withTrace('my.operation.ok', async () => {
const { trace_id, span_id } = getActiveTraceIds();
// trace_id / span_id are available here and in any log emitted inside
return doWork();
});Metrics
import { counter, gauge, histogram } from '@provide-io/telemetry';
const requests = counter('http.requests', { unit: '1', description: 'Total HTTP requests' });
requests.add(1, { method: 'GET', status: '200' });
const latency = histogram('http.duration', { unit: 'ms' });
latency.record(42, { route: '/api/users' });Context binding
import { bindContext, runWithContext, clearContext } from '@provide-io/telemetry';
bindContext({ request_id: 'req-abc', user_id: 7 });
// All log calls in this async context will include these fields automatically.
clearContext();
// Scoped — context is automatically cleaned up after fn resolves.
await runWithContext({ trace_id: '...' }, async () => { /* ... */ });Session correlation
import { bindSessionContext, getSessionId, clearSessionContext } from '@provide-io/telemetry';
bindSessionContext('sess-abc-123');
// All logs and traces now include session_id automatically.
const sid = getSessionId(); // 'sess-abc-123'
clearSessionContext();Error fingerprinting
import { computeErrorFingerprint } from '@provide-io/telemetry';
try {
throw new Error('connection refused');
} catch (e) {
const err = e as Error;
const fp = computeErrorFingerprint(err.constructor.name, err.stack);
// fp: 12-char hex digest, stable across deploys — use for dedup and alert grouping.
}W3C trace propagation
import { extractW3cContext, bindPropagationContext } from '@provide-io/telemetry';
// In an HTTP handler — extract incoming traceparent/tracestate.
const ctx = extractW3cContext(req.headers);
bindPropagationContext(ctx);PII sanitization
import { sanitize, registerPiiRule } from '@provide-io/telemetry';
// Built-in: redacts password, token, secret, authorization, api_key, ...
const obj = { user: 'alice', password: 'hunter2' }; // pragma: allowlist secret
sanitize(obj);
// obj is now { user: 'alice', password: '[REDACTED]' }
// Custom rule (dot-separated path; '*' as wildcard segment)
registerPiiRule({ path: 'user.ssn', mode: 'redact' });Health snapshot
import { getHealthSnapshot } from '@provide-io/telemetry';
const snap = getHealthSnapshot();
// snap.exportFailuresLogs, snap.tracesDropped, ...React integration
Requires React 18+ as a peer dependency.
import { useTelemetryContext, TelemetryErrorBoundary } from '@provide-io/telemetry/react';useTelemetryContext(values)
Binds key/value pairs into telemetry context for the lifetime of a component. Automatically cleans up on unmount and re-runs when values change (compared by content, not reference).
function UserDashboard({ userId }: { userId: string }) {
useTelemetryContext({ user_id: userId, page: 'dashboard' });
return <Dashboard />;
}TelemetryErrorBoundary
React error boundary that auto-logs caught render errors via getLogger('react.error_boundary'). Accepts a static fallback or a render-prop receiving the error and a reset callback.
<TelemetryErrorBoundary
fallback={(error, reset) => <ErrorPage error={error} onRetry={reset} />}
onError={(error, info) => reportToSentry(error, info)}
>
<App />
</TelemetryErrorBoundary>Browser support
The library is browser-compatible via conditional exports. OpenTelemetry providers become no-ops in browser environments, so no server-only imports leak into client bundles. No polyfills are required for modern browsers (ES2020+).
Browser-specific options in setupTelemetry():
| Option | Effect |
|--------|--------|
| captureToWindow: true | Buffers structured logs to window.__pinoLogs for devtools inspection |
| consoleOutput: true | Mirrors log output to console.debug / console.log / console.warn / console.error |
Configuration
All options can be set programmatically via setupTelemetry() or via environment variables:
| Env var | Default | Description |
|---------|---------|-------------|
| PROVIDE_TELEMETRY_SERVICE_NAME | provide-service | Service identity |
| PROVIDE_TELEMETRY_ENV | development | Deployment environment (fallback: PROVIDE_ENV) |
| PROVIDE_TELEMETRY_VERSION | unknown | Service version (fallback: PROVIDE_VERSION) |
| PROVIDE_LOG_LEVEL | info | Log level: debug / info / warn / error |
| PROVIDE_LOG_FORMAT | json | Output format: json / pretty |
| PROVIDE_TRACE_ENABLED | false | Enable OTLP export |
| OTEL_EXPORTER_OTLP_ENDPOINT | http://localhost:4318 | OTLP base endpoint |
| OTEL_EXPORTER_OTLP_HEADERS | — | Comma-separated key=value auth headers |
Pretty renderer
Set logFormat: 'pretty' (or PROVIDE_LOG_FORMAT=pretty) for human-readable colored output during local development. Color support respects FORCE_COLOR and NO_COLOR environment variables.
setupTelemetry({ logFormat: 'pretty' });Requirements
- Node.js ≥ 18
- TypeScript ≥ 5 (built with TypeScript 6)
License
Apache-2.0. See LICENSE.
