getsentry / sentry-javascript

Official Sentry SDKs for JavaScript
https://sentry.io
MIT License
7.97k stars 1.57k forks source link

Source maps with Node.js and Typescript #2563

Closed oddeirik closed 4 years ago

oddeirik commented 4 years ago

Package + Version

Version:

5.15.5

Description

Example event in Sentry: https://sentry.io/organizations/groupm-hg/issues/1636823097/events/6c9857d97e214e84b233255ca4de6169/json/

I have a Node.js/Typescript backend API that I want to integrate Sentry with. I've followed the documentation at https://docs.sentry.io/platforms/node/sourcemaps/ and https://docs.sentry.io/platforms/node/typescript/#sentry-sdk-and-source-maps-with-typescript to no avail.

If I use a custom iteratee in RewriteFrames, I can get it set up with paths that Sentry seems to be okay with (no complaints about missing source code), but it still shows me just the JS code, not the TS sources, even though it's set up with inlined sources in the source map. I've even tried inline sources AND source maps.

The project structure is

/ <- project root, with tsconfig.json and package.json
   /src/**/* <- TS sources
/dist <- TSC output

What I'd like to know is what path does Sentry require to get this working? Does it depend on a NIX-style path separator for everything? Why is it prepending 'app:///' in the RewriteFrames integration? Does it even support inlined source maps and sources?

I'm sure this is great out of the box when it works, but when it doesn't, there's not much documentation to go on.

oddeirik commented 4 years ago

Well, after a lot of trial and error, I got it into a somewhat working state.

What I had to do was set the root dir to a "sanitized"path, that is, a path with forward slashes only. If I just used __dirname ?? process.cwd() then the frame filenames were wrong somehow.

// Sentry is initialized in file /src/server.ts, which is also the root dir set
const rootDir = sanitizeSentryPath(__dirname ?? process.cwd()); // Converts "X:\path\to\git\repo\src" => "/path/to/git/repo/src"

Sentry.init({
  ...,
  ...,
  integrations: [
    new RewriteFrames({
      root: rootDir,
      iteratee: (frame) => {
        if (isNilOrEmpty(frame.filename)) return frame;
        const filename = path.basename(frame.filename);
        const filePath = sanitizeSentryPath(frame.filename); // Same regex as in the Sentry SDK, just strips away Windows drive prefix and replaces backslashes with forward slashes
        const fileDir = path.dirname(filePath);
        const relativePath = sanitizeSentryPath(path.relative(rootDir, fileDir));

        frame.filename = `app:///${relativePath}/${filename}`;
        return frame;
      },
    }),
  ]
});

An example event in Sentry now shows this: image

Which is the correct relative path to sources, as well, but more importantly, it picks up on the source maps uploaded (using sentry-cli):

image

I did not set the sourceRoot path in tsconfig.json, I only set sourceMap and inlineSources so I didn't have to upload source files as well.

So I guess it's working now, but I'd really like the documentation to elaborate on how to configure these things in a more manual way if needed. It feels too much like a black box at the moment when things do not work according to the documentation.

kamilogorek commented 4 years ago

@oddeirik we mention it here https://docs.sentry.io/platforms/node/pluggable-integrations/#rewriteframes But I agree, that it'd be much better if we handle the translation ourselves. Will keep that in mind.

ian commented 2 years ago

Running into same issue, no matter what Sentry just doesn't recognize source maps.

I'm typescript compiling src/ -> dist/ and running sentry-cli releases files "0.0.0" upload-sourcemaps ./dist --url-prefix 'app:///dist' --validate

I'm a bit confused as to how Sentry does path -> app:// mapping, is that ignored or do I need to have the generated maps match including the app:// prefix?

I have tried with app://, without app://, changing url prefix to be --url-prefix './dist' and sentry will not recognize maps.

I've verified that the source maps are being uploaded: CleanShot 2021-11-19 at 14 00 00 CleanShot 2021-11-19 at 14 00 22

My assumption would be that an identical name-for-name match should pull up the sourcemaps correctly but this isn't the case.