Skip to content

meta(changelog): Update changelog for 7.52.2 #8148

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

Closed
wants to merge 16 commits into from
Closed
Show file tree
Hide file tree
Changes from all 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
38 changes: 1 addition & 37 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -253,43 +253,6 @@ jobs:
# `job_build` can't see `job_install_deps` and what it returned)
dependency_cache_key: ${{ needs.job_install_deps.outputs.dependency_cache_key }}

job_pack_aws_lambda_layer:
name: Pack and Upload AWS Lambda Layer
needs: [job_get_metadata, job_build]
# only upload the zipped layer file if we're about to release
if: startsWith(github.ref, 'refs/heads/release/')
runs-on: ubuntu-20.04
steps:
- name: Check out current commit (${{ needs.job_get_metadata.outputs.commit_label }})
uses: actions/checkout@v3
with:
ref: ${{ env.HEAD_COMMIT }}
- name: Set up Node
uses: actions/setup-node@v3
with:
node-version-file: 'package.json'
- name: Restore caches
uses: ./.github/actions/restore-cache
env:
DEPENDENCY_CACHE_KEY: ${{ needs.job_build.outputs.dependency_cache_key }}

- name: Get SDK version
# `jq` reads JSON files, and `tee` pipes its input to the given location and to stdout. (Adding `-a` is the
# equivalent of using >> rather than >.)
run: |
export SDK_VERSION=$(cat packages/core/package.json | jq --raw-output '.version')
echo "SDK_VERSION=$SDK_VERSION" | tee -a $GITHUB_ENV
- name: Move dist-serverless to root directory (requirement for zipping action)
run: |
mv ./packages/serverless/build/aws/dist-serverless .
- name: Create and upload final zip file
uses: getsentry/action-build-aws-lambda-extension@v1
with:
artifact_name: ${{ env.HEAD_COMMIT }}
zip_file_name: sentry-node-serverless-${{ env.SDK_VERSION }}.zip
build_cache_paths: ${{ env.CACHED_BUILD_PATHS }}
build_cache_key: ${{ env.BUILD_CACHE_KEY }}

job_size_check:
name: Size Check
needs: [job_get_metadata, job_build]
Expand Down Expand Up @@ -399,6 +362,7 @@ jobs:
${{ github.workspace }}/packages/integrations/build/bundles/**
${{ github.workspace }}/packages/replay/build/bundles/**
${{ github.workspace }}/packages/**/*.tgz
${{ github.workspace }}/packages/serverless/build/aws/dist-serverless/*.zip

job_browser_unit_tests:
name: Browser Unit Tests
Expand Down
14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,20 @@

- "You miss 100 percent of the chances you don't take. — Wayne Gretzky" — Michael Scott

## 7.52.2

- feat(replay): Do not capture replays < 5 seconds (#7949)
- fix(nextjs): Import path issue on Windows (#8142)
- fix(node): Add debug logging for node checkin (#8131)
- fix(node): Add LRU map for tracePropagationTargets calculation (#8130)
- fix(node): remove new URL usage in Undici integration (#8147)
- fix(sveltekit): Avoid double-wrapping load functions (#8094)
- fix(tracing): Change where content-length gets added (#8139)
- fix(tracing): Use integer for content length (#8152)
- fix(utils): Fail silently if the provided Dsn is invalid (#8121)
- ref(node): Cache undici trace propagation decisions (#8136)
- ref(serverless): Remove relay extension from AWS Layer (#8080)

## 7.52.1

- feat(replay): Capture slow clicks (experimental) (#8052)
Expand Down
4 changes: 4 additions & 0 deletions packages/core/src/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,10 @@ export function getReportDialogEndpoint(
},
): string {
const dsn = makeDsn(dsnLike);
if (!dsn) {
return '';
}

const endpoint = `${getBaseApiEndpoint(dsn)}embed/error-page/`;

let encodedOptions = `dsn=${dsnToString(dsn)}`;
Expand Down
8 changes: 6 additions & 2 deletions packages/core/src/baseclient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,16 +112,20 @@ export abstract class BaseClient<O extends ClientOptions> implements Client<O> {
*/
protected constructor(options: O) {
this._options = options;

if (options.dsn) {
this._dsn = makeDsn(options.dsn);
} else {
__DEBUG_BUILD__ && logger.warn('No DSN provided, client will not do anything.');
}

if (this._dsn) {
const url = getEnvelopeEndpointWithUrlEncodedAuth(this._dsn, options);
this._transport = options.transport({
recordDroppedEvent: this.recordDroppedEvent.bind(this),
...options.transportOptions,
url,
});
} else {
__DEBUG_BUILD__ && logger.warn('No DSN provided, client will not do anything.');
}
}

Expand Down
12 changes: 9 additions & 3 deletions packages/core/src/transports/multiplexed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,13 @@ export function makeMultiplexedTransport<TO extends BaseTransportOptions>(
const fallbackTransport = createTransport(options);
const otherTransports: Record<string, Transport> = {};

function getTransport(dsn: string): Transport {
function getTransport(dsn: string): Transport | undefined {
if (!otherTransports[dsn]) {
const url = getEnvelopeEndpointWithUrlEncodedAuth(dsnFromString(dsn));
const validatedDsn = dsnFromString(dsn);
if (!validatedDsn) {
return undefined;
}
const url = getEnvelopeEndpointWithUrlEncodedAuth(validatedDsn);
otherTransports[dsn] = createTransport({ ...options, url });
}

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

const transports = matcher({ envelope, getEvent }).map(dsn => getTransport(dsn));
const transports = matcher({ envelope, getEvent })
.map(dsn => getTransport(dsn))
.filter((t): t is Transport => !!t);

// If we have no transports to send to, use the fallback transport
if (transports.length === 0) {
Expand Down
2 changes: 1 addition & 1 deletion packages/core/test/lib/api.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ const dsnPublic = 'https://abc@sentry.io:1234/subpath/123';
const tunnel = 'https://hello.com/world';
const _metadata = { sdk: { name: 'sentry.javascript.browser', version: '12.31.12' } } as ClientOptions['_metadata'];

const dsnPublicComponents = makeDsn(dsnPublic);
const dsnPublicComponents = makeDsn(dsnPublic)!;

describe('API', () => {
describe('getEnvelopeEndpointWithUrlEncodedAuth', () => {
Expand Down
12 changes: 6 additions & 6 deletions packages/core/test/lib/base.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,19 +70,19 @@ describe('BaseClient', () => {
});

test('allows missing Dsn', () => {
expect.assertions(1);

const options = getDefaultTestClientOptions();
const client = new TestClient(options);

expect(client.getDsn()).toBeUndefined();
expect(client.getTransport()).toBeUndefined();
});

test('throws with invalid Dsn', () => {
expect.assertions(1);

test('handles being passed an invalid Dsn', () => {
const options = getDefaultTestClientOptions({ dsn: 'abc' });
expect(() => new TestClient(options)).toThrow(SentryError);
const client = new TestClient(options);

expect(client.getDsn()).toBeUndefined();
expect(client.getTransport()).toBeUndefined();
});
});

Expand Down
18 changes: 16 additions & 2 deletions packages/core/test/lib/transports/multiplexed.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ import { TextEncoder } from 'util';
import { createTransport, getEnvelopeEndpointWithUrlEncodedAuth, makeMultiplexedTransport } from '../../../src';

const DSN1 = 'https://1234@5678.ingest.sentry.io/4321';
const DSN1_URL = getEnvelopeEndpointWithUrlEncodedAuth(dsnFromString(DSN1));
const DSN1_URL = getEnvelopeEndpointWithUrlEncodedAuth(dsnFromString(DSN1)!);

const DSN2 = 'https://5678@1234.ingest.sentry.io/8765';
const DSN2_URL = getEnvelopeEndpointWithUrlEncodedAuth(dsnFromString(DSN2));
const DSN2_URL = getEnvelopeEndpointWithUrlEncodedAuth(dsnFromString(DSN2)!);

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

it('Falls back to options DSN when a matched DSN is invalid', async () => {
expect.assertions(1);

const makeTransport = makeMultiplexedTransport(
createTestTransport(url => {
expect(url).toBe(DSN1_URL);
}),
() => ['invalidDsn'],
);

const transport = makeTransport({ url: DSN1_URL, ...transportOptions });
await transport.send(ERROR_ENVELOPE);
});

it('DSN can be overridden via match callback', async () => {
expect.assertions(1);

Expand Down
2 changes: 1 addition & 1 deletion packages/core/test/lib/transports/offline.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ const REPLAY_EVENT: ReplayEvent = {
replay_type: 'buffer',
};

const DSN = dsnFromString('https://public@dsn.ingest.sentry.io/1337');
const DSN = dsnFromString('https://public@dsn.ingest.sentry.io/1337')!;

const DATA = 'nothing';

Expand Down
3 changes: 3 additions & 0 deletions packages/nextjs/src/client/tunnelRoute.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ export function applyTunnelRouteOption(options: BrowserOptions): void {
const tunnelRouteOption = globalWithInjectedValues.__sentryRewritesTunnelPath__;
if (tunnelRouteOption && options.dsn) {
const dsnComponents = dsnFromString(options.dsn);
if (!dsnComponents) {
return;
}
const sentrySaasDsnMatch = dsnComponents.host.match(/^o(\d+)\.ingest\.sentry\.io$/);
if (sentrySaasDsnMatch) {
const orgId = sentrySaasDsnMatch[1];
Expand Down
10 changes: 9 additions & 1 deletion packages/nextjs/src/config/loaders/wrappingLoader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,15 @@ export default function wrappingLoader(
}

if (sentryConfigFilePath) {
templateCode = `import "${sentryConfigFilePath}";`.concat(templateCode);
let importPath = sentryConfigFilePath;

// absolute paths do not work with Windows
// https://github.com/getsentry/sentry-javascript/issues/8133
if (path.isAbsolute(importPath)) {
importPath = path.relative(path.dirname(this.resourcePath), importPath);
}

templateCode = `import "${importPath.replace(/\\/g, '/')}";\n`.concat(templateCode);
}
} else if (wrappingTargetKind === 'middleware') {
templateCode = middlewareWrapperTemplateCode;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,12 @@ test('should correctly instrument `fetch` for performance tracing', async ({ pag
expect(transaction[0].spans).toEqual(
expect.arrayContaining([
expect.objectContaining({
data: { 'http.method': 'GET', url: 'http://example.com', type: 'fetch' },
data: {
'http.method': 'GET',
url: 'http://example.com',
type: 'fetch',
'http.response_content_length': expect.any(Number),
},
description: 'GET http://example.com',
op: 'http.client',
parent_span_id: expect.any(String),
Expand Down
19 changes: 15 additions & 4 deletions packages/nextjs/test/utils/tunnelRoute.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ beforeEach(() => {
});

describe('applyTunnelRouteOption()', () => {
it('should correctly apply `tunnelRoute` option when conditions are met', () => {
it('Correctly applies `tunnelRoute` option when conditions are met', () => {
globalWithInjectedValues.__sentryRewritesTunnelPath__ = '/my-error-monitoring-route';
const options: any = {
dsn: 'https://11111111111111111111111111111111@o2222222.ingest.sentry.io/3333333',
Expand All @@ -22,7 +22,7 @@ describe('applyTunnelRouteOption()', () => {
expect(options.tunnel).toBe('/my-error-monitoring-route?o=2222222&p=3333333');
});

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

it("should not apply `tunnelRoute` option when `tunnelRoute` option wasn't injected", () => {
it("Doesn't apply `tunnelRoute` when DSN is invalid", () => {
globalWithInjectedValues.__sentryRewritesTunnelPath__ = '/my-error-monitoring-route';
const options: any = {
dsn: 'invalidDsn',
} as BrowserOptions;

applyTunnelRouteOption(options);

expect(options.tunnel).toBeUndefined();
});

it("Doesn't apply `tunnelRoute` option when `tunnelRoute` option wasn't injected", () => {
const options: any = {
dsn: 'https://11111111111111111111111111111111@o2222222.ingest.sentry.io/3333333',
} as BrowserOptions;
Expand All @@ -43,7 +54,7 @@ describe('applyTunnelRouteOption()', () => {
expect(options.tunnel).toBeUndefined();
});

it('should not apply `tunnelRoute` option when DSN is not a SaaS DSN', () => {
it("Doesn't `tunnelRoute` option when DSN is not a SaaS DSN", () => {
globalWithInjectedValues.__sentryRewritesTunnelPath__ = '/my-error-monitoring-route';
const options: any = {
dsn: 'https://11111111111111111111111111111111@example.com/3333333',
Expand Down
2 changes: 2 additions & 0 deletions packages/node/src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,8 @@ export class NodeClient extends BaseClient<NodeClientOptions> {
}

const envelope = createCheckInEnvelope(serializedCheckIn, this.getSdkMetadata(), tunnel, this.getDsn());

__DEBUG_BUILD__ && logger.info('Sending checkin:', checkIn.monitorSlug, checkIn.status);
void this._sendEnvelope(envelope);
return id;
}
Expand Down
13 changes: 7 additions & 6 deletions packages/node/src/integrations/http.ts
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ function _createWrappedRequestMethodFactory(
): WrappedRequestMethodFactory {
// We're caching results so we don't have to recompute regexp every time we create a request.
const createSpanUrlMap = new LRUMap<string, boolean>(100);
const headersUrlMap: Record<string, boolean> = {};
const headersUrlMap = new LRUMap<string, boolean>(100);

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

if (headersUrlMap[url]) {
return headersUrlMap[url];
const cachedDecision = headersUrlMap.get(url);
if (cachedDecision !== undefined) {
return cachedDecision;
}

headersUrlMap[url] = stringMatchesSomePattern(url, tracingOptions.tracePropagationTargets);

return headersUrlMap[url];
const decision = stringMatchesSomePattern(url, tracingOptions.tracePropagationTargets);
headersUrlMap.set(url, decision);
return decision;
};

return function wrappedRequestMethodFactory(originalRequestMethod: OriginalRequestMethod): WrappedRequestMethod {
Expand Down
Loading