Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Using Sentry v8 without HTTP autoinstrumentation #12982

nwalters512 started this conversation in Show and tell
Discussion options

Sentry v8 removed the very convenient Sentry.Handlers.requestHandler() that could be dropped easily into an Express application. Now, instrumentation is "automagical" and requires one to jump through some hoops to get it to work, particularly if you're running native ESM. In my case, it would require a pretty invasive restructuring of my application's bootstrapping process to ensure that Sentry could put its hooks into everything when it wants to. If, like me, you don't care about Sentry's performance/transaction features and just want it to reliably capture errors and their associated context, I've found that this little snippet will more or less give you a Sentry v7 experience in Express applications:

import * as Sentry from '@sentry/node';
import { stripUrlQueryAndFragment } from '@sentry/utils';
/**
 * Based on Sentry code that is not exported:
 * https://github.com/getsentry/sentry-javascript/blob/602703652959b581304a7849cb97117f296493bc/packages/utils/src/requestdata.ts#L102
 */
function extractTransaction(req: any) {
 const method = req.method?.toUpperCase() || '';
 const path = stripUrlQueryAndFragment(req.originalUrl || req.url || '');
 let name = '';
 if (method) {
 name += method;
 }
 if (method && path) {
 name += ' ';
 }
 if (path) {
 name += path;
 }
 return name;
}
export function requestHandler() {
 return (req: any, _res: any, next: any) => {
 Sentry.withIsolationScope((scope) => {
 scope.addEventProcessor((event) => {
 event.transaction = extractTransaction(req);
 return Sentry.addRequestDataToEvent(event, req);
 });
 next();
 });
 };
}

This can then be used as Express middleware:

app.use(requestHandler());
// You'll still need to add an error handler after all your
// application routes:
app.use(Sentry.expressErrorHandler());

I hopes this helps anyone else that's in a similar boat!

You must be logged in to vote

Replies: 1 comment 2 replies

Comment options

Now, instrumentation is "automagical" and requires one to jump through some hoops to get it to work

Unfortunately this is how Node.js has designed ESM to work - you have to use loaders to do auto-instrumentation (where we automatically wrap things). I understand it's not the best experience, we're trying to make changes in Node.js itself to make this better!

Three things to note from your snippet:

  1. distributed tracing will not work (spans/transactions are separate to the tracing concept in Sentry). So if you wanted to associate errors between different micro-services instrumented with Sentry, or link your frontend session replay to your backend express errors, you'll still need to use the auto-instrumentation included with the default Sentry setup. Otherwise you'll have to manually do this: https://docs.sentry.io/platforms/javascript/guides/node/tracing/trace-propagation/custom-instrumentation/

  2. event.transaction = extractTransaction(req); will set an un-parameterized name for the transaction name, because it parses req.originalUrl. This means you'll get something like /users/123/ instead of users/:id, which means that grouping related issues by route is less effective. The default express instrumentation does some extended logic to generated a parameterized name - I recommend vendoring this in some way.

OTEL implementation: https://github.com/open-telemetry/opentelemetry-js-contrib/blob/afccd0d62a0ea81afb8f5609f3ee802c038d11c6/plugins/node/opentelemetry-instrumentation-express/src/utils.ts#L153-L159

Old Sentry implementation:

routerProto.process_params = function process_params(
  1. The requestHandler implementation does not have logic around release health. You'll still need to use Sentry.expressErrorHandler to make sure aggregate sessions are being tracked properly:
    export function expressErrorHandler(options?: {
You must be logged in to vote
2 replies
Comment options

distributed tracing will not work

This is very much acceptable for me. As I called out in my post, I "don't care about Sentry's performance/transaction features and just want it to reliably capture errors and their associated context".

will set an un-parameterized name for the transaction name

This is actually an improvement for me over Sentry v7. Our application does something like the following:

const app = express();
const usersRouter = express.Router();
usersRouter.get('/', ...);
app.use('/users', usersRouter);

In practice, this meant that the transaction name was reported as GET / or POST / no matter what the actual route was, presumably because Sentry was only looking at the last "layer" of the route stack.

I did see that Sentry tried to derive a parameterized transaction name based on the Express route and thought that might have had something to do with grouping on the Sentry backend. I tested out the non-parameterized transaction name and didn't see any immediate adverse affects in the Sentry UI.

You'll still need to use Sentry.expressErrorHandler to make sure aggregate sessions are being tracked properly.

Indeed, I was already doing that, I'll add that to my above code snippet so anyone landing here isn't mislead!

Comment options

Unfortunately this is how Node.js has designed ESM to work - you have to use loaders to do auto-instrumentation (where we automatically wrap things).

Yep, I understand this from our other, direct usages of OTel. From what I can tell, there's no technical reason you couldn't have kept around Sentry.Handler.requestHandler() as an alternative option to auto-instrumentation of the HTTP module. I get that you're trying to make things easy for folks setting up Sentry for the first time. It's just a shame that the old, manual setup option wasn't retained as an "I know what I'm doing and am willing to add/keep an extra line of code in my application setup" option.

I understand it's not the best experience, we're trying to make changes in Node.js itself to make this better!

I'm very glad to hear you're advocating for that! I hope this will let us remove some annoying hacks we've used to work around this with our own OTel instrumentation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet

AltStyle によって変換されたページ (->オリジナル) /