question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

ExceptionHandler silences printing of console errors?

See original GitHub issue

In my Winston logger I use an exceptionHandler so that the node exceptions/errors also reach my logs. I now have a problem though. When I run the script from the command line using node index.js (instead of pm2) the script ends silently when it has an error.

Have a look at my Winston implementation below. I added three console.log()s which try to log an undefined variable. When I run the script using node index.js it gives me a ReferenceError for the first wrong console.log(undefinedVariable) as expected. When I now remove that first and/or the second console.log, the script ends silently.

"use strict";

let winston = require('winston');
const path = require('path');

const PRODUCTION = false;

// LOGGING
const myFormat = winston.format.printf(info => {
    return `${info.timestamp} ${info.level}: ${info.message}`;
});

console.log(undefinedVariable);  // THIS GIVES A REFERENCE ERROR

const logger = winston.createLogger({
    level: 'debug',
    format: winston.format.combine(winston.format.timestamp(), myFormat),  // winston.format.json(),
    transports: [
        new winston.transports.File({filename: 'logs/error.log', level: 'error'}),
        new winston.transports.File({filename: 'logs/combined.log'}),
    ],
    exceptionHandlers: [
        new winston.transports.File({ filename: 'logs/exceptions.log' }),
        new winston.transports.File({ filename: 'logs/combined.log' })
    ]
});

console.log(undefinedVariable);  // THIS DOES NOT GIVE A REFERENCE ERROR, BUT ENDS THE SCRIPT SILENTLY

if (!PRODUCTION) {
    // If we're not in production then also log to the `console`
    logger.add(new winston.transports.Console(
        {format: winston.format.combine(winston.format.timestamp(), myFormat), level: 'debug'}
    ));
}

console.log(undefinedVariable);  // THIS ALSO DOES NOT GIVE A REFERENCE ERROR, BUT ENDS THE SCRIPT SILENTLY

function log(message, level='debug'){
    // Levels: error, warn, info, verbose, debug, silly
    const e = new Error();
    const regex = /\((.*):(\d+):(\d+)\)$/
    const match = regex.exec(e.stack.split("\n")[2]);
    let log_source = path.basename(match[1]) + ':' + match[2];  // eg: index.js:285

    if (typeof message === 'object'){
        message = JSON.stringify(message);
    }
    logger[level](log_source + ' - ' + message);
}

I’m running version 3.0.0-rc5on Ubuntu 18.04.

Does anybody know what I’m doing wrong here? All tips are welcome!

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Reactions:1
  • Comments:8 (6 by maintainers)

github_iconTop GitHub Comments

4reactions
JarrodHollingworthcommented, May 28, 2019

I think this needs more work.

I came across this same issue with winston logging stopping when there is an unhandled exception. I was using an earlier version so I updated to 3.2.1 to get fix #1355 but it still not working as expected. I found the following two issues through extensive debugging.

  1. The exception handling transport was stopping after logging the unhandled exception (exitOnError = false). This caused further logging to throw an exception which causes the process to exit: /winston/lib/winston/logger.js:309 throw ex; ^ Error: write after end at writeAfterEnd (/winston/node_modules/readable-stream/lib/_stream_writable.js:257:12)

This is caused by fix #1355 always setting transport._ending to true. As a work-around I changed it to assign doExit instead of true, but really the whole asyncForEach should probably not be run if doExit is false.

  1. The default logger instance (created anytime you require(‘winston’)) interferes if you also create your own (second) instance using winston.createLogger() with exitOnError = false, because the default instance defaults to exitOnError = true and also hooks process.on(‘uncaughtException’). My work-around was to use the default instance only and not create my own, by changing winston.createLogger() to winston.Configure() but you could probably just configure the default instance exitOnError = false and use your own instance.
3reactions
indexzerocommented, Jun 12, 2018

This is somewhat a duplicate of #1263, but there is more sublty. Look at this modification of your MWE (thanks for that btw):

let winston = require('winston');
const path = require('path');

const PRODUCTION = false;

// LOGGING
const myFormat = winston.format.printf(info => {
    return `${info.timestamp} ${info.level}: ${info.message}`;
});

//console.log(undefinedVariable);  // THIS GIVES A REFERENCE ERROR

const logger = winston.createLogger({
    level: 'debug',
    format: winston.format.combine(winston.format.timestamp(), myFormat),  // winston.format.json(),
    transports: [
        new winston.transports.File({filename: 'error.log', level: 'error'}),
        new winston.transports.File({filename: 'combined.log'}),
    ],
    exceptionHandlers: [
        new winston.transports.File({ filename: 'exceptions.log' }),
        new winston.transports.File({ filename: 'combined.log' })
    ]
});

// console.log(undefinedVariable);  // THIS DOES NOT GIVE A REFERENCE ERROR, BUT ENDS THE SCRIPT SILENTLY

if (!PRODUCTION) {
    // If we're not in production then also log to the `console`
    logger.add(new winston.transports.Console({
        format: winston.format.combine(winston.format.timestamp(), myFormat),
        level: 'debug',
        handleExceptions: true
    }));
}

setTimeout(() => {
    console.log(undefinedVariable);  // THIS ALSO DOES NOT GIVE A REFERENCE ERROR, BUT ENDS THE SCRIPT SILENTLY
}, 2000);

I’ve done two things:

  1. Make the Console transport you add as handleExceptions: true
  2. Wait briefly before causing a ReferenceError to allow for the files to open that you are logging to.

Now when I run this the log of the exception is written to all three locations (Console, combined.log and exceptions.log) as we expect. In other words:

  1. The silent Console is silent by design because you have explicitly said do not log exceptions to the console by not passing handleExceptions: true when you create your new Console transport instance.
  2. The silent File transports are silent because they do not hold open the process when it attempts exit after the ReferenceError. I believe @DABH is heading in the right direction with #1355 but I’d like to discuss it this week and not rush out a fix.

Thanks for all your help! We’re going to release 3.0.0 in a few hours, but the fix for this land in 3.0.1.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Why does Winstonjs ExceptionHandler silence my node errors?
I now have a problem though. When I run the script from the command line using node index. js (instead of pm2) the...
Read more >
try...catch - JavaScript - MDN Web Docs - Mozilla
A common use case for this is to only catch (and silence) a small subset of expected errors, and then re-throw the error...
Read more >
Error handling in R with tryCatchLog: Catching, logging, post ...
Easy logging of errors, warnings and messages into a file or console; Complete stack trace with references to the source file names and...
Read more >
8. Exception handling - Advance Python Tutorials
Exception handling is the process of handling the run time error. Error may occur due ... In the below code, the type of...
Read more >
Error Control Operators - Manual - PHP
Error suppression should be avoided if possible as it doesn't just suppress the error that you are trying to stop, but will also...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found