Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Weird bug or inconsistency in Error object handling #1959

Open
1 of 2 tasks
enunez opened this issue Oct 23, 2021 · 4 comments
Open
1 of 2 tasks

Weird bug or inconsistency in Error object handling #1959

enunez opened this issue Oct 23, 2021 · 4 comments

Comments

@enunez
Copy link

enunez commented Oct 23, 2021

Please tell us about your environment:

  • winston version?
    • winston@2
    • winston@3 3.3.3
  • node -v outputs: v16.11.1
  • Operating System? Windows
  • Language? ES6/7

What is the problem?

import winston from 'winston';

const logger1 = winston.createLogger({
  transports: [
    new winston.transports.Console({
      level: 'info',
      format: winston.format.simple(),
    }),
  ],
});
logger1.error(new Error('uh oh')); // prints undefined

const logger2 = winston.createLogger({
  level: 'info',
  format: winston.format.simple(),
  transports: [new winston.transports.Console()],
});
logger2.error(new Error('uh oh')); // prints 'uh oh'

Output:

error: undefined
error: uh oh

What do you expect to happen instead?

I expect them to both print the uh oh message from the Error object.

Not sure if this is a bug or expected behavior, but it's very unintuitive. If I'm misusing the first construct in some way, then it should fail completely, not just fail when it's printing out Error objects.

I'm trying to pass Error objects directly to logger.error(), and I'd like the message to be automatically parsed and printed. But I want the formatting to be different when printing to console versus writing to log file. With the 1st construct, that would've been easy to do. With the 2nd construct, where the format specification is OUTSIDE the transport definition, I'm not exactly sure how to format the output differently for different (file) transports.

@DiniFarb
Copy link

Hi @enunez

There was already a long discuss about this issue see here.

In my understandig you sholud use winston.format.errors if you want to use a Error Object directly like:

const logger1 = winston.createLogger({
  format: winston.format.errors({ message: true }),
  transports: [
    new winston.transports.Console({
      level: "info",
      format: winston.format.simple(),
    }),
  ],
});
logger1.error(new Error("uh oh"));

const logger2 = winston.createLogger({
  level: "info",
  format: winston.format.combine(
    winston.format.simple(),
    winston.format.errors({ message: true })
  ),
  transports: [new winston.transports.Console()],
});
logger2.error(new Error("uh oh"));

But I would suggest you anyway to just use one logger and create multiple transports here a example:

const logger = winston.createLogger({
  format: winston.format.errors({ message: true }),
  transports: [
    new winston.transports.File({
      filename: "error.log",
      level: "error",
      format: winston.format.combine(
        winston.format.timestamp({ format: "YYYY-MM-DD HH:mm:ss:ms" }),
        winston.format.printf(
          (info) => `${info.timestamp} ${info.level}: ${info.message}`
        )
      ),
    }),
    new winston.transports.Console({
      level: "info",
      format: winston.format.combine(
        winston.format.colorize(),
        winston.format.simple()
      ),
    }),
  ],
});

logger.info("Some Info");
logger.warn("Warning!");
logger.error(new Error("OH no !!"));
``

@enunez
Copy link
Author

enunez commented Oct 29, 2021

format: winston.format.errors({ message: true }),

@andreasvogt89 Oh wow, thank you for this solution! That's way better than the hack workaround I was using. 🤢 Where is this { message: true } format option even documented? And, just out of curiosity, why is that format option ignored when included in the individual transport definitions? For instance:

const logger = winston.createLogger({
  transports: [
    new winston.transports.Console({
      level: "info",
      format: winston.format.combine(
        winston.format.errors({ message: true }),
        winston.format.colorize(),
        winston.format.simple()
      ),
    }),
  ],
});
logger.error(new Error("OH no !!"));  // prints undefined

Even more confusing, both of these options also work to produce the error message:

format: winston.format.errors({ message: false }),
format: winston.format.errors(),

🥴

@DiniFarb
Copy link

Yes it is very confusing, i thought that message: true would exists since it has the option stack: true.

Sorry my bad, Meanwhile I found some docs here
It looks like that the only option which can be made is indeed for the stack-trace to be displayed or not.

And yes it looks like it does only work in the main format option and not on the individual transports.. 😐

@paul-uz
Copy link

paul-uz commented May 31, 2024

Just ran into this issue. Documentation really needs to be updated and better examples provides.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants