Skip to content

Commit 3314dda

Browse files
committed
feat: Support existing Debug IDs in source
1 parent 958248e commit 3314dda

File tree

6 files changed

+44
-19
lines changed

6 files changed

+44
-19
lines changed

packages/bundler-plugin-core/src/debug-id-upload.ts

+12-9
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { promisify } from "util";
88
import SentryCli from "@sentry/cli";
99
import { dynamicSamplingContextToSentryBaggageHeader } from "@sentry/utils";
1010
import { safeFlushTelemetry } from "./sentry/telemetry";
11-
import { stripQueryAndHashFromPath } from "./utils";
11+
import { getDebugIdFromMagicComment, stripQueryAndHashFromPath } from "./utils";
1212
import { setMeasurement, spanToTraceHeader, startSpan } from "@sentry/core";
1313
import { getDynamicSamplingContextFromSpan, Scope } from "@sentry/core";
1414
import { Client } from "@sentry/types";
@@ -223,7 +223,8 @@ export async function prepareBundleForDebugIdUpload(
223223
return;
224224
}
225225

226-
const debugId = determineDebugIdFromBundleSource(bundleContent);
226+
const debugIdFromMagicComment = getDebugIdFromMagicComment(bundleContent);
227+
const debugId = debugIdFromMagicComment || getDebugIdFromPolyfill(bundleContent);
227228
if (debugId === undefined) {
228229
logger.debug(
229230
`Could not determine debug ID from bundle. This can happen if you did not clean your output folder before installing the Sentry plugin. File will not be source mapped: ${bundleFilePath}`
@@ -233,12 +234,14 @@ export async function prepareBundleForDebugIdUpload(
233234

234235
const uniqueUploadName = `${debugId}-${chunkIndex}`;
235236

236-
bundleContent += `\n//# debugId=${debugId}`;
237-
const writeSourceFilePromise = fs.promises.writeFile(
238-
path.join(uploadFolder, `${uniqueUploadName}.js`),
239-
bundleContent,
240-
"utf-8"
241-
);
237+
// Only add the debug ID magic comment if source file does not already contain it
238+
const writeSourceFilePromise = debugIdFromMagicComment
239+
? Promise.resolve()
240+
: fs.promises.writeFile(
241+
path.join(uploadFolder, `${uniqueUploadName}.js`),
242+
bundleContent + `\n//# debugId=${debugId}`,
243+
"utf-8"
244+
);
242245

243246
const writeSourceMapFilePromise = determineSourceMapPathFromBundle(
244247
bundleFilePath,
@@ -266,7 +269,7 @@ export async function prepareBundleForDebugIdUpload(
266269
*
267270
* The string pattern is injected via the debug ID injection snipped.
268271
*/
269-
function determineDebugIdFromBundleSource(code: string): string | undefined {
272+
function getDebugIdFromPolyfill(code: string): string | undefined {
270273
const match = code.match(
271274
/sentry-dbid-([0-9a-fA-F]{8}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{12})/
272275
);

packages/bundler-plugin-core/src/index.ts

+5-3
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import {
1616
generateGlobalInjectorCode,
1717
generateModuleMetadataInjectorCode,
1818
getDependencies,
19+
getDebugIdForCode,
1920
getPackageJson,
2021
parseMajorVersion,
2122
replaceBooleanFlagsInCode,
@@ -588,8 +589,9 @@ export function createRollupDebugIdInjectionHooks() {
588589
stripQueryAndHashFromPath(chunk.fileName).endsWith(ending)
589590
)
590591
) {
591-
const debugId = stringToUUID(code); // generate a deterministic debug ID
592-
const codeToInject = getDebugIdSnippet(debugId);
592+
// Gets an existing debug ID or generates a deterministic debug ID
593+
const debugId = getDebugIdForCode(code);
594+
const codeToInject = getDebugIdPolyfillSnippet(debugId);
593595

594596
const ms = new MagicString(code, { filename: chunk.fileName });
595597

@@ -740,7 +742,7 @@ export function createComponentNameAnnotateHooks(ignoredComponents?: string[]) {
740742
};
741743
}
742744

743-
export function getDebugIdSnippet(debugId: string): string {
745+
export function getDebugIdPolyfillSnippet(debugId: string): string {
744746
return `;{try{let e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="${debugId}",e._sentryDebugIdIdentifier="sentry-dbid-${debugId}")}catch(e){}};`;
745747
}
746748

packages/bundler-plugin-core/src/utils.ts

+20
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,26 @@ function lookupPackageJson(cwd: string, stopAt: string): PackageJson | undefined
169169
return lookupPackageJson(newCwd, stopAt);
170170
}
171171

172+
const DEBUG_ID_REGEX = /\/\/# debugId=([a-fA-F0-9-]+)(?![\s\S]*\/\/# debugId=)/m;
173+
174+
/**
175+
* Returns a debug ID if one can be found in a magic comment
176+
*/
177+
export function getDebugIdFromMagicComment(code: string): string | undefined {
178+
const match = code.match(DEBUG_ID_REGEX);
179+
return match?.[1];
180+
}
181+
182+
/**
183+
* Gets a debug ID for the passed source code.
184+
*
185+
* If the source already contains a debug ID magic comment, that existing debug
186+
* ID is used, otherwise a debug ID is created via hashing
187+
*/
188+
export function getDebugIdForCode(code: string): string {
189+
return getDebugIdFromMagicComment(code) || stringToUUID(code);
190+
}
191+
172192
/**
173193
* Deterministically hashes a string and turns the hash into a uuid.
174194
*/

packages/bundler-plugin-core/test/index.test.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
import { getDebugIdSnippet } from "../src";
1+
import { getDebugIdPolyfillSnippet } from "../src";
22

3-
describe("getDebugIdSnippet", () => {
3+
describe("getDebugIdPolyfillSnippet", () => {
44
it("returns the debugId injection snippet for a passed debugId", () => {
5-
const snippet = getDebugIdSnippet("1234");
5+
const snippet = getDebugIdPolyfillSnippet("1234");
66
expect(snippet).toMatchInlineSnapshot(
77
`";{try{let e=\\"undefined\\"!=typeof window?window:\\"undefined\\"!=typeof global?global:\\"undefined\\"!=typeof globalThis?globalThis:\\"undefined\\"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]=\\"1234\\",e._sentryDebugIdIdentifier=\\"sentry-dbid-1234\\")}catch(e){}};"`
88
);

packages/esbuild-plugin/src/index.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import {
22
sentryUnpluginFactory,
33
Options,
4-
getDebugIdSnippet,
4+
getDebugIdPolyfillSnippet,
55
SentrySDKBuildFlags,
66
} from "@sentry/bundler-plugin-core";
77
import type { Logger } from "@sentry/bundler-plugin-core";
@@ -125,7 +125,7 @@ function esbuildDebugIdInjectionPlugin(logger: Logger): UnpluginOptions {
125125
return {
126126
loader: "js",
127127
pluginName,
128-
contents: getDebugIdSnippet(uuidv4()),
128+
contents: getDebugIdPolyfillSnippet(uuidv4()),
129129
};
130130
});
131131
},

packages/webpack-plugin/src/webpack4and5.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import {
2-
getDebugIdSnippet,
2+
getDebugIdPolyfillSnippet,
33
Options,
44
sentryUnpluginFactory,
55
stringToUUID,
@@ -123,7 +123,7 @@ function webpackDebugIdInjectionPlugin(
123123
banner: (arg?: BannerPluginCallbackArg) => {
124124
const hash = arg?.chunk?.contentHash?.javascript ?? arg?.chunk?.hash;
125125
const debugId = hash ? stringToUUID(hash) : uuidv4();
126-
return getDebugIdSnippet(debugId);
126+
return getDebugIdPolyfillSnippet(debugId);
127127
},
128128
})
129129
);

0 commit comments

Comments
 (0)