Skip to content

Commit f120f1a

Browse files
authored
feat: API changes (#1497)
* feat: API changes - Add hint parameter - Remove eventprocessors from hub * feat: Return event_id from capture calls * feat: Add lastEventId * fix: Remove keepalive from browser Create only one instance of transport * fix: Transports, Add additional info in hint for global errros * feat: Rebase master with beacon transport * fix: Remove debugger and fix rollup names... * feat: Bring beforeBreadcrumb back * test: Fix integration tests for breadcrumbs * fix: Linting erros * fix: Use object literal for data * fix: Linting
1 parent d54c762 commit f120f1a

File tree

33 files changed

+522
-449
lines changed

33 files changed

+522
-449
lines changed

packages/browser/rollup.config.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,12 +58,12 @@ export default [
5858
},
5959
Object.assign({}, bundleConfig, {
6060
output: Object.assign({}, bundleConfig.output, {
61-
file: 'build/bundle.min.js',
61+
file: 'build/bundle.js',
6262
}),
6363
}),
6464
Object.assign({}, bundleConfig, {
6565
output: Object.assign({}, bundleConfig.output, {
66-
file: 'build/bundle.js',
66+
file: 'build/bundle.min.js',
6767
}),
6868
// Uglify has to be at the end of compilation, BUT before the license banner
6969
plugins: bundleConfig.plugins

packages/browser/src/backend.ts

Lines changed: 33 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import { Backend, logger, Options, SentryError } from '@sentry/core';
2-
import { SentryEvent, SentryResponse, Status } from '@sentry/types';
2+
import { SentryEvent, SentryEventHint, SentryResponse, Severity, Status, Transport } from '@sentry/types';
33
import { isDOMError, isDOMException, isError, isErrorEvent, isPlainObject } from '@sentry/utils/is';
4-
import { supportsFetch } from '@sentry/utils/supports';
4+
import { supportsBeacon, supportsFetch } from '@sentry/utils/supports';
55
import { eventFromPlainObject, eventFromStacktrace, prepareFramesForEvent } from './parsers';
66
import { computeStackTrace } from './tracekit';
7-
import { FetchTransport, XHRTransport } from './transports';
7+
import { BeaconTransport, FetchTransport, XHRTransport } from './transports';
88

99
/**
1010
* Configuration options for the Sentry Browser SDK.
@@ -37,6 +37,9 @@ export class BrowserBackend implements Backend {
3737
/** Creates a new browser backend instance. */
3838
public constructor(private readonly options: BrowserOptions = {}) {}
3939

40+
/** Cached transport used internally. */
41+
private transport?: Transport;
42+
4043
/**
4144
* @inheritDoc
4245
*/
@@ -57,7 +60,7 @@ export class BrowserBackend implements Backend {
5760
/**
5861
* @inheritDoc
5962
*/
60-
public async eventFromException(exception: any, syntheticException: Error | null): Promise<SentryEvent> {
63+
public async eventFromException(exception: any, hint?: SentryEventHint): Promise<SentryEvent> {
6164
let event;
6265

6366
if (isErrorEvent(exception as ErrorEvent) && (exception as ErrorEvent).error) {
@@ -74,16 +77,16 @@ export class BrowserBackend implements Backend {
7477
const name = ex.name || (isDOMError(ex) ? 'DOMError' : 'DOMException');
7578
const message = ex.message ? `${name}: ${ex.message}` : name;
7679

77-
event = await this.eventFromMessage(message, syntheticException);
80+
event = await this.eventFromMessage(message, undefined, hint);
7881
} else if (isError(exception as Error)) {
7982
// we have a real Error object, do nothing
8083
event = eventFromStacktrace(computeStackTrace(exception as Error));
81-
} else if (isPlainObject(exception as {})) {
84+
} else if (isPlainObject(exception as {}) && hint && hint.syntheticException) {
8285
// If it is plain Object, serialize it manually and extract options
8386
// This will allow us to group events based on top-level keys
8487
// which is much better than creating new group when any key/value change
8588
const ex = exception as {};
86-
event = eventFromPlainObject(ex, syntheticException);
89+
event = eventFromPlainObject(ex, hint.syntheticException);
8790
} else {
8891
// If none of previous checks were valid, then it means that
8992
// it's not a DOMError/DOMException
@@ -92,11 +95,12 @@ export class BrowserBackend implements Backend {
9295
// it's not an Error
9396
// So bail out and capture it as a simple message:
9497
const ex = exception as string;
95-
event = await this.eventFromMessage(ex, syntheticException);
98+
event = await this.eventFromMessage(ex, undefined, hint);
9699
}
97100

98101
event = {
99102
...event,
103+
event_id: hint && hint.event_id,
100104
exception: {
101105
...event.exception,
102106
mechanism: {
@@ -112,14 +116,16 @@ export class BrowserBackend implements Backend {
112116
/**
113117
* @inheritDoc
114118
*/
115-
public async eventFromMessage(message: string, syntheticException: Error | null): Promise<SentryEvent> {
119+
public async eventFromMessage(message: string, level?: Severity, hint?: SentryEventHint): Promise<SentryEvent> {
116120
const event: SentryEvent = {
121+
event_id: hint && hint.event_id,
117122
fingerprint: [message],
123+
level,
118124
message,
119125
};
120126

121-
if (this.options.attachStacktrace && syntheticException) {
122-
const stacktrace = computeStackTrace(syntheticException);
127+
if (this.options.attachStacktrace && hint && hint.syntheticException) {
128+
const stacktrace = computeStackTrace(hint.syntheticException);
123129
const frames = prepareFramesForEvent(stacktrace.stack);
124130
event.stacktrace = {
125131
frames,
@@ -139,15 +145,23 @@ export class BrowserBackend implements Backend {
139145
return { status: Status.Skipped };
140146
}
141147

142-
const transportOptions = this.options.transportOptions ? this.options.transportOptions : { dsn: this.options.dsn };
143-
144-
const transport = this.options.transport
145-
? new this.options.transport({ dsn: this.options.dsn })
146-
: supportsFetch()
147-
? new FetchTransport(transportOptions)
148-
: new XHRTransport(transportOptions);
148+
if (!this.transport) {
149+
const transportOptions = this.options.transportOptions
150+
? this.options.transportOptions
151+
: { dsn: this.options.dsn };
152+
153+
if (this.options.transport) {
154+
this.transport = new this.options.transport({ dsn: this.options.dsn });
155+
} else if (supportsBeacon()) {
156+
this.transport = new BeaconTransport(transportOptions);
157+
} else if (supportsFetch()) {
158+
this.transport = new FetchTransport(transportOptions);
159+
} else {
160+
this.transport = new XHRTransport(transportOptions);
161+
}
162+
}
149163

150-
return transport.send(event);
164+
return this.transport.send(event);
151165
}
152166

153167
/**

packages/browser/src/integrations/dedupe.ts

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { logger } from '@sentry/core';
2-
import { getCurrentHub } from '@sentry/hub';
2+
import { getCurrentHub, Scope } from '@sentry/hub';
33
import { Integration, SentryEvent, SentryException, StackFrame } from '@sentry/types';
44

55
/** Deduplication filter */
@@ -18,17 +18,19 @@ export class Dedupe implements Integration {
1818
* @inheritDoc
1919
*/
2020
public install(): void {
21-
getCurrentHub().addEventProcessor(async (event: SentryEvent) => {
22-
// Juuust in case something goes wrong
23-
try {
24-
if (this.shouldDropEvent(event)) {
25-
return null;
21+
getCurrentHub().configureScope((scope: Scope) => {
22+
scope.addEventProcessor(async (event: SentryEvent) => {
23+
// Juuust in case something goes wrong
24+
try {
25+
if (this.shouldDropEvent(event)) {
26+
return null;
27+
}
28+
} catch (_oO) {
29+
return (this.previousEvent = event);
2630
}
27-
} catch (_oO) {
28-
return (this.previousEvent = event);
29-
}
3031

31-
return (this.previousEvent = event);
32+
return (this.previousEvent = event);
33+
});
3234
});
3335
}
3436

packages/browser/src/integrations/globalhandlers.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { logger } from '@sentry/core';
2-
import { captureEvent } from '@sentry/minimal';
2+
import { getCurrentHub } from '@sentry/hub';
33
import { Integration, SentryEvent } from '@sentry/types';
44
import { eventFromStacktrace } from '../parsers';
55
import {
@@ -29,7 +29,7 @@ export class GlobalHandlers implements Integration {
2929
* @inheritDoc
3030
*/
3131
public install(): void {
32-
subscribe((stack: TraceKitStackTrace) => {
32+
subscribe((stack: TraceKitStackTrace, _: boolean, error: Error) => {
3333
// TODO: use stack.context to get a valuable information from TraceKit, eg.
3434
// [
3535
// 0: " })"
@@ -47,7 +47,7 @@ export class GlobalHandlers implements Integration {
4747
if (shouldIgnoreOnError()) {
4848
return;
4949
}
50-
captureEvent(this.eventFromGlobalHandler(stack));
50+
getCurrentHub().captureEvent(this.eventFromGlobalHandler(stack), { originalException: error, data: { stack } });
5151
});
5252

5353
if (this.options.onerror) {

packages/browser/src/integrations/helpers.ts

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { getCurrentHub } from '@sentry/hub';
1+
import { getCurrentHub, Scope } from '@sentry/hub';
22
import { Mechanism, SentryEvent, SentryWrappedFunction } from '@sentry/types';
33
import { isFunction } from '@sentry/utils/is';
44
import { htmlTreeAsString } from '@sentry/utils/misc';
@@ -66,18 +66,20 @@ export function wrap(
6666
ignoreNextOnError();
6767

6868
getCurrentHub().withScope(async () => {
69-
getCurrentHub().addEventProcessor(async (event: SentryEvent) => {
70-
const processedEvent = { ...event };
69+
getCurrentHub().configureScope((scope: Scope) => {
70+
scope.addEventProcessor(async (event: SentryEvent) => {
71+
const processedEvent = { ...event };
7172

72-
if (options.mechanism) {
73-
processedEvent.exception = processedEvent.exception || {};
74-
processedEvent.exception.mechanism = options.mechanism;
75-
}
73+
if (options.mechanism) {
74+
processedEvent.exception = processedEvent.exception || {};
75+
processedEvent.exception.mechanism = options.mechanism;
76+
}
7677

77-
return processedEvent;
78+
return processedEvent;
79+
});
7880
});
7981

80-
getCurrentHub().captureException(ex);
82+
getCurrentHub().captureException(ex, { originalException: ex });
8183
});
8284

8385
throw ex;

packages/browser/src/integrations/inboundfilters.ts

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { logger } from '@sentry/core';
2-
import { getCurrentHub } from '@sentry/hub';
2+
import { getCurrentHub, Scope } from '@sentry/hub';
33
import { Integration, SentryEvent } from '@sentry/types';
44
import { isRegExp } from '@sentry/utils/is';
55
import { BrowserOptions } from '../backend';
@@ -27,11 +27,13 @@ export class InboundFilters implements Integration {
2727
public install(options: BrowserOptions = {}): void {
2828
this.configureOptions(options);
2929

30-
getCurrentHub().addEventProcessor(async (event: SentryEvent) => {
31-
if (this.shouldDropEvent(event)) {
32-
return null;
33-
}
34-
return event;
30+
getCurrentHub().configureScope((scope: Scope) => {
31+
scope.addEventProcessor(async (event: SentryEvent) => {
32+
if (this.shouldDropEvent(event)) {
33+
return null;
34+
}
35+
return event;
36+
});
3537
});
3638
}
3739

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { getCurrentHub } from '@sentry/hub';
1+
import { getCurrentHub, Scope } from '@sentry/hub';
22
import { Integration, SentryEvent } from '@sentry/types';
33
import { SDK_NAME, SDK_VERSION } from '../version';
44

@@ -13,19 +13,21 @@ export class SDKInformation implements Integration {
1313
* @inheritDoc
1414
*/
1515
public install(): void {
16-
getCurrentHub().addEventProcessor(async (event: SentryEvent) => ({
17-
...event,
18-
sdk: {
19-
name: SDK_NAME,
20-
packages: [
21-
...((event.sdk && event.sdk.packages) || []),
22-
{
23-
name: 'npm:@sentry/browser',
24-
version: SDK_VERSION,
25-
},
26-
],
27-
version: SDK_VERSION,
28-
},
29-
}));
16+
getCurrentHub().configureScope((scope: Scope) => {
17+
scope.addEventProcessor(async (event: SentryEvent) => ({
18+
...event,
19+
sdk: {
20+
name: SDK_NAME,
21+
packages: [
22+
...((event.sdk && event.sdk.packages) || []),
23+
{
24+
name: 'npm:@sentry/browser',
25+
version: SDK_VERSION,
26+
},
27+
],
28+
version: SDK_VERSION,
29+
},
30+
}));
31+
});
3032
}
3133
}

packages/browser/src/tracekit/index.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,6 @@ TraceKit.report = (function reportModuleWrapper() {
230230
* @memberof TraceKit.report
231231
*/
232232
function traceKitWindowOnError(message, url, lineNo, columnNo, errorObj) {
233-
debugger;
234233
var stack = null;
235234
// If 'errorObj' is ErrorEvent, get real Error from inside
236235
errorObj = isErrorEvent(errorObj) ? errorObj.error : errorObj;

packages/browser/src/transports/fetch.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ export class FetchTransport extends BaseTransport {
1414
public async send(event: SentryEvent): Promise<SentryResponse> {
1515
const defaultOptions: RequestInit = {
1616
body: serialize(event),
17-
keepalive: true,
1817
method: 'POST',
1918
// Despite all stars in the sky saying that Edge supports old draft syntax, aka 'never', 'always', 'origin' and 'default
2019
// https://caniuse.com/#feat=referrer-policy

packages/browser/test/index.test.ts

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import {
1212
init,
1313
Scope,
1414
SentryEvent,
15+
Status,
1516
} from '../src';
1617

1718
const dsn = 'https://[email protected]/4291';
@@ -64,7 +65,7 @@ describe('SentryBrowser', () => {
6465
let s: sinon.SinonStub;
6566

6667
beforeEach(() => {
67-
s = stub(BrowserBackend.prototype, 'sendEvent').returns(Promise.resolve(200));
68+
s = stub(BrowserBackend.prototype, 'sendEvent').returns(Promise.resolve({ status: Status.Success }));
6869
});
6970

7071
afterEach(() => {
@@ -75,9 +76,10 @@ describe('SentryBrowser', () => {
7576
getCurrentHub().pushScope();
7677
getCurrentHub().bindClient(
7778
new BrowserClient({
78-
afterSend: (event: SentryEvent) => {
79+
beforeSend: (event: SentryEvent) => {
7980
expect(event.breadcrumbs!).to.have.lengthOf(2);
8081
done();
82+
return event;
8183
},
8284
dsn,
8385
}),
@@ -95,7 +97,7 @@ describe('SentryBrowser', () => {
9597
let s: sinon.SinonStub;
9698

9799
beforeEach(() => {
98-
s = stub(BrowserBackend.prototype, 'sendEvent').returns(Promise.resolve(200));
100+
s = stub(BrowserBackend.prototype, 'sendEvent').returns(Promise.resolve({ status: Status.Success }));
99101
});
100102

101103
afterEach(() => {
@@ -106,13 +108,14 @@ describe('SentryBrowser', () => {
106108
getCurrentHub().pushScope();
107109
getCurrentHub().bindClient(
108110
new BrowserClient({
109-
afterSend: (event: SentryEvent) => {
111+
beforeSend: (event: SentryEvent) => {
110112
expect(event.exception).to.not.be.undefined;
111113
expect(event.exception!.values![0]).to.not.be.undefined;
112114
expect(event.exception!.values![0].type).to.equal('Error');
113115
expect(event.exception!.values![0].value).to.equal('test');
114116
expect(event.exception!.values![0].stacktrace).to.not.be.empty;
115117
done();
118+
return event;
116119
},
117120
dsn,
118121
}),
@@ -129,10 +132,11 @@ describe('SentryBrowser', () => {
129132
getCurrentHub().pushScope();
130133
getCurrentHub().bindClient(
131134
new BrowserClient({
132-
afterSend: (event: SentryEvent) => {
135+
beforeSend: (event: SentryEvent) => {
133136
expect(event.message).to.equal('test');
134137
expect(event.exception).to.be.undefined;
135138
done();
139+
return event;
136140
},
137141
dsn,
138142
}),
@@ -145,10 +149,11 @@ describe('SentryBrowser', () => {
145149
getCurrentHub().pushScope();
146150
getCurrentHub().bindClient(
147151
new BrowserClient({
148-
afterSend: (event: SentryEvent) => {
152+
beforeSend: (event: SentryEvent) => {
149153
expect(event.message).to.equal('event');
150154
expect(event.exception).to.be.undefined;
151155
done();
156+
return event;
152157
},
153158
dsn,
154159
}),

0 commit comments

Comments
 (0)