Skip to content

Commit 93200d1

Browse files
authored
feat: Add setContext on scope (getsentry#2026)
* feat: Add setContext on scope * meta: Add changelog
1 parent f686dbf commit 93200d1

File tree

4 files changed

+92
-3
lines changed

4 files changed

+92
-3
lines changed

CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Changelog
22

3+
## Unreleased
4+
5+
- [hub] feat: Add `setContext` on the scope
6+
37
## 5.0.8
48

59
- [core] fix: Don't disable client before flushing

packages/hub/src/scope.ts

+17
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@ export class Scope implements ScopeInterface {
2727
/** Extra */
2828
protected _extra: { [key: string]: any } = {};
2929

30+
/** Contexts */
31+
protected _context: { [key: string]: any } = {};
32+
3033
/** Fingerprint */
3134
protected _fingerprint?: string[];
3235

@@ -162,6 +165,15 @@ export class Scope implements ScopeInterface {
162165
return this;
163166
}
164167

168+
/**
169+
* @inheritDoc
170+
*/
171+
public setContext(name: string, context: { [key: string]: any } | null): this {
172+
this._context[name] = context ? normalize(context) : undefined;
173+
this._notifyScopeListeners();
174+
return this;
175+
}
176+
165177
/**
166178
* Inherit values from the parent scope.
167179
* @param scope to clone.
@@ -175,6 +187,7 @@ export class Scope implements ScopeInterface {
175187
newScope._breadcrumbs = [...scope._breadcrumbs];
176188
newScope._tags = { ...scope._tags };
177189
newScope._extra = { ...scope._extra };
190+
newScope._context = { ...scope._context };
178191
newScope._user = scope._user;
179192
newScope._level = scope._level;
180193
newScope._fingerprint = scope._fingerprint;
@@ -191,6 +204,7 @@ export class Scope implements ScopeInterface {
191204
this._tags = {};
192205
this._extra = {};
193206
this._user = {};
207+
this._context = {};
194208
this._level = undefined;
195209
this._fingerprint = undefined;
196210
this._notifyScopeListeners();
@@ -263,6 +277,9 @@ export class Scope implements ScopeInterface {
263277
if (this._user && Object.keys(this._user).length) {
264278
event.user = { ...this._user, ...event.user };
265279
}
280+
if (this._context && Object.keys(this._context).length) {
281+
event.contexts = { ...this._context, ...event.contexts };
282+
}
266283
if (this._level) {
267284
event.level = this._level;
268285
}

packages/hub/test/scope.test.ts

+64-3
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
import { Event, EventHint, Severity } from '@sentry/types';
2+
import { getGlobalObject } from '@sentry/utils';
23

3-
import { Scope } from '../src';
4+
import { addGlobalEventProcessor, Scope } from '../src';
45

56
describe('Scope', () => {
67
afterEach(() => {
78
jest.resetAllMocks();
89
jest.useRealTimers();
10+
getGlobalObject<any>().__SENTRY__.globalEventProcessors = undefined;
911
});
1012

1113
describe('fingerprint', () => {
@@ -59,6 +61,7 @@ describe('Scope', () => {
5961
});
6062
test('unset', () => {
6163
const scope = new Scope();
64+
scope.setUser({ id: '1' });
6265
scope.setUser(null);
6366
expect((scope as any)._user).toEqual(null);
6467
});
@@ -80,6 +83,20 @@ describe('Scope', () => {
8083
});
8184
});
8285

86+
describe('context', () => {
87+
test('set', () => {
88+
const scope = new Scope();
89+
scope.setContext('os', { id: '1' });
90+
expect((scope as any)._context.os).toEqual({ id: '1' });
91+
});
92+
test('unset', () => {
93+
const scope = new Scope();
94+
scope.setContext('os', { id: '1' });
95+
scope.setContext('os', null);
96+
expect((scope as any)._user).toEqual({});
97+
});
98+
});
99+
83100
test('chaining', () => {
84101
const scope = new Scope();
85102
scope.setLevel(Severity.Critical).setUser({ id: '1' });
@@ -113,14 +130,15 @@ describe('Scope', () => {
113130
});
114131

115132
test('applyToEvent', () => {
116-
expect.assertions(6);
133+
expect.assertions(7);
117134
const scope = new Scope();
118135
scope.setExtra('a', 2);
119136
scope.setTag('a', 'b');
120137
scope.setUser({ id: '1' });
121138
scope.setFingerprint(['abcd']);
122139
scope.setLevel(Severity.Warning);
123140
scope.addBreadcrumb({ message: 'test' }, 100);
141+
scope.setContext('os', { id: '1' });
124142
const event: Event = {};
125143
return scope.applyToEvent(event).then(processedEvent => {
126144
expect(processedEvent!.extra).toEqual({ a: 2 });
@@ -129,19 +147,22 @@ describe('Scope', () => {
129147
expect(processedEvent!.fingerprint).toEqual(['abcd']);
130148
expect(processedEvent!.level).toEqual('warning');
131149
expect(processedEvent!.breadcrumbs![0]).toHaveProperty('message', 'test');
150+
expect(processedEvent!.contexts).toEqual({ os: { id: '1' } });
132151
});
133152
});
134153

135154
test('applyToEvent merge', () => {
136-
expect.assertions(7);
155+
expect.assertions(8);
137156
const scope = new Scope();
138157
scope.setExtra('a', 2);
139158
scope.setTag('a', 'b');
140159
scope.setUser({ id: '1' });
141160
scope.setFingerprint(['abcd']);
142161
scope.addBreadcrumb({ message: 'test' }, 100);
162+
scope.setContext('server', { id: '2' });
143163
const event: Event = {
144164
breadcrumbs: [{ message: 'test1' }],
165+
contexts: { os: { id: '1' } },
145166
extra: { b: 3 },
146167
fingerprint: ['efgh'],
147168
tags: { b: 'c' },
@@ -155,6 +176,10 @@ describe('Scope', () => {
155176
expect(processedEvent!.breadcrumbs).toHaveLength(2);
156177
expect(processedEvent!.breadcrumbs![0]).toHaveProperty('message', 'test1');
157178
expect(processedEvent!.breadcrumbs![1]).toHaveProperty('message', 'test');
179+
expect(processedEvent!.contexts).toEqual({
180+
os: { id: '1' },
181+
server: { id: '2' },
182+
});
158183
});
159184
});
160185

@@ -193,6 +218,14 @@ describe('Scope', () => {
193218
expect((scope as any)._extra).toEqual({});
194219
});
195220

221+
test('clearBreadcrumbs', () => {
222+
const scope = new Scope();
223+
scope.addBreadcrumb({ message: 'test' }, 100);
224+
expect((scope as any)._breadcrumbs).toHaveLength(1);
225+
scope.clearBreadcrumbs();
226+
expect((scope as any)._breadcrumbs).toHaveLength(0);
227+
});
228+
196229
test('addEventProcessor', () => {
197230
expect.assertions(3);
198231
const event: Event = {
@@ -218,6 +251,34 @@ describe('Scope', () => {
218251
});
219252
});
220253

254+
test('addEventProcessor + global', () => {
255+
expect.assertions(3);
256+
const event: Event = {
257+
extra: { b: 3 },
258+
};
259+
const localScope = new Scope();
260+
localScope.setExtra('a', 'b');
261+
262+
addGlobalEventProcessor((processedEvent: Event) => {
263+
processedEvent.dist = '1';
264+
return processedEvent;
265+
});
266+
267+
localScope.addEventProcessor((processedEvent: Event) => {
268+
expect(processedEvent.extra).toEqual({ a: 'b', b: 3 });
269+
return processedEvent;
270+
});
271+
272+
localScope.addEventProcessor((processedEvent: Event) => {
273+
expect(processedEvent.dist).toEqual('1');
274+
return processedEvent;
275+
});
276+
277+
return localScope.applyToEvent(event).then(final => {
278+
expect(final!.dist).toEqual('1');
279+
});
280+
});
281+
221282
test('addEventProcessor async', async () => {
222283
jest.useFakeTimers();
223284
expect.assertions(6);

packages/types/src/scope.ts

+7
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,13 @@ export interface Scope {
5656
*/
5757
setLevel(level: Severity): this;
5858

59+
/**
60+
* Sets context data with the given name.
61+
* @param name of the context
62+
* @param context Any kind of data. This data will be normailzed.
63+
*/
64+
setContext(name: string, context: { [key: string]: any } | null): this;
65+
5966
/** Clears the current scope and resets its properties. */
6067
clear(): this;
6168

0 commit comments

Comments
 (0)