Mailspring/src/task-bootstrap.coffee
Evan Morikawa d4db0737cf feat(error): improve error reporting. Now NylasEnv.reportError
Summary:
The goal is to let us see what plugins are throwing errors on Sentry.

We are using a Sentry `tag` to identify and group plugins and their
errors.

Along the way, I cleaned up the error catching and reporting system. There
was a lot of duplicate error logic (that wasn't always right) and some
legacy Atom error handling.

Now, if you catch an error that we should report (like when handling
extensions), call `NylasEnv.reportError`. This used to be called
`emitError` but I changed it to `reportError` to be consistent with the
ErrorReporter and be a bit more indicative of what it does.

In the production version, the `ErrorLogger` will forward the request to
the `nylas-private-error-reporter` which will report to Sentry.

The `reportError` function also now inspects the stack to determine which
plugin(s) it came from. These are passed along to Sentry.

I also cleaned up the `console.log` and `console.error` code. We were
logging errors multiple times making the console confusing to read. Worse
is that we were logging the `error` object, which would print not the
stack of the actual error, but rather the stack of where the console.error
was logged from. Printing `error.stack` instead shows much more accurate
stack traces.

See changes in the Edgehill repo here: 8c4a86eb7e

Test Plan: Manual

Reviewers: juan, bengotow

Reviewed By: bengotow

Differential Revision: https://phab.nylas.com/D2509
2016-02-03 18:06:52 -05:00

56 lines
1.5 KiB
CoffeeScript

{userAgent, taskPath} = process.env
handler = null
setupGlobals = ->
global.attachEvent = ->
console =
warn: -> emit 'task:warn', arguments...
log: -> emit 'task:log', arguments...
error: -> emit 'task:error', arguments...
trace: ->
global.__defineGetter__ 'console', -> console
global.document =
createElement: ->
setAttribute: ->
getElementsByTagName: -> []
appendChild: ->
documentElement:
insertBefore: ->
removeChild: ->
getElementById: -> {}
createComment: -> {}
createDocumentFragment: -> {}
global.emit = (event, args...) ->
process.send({event, args})
global.navigator = {userAgent}
global.window = global
handleEvents = ->
process.on 'unhandledRejection', (reason, promise) ->
console.error(reason.stack, promise)
process.on 'uncaughtException', (error) ->
console.error(error.message, error.stack)
process.on 'message', ({event, args}={}) ->
return unless event is 'start'
isAsync = false
async = ->
isAsync = true
(result) ->
emit('task:completed', result)
result = handler.bind({async})(args...)
emit('task:completed', result) unless isAsync
setupDeprecations = ->
Grim = require 'grim'
Grim.on 'updated', ->
deprecations = Grim.getDeprecations().map (deprecation) -> deprecation.serialize()
Grim.clearDeprecations()
emit('task:deprecations', deprecations)
setupGlobals()
handleEvents()
setupDeprecations()
handler = require(taskPath)