strapi-plugin-sentry
does not include the tracing/performance functionality, but this can be added by adding a middelware with the code provided in the Strapi Koa documentation (https://docs.sentry.io/platforms/node/guides/koa/#monitor-performance).
Before beginning make sure that you installed strapi-plugin-sentry
and that it works (i.e. it logs the errors inside of the Sentry dashboard).
Create a middelware, but don't call it sentry
, because there may be a problem with the plugin. I called mine stracing
.
Inside of ./middlewares/stracing/index.js
:
const {
extractTraceparentData,
Span,
stripUrlQueryAndFragment,
} = require("@sentry/tracing");
const domain = require("domain");
// not mandatory, but adding domains does help a lot with breadcrumbs
const requestHandler = (ctx, next) => {
const sentryInstance = strapi.plugins.sentry.services.sentry.getInstance();
return new Promise((resolve, _) => {
const local = domain.create();
local.add(ctx);
local.on("error", (err) => {
ctx.status = err.status || 500;
ctx.body = err.message;
ctx.app.emit("error", err, ctx);
});
local.run(async () => {
sentryInstance.getCurrentHub().configureScope((scope) =>
scope.addEventProcessor((event) =>
sentryInstance.Handlers.parseRequest(event, ctx.request, {
user: false,
})
)
);
await next();
resolve();
});
});
};
// this tracing middleware creates a transaction per request
const tracingMiddleWare = async (ctx, next) => {
console.log("tracingMiddleWare called");
const sentryInstance = strapi.plugins.sentry.services.sentry.getInstance();
const reqMethod = (ctx.method || "").toUpperCase();
const reqUrl = ctx.url && stripUrlQueryAndFragment(ctx.url);
// this can be used to see if the middleware is getting the right DSN
// console.log(
// "sentryInstance.getCurrentHub()._stack[0].client",
// sentryInstance.getCurrentHub()._stack[0].client
// );
// connect to trace of upstream app
let traceparentData;
if (ctx.request.get("sentry-trace")) {
traceparentData = extractTraceparentData(ctx.request.get("sentry-trace"));
}
const transaction = sentryInstance.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
sentryInstance.getCurrentHub().configureScope((scope) => {
scope.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();
});
});
await next();
};
module.exports = (strapi) => {
return {
initialize() {
strapi.app.use(requestHandler);
strapi.app.use(tracingMiddleWare);
},
};
};
This is basically the same as the documentation but using strapi.plugins.sentry.services.sentry.getInstance();
to get the Strapi instance.
Then in the configuration of the sentry plugin add init.tracesSampleRate
(if not it will not record without giving an error) so the config should look something like this:
sentry: {
dsn: env("SENTRY_DSN"),
init: {
tracesSampleRate: 1.0,
},
},
And make sure that the middelware is active in the ./config/middleware.js
(it should look something like this):
module.exports = ({ env }) => ({
load: {
before: [
"stracing",
...
],
},
settings: {
stracing: {
enabled: true,
},
},
});