Performance Monitoring
When integrating Sentry with an Express application, you can leverage provided middlewares to automatically instrument and monitor the performance of your application.
If you’re adopting Performance in a high-throughput environment, we recommend testing prior to deployment to ensure that your service’s performance characteristics maintain expectations.
const Sentry = require("@sentry/node");
const express = require("express");
const app = express();
Sentry.init({
dsn: "https://examplePublicKey@o0.ingest.sentry.io/0",
integrations: [
// enable Express.js middleware tracing
new Sentry.Integrations.Express({
// to trace all requests to the default router
app,
// alternatively, you can specify the routes you want to trace:
// router: someRouter,
}),
],
// We recommend adjusting this value in production, or using tracesSampler
// for finer control
tracesSampleRate: 1.0,
});
// RequestHandler creates a separate execution context, so that all
// transactions/spans/breadcrumbs are isolated across requests
app.use(Sentry.Handlers.requestHandler());
// TracingHandler creates a trace for every incoming request
app.use(Sentry.Handlers.tracingHandler());
// the rest of your app
// The Sentry error handler middleware must be registered before any other error middleware and after all controllers
app.use(Sentry.Handlers.errorHandler());
app.listen(3000);
You can also manually create transactions in your app:
const Sentry = require("@sentry/node");
const http = require("http");
const transaction = Sentry.startTransaction({
op: "transaction",
name: "My Transaction",
});
// Note that we set the transaction as the span on the scope.
// This step makes sure that if an error happens during the lifetime of the transaction
// the transaction context will be attached to the error event
Sentry.getCurrentScope().setSpan(transaction);
let request;
try {
// this should generate an http span
request = http.get("http://sentry.io", (res) => {
console.log(`STATUS: ${res.statusCode}`);
console.log(`HEADERS: ${JSON.stringify(res.headers)}`);
});
// this error event should have trace context
foo();
} catch (err) {
Sentry.captureException(err);
}
request.on("close", () => {
transaction.finish();
});
To instrument a specific region of your code, you can create a transaction to capture it.
The following example creates a transaction for a part of the code that contains an expensive operation (for example, processItem
), and sends the result to Sentry:
app.use(function processItems(req, res, next) {
const item = getFromQueue();
const transaction = Sentry.startTransaction({
op: "task",
name: item.getTransaction(),
});
// processItem may create more spans internally (see next examples)
processItem(item, transaction).then(() => {
transaction.finish();
next();
});
});
In cases where you want to attach Spans to an already ongoing Transaction you can use Sentry.getActiveTransaction()
. This function will return a Transaction
in case there is a running Transaction otherwise it returns undefined
. If you are using our Express integration by default we attach the Transaction to the Scope. So you could do something like this:
app.get("/success", function successHandler(req, res) {
const transaction = Sentry.getActiveTransaction();
if (transaction) {
let span = transaction.startChild({
op: "encode",
description: "parseAvatarImages",
});
// Do something
span.finish();
}
res.status(200).end();
});
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").