Skip to content

Commit 5bf9f51

Browse files
authored
Merge branch 'develop' into ryan953/replay-maskFn-docs
2 parents 0354135 + ad3547d commit 5bf9f51

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+1504
-387
lines changed

.github/workflows/build.yml

Lines changed: 1 addition & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -253,43 +253,6 @@ jobs:
253253
# `job_build` can't see `job_install_deps` and what it returned)
254254
dependency_cache_key: ${{ needs.job_install_deps.outputs.dependency_cache_key }}
255255

256-
job_pack_aws_lambda_layer:
257-
name: Pack and Upload AWS Lambda Layer
258-
needs: [job_get_metadata, job_build]
259-
# only upload the zipped layer file if we're about to release
260-
if: startsWith(github.ref, 'refs/heads/release/')
261-
runs-on: ubuntu-20.04
262-
steps:
263-
- name: Check out current commit (${{ needs.job_get_metadata.outputs.commit_label }})
264-
uses: actions/checkout@v3
265-
with:
266-
ref: ${{ env.HEAD_COMMIT }}
267-
- name: Set up Node
268-
uses: actions/setup-node@v3
269-
with:
270-
node-version-file: 'package.json'
271-
- name: Restore caches
272-
uses: ./.github/actions/restore-cache
273-
env:
274-
DEPENDENCY_CACHE_KEY: ${{ needs.job_build.outputs.dependency_cache_key }}
275-
276-
- name: Get SDK version
277-
# `jq` reads JSON files, and `tee` pipes its input to the given location and to stdout. (Adding `-a` is the
278-
# equivalent of using >> rather than >.)
279-
run: |
280-
export SDK_VERSION=$(cat packages/core/package.json | jq --raw-output '.version')
281-
echo "SDK_VERSION=$SDK_VERSION" | tee -a $GITHUB_ENV
282-
- name: Move dist-serverless to root directory (requirement for zipping action)
283-
run: |
284-
mv ./packages/serverless/build/aws/dist-serverless .
285-
- name: Create and upload final zip file
286-
uses: getsentry/action-build-aws-lambda-extension@v1
287-
with:
288-
artifact_name: ${{ env.HEAD_COMMIT }}
289-
zip_file_name: sentry-node-serverless-${{ env.SDK_VERSION }}.zip
290-
build_cache_paths: ${{ env.CACHED_BUILD_PATHS }}
291-
build_cache_key: ${{ env.BUILD_CACHE_KEY }}
292-
293256
job_size_check:
294257
name: Size Check
295258
needs: [job_get_metadata, job_build]
@@ -399,6 +362,7 @@ jobs:
399362
${{ github.workspace }}/packages/integrations/build/bundles/**
400363
${{ github.workspace }}/packages/replay/build/bundles/**
401364
${{ github.workspace }}/packages/**/*.tgz
365+
${{ github.workspace }}/packages/serverless/build/aws/dist-serverless/*.zip
402366
403367
job_browser_unit_tests:
404368
name: Browser Unit Tests

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
## Unreleased
44

5+
- feat(replay): Add `beforeAddRecordingEvent` Replay option
6+
57
- "You miss 100 percent of the chances you don't take. — Wayne Gretzky" — Michael Scott
68

79
## 7.52.1

packages/core/src/api.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,10 @@ export function getReportDialogEndpoint(
5858
},
5959
): string {
6060
const dsn = makeDsn(dsnLike);
61+
if (!dsn) {
62+
return '';
63+
}
64+
6165
const endpoint = `${getBaseApiEndpoint(dsn)}embed/error-page/`;
6266

6367
let encodedOptions = `dsn=${dsnToString(dsn)}`;

packages/core/src/baseclient.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,16 +112,20 @@ export abstract class BaseClient<O extends ClientOptions> implements Client<O> {
112112
*/
113113
protected constructor(options: O) {
114114
this._options = options;
115+
115116
if (options.dsn) {
116117
this._dsn = makeDsn(options.dsn);
118+
} else {
119+
__DEBUG_BUILD__ && logger.warn('No DSN provided, client will not do anything.');
120+
}
121+
122+
if (this._dsn) {
117123
const url = getEnvelopeEndpointWithUrlEncodedAuth(this._dsn, options);
118124
this._transport = options.transport({
119125
recordDroppedEvent: this.recordDroppedEvent.bind(this),
120126
...options.transportOptions,
121127
url,
122128
});
123-
} else {
124-
__DEBUG_BUILD__ && logger.warn('No DSN provided, client will not do anything.');
125129
}
126130
}
127131

packages/core/src/transports/multiplexed.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,13 @@ export function makeMultiplexedTransport<TO extends BaseTransportOptions>(
5151
const fallbackTransport = createTransport(options);
5252
const otherTransports: Record<string, Transport> = {};
5353

54-
function getTransport(dsn: string): Transport {
54+
function getTransport(dsn: string): Transport | undefined {
5555
if (!otherTransports[dsn]) {
56-
const url = getEnvelopeEndpointWithUrlEncodedAuth(dsnFromString(dsn));
56+
const validatedDsn = dsnFromString(dsn);
57+
if (!validatedDsn) {
58+
return undefined;
59+
}
60+
const url = getEnvelopeEndpointWithUrlEncodedAuth(validatedDsn);
5761
otherTransports[dsn] = createTransport({ ...options, url });
5862
}
5963

@@ -66,7 +70,9 @@ export function makeMultiplexedTransport<TO extends BaseTransportOptions>(
6670
return eventFromEnvelope(envelope, eventTypes);
6771
}
6872

69-
const transports = matcher({ envelope, getEvent }).map(dsn => getTransport(dsn));
73+
const transports = matcher({ envelope, getEvent })
74+
.map(dsn => getTransport(dsn))
75+
.filter((t): t is Transport => !!t);
7076

7177
// If we have no transports to send to, use the fallback transport
7278
if (transports.length === 0) {

packages/core/test/lib/api.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ const dsnPublic = 'https://[email protected]:1234/subpath/123';
99
const tunnel = 'https://hello.com/world';
1010
const _metadata = { sdk: { name: 'sentry.javascript.browser', version: '12.31.12' } } as ClientOptions['_metadata'];
1111

12-
const dsnPublicComponents = makeDsn(dsnPublic);
12+
const dsnPublicComponents = makeDsn(dsnPublic)!;
1313

1414
describe('API', () => {
1515
describe('getEnvelopeEndpointWithUrlEncodedAuth', () => {

packages/core/test/lib/base.test.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -70,19 +70,19 @@ describe('BaseClient', () => {
7070
});
7171

7272
test('allows missing Dsn', () => {
73-
expect.assertions(1);
74-
7573
const options = getDefaultTestClientOptions();
7674
const client = new TestClient(options);
7775

7876
expect(client.getDsn()).toBeUndefined();
77+
expect(client.getTransport()).toBeUndefined();
7978
});
8079

81-
test('throws with invalid Dsn', () => {
82-
expect.assertions(1);
83-
80+
test('handles being passed an invalid Dsn', () => {
8481
const options = getDefaultTestClientOptions({ dsn: 'abc' });
85-
expect(() => new TestClient(options)).toThrow(SentryError);
82+
const client = new TestClient(options);
83+
84+
expect(client.getDsn()).toBeUndefined();
85+
expect(client.getTransport()).toBeUndefined();
8686
});
8787
});
8888

packages/core/test/lib/transports/multiplexed.test.ts

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,10 @@ import { TextEncoder } from 'util';
1212
import { createTransport, getEnvelopeEndpointWithUrlEncodedAuth, makeMultiplexedTransport } from '../../../src';
1313

1414
const DSN1 = 'https://[email protected]/4321';
15-
const DSN1_URL = getEnvelopeEndpointWithUrlEncodedAuth(dsnFromString(DSN1));
15+
const DSN1_URL = getEnvelopeEndpointWithUrlEncodedAuth(dsnFromString(DSN1)!);
1616

1717
const DSN2 = 'https://[email protected]/8765';
18-
const DSN2_URL = getEnvelopeEndpointWithUrlEncodedAuth(dsnFromString(DSN2));
18+
const DSN2_URL = getEnvelopeEndpointWithUrlEncodedAuth(dsnFromString(DSN2)!);
1919

2020
const ERROR_EVENT = { event_id: 'aa3ff046696b4bc6b609ce6d28fde9e2' };
2121
const ERROR_ENVELOPE = createEnvelope<EventEnvelope>({ event_id: 'aa3ff046696b4bc6b609ce6d28fde9e2', sent_at: '123' }, [
@@ -83,6 +83,20 @@ describe('makeMultiplexedTransport', () => {
8383
await transport.send(ERROR_ENVELOPE);
8484
});
8585

86+
it('Falls back to options DSN when a matched DSN is invalid', async () => {
87+
expect.assertions(1);
88+
89+
const makeTransport = makeMultiplexedTransport(
90+
createTestTransport(url => {
91+
expect(url).toBe(DSN1_URL);
92+
}),
93+
() => ['invalidDsn'],
94+
);
95+
96+
const transport = makeTransport({ url: DSN1_URL, ...transportOptions });
97+
await transport.send(ERROR_ENVELOPE);
98+
});
99+
86100
it('DSN can be overridden via match callback', async () => {
87101
expect.assertions(1);
88102

packages/core/test/lib/transports/offline.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ const REPLAY_EVENT: ReplayEvent = {
3838
replay_type: 'buffer',
3939
};
4040

41-
const DSN = dsnFromString('https://[email protected]/1337');
41+
const DSN = dsnFromString('https://[email protected]/1337')!;
4242

4343
const DATA = 'nothing';
4444

packages/nextjs/src/client/index.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,13 @@ function addClientIntegrations(options: BrowserOptions): void {
123123
options.integrations = integrations;
124124
}
125125

126+
/**
127+
* Just a passthrough in case this is imported from the client.
128+
*/
129+
export function withSentryConfig<T>(exportedUserNextConfig: T): T {
130+
return exportedUserNextConfig;
131+
}
132+
126133
export {
127134
// eslint-disable-next-line deprecation/deprecation
128135
withSentryServerSideGetInitialProps,

packages/nextjs/src/client/tunnelRoute.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ export function applyTunnelRouteOption(options: BrowserOptions): void {
1212
const tunnelRouteOption = globalWithInjectedValues.__sentryRewritesTunnelPath__;
1313
if (tunnelRouteOption && options.dsn) {
1414
const dsnComponents = dsnFromString(options.dsn);
15+
if (!dsnComponents) {
16+
return;
17+
}
1518
const sentrySaasDsnMatch = dsnComponents.host.match(/^o(\d+)\.ingest\.sentry\.io$/);
1619
if (sentrySaasDsnMatch) {
1720
const orgId = sentrySaasDsnMatch[1];

packages/nextjs/src/config/loaders/wrappingLoader.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -202,8 +202,13 @@ export default function wrappingLoader(
202202
templateCode = templateCode.replace(/__COMPONENT_TYPE__/g, 'Unknown');
203203
}
204204

205-
if (sentryConfigFilePath) {
206-
templateCode = `import "${sentryConfigFilePath}";`.concat(templateCode);
205+
// We check whether `this.resourcePath` is absolute because there is no contract by webpack that says it is absolute,
206+
// however we can only create relative paths to the sentry config from absolute paths.Examples where this could possibly be non - absolute are virtual modules.
207+
if (sentryConfigFilePath && path.isAbsolute(this.resourcePath)) {
208+
const sentryConfigImportPath = path
209+
.relative(path.dirname(this.resourcePath), sentryConfigFilePath) // Absolute paths do not work with Windows: https://github.com/getsentry/sentry-javascript/issues/8133
210+
.replace(/\\/g, '/');
211+
templateCode = `import "${sentryConfigImportPath}";\n`.concat(templateCode);
207212
}
208213
} else if (wrappingTargetKind === 'middleware') {
209214
templateCode = middlewareWrapperTemplateCode;

packages/nextjs/src/edge/index.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,13 @@ export function lastEventId(): string | undefined {
126126
return getCurrentHub().lastEventId();
127127
}
128128

129+
/**
130+
* Just a passthrough in case this is imported from the client.
131+
*/
132+
export function withSentryConfig<T>(exportedUserNextConfig: T): T {
133+
return exportedUserNextConfig;
134+
}
135+
129136
export { flush } from './utils/flush';
130137

131138
export * from '@sentry/core';

packages/nextjs/src/index.types.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ export declare const withErrorBoundary: typeof clientSdk.withErrorBoundary;
3939
export declare const Span: typeof edgeSdk.Span;
4040
export declare const Transaction: typeof edgeSdk.Transaction;
4141

42+
export { withSentryConfig } from './config';
43+
4244
/**
4345
* @deprecated Use `wrapApiHandlerWithSentry` instead
4446
*/

packages/nextjs/test/integration/test/client/tracingFetch.test.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,12 @@ test('should correctly instrument `fetch` for performance tracing', async ({ pag
3131
expect(transaction[0].spans).toEqual(
3232
expect.arrayContaining([
3333
expect.objectContaining({
34-
data: { 'http.method': 'GET', url: 'http://example.com', type: 'fetch' },
34+
data: {
35+
'http.method': 'GET',
36+
url: 'http://example.com',
37+
type: 'fetch',
38+
'http.response_content_length': expect.any(Number),
39+
},
3540
description: 'GET http://example.com',
3641
op: 'http.client',
3742
parent_span_id: expect.any(String),

packages/nextjs/test/integration/test/server/utils/helpers.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import next from 'next';
99
// Type not exported from NextJS
1010
// @ts-ignore
1111
export const createNextServer = async config => {
12-
const app = next(config);
12+
const app = next({ ...config, customServer: false }); // customServer: false because: https://github.com/vercel/next.js/pull/49805#issuecomment-1557321794
1313
const handle = app.getRequestHandler();
1414
await app.prepare();
1515

packages/nextjs/test/utils/tunnelRoute.test.ts

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ beforeEach(() => {
1111
});
1212

1313
describe('applyTunnelRouteOption()', () => {
14-
it('should correctly apply `tunnelRoute` option when conditions are met', () => {
14+
it('Correctly applies `tunnelRoute` option when conditions are met', () => {
1515
globalWithInjectedValues.__sentryRewritesTunnelPath__ = '/my-error-monitoring-route';
1616
const options: any = {
1717
dsn: 'https://[email protected]/3333333',
@@ -22,7 +22,7 @@ describe('applyTunnelRouteOption()', () => {
2222
expect(options.tunnel).toBe('/my-error-monitoring-route?o=2222222&p=3333333');
2323
});
2424

25-
it('should not apply `tunnelRoute` when DSN is missing', () => {
25+
it("Doesn't apply `tunnelRoute` when DSN is missing", () => {
2626
globalWithInjectedValues.__sentryRewritesTunnelPath__ = '/my-error-monitoring-route';
2727
const options: any = {
2828
// no dsn
@@ -33,7 +33,18 @@ describe('applyTunnelRouteOption()', () => {
3333
expect(options.tunnel).toBeUndefined();
3434
});
3535

36-
it("should not apply `tunnelRoute` option when `tunnelRoute` option wasn't injected", () => {
36+
it("Doesn't apply `tunnelRoute` when DSN is invalid", () => {
37+
globalWithInjectedValues.__sentryRewritesTunnelPath__ = '/my-error-monitoring-route';
38+
const options: any = {
39+
dsn: 'invalidDsn',
40+
} as BrowserOptions;
41+
42+
applyTunnelRouteOption(options);
43+
44+
expect(options.tunnel).toBeUndefined();
45+
});
46+
47+
it("Doesn't apply `tunnelRoute` option when `tunnelRoute` option wasn't injected", () => {
3748
const options: any = {
3849
dsn: 'https://[email protected]/3333333',
3950
} as BrowserOptions;
@@ -43,7 +54,7 @@ describe('applyTunnelRouteOption()', () => {
4354
expect(options.tunnel).toBeUndefined();
4455
});
4556

46-
it('should not apply `tunnelRoute` option when DSN is not a SaaS DSN', () => {
57+
it("Doesn't `tunnelRoute` option when DSN is not a SaaS DSN", () => {
4758
globalWithInjectedValues.__sentryRewritesTunnelPath__ = '/my-error-monitoring-route';
4859
const options: any = {
4960
dsn: 'https://[email protected]/3333333',

packages/node/src/client.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,8 @@ export class NodeClient extends BaseClient<NodeClientOptions> {
186186
}
187187

188188
const envelope = createCheckInEnvelope(serializedCheckIn, this.getSdkMetadata(), tunnel, this.getDsn());
189+
190+
__DEBUG_BUILD__ && logger.info('Sending checkin:', checkIn.monitorSlug, checkIn.status);
189191
void this._sendEnvelope(envelope);
190192
return id;
191193
}

packages/node/src/integrations/http.ts

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ function _createWrappedRequestMethodFactory(
138138
): WrappedRequestMethodFactory {
139139
// We're caching results so we don't have to recompute regexp every time we create a request.
140140
const createSpanUrlMap = new LRUMap<string, boolean>(100);
141-
const headersUrlMap: Record<string, boolean> = {};
141+
const headersUrlMap = new LRUMap<string, boolean>(100);
142142

143143
const shouldCreateSpan = (url: string): boolean => {
144144
if (tracingOptions?.shouldCreateSpanForRequest === undefined) {
@@ -160,13 +160,14 @@ function _createWrappedRequestMethodFactory(
160160
return true;
161161
}
162162

163-
if (headersUrlMap[url]) {
164-
return headersUrlMap[url];
163+
const cachedDecision = headersUrlMap.get(url);
164+
if (cachedDecision !== undefined) {
165+
return cachedDecision;
165166
}
166167

167-
headersUrlMap[url] = stringMatchesSomePattern(url, tracingOptions.tracePropagationTargets);
168-
169-
return headersUrlMap[url];
168+
const decision = stringMatchesSomePattern(url, tracingOptions.tracePropagationTargets);
169+
headersUrlMap.set(url, decision);
170+
return decision;
170171
};
171172

172173
return function wrappedRequestMethodFactory(originalRequestMethod: OriginalRequestMethod): WrappedRequestMethod {

0 commit comments

Comments
 (0)