Koa
Learn about using Sentry with Koa.
Add @sentry/node
as a dependency:
Copied
npm install --save @sentry/node @sentry/utils
Initialize the Sentry SDK and install the on error hook:
Copied
import Koa from 'koa';
import * as Sentry from '@sentry/node';
// or using CommonJS
// const Koa = require('koa');
// const Sentry = require('@sentry/node');
const app = new Koa();
Sentry.init({dsn: 'https://examplePublicKey@o0.ingest.sentry.io/0'});
app.on('error', (err, ctx) => {
Sentry.withScope(scope => {
scope.setSDKProcessingMetadata({request: ctx.request});
Sentry.captureException(err);
});
});
app.listen(3000);
Create and attach a transaction to each request:
Copied
const Sentry = require('@sentry/node');
const {stripUrlQueryAndFragment} = require('@sentry/utils');
const Koa = require('koa');
const app = new Koa();
Sentry.init({
dsn: 'https://examplePublicKey@o0.ingest.sentry.io/0',
// We recommend adjusting this value in production, or using tracesSampler
// for finer control
tracesSampleRate: 1.0,
integrations: [
// Automatically instrument Node.js libraries and frameworks
...Sentry.autoDiscoverNodePerformanceMonitoringIntegrations(),
],
});
const requestHandler = (ctx, next) => {
Sentry.runWithAsyncContext(() => {
const scope = Sentry.getCurrentScope();
scope.addEventProcessor(event =>
Sentry.addRequestDataToEvent(event, ctx.request, {
include: {
user: false,
},
})
);
next();
});
};
// this tracing middleware creates a transaction per request
const tracingMiddleWare = (ctx, next) => {
const reqMethod = (ctx.method || '').toUpperCase();
const reqUrl = ctx.url && stripUrlQueryAndFragment(ctx.url);
// connect to trace of upstream app
let traceparentData;
if (ctx.request.get('sentry-trace')) {
traceparentData = Sentry.extractTraceparentData(ctx.request.get('sentry-trace'));
}
const transaction = Sentry.startTransaction({
name: `${reqMethod} ${reqUrl}`,
op: 'http.server',
...traceparentData,
});
ctx.__sentry_transaction = transaction;
// We put the transaction on the scope so users can attach children to it
Sentry.getCurrentScope().setSpan(transaction);
ctx.res.on('finish', () => {
// Push `transaction.finish` to the next event loop so open spans have a chance to finish before the transaction closes
setImmediate(() => {
// if using koa router, a nicer way to capture transaction using the matched route
if (ctx._matchedRoute) {
const mountPath = ctx.mountPath || '';
transaction.setName(`${reqMethod} ${mountPath}${ctx._matchedRoute}`);
}
transaction.setHttpStatus(ctx.status);
transaction.finish();
});
});
next();
};
app.use(requestHandler);
app.use(tracingMiddleWare);
// usual error handler
app.on('error', (err, ctx) => {
Sentry.withScope(scope => {
scope.addEventProcessor(event => {
return Sentry.addRequestDataToEvent(event, ctx.request);
});
Sentry.captureException(err);
});
});
// the rest of your app
The following example creates a span for a part of the code that contains an expensive operation and sends the result to Sentry. You will need to use the transaction stored in the context.
Copied
const myMiddleware = async (ctx, next) => {
let span;
const transaction = ctx.__sentry_transaction;
if (transaction) {
span = transaction.startChild({
description: route,
op: 'myMiddleware',
});
}
await myExpensiveOperation();
if (span) {
span.finish();
}
return next();
};
Help improve this content
Our documentation is open source and available on GitHub. Your contributions are welcome, whether fixing a typo (drat!) or suggesting an update ("yeah, this would be better").
Our documentation is open source and available on GitHub. Your contributions are welcome, whether fixing a typo (drat!) or suggesting an update ("yeah, this would be better").