Skip to content

[Bug]: winston.loggers.get is winston.loggers.add #2580

@bengsparks

Description

@bengsparks

🔎 Search Terms

loggers get add same identical defaultMeta

The problem

Preamble

Preconfiguring loggers is a good thing, as it allows logging to be more uniform, with labels, level, metadata and more being configurable.
The docs agree with this, referencing both loggers.get and loggers.add to flexibly configure multiple loggers.
What they fail to mention is that winston.loggers.get is defined to do only winston.loggers.add, meaning they are the same!

return this.add(id, options);

Problem

This leads to confusing bugs, where the options parameter has been specified in a call to get, in a misguided attempt to extend the preconfigured logger, is not applied. See the first MRE below for an example with defaultMeta.
Moving defaultMeta to the add command works, and so does forgoing the add call, and just calling get (see further MREs below)

Solutions

  1. rename get to getOrCreate, and update the docs to show that the specified options will only be used if the requested logger does not exist yet.
  2. Keep get and make it return winston.Logger | undefined, and implement a separate getOrCreate that returns winston.Logger.
  3. make get return winston.Logger | undefined, and add an winston.Logger.extendBy method to implement config merging to tweak configured loggers for that scope, and don't add that one to the registry

What version of Winston presents the issue?

v3.11.0

What version of Node are you using?

v22.16.0

If this worked in a previous version of Winston, which was it?

No response

Minimum Working Example

import { format, loggers, transports } from 'winston';

const KEY = 'main';
loggers.add(KEY, {
  transports: new transports.Console({ format: format.metadata() }),
});
const logger = loggers.get(KEY, {
  defaultMeta: { example: 'Hello World' }, // <-- trying to extend config
});
logger.info('lets go!');
$ yarn run play 
{"level":"info","message":"lets go!"}    # <-- no metadata!

Moving defaultMeta to the add command works

import { format, loggers, transports } from 'winston';

const KEY = 'main';
loggers.add(KEY, {
  transports: new transports.Console({ format: format.metadata() }),
  defaultMeta: { example: 'Hello World' }, // <-- hardcoded config
});
const logger = loggers.get(KEY);
logger.info('lets go!');
$ yarn run play                  
{"example":"Hello World","level":"info","message":"lets go!"}

As does forgoing the add, and just doing get.

import { format, loggers, transports } from 'winston';

const KEY = 'main';
const logger = loggers.get(KEY, {
  transports: new transports.Console({ format: format.metadata() }),
  defaultMeta: { example: 'Hello World' },
});
logger.info('lets go!');
$ yarn run play                  
{"example":"Hello World","level":"info","message":"lets go!"}

Additional information

No response

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions