Skip to content

[instrumentation-winston] May duplicate transport (and logs) without notice #2283

@falsyvalues

Description

@falsyvalues

What version of OpenTelemetry are you using?

    "@opentelemetry/api": "^1.8.0",
    "@opentelemetry/api-logs": "^0.51.1",
    "@opentelemetry/auto-instrumentations-node": "^0.46.0",
    "@opentelemetry/winston-transport": "^0.3.0",

What version of Node are you using?

node --version
v18.20.3

What did you do?

I found an issue while testing instrumentation-winston which may lead to duplicated logs (via duplicated transports).
To have logger working with logs exporter we may be tempted to follow [winston-transport/README.md#usage] (https://github.com/open-telemetry/opentelemetry-js-contrib/blob/main/packages/winston-transport/README.md#usage) guide, extended with exporter configuration (posted also in #2090) e.g.

import * as api from "@opentelemetry/api-logs";
import { OTLPLogExporter } from "@opentelemetry/exporter-logs-otlp-http";
import {
  detectResourcesSync,
  envDetectorSync,
  hostDetectorSync,
  processDetectorSync,
} from "@opentelemetry/resources";
import {
  BatchLogRecordProcessor,
  LoggerProvider
} from "@opentelemetry/sdk-logs";
import { OpenTelemetryTransportV3 } from "@opentelemetry/winston-transport";

import * as winston from "winston";

const logExporter = new OTLPLogExporter();
const loggerProvider = new LoggerProvider({
  resource: detectResourcesSync({
    detectors: [envDetectorSync, processDetectorSync, hostDetectorSync],
  }),
});

loggerProvider.addLogRecordProcessor(
  new BatchLogRecordProcessor(logExporter)
);
api.logs.setGlobalLoggerProvider(loggerProvider);

export const logger = winston.createLogger({
  level: "info",
  transports: [
    new winston.transports.Console(),
    new OpenTelemetryTransportV3(),
  ],
});

logger.info('Hello world');

And that will already cause a problem combined with instrumentation-winston because transport aren't deduplicated and instrumentation.ts#L220 adds it without deduplication even if transport is already there. Which in the end leads to duplicated logs in collector / APM.

What did you expect to see?

I expect that I won't have duplicated logs at the end.

What did you see instead?

I observed duplicated logs because instrumentation added another OpenTelemetryTransportV3 to list of transports in winston instance.

Additional context

Instrumentation code that adds transport:

const openTelemetryTransport = new OpenTelemetryTransportV3(
  transportOptions
);
if (originalTransports && !Array.isArray(originalTransports)) {
  newTransports = [originalTransports];
}
newTransports.push(openTelemetryTransport);
args[0].transports = newTransports;

instrumentation.ts#L220

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions