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

Enable a better unhandled exception experience #84

Closed
kenperkins opened this issue Jan 13, 2012 · 24 comments
Closed

Enable a better unhandled exception experience #84

kenperkins opened this issue Jan 13, 2012 · 24 comments
Labels
Feature Request Request for new functionality to support use cases not already covered

Comments

@kenperkins
Copy link
Contributor

tldr: Preserve formatting for handled exceptions in a transport when json=false.

Currently, at Clipboard.com we wrap all node applications in an upstart script that essentially ends up as:

/usr/local/bin/node $APP 1>>$LOGFILE 2>>$ERRORFILE

Combined with console.log and console.error, we're in a position to monitor for unhanded exceptions which are still human readable in the error log.

I've been evaluating winston, but I have one gripe re: error handling with unhanded exceptions.

Here's the output of a unhanded exception to the console:

node.js:201
    throw e; // process.nextTick error, or 'error' event on first tick
          ^
ReferenceError: x is not defined
    at Object.<anonymous> (/clipboard/src/node/winston-log.js:56:1)
    at Module._compile (module.js:432:26)
    at Object..js (module.js:450:10)
    at Module.load (module.js:351:31)
    at Function._load (module.js:310:12)
    at Array.0 (module.js:470:10)
    at EventEmitter._tickCallback (node.js:192:40)

When we catch this with stderr, it's nice and human readable. However, when we use Winston combined with a File transport and handled exceptions (with json=false) you get the following:

13 Jan 13:37:46 - error: uncaughtException pid=4874, uid=0, gid=0, cwd=/var/log/clipboard, execPath=/usr/local/bin/node, version=v0.6.5, argv=[node, /clipboard/src/node/winston-log.js], rss=12767232, heapTotal=7829952, heapUsed=3200976, loadavg=[0.6064453125, 0.48388671875, 0.4375], uptime=10935.226142303, trace=[column=1, file=/clipboard/src/node/winston-log.js, function=, line=56, method=null, native=false, column=26, file=module.js, function=Module._compile, line=432, method=_compile, native=false, column=10, file=module.js, function=Object..js, line=450, method=.js, native=false, column=31, file=module.js, function=Module.load, line=351, method=load, native=false, column=12, file=module.js, function=Function._load, line=310, method=_load, native=false, column=10, file=module.js, function=Array.0, line=470, method=0, native=false, column=40, file=node.js, function=EventEmitter._tickCallback, line=192, method=_tickCallback, native=false], stack=[ReferenceError: x is not defined,     at Object.<anonymous> (/clipboard/src/node/winston-log.js:56:1),     at Module._compile (module.js:432:26),     at Object..js (module.js:450:10),     at Module.load (module.js:351:31),     at Function._load (module.js:310:12),     at Array.0 (module.js:470:10),     at EventEmitter._tickCallback (node.js:192:40)]

Of course, this wraps on most consoles, and you end up with something to this effect:

13 Jan 13:37:46 - error: uncaughtException pid=4874, uid=0, gid=0, cwd=/var/log/clipboard, execPath=/usr/local/bin/node,
version=v0.6.5, argv=[node, /clipboard/src/node/winston-log.js], rss=12767232, heapTotal=7829952, heapUsed=3200976,
loadavg=[0.6064453125, 0.48388671875, 0.4375], uptime=10935.226142303, trace=[column=1,
file=/clipboard/src/node/winston-log.js, function=, line=56, method=null, native=false, column=26, file=module.js, 
function=Module._compile, line=432, method=_compile, native=false, column=10, file=module.js, function=Object..js,
line=450, method=.js, native=false, column=31, file=module.js, function=Module.load, line=351, method=load, native=false,
column=12, file=module.js, function=Function._load, line=310, method=_load, native=false, column=10, file=module.js,
function=Array.0, line=470, method=0, native=false, column=40, file=node.js, function=EventEmitter._tickCallback, line=192,
method=_tickCallback, native=false], stack=[ReferenceError: x is not defined,     at Object.<anonymous>
(/clipboard/src/node/winston-log.js:56:1),     at Module._compile (module.js:432:26),     at Object..js (module.js:450:10),     at
Module.load (module.js:351:31),     at Function._load (module.js:310:12),     at Array.0 (module.js:470:10),     at
EventEmitter._tickCallback (node.js:192:40)]

When we look at this output, it's exceptionally difficult to digest what's going on.

Link from IRC with some commentary: https://gist.github.com/1608837

@indexzero
Copy link
Member

You can set the json option on the console to get a JSON literal with stack trace

@kenperkins
Copy link
Contributor Author

But the json formatted exception is still not human consumable; in the log the json is a single line that is entirely un-consumable.

{"process":{"pid":4879,"uid":0,"gid":0,"cwd":"/var/log/clipboard","execPath":"/usr/local/bin/node","version":"v0.6.5","argv":["node","/clipboard/src/node/winston-log.js"],"memoryUsage":{"rss":12902400,"heapTotal":7829952,"heapUsed":3230752}},"os":{"loadavg":[0.33642578125,0.4287109375,0.42041015625],"uptime":10967.267525449},"trace":[{"column":1,"file":"/clipboard/src/node/winston-log.js","function":"","line":56,"method":null,"native":false},{"column":26,"file":"module.js","function":"Module._compile","line":432,"method":"_compile","native":false},{"column":10,"file":"module.js","function":"Object..js","line":450,"method":".js","native":false},{"column":31,"file":"module.js","function":"Module.load","line":351,"method":"load","native":false},{"column":12,"file":"module.js","function":"Function._load","line":310,"method":"_load","native":false},{"column":10,"file":"module.js","function":"Array.0","line":470,"method":"0","native":false},{"column":40,"file":"node.js","function":"EventEmitter._tickCallback","line":192,"method":"_tickCallback","native":false}],"stack":["ReferenceError: x is not defined","    at Object.<anonymous> (/clipboard/src/node/winston-log.js:56:1)","    at Module._compile (module.js:432:26)","    at Object..js (module.js:450:10)","    at Module.load (module.js:351:31)","    at Function._load (module.js:310:12)","    at Array.0 (module.js:470:10)","    at EventEmitter._tickCallback (node.js:192:40)"],"level":"error","message":"uncaughtException","timestamp":"13 Jan 13:38:18"}

Even beautified, the stacktrace is significantly harder to digest than the original exception.

{
    "process": {
        "pid": 4879,
        "uid": 0,
        "gid": 0,
        "cwd": "/var/log/clipboard",
        "execPath": "/usr/local/bin/node",
        "version": "v0.6.5",
        "argv": ["node", "/clipboard/src/node/winston-log.js"],
        "memoryUsage": {
            "rss": 12902400,
            "heapTotal": 7829952,
            "heapUsed": 3230752
        }
    },
    "os": {
        "loadavg": [0.33642578125, 0.4287109375, 0.42041015625],
        "uptime": 10967.267525449
    },
    "trace": [{
        "column": 1,
        "file": "/clipboard/src/node/winston-log.js",
        "function": "",
        "line": 56,
        "method": null,
        "native": false
    }, {
        "column": 26,
        "file": "module.js",
        "function": "Module._compile",
        "line": 432,
        "method": "_compile",
        "native": false
    }, {
        "column": 10,
        "file": "module.js",
        "function": "Object..js",
        "line": 450,
        "method": ".js",
        "native": false
    }, {
        "column": 31,
        "file": "module.js",
        "function": "Module.load",
        "line": 351,
        "method": "load",
        "native": false
    }, {
        "column": 12,
        "file": "module.js",
        "function": "Function._load",
        "line": 310,
        "method": "_load",
        "native": false
    }, {
        "column": 10,
        "file": "module.js",
        "function": "Array.0",
        "line": 470,
        "method": "0",
        "native": false
    }, {
        "column": 40,
        "file": "node.js",
        "function": "EventEmitter._tickCallback",
        "line": 192,
        "method": "_tickCallback",
        "native": false
    }],
    "stack": ["ReferenceError: x is not defined", "    at Object.<anonymous> (/clipboard/src/node/winston-log.js:56:1)", "    at Module._compile (module.js:432:26)", "    at Object..js (module.js:450:10)", "    at Module.load (module.js:351:31)", "    at Function._load (module.js:310:12)", "    at Array.0 (module.js:470:10)", "    at EventEmitter._tickCallback (node.js:192:40)"],
    "level": "error",
    "message": "uncaughtException",
    "timestamp": "13 Jan 13:38:18"
}

@indexzero
Copy link
Member

@kenperkins I'm open to suggestions here. Pull request?

@SeanBannister
Copy link
Contributor

One other slight disadvantage to setting json to true is you loose colorize on the console

@faridnsh
Copy link
Contributor

This might help, can have both colors and human readable. #109

@simonexmachina
Copy link

+1

1 similar comment
@jimthedev
Copy link

+1

@fizerkhan
Copy link

+1
Desperately needed.

@srlowe
Copy link

srlowe commented May 2, 2013

+1 This is currently my biggest gripe with winston. It makes diagnosing problems much slower and more painful than it should be.

srlowe added a commit to srlowe/winston that referenced this issue May 2, 2013
Simple hack I use to solve the problem described in 84.  I remove 'trace' completely from the meta info (seems to be it's duplicated in err.stack.  I also remove the split('\n') from err.stack, which causes the one line problem.
@srlowe
Copy link

srlowe commented May 2, 2013

I've added a pull request containing the simple hack I use to solve this problem myself (#245) I don't expect you to merge this as is, but perhaps people could try it and comment as to whether this is a suitable fix, and whether there are any side effects.

@mondalaci
Copy link

+1

@davidleureka
Copy link

It would really be nice to have stack traces that are easy to read.

@chrisspiegl
Copy link

+1

2 similar comments
@moxystudios
Copy link

+1

@eugeneiiim
Copy link

+1

@givan
Copy link

givan commented Feb 21, 2014

+1. I want to be able to set the logging level for the unhandled exceptions. Currently my transport is defined as:

new winston.transports.DailyRotateFile(
            { name: 'mainlog', level: "info", handleExceptions: true, filename: activeConfig.logger.main, maxsize: 107374182400, maxFiles: 10, datePattern: '.yyyy-MM-dd'}
        )

And the unhandled exceptions are logged at level info. I want them to be logged as level error.

@danielealbano
Copy link

+1

@eallegretta
Copy link

+1

1 similar comment
@callicles
Copy link

+1

@oojacoboo
Copy link
Contributor

Anything on this, been 2 years :(

@JohannesRudolph
Copy link

+1

@ykka
Copy link

ykka commented Dec 23, 2014

I've spent like 3 hours trying to figure it out... This pull request is going to be part of 0.9.0, whereas we got 0.8.x at the moment?

So... there is a solution where you use .cli() and colorize: true on your logger and it prints the stack (stacktrace) as last thing so it's easier to debug.

but yeah, +1 so badly.

@samejack
Copy link

use humanReadableUnhandledException:true config to fix it. as follows

{
      level: 'debug',
      humanReadableUnhandledException: true,
      handleExceptions: true,
      json: false,
      colorize: true
    }

@indexzero
Copy link
Member

Oh yeah, this is totally fixed. Thanks for the comment @samejack!

alandotcom pushed a commit to alandotcom/ripple-rest that referenced this issue Apr 9, 2015
Plenty of nice changes since 0.7

Highlights:

- Correctly log Error objects:
  winstonjs/winston@ad2d5e1

- Logging objects to file causes slowdown (we don't log to file in this
  project)
  winstonjs/winston@5c4bd41

- Better logging of unhandled exceptions
  winstonjs/winston#84
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Feature Request Request for new functionality to support use cases not already covered
Projects
None yet
Development

No branches or pull requests