Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Promote experimental moduleMetadata option to stable #538

Merged
merged 3 commits into from
May 31, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 14 additions & 9 deletions packages/bundler-plugin-core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ import { logger } from "@sentry/utils";
interface SentryUnpluginFactoryOptions {
releaseInjectionPlugin: (injectionCode: string) => UnpluginOptions;
componentNameAnnotatePlugin?: () => UnpluginOptions;
moduleMetadataInjectionPlugin?: (injectionCode: string) => UnpluginOptions;
moduleMetadataInjectionPlugin: (injectionCode: string) => UnpluginOptions;
debugIdInjectionPlugin: (logger: Logger) => UnpluginOptions;
debugIdUploadPlugin: (upload: (buildArtifacts: string[]) => Promise<void>) => UnpluginOptions;
bundleSizeOptimizationsPlugin: (buildFlags: SentrySDKBuildFlags) => UnpluginOptions;
Expand Down Expand Up @@ -96,6 +96,13 @@ export function sentryUnpluginFactory({

const options = normalizeUserOptions(userOptions);

// TODO(v3): Remove this warning
if (userOptions._experiments?.moduleMetadata) {
logger.warn(
"The `_experiments.moduleMetadata` option has been promoted to being stable. You can safely move the option out of the `_experiments` object scope."
);
}

if (unpluginMetaContext.watchMode || options.disable) {
return [
{
Expand Down Expand Up @@ -217,25 +224,23 @@ export function sentryUnpluginFactory({
plugins.push(releaseInjectionPlugin(injectionCode));
}

if (moduleMetadataInjectionPlugin && options._experiments.moduleMetadata) {
let metadata: object;
if (typeof options._experiments.moduleMetadata === "function") {
if (options.moduleMetadata) {
let metadata: Record<string, unknown>;
if (typeof options.moduleMetadata === "function") {
const args = {
org: options.org,
project: options.project,
release: options.release.name,
};
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call
metadata = options._experiments.moduleMetadata(args);
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
metadata = options.moduleMetadata(args);
} else {
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
metadata = options._experiments.moduleMetadata;
metadata = options.moduleMetadata;
}

const injectionCode = generateModuleMetadataInjectorCode(metadata);
plugins.push(moduleMetadataInjectionPlugin(injectionCode));
} else if (options._experiments.moduleMetadata) {
logger.warn("'moduleMetadata' is currently only supported by '@sentry/webpack-plugin'");
}

if (!options.release.name) {
Expand Down
1 change: 1 addition & 0 deletions packages/bundler-plugin-core/src/options-mapping.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export function normalizeUserOptions(userOptions: UserOptions) {
},
bundleSizeOptimizations: userOptions.bundleSizeOptimizations,
reactComponentAnnotation: userOptions.reactComponentAnnotation,
moduleMetadata: userOptions.moduleMetadata || userOptions._experiments?.moduleMetadata,
_experiments: userOptions._experiments ?? {},
};

Expand Down
2 changes: 1 addition & 1 deletion packages/bundler-plugin-core/src/sentry/telemetry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ export function setTelemetryDataOnHub(options: NormalizedOptions, hub: Hub, bund
);
}

hub.setTag("module-metadata", !!options._experiments.moduleMetadata);
hub.setTag("module-metadata", !!options._experiments.moduleMetadata || !!options.moduleMetadata);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are we setting this tag before we normalize options? If not, we could remove the _experimental flag, right?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh you're right. This is after normalization. 👌

hub.setTag("inject-build-information", !!options._experiments.injectBuildInformation);

// Optional release pipeline steps
Expand Down
36 changes: 31 additions & 5 deletions packages/bundler-plugin-core/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -297,11 +297,27 @@ export interface Options {
enabled?: boolean;
};

/**
* Metadata that should be associated with the built application.
*
* The metadata is serialized and can be looked up at runtime from within the SDK (for example in the `beforeSend`,
* event processors, or the transport), allowing for custom event filtering logic or routing of events.
*
* Metadata can either be passed directly or alternatively a callback can be provided that will be
* called with the following parameters:
* - `org`: The organization slug.
* - `project`: The project slug.
* - `release`: The release name.
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
moduleMetadata?: ModuleMetadata | ModuleMetadataCallback;

/**
* Options that are considered experimental and subject to change.
*
* @experimental API that does not follow semantic versioning and may change in any release
*/
// TODO(v3): Remove these
_experiments?: {
/**
* If set to true, the plugin will inject an additional `SENTRY_BUILD_INFO` variable.
Expand All @@ -312,18 +328,23 @@ export interface Options {
injectBuildInformation?: boolean;

/**
* Metadata associated with this module.
* NOTE: This option has been promoted to stable.
*
* The metadata is serialized and can be looked up at runtime by filename.
* Metadata that should be associated with the built application.
*
* The metadata is serialized and can be looked up at runtime from within the SDK (for example in the `beforeSend`,
* event processors, or the transport), allowing for custom event filtering logic or routing of events.
*
* Metadata can either be passed directly or alternatively a callback can be provided that will be
* called with the following arguments:
* called with the following parameters:
* - `org`: The organization slug.
* - `project`: The project slug.
* - `release`: The release name.
*
* @deprecated Use the non-experimental `moduleMetadata` option instead. (Basically just move this option out of `_experiments`)
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
moduleMetadata?: any | ModuleMetadataCallback;
moduleMetadata?: ModuleMetadata | ModuleMetadataCallback;
};

/**
Expand All @@ -340,13 +361,18 @@ export interface Options {
};
}

export interface ModuleMetadata {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
[key: string]: any;
}

export interface ModuleMetadataCallbackArgs {
org?: string;
project?: string;
release?: string;
}

export type ModuleMetadataCallback = (args: ModuleMetadataCallbackArgs) => object;
export type ModuleMetadataCallback = (args: ModuleMetadataCallbackArgs) => ModuleMetadata;

export type IncludeEntry = {
/**
Expand Down
33 changes: 21 additions & 12 deletions packages/bundler-plugin-core/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -280,18 +280,27 @@ export function generateGlobalInjectorCode({
export function generateModuleMetadataInjectorCode(metadata: any) {
// The code below is mostly ternary operators because it saves bundle size.
// The checks are to support as many environments as possible. (Node.js, Browser, webworkers, etc.)
return `
var _global2 =
typeof window !== 'undefined' ?
window :
typeof global !== 'undefined' ?
global :
typeof self !== 'undefined' ?
self :
{};

_global2._sentryModuleMetadata = _global2._sentryModuleMetadata || {};
_global2._sentryModuleMetadata[new Error().stack] = ${JSON.stringify(metadata)};`;
// We are merging the metadata objects in case modules are bundled twice with the plugin
return `{
var _sentryModuleMetadataGlobal =
typeof window !== "undefined"
? window
: typeof global !== "undefined"
? global
: typeof self !== "undefined"
? self
: {};

_sentryModuleMetadataGlobal._sentryModuleMetadata =
_sentryModuleMetadataGlobal._sentryModuleMetadata || {};

_sentryModuleMetadataGlobal._sentryModuleMetadata[new Error().stack] =
Object.assign(
{},
_sentryModuleMetadataGlobal._sentryModuleMetadata[new Error().stack],
${JSON.stringify(metadata)}
);
}`;
}

function getBuildInformation() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,7 @@ createCjsBundles(
},
outputDir,
{
_experiments: {
moduleMetadata: { team: "frontend" },
},
moduleMetadata: { team: "frontend" },
},
["webpack4", "webpack5", "esbuild", "rollup", "vite"]
);
Loading