Skip to content

Commit 815a1d6

Browse files
committed
Merge remote-tracking branch 'upstream/master' into feat/stack-locals
2 parents 8635c2d + d9c6887 commit 815a1d6

11 files changed

+214
-154
lines changed

docs/event-sending.md

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
# Event processing & sending
2+
3+
This document gives an outline for how event sending works, and which which places it goes through.
4+
5+
## Errors
6+
7+
* `hub.captureException()`
8+
* `client.captureException()` (see baseclient)
9+
* `checkOrSetAlreadyCaught()`
10+
* `baseclient._process()`
11+
* `baseclient.eventFromException()`
12+
* `baseclient._captureEvent()`
13+
* `baseclient._processEvent()`
14+
* `baseclient._prepareEvent()`
15+
* `baseclient._applyClientOptions()`
16+
* `baseclient._applyIntegrationsMetadata()`
17+
* `scope.applyToEvent()`
18+
* `baseclient._normalizeEvent()`
19+
* `baseclient._updateSessionFromEvent()`
20+
* `baseclient.sendEvent()`
21+
* `createEventEnvelope()`
22+
* `getSdkMetadataForEnvelopeHeader()`
23+
* `enhanceEventWithSdkInfo()`
24+
* `createEventEnvelopeHeaders()`
25+
* `createEnvelope()`
26+
* `addItemToEnvelope()`
27+
* `createAttachmentEnvelopeItem()`
28+
* `baseclient._sendEnvelope()`
29+
* `transport.send()`
30+
31+
## Transactions
32+
33+
* `transaction.finish()`
34+
* `transaction.getTraceContext()`
35+
* `transaction.getDynamicSamplingContext()`
36+
* `hub.captureEvent()`
37+
* `client.captureEvent()` (see baseclient)
38+
* `checkOrSetAlreadyCaught()`
39+
* `baseclient._process()`
40+
* `baseclient.eventFromException()`
41+
* `baseclient._captureEvent()`
42+
* `baseclient._processEvent()`
43+
* `baseclient._prepareEvent()`
44+
* `baseclient._applyClientOptions()`
45+
* `baseclient._applyIntegrationsMetadata()`
46+
* `scope.applyToEvent()`
47+
* `baseclient._normalizeEvent()`
48+
* `baseclient._updateSessionFromEvent()`
49+
* `baseclient.sendEvent()`
50+
* `createEventEnvelope()`
51+
* `getSdkMetadataForEnvelopeHeader()`
52+
* `enhanceEventWithSdkInfo()`
53+
* `createEventEnvelopeHeaders()`
54+
* `createEnvelope()`
55+
* `addItemToEnvelope()`
56+
* `createAttachmentEnvelopeItem()`
57+
* `baseclient._sendEnvelope()`
58+
* `transport.send()`
59+
60+
## Sessions
61+
62+
* `hub.captureSession()`
63+
* `hub.endSession()`
64+
* `closeSession()`
65+
* `hub._sendSessionUpdate()`
66+
* `scope.setSession()`
67+
* `hub._sendSessionUpdate()`
68+
* `client.captureSession()` (see baseclient)
69+
* `baseclient.sendSession()`
70+
* `createSessionEnvelope()`
71+
* `getSdkMetadataForEnvelopeHeader()`
72+
* `createEnvelope()`
73+
* `baseclient._sendEnvelope()`
74+
* `transport.send()`
75+
* `updateSession()`
76+
77+
## Replay (WIP)
78+
79+
* `replay.sendReplayRequest()`
80+
* `createPayload()`
81+
* `getReplayEvent()`
82+
* `client._prepareEvent()` (see baseclient)
83+
* `baseclient._applyClientOptions()`
84+
* `baseclient._applyIntegrationsMetadata()`
85+
* `scope.applyToEvent()`
86+
* `baseclient._normalizeEvent()`
87+
* `baseclient._updateSessionFromEvent()`
88+
* `createReplayEnvelope()`
89+
* `createEnvelope()`
90+
* `transport.send()`
91+
92+
## Client Reports
93+
94+
* `browser.client.constructor()`
95+
* `browser.client._flushOutcomes()`
96+
* `getEnvelopeEndpointWithUrlEncodedAuth()`
97+
* `createClientReportEnvelope()`
98+
* `baseclient._sendEnvelope()`
99+
* `transport.send()`

packages/nextjs/rollup.npm.config.js

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,6 @@ export default [
2020
...makeNPMConfigVariants(
2121
makeBaseNPMConfig({
2222
entrypoints: [
23-
'src/config/templates/serverRewriteFramesPrefixLoaderTemplate.ts',
24-
'src/config/templates/clientRewriteFramesPrefixLoaderTemplate.ts',
25-
'src/config/templates/releasePrefixLoaderTemplate.ts',
2623
'src/config/templates/pageProxyLoaderTemplate.ts',
2724
'src/config/templates/apiProxyLoaderTemplate.ts',
2825
],
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
1+
export { default as valueInjectionLoader } from './valueInjectionLoader';
12
export { default as prefixLoader } from './prefixLoader';
23
export { default as proxyLoader } from './proxyLoader';
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { LoaderThis } from './types';
2+
3+
type LoaderOptions = {
4+
values: Record<string, unknown>;
5+
};
6+
7+
/**
8+
* Set values on the global/window object at the start of a module.
9+
*
10+
* Options:
11+
* - `values`: An object where the keys correspond to the keys of the global values to set and the values
12+
* correspond to the values of the values on the global object. Values must be JSON serializable.
13+
*/
14+
export default function valueInjectionLoader(this: LoaderThis<LoaderOptions>, userCode: string): string {
15+
// We know one or the other will be defined, depending on the version of webpack being used
16+
const { values } = 'getOptions' in this ? this.getOptions() : this.query;
17+
18+
// Define some global proxy that works on server and on the browser.
19+
let injectedCode = 'var _sentryCollisionFreeGlobalObject = typeof window === "undefined" ? global : window;\n';
20+
21+
Object.entries(values).forEach(([key, value]) => {
22+
injectedCode += `_sentryCollisionFreeGlobalObject["${key}"] = ${JSON.stringify(value)};\n`;
23+
});
24+
25+
return `${injectedCode}\n${userCode}`;
26+
}

packages/nextjs/src/config/templates/clientRewriteFramesPrefixLoaderTemplate.ts

Lines changed: 0 additions & 9 deletions
This file was deleted.

packages/nextjs/src/config/templates/releasePrefixLoaderTemplate.ts

Lines changed: 0 additions & 16 deletions
This file was deleted.

packages/nextjs/src/config/templates/serverRewriteFramesPrefixLoaderTemplate.ts

Lines changed: 0 additions & 6 deletions
This file was deleted.

packages/nextjs/src/config/webpack.ts

Lines changed: 66 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -87,26 +87,8 @@ export function constructWebpackConfigFunction(
8787
// `newConfig.module.rules` is required, so we don't have to keep asserting its existence
8888
const newConfig = setUpModuleRules(rawNewConfig);
8989

90-
// Add a loader which will inject code that sets global values for use by `RewriteFrames`
91-
addRewriteFramesLoader(newConfig, isServer ? 'server' : 'client', userNextConfig);
92-
93-
newConfig.module.rules.push({
94-
test: /sentry\.(server|client)\.config\.(jsx?|tsx?)/,
95-
use: [
96-
{
97-
// Inject the release value the same way the webpack plugin does.
98-
loader: path.resolve(__dirname, 'loaders/prefixLoader.js'),
99-
options: {
100-
templatePrefix: 'release',
101-
replacements: [
102-
['__RELEASE__', webpackPluginOptions.release || process.env.SENTRY_RELEASE],
103-
['__ORG__', webpackPluginOptions.org || process.env.SENTRY_ORG],
104-
['__PROJECT__', webpackPluginOptions.project || process.env.SENTRY_PROJECT || ''],
105-
],
106-
},
107-
},
108-
],
109-
});
90+
// Add a loader which will inject code that sets global values
91+
addValueInjectionLoader(newConfig, userNextConfig, webpackPluginOptions);
11092

11193
if (isServer) {
11294
if (userSentryOptions.autoInstrumentServerFunctions !== false) {
@@ -667,49 +649,76 @@ function setUpModuleRules(newConfig: WebpackConfigObject): WebpackConfigObjectWi
667649
}
668650

669651
/**
670-
* Support the `distDir` and `assetPrefix` options by making their values (easy to get here at build-time) available at
671-
* runtime (for use by `RewriteFrames`), by injecting code to attach their values to `global` or `window`.
672-
*
673-
* @param newConfig The webpack config object being constructed
674-
* @param target Either 'server' or 'client'
675-
* @param userNextConfig The user's nextjs config options
652+
* Adds loaders to inject values on the global object based on user configuration.
676653
*/
677-
function addRewriteFramesLoader(
654+
function addValueInjectionLoader(
678655
newConfig: WebpackConfigObjectWithModuleRules,
679-
target: 'server' | 'client',
680656
userNextConfig: NextConfigObject,
657+
webpackPluginOptions: SentryWebpackPlugin.SentryCliPluginOptions,
681658
): void {
682-
// Nextjs will use `basePath` in place of `assetPrefix` if it's defined but `assetPrefix` is not
683659
const assetPrefix = userNextConfig.assetPrefix || userNextConfig.basePath || '';
684-
const replacements = {
685-
server: [
686-
[
687-
'__DIST_DIR__',
688-
// Make sure that if we have a windows path, the backslashes are interpreted as such (rather than as escape
689-
// characters)
690-
userNextConfig.distDir?.replace(/\\/g, '\\\\') || '.next',
691-
],
692-
],
693-
client: [
694-
[
695-
'__ASSET_PREFIX_PATH__',
696-
// Get the path part of `assetPrefix`, minus any trailing slash. (We use a placeholder for the origin if
697-
// `assetPreix` doesn't include one. Since we only care about the path, it doesn't matter what it is.)
698-
assetPrefix ? new URL(assetPrefix, 'http://dogs.are.great').pathname.replace(/\/$/, '') : '',
699-
],
700-
],
660+
const releaseValue = webpackPluginOptions.release || process.env.SENTRY_RELEASE;
661+
const orgValue = webpackPluginOptions.org || process.env.SENTRY_ORG;
662+
const projectValue = webpackPluginOptions.project || process.env.SENTRY_PROJECT;
663+
664+
const isomorphicValues = {
665+
// Inject release into SDK
666+
...(releaseValue
667+
? {
668+
SENTRY_RELEASE: {
669+
id: releaseValue,
670+
},
671+
}
672+
: undefined),
673+
674+
// Enable module federation support (see https://github.com/getsentry/sentry-webpack-plugin/pull/307)
675+
...(projectValue && releaseValue
676+
? {
677+
SENTRY_RELEASES: {
678+
[orgValue ? `${projectValue}@${orgValue}` : projectValue]: { id: releaseValue },
679+
},
680+
}
681+
: undefined),
701682
};
702683

703-
newConfig.module.rules.push({
704-
test: new RegExp(`sentry\\.${target}\\.config\\.(jsx?|tsx?)`),
705-
use: [
706-
{
707-
loader: path.resolve(__dirname, 'loaders/prefixLoader.js'),
708-
options: {
709-
templatePrefix: `${target}RewriteFrames`,
710-
replacements: replacements[target],
684+
const serverValues = {
685+
...isomorphicValues,
686+
// Make sure that if we have a windows path, the backslashes are interpreted as such (rather than as escape
687+
// characters)
688+
__rewriteFramesDistDir__: userNextConfig.distDir?.replace(/\\/g, '\\\\') || '.next',
689+
};
690+
691+
const clientValues = {
692+
...isomorphicValues,
693+
// Get the path part of `assetPrefix`, minus any trailing slash. (We use a placeholder for the origin if
694+
// `assetPreix` doesn't include one. Since we only care about the path, it doesn't matter what it is.)
695+
__rewriteFramesAssetPrefixPath__: assetPrefix
696+
? new URL(assetPrefix, 'http://dogs.are.great').pathname.replace(/\/$/, '')
697+
: '',
698+
};
699+
700+
newConfig.module.rules.push(
701+
{
702+
test: /sentry\.server\.config\.(jsx?|tsx?)/,
703+
use: [
704+
{
705+
loader: path.resolve(__dirname, 'loaders/valueInjectionLoader.js'),
706+
options: {
707+
values: serverValues,
708+
},
711709
},
712-
},
713-
],
714-
});
710+
],
711+
},
712+
{
713+
test: /sentry\.client\.config\.(jsx?|tsx?)/,
714+
use: [
715+
{
716+
loader: path.resolve(__dirname, 'loaders/valueInjectionLoader.js'),
717+
options: {
718+
values: clientValues,
719+
},
720+
},
721+
],
722+
},
723+
);
715724
}

packages/nextjs/src/index.client.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,10 @@ declare const __SENTRY_TRACING__: boolean;
3535
// https://github.com/vercel/next.js/blob/166e5fb9b92f64c4b5d1f6560a05e2b9778c16fb/packages/next/build/webpack-config.ts#L206
3636
declare const EdgeRuntime: string | undefined;
3737

38-
type GlobalWithAssetPrefixPath = typeof global & { __rewriteFramesAssetPrefixPath__: string };
38+
const globalWithInjectedValues = global as typeof global & {
39+
__rewriteFramesAssetPrefixPath__: string;
40+
__sentryRewritesTunnelPath__?: string;
41+
};
3942

4043
/** Inits the Sentry NextJS SDK on the browser with the React SDK. */
4144
export function init(options: NextjsOptions): void {
@@ -67,7 +70,7 @@ function addClientIntegrations(options: NextjsOptions): void {
6770

6871
// This value is injected at build time, based on the output directory specified in the build config. Though a default
6972
// is set there, we set it here as well, just in case something has gone wrong with the injection.
70-
const assetPrefixPath = (global as GlobalWithAssetPrefixPath).__rewriteFramesAssetPrefixPath__ || '';
73+
const assetPrefixPath = globalWithInjectedValues.__rewriteFramesAssetPrefixPath__ || '';
7174

7275
const defaultRewriteFramesIntegration = new RewriteFrames({
7376
// Turn `<origin>/<path>/_next/static/...` into `app:///_next/static/...`

packages/nextjs/src/index.server.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,10 @@ export { captureUnderscoreErrorException } from './utils/_error';
1919
// because or SSR of next.js we can only use this.
2020
export { ErrorBoundary, showReportDialog, withErrorBoundary } from '@sentry/react';
2121

22-
type GlobalWithDistDir = typeof global & { __rewriteFramesDistDir__: string };
22+
const globalWithInjectedValues = global as typeof global & {
23+
__rewriteFramesDistDir__: string;
24+
};
25+
2326
const domain = domainModule as typeof domainModule & { active: (domainModule.Domain & Carrier) | null };
2427

2528
// This is a variable that Next.js will string replace during build with a string if run in an edge runtime from Next.js
@@ -114,7 +117,7 @@ function addServerIntegrations(options: NextjsOptions): void {
114117

115118
// This value is injected at build time, based on the output directory specified in the build config. Though a default
116119
// is set there, we set it here as well, just in case something has gone wrong with the injection.
117-
const distDirName = (global as GlobalWithDistDir).__rewriteFramesDistDir__ || '.next';
120+
const distDirName = globalWithInjectedValues.__rewriteFramesDistDir__ || '.next';
118121
// nextjs always puts the build directory at the project root level, which is also where you run `next start` from, so
119122
// we can read in the project directory from the currently running process
120123
const distDirAbsPath = path.resolve(process.cwd(), distDirName);

0 commit comments

Comments
 (0)