googleapis / nodejs-logging-winston

Node.js client integration between Stackdriver Logging and Winston.
https://cloud.google.com/logging/
Apache License 2.0
105 stars 50 forks source link

How to format an error as Error? #754

Open christian-schwaderer opened 1 year ago

christian-schwaderer commented 1 year ago

My goal is that each time I call logger.error with whatever content an entry in Error Reporting is created.

However, that doesn't work. Only some errors make it to the Error Reporting, some others appear well in the logs, but not in Error Reporting.

I've read the "Error Reporting" paragraph in the docs. But, still, I don't get it.

  1. How do you pass an Error object? Tried like Object.assign(info, { message: new Error(info.message) }); - but without luck so far.
  2. What is the expected content of service and version? I've set a random string in service and left version aside.
  3. What else am I missing?

Here's my complete config:

import winston from 'winston';
import { LoggingWinston } from '@google-cloud/logging-winston';
import compact from 'lodash/compact';

const loggingWinston = new LoggingWinston({ serviceContext: {  service: `some-random-string-here` } });

const formatErrorsAsError = winston.format((info) => {
  if (info.level === 'error') {
    Object.assign(info, { message: new Error(info.message) });
  }
  return info;
});

const logger = winston.createLogger({
  level: vars.env === 'development' ? 'debug' : 'info',
  format: winston.format.combine(
    formatErrorsAsError(),
    vars.env === 'development'
      ? winston.format.colorize()
      : winston.format.uncolorize(),
    winston.format.splat(),
    winston.format.printf(({ level, message }) => `${level}: ${message}`),
  ),
  transports: compact([
    new winston.transports.Console({
      stderrLevels: ['error'],
    }),
    vars.env !== 'development' && loggingWinston,
  ]),
});
losalex commented 1 year ago

Thanks @christian-schwaderer for opening the issue! Can you please also share the way you log errors?

christian-schwaderer commented 1 year ago

Sorry, I don't get what you mean exactly. If I call logger.error("whatever") I want that whatever appears in the error reporting as a new error group - whatever being any arbitrary string which I consider to be worth treating as an "error" based on the business logic of my application.

losalex commented 1 year ago

Thanks @christian-schwaderer for clarification - I just wanted to make sure you call logger.error API. Reading error-reporting info, it seems you need to add both, service and version. Did you tried adding any random version to serviceContext just to see it works, e.g. 1.0.0? I believe this link should also be helpful - please let me know if this is something you would be able to use and if you have any questions.

christian-schwaderer commented 1 year ago

Thanks for that link. The information given there was, however, not entirely new to me. I knew that somehow I need to format my string as an Error. The question I had was rather how to achieve that formatting. So, after a lot of experimenting I ended up with.

Object.assign(info, { message: `${info.message}${(new Error()).stack}` });

But that feels somewhat hacky. If this is really the way to go it might be a good idea to add that to the documentation with a few words of explanation why it should be done like this. I don't think I'm the first one to run into that problem.

I did not find out how the manipulate the @type property in Winston.

losalex commented 1 year ago

I see, thanks for letting me know @christian-schwaderer! Indeed, the workaround you are using seems to me as the only option for now (given also fact that adding @type field indeed tricky). It seems that Error Reporting inspects the payload and only picks entries which look like an error - in order to be able to propagate even business related errors we might need to implement a feature for this. I am talking to Error Reporting team now to understand if this feature could be implemented and will update on the progress. As of now, I am turning this work item to be a feature request.