-
-
Notifications
You must be signed in to change notification settings - Fork 354
feat: Add Sentry Babel Transformer #3916
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
Merged
krystofwoldrich
merged 16 commits into
feat/replay
from
kw/add-sentry-babel-transaformer
Jul 3, 2024
Merged
Changes from all commits
Commits
Show all changes
16 commits
Select commit
Hold shift + click to select a range
3ac1315
wip: Add Sentry Babel Transformer
krystofwoldrich d558312
add annotate react as opt in feature
krystofwoldrich 670bfc6
fix lint
krystofwoldrich ea413b7
revert: touch events changes
krystofwoldrich 50005b3
Add expo support for react annotate
krystofwoldrich b030816
remove babel config, add tests
krystofwoldrich 0a9d0e1
add more tests
krystofwoldrich 4ac1605
fix lint
krystofwoldrich f5d0d6e
add changelog
krystofwoldrich 35a0038
add react annotate to e2e tests
krystofwoldrich 4174f98
add reason why annotate plugin can't be used in the warning
krystofwoldrich d31895e
update debug logs
krystofwoldrich 6a83025
Merge remote-tracking branch 'origin/feat/replay' into kw/add-sentry-…
krystofwoldrich c0fbda2
fix fs review comments
krystofwoldrich 49e403a
fix tests
krystofwoldrich 6463a17
Merge branch 'feat/replay' into kw/add-sentry-babel-transaformer
krystofwoldrich File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -74,3 +74,6 @@ yalc.lock | |
|
|
||
| # E2E tests | ||
| test/react-native/versions | ||
|
|
||
| # Created by Sentry Metro Plugin | ||
| .sentry/ | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| import { logger } from '@sentry/utils'; | ||
|
|
||
| /** | ||
| * Enables debug logger when SENTRY_LOG_LEVEL=debug. | ||
| */ | ||
| export function enableLogger(): void { | ||
| if (process.env.SENTRY_LOG_LEVEL === 'debug') { | ||
| logger.enable(); | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,24 +1,51 @@ | ||
| import { logger } from '@sentry/utils'; | ||
| import type { MetroConfig, MixedOutput, Module, ReadOnlyGraph } from 'metro'; | ||
| import * as process from 'process'; | ||
| import { env } from 'process'; | ||
|
|
||
| import { enableLogger } from './enableLogger'; | ||
| import { cleanDefaultBabelTransformerPath, saveDefaultBabelTransformerPath } from './sentryBabelTransformerUtils'; | ||
| import { createSentryMetroSerializer, unstable_beforeAssetSerializationPlugin } from './sentryMetroSerializer'; | ||
| import type { DefaultConfigOptions } from './vendor/expo/expoconfig'; | ||
|
|
||
| export * from './sentryMetroSerializer'; | ||
|
|
||
| enableLogger(); | ||
|
|
||
| export interface SentryMetroConfigOptions { | ||
| /** | ||
| * Annotates React components with Sentry data. | ||
| * @default false | ||
| */ | ||
| annotateReactComponents?: boolean; | ||
| } | ||
|
|
||
| export interface SentryExpoConfigOptions { | ||
| /** | ||
| * Pass a custom `getDefaultConfig` function to override the default Expo configuration getter. | ||
| */ | ||
| getDefaultConfig?: typeof getSentryExpoConfig; | ||
| } | ||
|
|
||
| /** | ||
| * Adds Sentry to the Metro config. | ||
| * | ||
| * Adds Debug ID to the output bundle and source maps. | ||
| * Collapses Sentry frames from the stack trace view in LogBox. | ||
| */ | ||
| export function withSentryConfig(config: MetroConfig): MetroConfig { | ||
| export function withSentryConfig( | ||
| config: MetroConfig, | ||
| { annotateReactComponents = false }: SentryMetroConfigOptions = {}, | ||
| ): MetroConfig { | ||
| setSentryMetroDevServerEnvFlag(); | ||
|
|
||
| let newConfig = config; | ||
|
|
||
| newConfig = withSentryDebugId(newConfig); | ||
| newConfig = withSentryFramesCollapsed(newConfig); | ||
| if (annotateReactComponents) { | ||
| newConfig = withSentryBabelTransformer(newConfig); | ||
| } | ||
|
|
||
| return newConfig; | ||
| } | ||
|
|
@@ -28,7 +55,7 @@ export function withSentryConfig(config: MetroConfig): MetroConfig { | |
| */ | ||
| export function getSentryExpoConfig( | ||
| projectRoot: string, | ||
| options: DefaultConfigOptions & { getDefaultConfig?: typeof getSentryExpoConfig } = {}, | ||
| options: DefaultConfigOptions & SentryExpoConfigOptions & SentryMetroConfigOptions = {}, | ||
| ): MetroConfig { | ||
| setSentryMetroDevServerEnvFlag(); | ||
|
|
||
|
|
@@ -41,7 +68,12 @@ export function getSentryExpoConfig( | |
| ], | ||
| }); | ||
|
|
||
| return withSentryFramesCollapsed(config); | ||
| let newConfig = withSentryFramesCollapsed(config); | ||
| if (options.annotateReactComponents) { | ||
| newConfig = withSentryBabelTransformer(newConfig); | ||
| } | ||
|
|
||
| return newConfig; | ||
| } | ||
|
|
||
| function loadExpoMetroConfigModule(): { | ||
|
|
@@ -64,6 +96,38 @@ function loadExpoMetroConfigModule(): { | |
| } | ||
| } | ||
|
|
||
| /** | ||
| * Adds Sentry Babel transformer to the Metro config. | ||
| */ | ||
| export function withSentryBabelTransformer(config: MetroConfig): MetroConfig { | ||
| const defaultBabelTransformerPath = config.transformer && config.transformer.babelTransformerPath; | ||
| logger.debug('Default Babel transformer path from `config.transformer`:', defaultBabelTransformerPath); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The Sentry SDK logger is mostly intended to be used when the SDK is initialized. For build tooling we usually don't rely on it. I would do a good ol' console.log instead. |
||
|
|
||
| if (!defaultBabelTransformerPath) { | ||
| // This has to be console.warn because the options is enabled but won't be used | ||
| // eslint-disable-next-line no-console | ||
| console.warn('`transformer.babelTransformerPath` is undefined.'); | ||
| // eslint-disable-next-line no-console | ||
| console.warn('Sentry Babel transformer cannot be used. Not adding it...'); | ||
| return config; | ||
| } | ||
|
|
||
| if (defaultBabelTransformerPath) { | ||
| saveDefaultBabelTransformerPath(defaultBabelTransformerPath); | ||
| process.on('exit', () => { | ||
| cleanDefaultBabelTransformerPath(); | ||
| }); | ||
| } | ||
|
|
||
| return { | ||
| ...config, | ||
| transformer: { | ||
| ...config.transformer, | ||
| babelTransformerPath: require.resolve('./sentryBabelTransformer'), | ||
krystofwoldrich marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| }, | ||
| }; | ||
| } | ||
|
|
||
| type MetroCustomSerializer = Required<Required<MetroConfig>['serializer']>['customSerializer'] | undefined; | ||
|
|
||
| function withSentryDebugId(config: MetroConfig): MetroConfig { | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| import componentAnnotatePlugin from '@sentry/babel-plugin-component-annotate'; | ||
|
|
||
| import { enableLogger } from './enableLogger'; | ||
| import { loadDefaultBabelTransformer } from './sentryBabelTransformerUtils'; | ||
| import type { BabelTransformer, BabelTransformerArgs } from './vendor/metro/metroBabelTransformer'; | ||
|
|
||
| enableLogger(); | ||
krystofwoldrich marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| /** | ||
| * Creates a Babel transformer with Sentry component annotation plugin. | ||
| */ | ||
| function createSentryBabelTransformer(): BabelTransformer { | ||
| const defaultTransformer = loadDefaultBabelTransformer(); | ||
|
|
||
| // Using spread operator to avoid any conflicts with the default transformer | ||
| const transform: BabelTransformer['transform'] = (...args) => { | ||
| const transformerArgs = args[0]; | ||
|
|
||
| addSentryComponentAnnotatePlugin(transformerArgs); | ||
|
|
||
| return defaultTransformer.transform(...args); | ||
| }; | ||
|
|
||
| return { | ||
| ...defaultTransformer, | ||
| transform, | ||
| }; | ||
| } | ||
|
|
||
| function addSentryComponentAnnotatePlugin(args: BabelTransformerArgs | undefined): void { | ||
| if (!args || typeof args.filename !== 'string' || !Array.isArray(args.plugins)) { | ||
| return undefined; | ||
| } | ||
|
|
||
| if (!args.filename.includes('node_modules')) { | ||
| args.plugins.push(componentAnnotatePlugin); | ||
| } | ||
| } | ||
|
|
||
| const sentryBabelTransformer = createSentryBabelTransformer(); | ||
| // With TS set to `commonjs` this will be translated to `module.exports = sentryBabelTransformer;` | ||
| // which will be correctly picked up by Metro | ||
| export = sentryBabelTransformer; | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,65 @@ | ||
| import { logger } from '@sentry/utils'; | ||
| import * as fs from 'fs'; | ||
| import * as path from 'path'; | ||
| import * as process from 'process'; | ||
|
|
||
| import type { BabelTransformer } from './vendor/metro/metroBabelTransformer'; | ||
|
|
||
| /** | ||
| * Saves default Babel transformer path to the project root. | ||
| */ | ||
| export function saveDefaultBabelTransformerPath(defaultBabelTransformerPath: string): void { | ||
| try { | ||
| fs.mkdirSync(path.join(process.cwd(), '.sentry'), { recursive: true }); | ||
| fs.writeFileSync(getDefaultBabelTransformerPath(), defaultBabelTransformerPath); | ||
| logger.debug('Saved default Babel transformer path'); | ||
| } catch (e) { | ||
| // eslint-disable-next-line no-console | ||
| console.error('[Sentry] Failed to save default Babel transformer path:', e); | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Reads default Babel transformer path from the project root. | ||
| */ | ||
| export function readDefaultBabelTransformerPath(): string | undefined { | ||
| try { | ||
| return fs.readFileSync(getDefaultBabelTransformerPath()).toString(); | ||
| } catch (e) { | ||
| // eslint-disable-next-line no-console | ||
| console.error('[Sentry] Failed to read default Babel transformer path:', e); | ||
| } | ||
| return undefined; | ||
| } | ||
|
|
||
| /** | ||
| * Cleans default Babel transformer path from the project root. | ||
| */ | ||
| export function cleanDefaultBabelTransformerPath(): void { | ||
| try { | ||
| fs.unlinkSync(getDefaultBabelTransformerPath()); | ||
| logger.debug('Cleaned default Babel transformer path'); | ||
| } catch (e) { | ||
| // We don't want to fail the build if we can't clean the file | ||
| // eslint-disable-next-line no-console | ||
| console.error('[Sentry] Failed to clean default Babel transformer path:', e); | ||
| } | ||
| } | ||
|
|
||
| function getDefaultBabelTransformerPath(): string { | ||
| return path.join(process.cwd(), '.sentry/.defaultBabelTransformerPath'); | ||
| } | ||
|
|
||
| /** | ||
| * Loads default Babel transformer from `@react-native/metro-config` -> `@react-native/metro-babel-transformer`. | ||
| */ | ||
| export function loadDefaultBabelTransformer(): BabelTransformer { | ||
| const defaultBabelTransformerPath = readDefaultBabelTransformerPath(); | ||
| if (!defaultBabelTransformerPath) { | ||
| throw new Error('Default Babel Transformer Path not found in `.sentry` directory.'); | ||
| } | ||
|
|
||
| logger.debug(`Loading default Babel transformer from ${defaultBabelTransformerPath}`); | ||
| // eslint-disable-next-line @typescript-eslint/no-var-requires | ||
| return require(defaultBabelTransformerPath); | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.