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

Fix the Koa plugin suppressing other error handlers #1482

Merged
merged 12 commits into from
Jul 21, 2021
4 changes: 2 additions & 2 deletions .buildkite/node-pipeline.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ steps:
run: node-maze-runner
use-aliases: true
verbose: true
command: ["-e", "koa.feature", "-e", "koa-1x.feature", "-e", "koa_disabled.feature", "-e", "webpack.feature"]
command: ["-e", "koa.feature", "-e", "koa-1x.feature", "-e", "koa_disabled.feature", "-e", "koa-1x_disabled.feature", "-e", "webpack.feature"]
env:
NODE_VERSION: "4"

Expand All @@ -37,7 +37,7 @@ steps:
run: node-maze-runner
use-aliases: true
verbose: true
command: ["-e", "koa.feature", "-e", "koa-1x.feature", "-e", "koa_disabled.feature"]
command: ["-e", "koa.feature", "-e", "koa-1x.feature", "-e", "koa_disabled.feature", "-e", "koa-1x_disabled.feature"]
env:
NODE_VERSION: "6"

Expand Down
74 changes: 33 additions & 41 deletions packages/plugin-koa/src/koa.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,24 +27,7 @@ module.exports = {
event.addMetadata('request', metadata)
}, true)

if (!client._config.autoDetectErrors) return next()

try {
await next()
} catch (err) {
if (err.status === undefined || err.status >= 500) {
const event = client.Event.create(err, false, handledState, 'koa middleware', 1)
ctx.bugsnag._notify(event)
}
if (!ctx.response.headerSent) ctx.response.status = err.status || 500
try {
// this function will throw if you give it a non-error, but we still want
// to output that, so if it throws, pass it back what it threw (a TypeError)
ctx.app.onerror(err)
} catch (e) {
ctx.app.onerror(e)
}
}
await next()
}

requestHandler.v1 = function * (next) {
Expand All @@ -55,39 +38,48 @@ module.exports = {
this.bugsnag = requestClient

// extract request info and pass it to the relevant bugsnag properties
const { request, metadata } = getRequestAndMetadataFromCtx(this)
requestClient.addMetadata('request', metadata)
requestClient.addOnError((event) => {
const { request, metadata } = getRequestAndMetadataFromCtx(this)
event.request = { ...event.request, ...request }
requestClient.addMetadata('request', metadata)
}, true)

if (!client._config.autoDetectErrors) return next()

try {
yield next
} catch (err) {
if (err.status === undefined || err.status >= 500) {
const event = client.Event.create(err, false, handledState, 'koa middleware', 1)
this.bugsnag._notify(event)
}
if (!this.headerSent) this.status = err.status || 500
}
yield next
}

const errorHandler = (err, ctx) => {
if (!client._config.autoDetectErrors) return
// don't notify if "autoDetectErrors" is disabled OR the error was triggered
// by ctx.throw with a non 5xx status
const shouldNotify =
client._config.autoDetectErrors &&
(err.status === undefined || err.status >= 500)

if (shouldNotify) {
const event = client.Event.create(err, false, handledState, 'koa middleware', 1)

if (ctx.bugsnag) {
ctx.bugsnag._notify(event)
} else {
client._logger.warn('ctx.bugsnag is not defined. Make sure the @bugsnag/plugin-koa requestHandler middleware is added first.')

const event = client.Event.create(err, false, handledState, 'koa middleware', 1)
// the request metadata should be added by the requestHandler, but as there's
// no "ctx.bugsnag" we have to assume the requestHandler has not run
const { metadata, request } = getRequestAndMetadataFromCtx(ctx)
event.request = { ...event.request, ...request }
event.addMetadata('request', metadata)

client._notify(event)
}
}

const { metadata, request } = getRequestAndMetadataFromCtx(ctx)
event.request = { ...event.request, ...request }
event.addMetadata('request', metadata)
const app = ctx.app

if (ctx.bugsnag) {
ctx.bugsnag._notify(event)
} else {
client._logger.warn('ctx.bugsnag is not defined. Make sure the @bugsnag/plugin-koa requestHandler middleware is added first.')
client._notify(event)
// call Koa's built in onerror if we're the only registered error handler
// Koa will not add its own error handler if one has already been added,
// but we want to ensure the default handler still runs after adding Bugsnag
// unless another handler has also been added
if (app && typeof app.listenerCount === 'function' && app.listenerCount('error') === 1) {
app.onerror(err)
}
}

Expand Down
Loading