Skip to content

Commit

Permalink
Merge branch 'master' into jb/feat/browser-profiling
Browse files Browse the repository at this point in the history
  • Loading branch information
JonasBa committed Jun 21, 2023
2 parents a8cc694 + 4fb043e commit 707c5cd
Show file tree
Hide file tree
Showing 138 changed files with 3,313 additions and 1,901 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -424,7 +424,7 @@ jobs:
name: Nextjs (Node ${{ matrix.node }}) Tests
needs: [job_get_metadata, job_build]
if: needs.job_get_metadata.outputs.changed_nextjs == 'true' || github.event_name != 'pull_request'
timeout-minutes: 15
timeout-minutes: 25
runs-on: ubuntu-20.04
strategy:
fail-fast: false
Expand Down
27 changes: 27 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,33 @@

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

## 7.56.0

- feat(replay): Rework slow click & multi click detection (#8322)
- feat(replay): Stop replay when event buffer exceeds max. size (#8315)
- feat(replay): Consider `window.open` for slow clicks (#8308)
- fix(core): Temporarily store debug IDs in stack frame and only put them into `debug_meta` before sending (#8347)
- fix(remix): Extract deferred responses correctly in root loaders. (#8305)
- fix(vue): Don't call `next` in Vue router 4 instrumentation (#8351)

## 7.55.2

- fix(replay): Stop exporting `EventType` from `@sentry-internal/rrweb` (#8334)
- fix(serverless): Export captureCheckIn (#8333)

## 7.55.1

- fix(replay): Do not export types from `@sentry-internal/rrweb` (#8329)

## 7.55.0

- feat(replay): Capture slow clicks (GA) (#8298)
- feat(replay): Improve types for replay recording events (#8224)
- fix(nextjs): Strip query params from transaction names of navigations to unknown routes (#8278)
- fix(replay): Ignore max session life for buffered sessions (#8258)
- fix(sveltekit): Export captureCheckIn (#8313)
- ref(svelte): Add Svelte 4 as a peer dependency (#8280)

## 7.54.0

### Important Changes
Expand Down
2 changes: 1 addition & 1 deletion lerna.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"$schema": "node_modules/lerna/schemas/lerna-schema.json",
"version": "7.54.0",
"version": "7.56.0",
"npmClient": "yarn",
"useWorkspaces": true
}
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
"yalc:publish": "lerna run yalc:publish"
},
"volta": {
"node": "18.12.1",
"node": "16.19.0",
"yarn": "1.22.19"
},
"workspaces": [
Expand Down
8 changes: 4 additions & 4 deletions packages/angular-ivy/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@sentry/angular-ivy",
"version": "7.54.0",
"version": "7.56.0",
"description": "Official Sentry SDK for Angular with full Ivy Support",
"repository": "git://github.com/getsentry/sentry-javascript.git",
"homepage": "https://github.com/getsentry/sentry-javascript/tree/master/packages/angular-ivy",
Expand All @@ -21,9 +21,9 @@
"rxjs": "^6.5.5 || ^7.x"
},
"dependencies": {
"@sentry/browser": "7.54.0",
"@sentry/types": "7.54.0",
"@sentry/utils": "7.54.0",
"@sentry/browser": "7.56.0",
"@sentry/types": "7.56.0",
"@sentry/utils": "7.56.0",
"tslib": "^2.3.0"
},
"devDependencies": {
Expand Down
14 changes: 13 additions & 1 deletion packages/angular-ivy/src/sdk.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { VERSION } from '@angular/core';
import type { BrowserOptions } from '@sentry/browser';
import { init as browserInit, SDK_VERSION, setContext } from '@sentry/browser';
import { defaultIntegrations, init as browserInit, SDK_VERSION, setContext } from '@sentry/browser';
import { logger } from '@sentry/utils';

import { IS_DEBUG_BUILD } from './flags';
Expand All @@ -21,6 +21,18 @@ export function init(options: BrowserOptions): void {
version: SDK_VERSION,
};

// Filter out TryCatch integration as it interferes with our Angular `ErrorHandler`:
// TryCatch would catch certain errors before they reach the `ErrorHandler` and thus provide a
// lower fidelity error than what `SentryErrorHandler` (see errorhandler.ts) would provide.
// see:
// - https://github.com/getsentry/sentry-javascript/issues/5417#issuecomment-1453407097
// - https://github.com/getsentry/sentry-javascript/issues/2744
if (options.defaultIntegrations === undefined) {
options.defaultIntegrations = defaultIntegrations.filter(integration => {
return integration.name !== 'TryCatch';
});
}

checkAndSetAngularVersion();
browserInit(options);
}
Expand Down
8 changes: 4 additions & 4 deletions packages/angular/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@sentry/angular",
"version": "7.54.0",
"version": "7.56.0",
"description": "Official Sentry SDK for Angular",
"repository": "git://github.com/getsentry/sentry-javascript.git",
"homepage": "https://github.com/getsentry/sentry-javascript/tree/master/packages/angular",
Expand All @@ -21,9 +21,9 @@
"rxjs": "^6.5.5 || ^7.x"
},
"dependencies": {
"@sentry/browser": "7.54.0",
"@sentry/types": "7.54.0",
"@sentry/utils": "7.54.0",
"@sentry/browser": "7.56.0",
"@sentry/types": "7.56.0",
"@sentry/utils": "7.56.0",
"tslib": "^2.0.0"
},
"devDependencies": {
Expand Down
14 changes: 13 additions & 1 deletion packages/angular/src/sdk.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { VERSION } from '@angular/core';
import type { BrowserOptions } from '@sentry/browser';
import { init as browserInit, SDK_VERSION, setContext } from '@sentry/browser';
import { defaultIntegrations, init as browserInit, SDK_VERSION, setContext } from '@sentry/browser';
import { logger } from '@sentry/utils';

import { IS_DEBUG_BUILD } from './flags';
Expand All @@ -21,6 +21,18 @@ export function init(options: BrowserOptions): void {
version: SDK_VERSION,
};

// Filter out TryCatch integration as it interferes with our Angular `ErrorHandler`:
// TryCatch would catch certain errors before they reach the `ErrorHandler` and thus provide a
// lower fidelity error than what `SentryErrorHandler` (see errorhandler.ts) would provide.
// see:
// - https://github.com/getsentry/sentry-javascript/issues/5417#issuecomment-1453407097
// - https://github.com/getsentry/sentry-javascript/issues/2744
if (options.defaultIntegrations === undefined) {
options.defaultIntegrations = defaultIntegrations.filter(integration => {
return integration.name !== 'TryCatch';
});
}

checkAndSetAngularVersion();
browserInit(options);
}
Expand Down
6 changes: 4 additions & 2 deletions packages/angular/src/tracing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import type { ActivatedRouteSnapshot, Event, RouterState } from '@angular/router
// Duplicated import to work around a TypeScript bug where it'd complain that `Router` isn't imported as a type.
// We need to import it as a value to satisfy Angular dependency injection. So:
// eslint-disable-next-line @typescript-eslint/consistent-type-imports, import/no-duplicates
import { Router } from '@angular/router';
import { NavigationCancel, NavigationError, Router } from '@angular/router';
// eslint-disable-next-line import/no-duplicates
import { NavigationEnd, NavigationStart, ResolveEnd } from '@angular/router';
import { getCurrentHub, WINDOW } from '@sentry/browser';
Expand Down Expand Up @@ -131,7 +131,9 @@ export class TraceService implements OnDestroy {
);

public navEnd$: Observable<Event> = this._router.events.pipe(
filter(event => event instanceof NavigationEnd),
filter(
event => event instanceof NavigationEnd || event instanceof NavigationCancel || event instanceof NavigationError,
),
tap(() => {
if (this._routingSpan) {
runOutsideAngular(() => {
Expand Down
31 changes: 30 additions & 1 deletion packages/angular/test/sdk.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as SentryBrowser from '@sentry/browser';

import { init } from '../src/sdk';
import { defaultIntegrations, init } from '../src/index';

describe('init', () => {
it('sets the Angular version (if available) in the global scope', () => {
Expand All @@ -13,4 +13,33 @@ describe('init', () => {
expect(setContextSpy).toHaveBeenCalledTimes(1);
expect(setContextSpy).toHaveBeenCalledWith('angular', { version: 10 });
});

describe('filtering out the `TryCatch` integration', () => {
const browserInitSpy = jest.spyOn(SentryBrowser, 'init');

beforeEach(() => {
browserInitSpy.mockClear();
});

it('filters if `defaultIntegrations` is not set', () => {
init({});

expect(browserInitSpy).toHaveBeenCalledTimes(1);

const options = browserInitSpy.mock.calls[0][0] || {};
expect(options.defaultIntegrations).not.toContainEqual(expect.objectContaining({ name: 'TryCatch' }));
});

it.each([false as const, defaultIntegrations])(
"doesn't filter if `defaultIntegrations` is set to %s",
defaultIntegrations => {
init({ defaultIntegrations });

expect(browserInitSpy).toHaveBeenCalledTimes(1);

const options = browserInitSpy.mock.calls[0][0] || {};
expect(options.defaultIntegrations).toEqual(defaultIntegrations);
},
);
});
});
62 changes: 61 additions & 1 deletion packages/angular/test/tracing.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Component } from '@angular/core';
import type { ActivatedRouteSnapshot } from '@angular/router';
import type { ActivatedRouteSnapshot, CanActivate, RouterStateSnapshot } from '@angular/router';
import type { Hub } from '@sentry/types';

import { instrumentAngularRouting, TraceClassDecorator, TraceDirective, TraceMethodDecorator } from '../src';
Expand Down Expand Up @@ -185,6 +185,66 @@ describe('Angular Tracing', () => {
env.destroy();
});

it('finishes routing span on navigation error', async () => {
const customStartTransaction = jest.fn(defaultStartTransaction);

const env = await TestEnv.setup({
customStartTransaction,
routes: [
{
path: '',
component: AppComponent,
},
],
useTraceService: true,
});

const finishMock = jest.fn();
transaction.startChild = jest.fn(() => ({
finish: finishMock,
}));

await env.navigateInAngular('/somewhere');

expect(finishMock).toHaveBeenCalledTimes(1);

env.destroy();
});

it('finishes routing span on navigation cancel', async () => {
const customStartTransaction = jest.fn(defaultStartTransaction);

class CanActivateGuard implements CanActivate {
canActivate(_route: ActivatedRouteSnapshot, _state: RouterStateSnapshot): boolean {
return false;
}
}

const env = await TestEnv.setup({
customStartTransaction,
routes: [
{
path: 'cancel',
component: AppComponent,
canActivate: [CanActivateGuard],
},
],
useTraceService: true,
additionalProviders: [{ provide: CanActivateGuard, useClass: CanActivateGuard }],
});

const finishMock = jest.fn();
transaction.startChild = jest.fn(() => ({
finish: finishMock,
}));

await env.navigateInAngular('/cancel');

expect(finishMock).toHaveBeenCalledTimes(1);

env.destroy();
});

describe('URL parameterization', () => {
it.each([
[
Expand Down
22 changes: 16 additions & 6 deletions packages/angular/test/utils/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import type { Provider } from '@angular/core';
import { Component, NgModule } from '@angular/core';
import type { ComponentFixture } from '@angular/core/testing';
import { TestBed } from '@angular/core/testing';
Expand Down Expand Up @@ -47,6 +48,7 @@ export class TestEnv {
startTransactionOnPageLoad?: boolean;
startTransactionOnNavigation?: boolean;
useTraceService?: boolean;
additionalProviders?: Provider[];
}): Promise<TestEnv> {
instrumentAngularRouting(
conf.customStartTransaction || jest.fn(),
Expand All @@ -60,14 +62,16 @@ export class TestEnv {
TestBed.configureTestingModule({
imports: [AppModule, RouterTestingModule.withRoutes(routes)],
declarations: [...(conf.components || []), AppComponent],
providers: useTraceService
providers: (useTraceService
? [
{
provide: TraceService,
deps: [Router],
},
...(conf.additionalProviders || []),
]
: [],
: []
).concat(...(conf.additionalProviders || [])),
});

const router: Router = TestBed.inject(Router);
Expand All @@ -80,10 +84,16 @@ export class TestEnv {
public async navigateInAngular(url: string): Promise<void> {
return new Promise(resolve => {
return this.fixture.ngZone?.run(() => {
void this.router.navigateByUrl(url).then(() => {
this.fixture.detectChanges();
resolve();
});
void this.router
.navigateByUrl(url)
.then(() => {
this.fixture.detectChanges();
resolve();
})
.catch(() => {
this.fixture.detectChanges();
resolve();
});
});
});
}
Expand Down
2 changes: 1 addition & 1 deletion packages/browser-integration-tests/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@sentry-internal/browser-integration-tests",
"version": "7.54.0",
"version": "7.56.0",
"main": "index.js",
"license": "MIT",
"engines": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ sentryTest(
let errorEventId: string | undefined;
const reqPromise0 = waitForReplayRequest(page, 0);
const reqPromise1 = waitForReplayRequest(page, 1);
const reqPromise2 = waitForReplayRequest(page, 2);
const reqErrorPromise = waitForErrorRequest(page);

await page.route('https://dsn.ingest.sentry.io/**/*', route => {
Expand Down Expand Up @@ -101,18 +100,14 @@ sentryTest(

// Switches to session mode and then goes to background
const req1 = await reqPromise1;
const req2 = await reqPromise2;
expect(callsToSentry).toBeGreaterThanOrEqual(5);
expect(callsToSentry).toBeGreaterThanOrEqual(4);

const event0 = getReplayEvent(req0);
const content0 = getReplayRecordingContent(req0);

const event1 = getReplayEvent(req1);
const content1 = getReplayRecordingContent(req1);

const event2 = getReplayEvent(req2);
const content2 = getReplayRecordingContent(req2);

expect(event0).toEqual(
getExpectedReplayEvent({
error_ids: [errorEventId!],
Expand Down Expand Up @@ -157,17 +152,7 @@ sentryTest(

// From switching to session mode
expect(content1.fullSnapshots).toHaveLength(1);

expect(event2).toEqual(
getExpectedReplayEvent({
replay_type: 'buffer', // although we're in session mode, we still send 'buffer' as replay_type
segment_id: 2,
urls: [],
}),
);

expect(content2.fullSnapshots).toHaveLength(0);
expect(content2.breadcrumbs).toEqual(expect.arrayContaining([expectedClickBreadcrumb]));
expect(content1.breadcrumbs).toEqual(expect.arrayContaining([expectedClickBreadcrumb]));
},
);

Expand Down
Loading

0 comments on commit 707c5cd

Please sign in to comment.