@primafuture/telemetry-otel-winston-transport
v0.3.1
Published
Winston transport that emits OpenTelemetry log records with high-resolution timestamps.
Maintainers
Readme
@primafuture/telemetry-otel-winston-transport
Winston transport that emits OpenTelemetry log records with explicit
high-resolution HrTime timestamps.
It is a small, explicit replacement for @opentelemetry/winston-transport when
you need Winston logs to align better with trace timelines.
Install
npm install @primafuture/telemetry-otel-winston-transportThe host application must also install and configure Winston and an OpenTelemetry Logs SDK pipeline.
Usage
Start OpenTelemetry before importing the real application and before creating the Winston logger. Then add this transport explicitly:
import winston from 'winston';
import { OpenTelemetryWinstonTransport } from '@primafuture/telemetry-otel-winston-transport';
const logger = winston.createLogger({
level: 'debug',
transports: [
new winston.transports.Console(),
new OpenTelemetryWinstonTransport(),
],
});
logger.info('Request handled', {
requestId: 'abc',
user: {
id: 'u1',
deletedAt: null,
},
});By default, metadata is encoded with the same structured metadata contract used
by @primafuture/telemetry-otel span attributes and span events:
app.value.requestId = "abc"
app.value.user.id = "u1"
app.type.user.deletedAt = "null"
app.meta.json = "{\"requestId\":\"abc\",\"user\":{\"id\":\"u1\",\"deletedAt\":null}}"The explicit telemetryTraceId, telemetrySpanId, and telemetryTraceFlags
metadata keys are used only to build the OTel log context. They are not exported
as application metadata.
Winston formats and OpenTelemetry Winston instrumentation can add technical
fields to the same info object as application metadata. This transport filters
timestamp, trace_id, span_id, and trace_flags before metadata encoding,
so they do not appear as app.value.* fields. Native OTel correlation fields are
still emitted on the log record itself.
When the host application also uses @primafuture/telemetry-otel, pass its
clock helper so traces and Winston logs use the same epoch anchor:
import { nowTelemetryHrTime } from '@primafuture/telemetry-otel';
import { OpenTelemetryWinstonTransport } from '@primafuture/telemetry-otel-winston-transport';
new OpenTelemetryWinstonTransport({
hrTimeProvider: nowTelemetryHrTime,
});Difference From @opentelemetry/winston-transport
The official transport emits an OTel log record without explicit timestamp and
observedTimestamp. The Logs SDK then fills both from Date.now(), which has
millisecond precision.
This transport sets both timestamps itself using an epoch HrTime built from:
Date.now()as the wall-clock anchorprocess.hrtime.bigint()as the high-resolution monotonic offset
It also attaches context.active() to the emitted OTel log record, so the Logs
SDK can resolve the active span context directly.
If traces and logs are produced by two different high-resolution helpers, each
helper has its own Date.now() anchor. Since Date.now() is millisecond based,
very close span events and log records can appear shifted by a fraction of a
millisecond. Use hrTimeProvider to share one clock with the tracing layer.
Auto-Instrumentation Warning
Do not use this transport together with automatic Winston log sending from
@opentelemetry/instrumentation-winston; that creates duplicate exported logs.
Recommended model:
- use
@opentelemetry/instrumentation-winstonfor trace correlation if needed - disable its automatic log sending
- add
OpenTelemetryWinstonTransportto your Winston logger manually
API
new OpenTelemetryWinstonTransport({
level: 'info',
loggerName: 'my-app-winston',
loggerVersion: '1.0.0',
hrTimeProvider: nowTelemetryHrTime,
structuredMetadata: {
flatten: {
enabled: true,
typeFields: 'when-needed',
},
json: {
enabled: true,
valueEncoding: 'typed',
},
raw: {
enabled: false,
},
},
});Options extend winston-transport options and add:
loggerName: OTel logger scope nameloggerVersion: OTel logger scope versionloggerOptions: OTel logger options, such asschemaUrlhrTimeProvider: optional shared OTelHrTimeproviderstructuredMetadata: optional metadata encoder config shared with the core telemetry package
Development
npm install
npm run typecheck
npm test
npm run build
npm run prepublishOnly