Skip to content

Commit 450f2a9

Browse files
authored
feat: Add applicationKey option to identify application code from within the SDK (#540)
1 parent 45c7f1c commit 450f2a9

File tree

6 files changed

+78
-4
lines changed

6 files changed

+78
-4
lines changed

Diff for: packages/bundler-plugin-core/src/index.ts

+15-4
Original file line numberDiff line numberDiff line change
@@ -224,19 +224,30 @@ export function sentryUnpluginFactory({
224224
plugins.push(releaseInjectionPlugin(injectionCode));
225225
}
226226

227-
if (options.moduleMetadata) {
228-
let metadata: Record<string, unknown>;
227+
if (options.moduleMetadata || options.applicationKey) {
228+
let metadata: Record<string, unknown> = {};
229+
230+
if (options.applicationKey) {
231+
// We use different keys so that if user-code receives multiple bundling passes, we will store the application keys of all the passes.
232+
// It is a bit unfortunate that we have to inject the metadata snippet at the top, because after multiple
233+
// injections, the first injection will always "win" because it comes last in the code. We would generally be
234+
// fine with making the last bundling pass win. But because it cannot win, we have to use a workaround of storing
235+
// the app keys in different object keys.
236+
// We can simply use the `_sentryBundlerPluginAppKey:` to filter for app keys in the SDK.
237+
metadata[`_sentryBundlerPluginAppKey:${options.applicationKey}`] = true;
238+
}
239+
229240
if (typeof options.moduleMetadata === "function") {
230241
const args = {
231242
org: options.org,
232243
project: options.project,
233244
release: options.release.name,
234245
};
235246
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
236-
metadata = options.moduleMetadata(args);
247+
metadata = { ...metadata, ...options.moduleMetadata(args) };
237248
} else {
238249
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
239-
metadata = options.moduleMetadata;
250+
metadata = { ...metadata, ...options.moduleMetadata };
240251
}
241252

242253
const injectionCode = generateModuleMetadataInjectorCode(metadata);

Diff for: packages/bundler-plugin-core/src/options-mapping.ts

+1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ export function normalizeUserOptions(userOptions: UserOptions) {
3434
metaFramework: userOptions._metaOptions?.telemetry?.metaFramework,
3535
},
3636
},
37+
applicationKey: userOptions.applicationKey,
3738
moduleMetadata: userOptions.moduleMetadata || userOptions._experiments?.moduleMetadata,
3839
_experiments: userOptions._experiments ?? {},
3940
};

Diff for: packages/bundler-plugin-core/src/types.ts

+6
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,12 @@ export interface Options {
312312
// eslint-disable-next-line @typescript-eslint/no-explicit-any
313313
moduleMetadata?: ModuleMetadata | ModuleMetadataCallback;
314314

315+
/**
316+
* A key which will embedded in all the bundled files. The SDK will be able to use the key to apply filtering
317+
* rules, for example using the `thirdPartyErrorFilterIntegration`.
318+
*/
319+
applicationKey?: string;
320+
315321
/**
316322
* Options that are considered experimental and subject to change.
317323
*
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
// Simply output the metadata to the console so it can be checked in a test
2+
// eslint-disable-next-line no-console
3+
console.log(JSON.stringify(global._sentryModuleMetadata));
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/* eslint-disable jest/no-standalone-expect */
2+
/* eslint-disable jest/expect-expect */
3+
import { execSync } from "child_process";
4+
import path from "path";
5+
import { testIfNodeMajorVersionIsLessThan18 } from "../../utils/testIf";
6+
7+
function checkBundle(bundlePath: string): void {
8+
const output = execSync(`node ${bundlePath}`, { encoding: "utf-8" });
9+
10+
const map = JSON.parse(output) as Record<string, string>;
11+
12+
// There should be only one key in the map
13+
expect(Object.values(map)).toHaveLength(1);
14+
// The value should be the expected metadata
15+
expect(Object.values(map)).toEqual([{ ["_sentryBundlerPluginAppKey:my-app"]: true }]);
16+
}
17+
18+
describe("appKey injection", () => {
19+
testIfNodeMajorVersionIsLessThan18("webpack 4 bundle", () => {
20+
checkBundle(path.join(__dirname, "out", "webpack4", "bundle.js"));
21+
});
22+
23+
test("webpack 5 bundle", () => {
24+
checkBundle(path.join(__dirname, "out", "webpack5", "bundle.js"));
25+
});
26+
27+
test("esbuild bundle", () => {
28+
checkBundle(path.join(__dirname, "out", "esbuild", "bundle.js"));
29+
});
30+
31+
test("rollup bundle", () => {
32+
checkBundle(path.join(__dirname, "out", "rollup", "bundle.js"));
33+
});
34+
35+
test("vite bundle", () => {
36+
checkBundle(path.join(__dirname, "out", "vite", "bundle.js"));
37+
});
38+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import * as path from "path";
2+
import { createCjsBundles } from "../../utils/create-cjs-bundles";
3+
4+
const outputDir = path.resolve(__dirname, "out");
5+
6+
createCjsBundles(
7+
{
8+
bundle: path.resolve(__dirname, "input", "bundle.js"),
9+
},
10+
outputDir,
11+
{
12+
applicationKey: "my-app",
13+
},
14+
["webpack4", "webpack5", "esbuild", "rollup", "vite"]
15+
);

0 commit comments

Comments
 (0)