Skip to content

Commit 8578a89

Browse files
author
Luca Forstner
authored
Merge branch 'develop' into lforst-sourcemap-debug-meta
2 parents 2da12d1 + f8047f6 commit 8578a89

30 files changed

+298
-52
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@
5252
"packages/react",
5353
"packages/remix",
5454
"packages/replay",
55+
"packages/replay-worker",
5556
"packages/serverless",
5657
"packages/svelte",
5758
"packages/tracing",

packages/browser/src/integrations/dedupe.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,12 @@ export class Dedupe implements Integration {
2323
*/
2424
public setupOnce(addGlobalEventProcessor: (callback: EventProcessor) => void, getCurrentHub: () => Hub): void {
2525
const eventProcessor: EventProcessor = currentEvent => {
26+
// We want to ignore any non-error type events, e.g. transactions or replays
27+
// These should never be deduped, and also not be compared against as _previousEvent.
28+
if (currentEvent.type) {
29+
return currentEvent;
30+
}
31+
2632
const self = getCurrentHub().getIntegration(Dedupe);
2733
if (self) {
2834
// Juuust in case something goes wrong

packages/browser/test/integration/suites/api.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,12 +112,26 @@ describe('API', function () {
112112

113113
// Same exceptions, different stacktrace (different line number), don't dedupe
114114
throwSameConsecutiveErrors('bar');
115+
116+
// Same exception, with transaction in between, dedupe
117+
throwError();
118+
Sentry.captureEvent({
119+
event_id: 'aa3ff046696b4bc6b609ce6d28fde9e2',
120+
message: 'someMessage',
121+
transaction: 'wat',
122+
type: 'transaction',
123+
});
124+
throwError();
115125
}).then(function (summary) {
126+
// We have a length of one here since transactions don't go through beforeSend
127+
// and we add events to summary in beforeSend
128+
assert.equal(summary.events.length, 6);
116129
assert.match(summary.events[0].exception.values[0].value, /Exception no \d+/);
117130
assert.match(summary.events[1].exception.values[0].value, /Exception no \d+/);
118131
assert.equal(summary.events[2].exception.values[0].value, 'foo');
119132
assert.equal(summary.events[3].exception.values[0].value, 'bar');
120133
assert.equal(summary.events[4].exception.values[0].value, 'bar');
134+
assert.equal(summary.events[5].exception.values[0].value, 'foo');
121135
});
122136
});
123137

packages/integrations/src/dedupe.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,12 @@ export class Dedupe implements Integration {
2323
*/
2424
public setupOnce(addGlobalEventProcessor: (callback: EventProcessor) => void, getCurrentHub: () => Hub): void {
2525
const eventProcessor: EventProcessor = currentEvent => {
26+
// We want to ignore any non-error type events, e.g. transactions or replays
27+
// These should never be deduped, and also not be compared against as _previousEvent.
28+
if (currentEvent.type) {
29+
return currentEvent;
30+
}
31+
2632
const self = getCurrentHub().getIntegration(Dedupe);
2733
if (self) {
2834
// Juuust in case something goes wrong

packages/integrations/test/dedupe.test.ts

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
import type { Event as SentryEvent, Exception, StackFrame, Stacktrace } from '@sentry/types';
1+
import type { Event as SentryEvent, EventProcessor, Exception, Hub, StackFrame, Stacktrace } from '@sentry/types';
22

3-
import { _shouldDropEvent } from '../src/dedupe';
3+
import { _shouldDropEvent, Dedupe } from '../src/dedupe';
44

55
type EventWithException = SentryEvent & {
66
exception: {
@@ -175,4 +175,48 @@ describe('Dedupe', () => {
175175
expect(_shouldDropEvent(eventB, eventC)).toBe(false);
176176
});
177177
});
178+
179+
describe('setupOnce', () => {
180+
let dedupeFunc: EventProcessor;
181+
182+
beforeEach(function () {
183+
const integration = new Dedupe();
184+
const addGlobalEventProcessor = (callback: EventProcessor) => {
185+
dedupeFunc = callback;
186+
};
187+
188+
const getCurrentHub = () => {
189+
return {
190+
getIntegration() {
191+
return integration;
192+
},
193+
} as unknown as Hub;
194+
};
195+
196+
integration.setupOnce(addGlobalEventProcessor, getCurrentHub);
197+
});
198+
199+
it('ignores consecutive errors', () => {
200+
expect(dedupeFunc(clone(exceptionEvent), {})).not.toBeNull();
201+
expect(dedupeFunc(clone(exceptionEvent), {})).toBeNull();
202+
expect(dedupeFunc(clone(exceptionEvent), {})).toBeNull();
203+
});
204+
205+
it('ignores transactions between errors', () => {
206+
expect(dedupeFunc(clone(exceptionEvent), {})).not.toBeNull();
207+
expect(
208+
dedupeFunc(
209+
{
210+
event_id: 'aa3ff046696b4bc6b609ce6d28fde9e2',
211+
message: 'someMessage',
212+
transaction: 'wat',
213+
type: 'transaction',
214+
},
215+
{},
216+
),
217+
).not.toBeNull();
218+
expect(dedupeFunc(clone(exceptionEvent), {})).toBeNull();
219+
expect(dedupeFunc(clone(exceptionEvent), {})).toBeNull();
220+
});
221+
});
178222
});
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
vendor
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Note: All paths are relative to the directory in which eslint is being run, rather than the directory where this file
2+
// lives
3+
4+
// ESLint config docs: https://eslint.org/docs/user-guide/configuring/
5+
6+
module.exports = {
7+
extends: ['../../.eslintrc.js'],
8+
overrides: [
9+
{
10+
files: ['src/**/*.ts'],
11+
rules: {
12+
// We cannot use backticks, as that conflicts with the stringified worker
13+
'prefer-template': 'off',
14+
},
15+
},
16+
],
17+
};

packages/replay-worker/.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
node_modules
2+
/*.tgz
3+
.eslintcache
4+
build
5+
!vendor/*.d.ts

packages/replay-worker/LICENSE

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
Copyright (c) 2023 Sentry (https://sentry.io) and individual contributors. All rights reserved.
2+
3+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
4+
documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
5+
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
6+
persons to whom the Software is furnished to do so, subject to the following conditions:
7+
8+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
9+
Software.
10+
11+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
12+
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
13+
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
14+
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

packages/replay-worker/README.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<p align="center">
2+
<a href="https://sentry.io/?utm_source=github&utm_medium=logo" target="_blank">
3+
<img src="https://sentry-brand.storage.googleapis.com/sentry-wordmark-dark-280x84.png" alt="Sentry" width="280" height="84">
4+
</a>
5+
</p>
6+
7+
# Sentry Session Replay Worker
8+
9+
This is an internal package that is used by @sentry/replay.
10+
It generates a web worker and converts it to a string, so that we can process it easier in replay.
11+
12+
By extracting this into a dedicated (private, internal) package, we can streamline the build of replay.

0 commit comments

Comments
 (0)