UNPKG

16.2 kBJavaScriptView Raw
1Object.defineProperty(exports, "__esModule", { value: true });
2var tslib_1 = require("tslib");
3var utils_1 = require("@sentry/utils");
4/**
5 * Absolute maximum number of breadcrumbs added to an event.
6 * The `maxBreadcrumbs` option cannot be higher than this value.
7 */
8var MAX_BREADCRUMBS = 100;
9/**
10 * Holds additional event information. {@link Scope.applyToEvent} will be
11 * called by the client before an event will be sent.
12 */
13var Scope = /** @class */ (function () {
14 function Scope() {
15 /** Flag if notifying is happening. */
16 this._notifyingListeners = false;
17 /** Callback for client to receive scope changes. */
18 this._scopeListeners = [];
19 /** Callback list that will be called after {@link applyToEvent}. */
20 this._eventProcessors = [];
21 /** Array of breadcrumbs. */
22 this._breadcrumbs = [];
23 /** User */
24 this._user = {};
25 /** Tags */
26 this._tags = {};
27 /** Extra */
28 this._extra = {};
29 /** Contexts */
30 this._contexts = {};
31 }
32 /**
33 * Inherit values from the parent scope.
34 * @param scope to clone.
35 */
36 Scope.clone = function (scope) {
37 var newScope = new Scope();
38 if (scope) {
39 newScope._breadcrumbs = tslib_1.__spread(scope._breadcrumbs);
40 newScope._tags = tslib_1.__assign({}, scope._tags);
41 newScope._extra = tslib_1.__assign({}, scope._extra);
42 newScope._contexts = tslib_1.__assign({}, scope._contexts);
43 newScope._user = scope._user;
44 newScope._level = scope._level;
45 newScope._span = scope._span;
46 newScope._session = scope._session;
47 newScope._transactionName = scope._transactionName;
48 newScope._fingerprint = scope._fingerprint;
49 newScope._eventProcessors = tslib_1.__spread(scope._eventProcessors);
50 newScope._requestSession = scope._requestSession;
51 }
52 return newScope;
53 };
54 /**
55 * Add internal on change listener. Used for sub SDKs that need to store the scope.
56 * @hidden
57 */
58 Scope.prototype.addScopeListener = function (callback) {
59 this._scopeListeners.push(callback);
60 };
61 /**
62 * @inheritDoc
63 */
64 Scope.prototype.addEventProcessor = function (callback) {
65 this._eventProcessors.push(callback);
66 return this;
67 };
68 /**
69 * @inheritDoc
70 */
71 Scope.prototype.setUser = function (user) {
72 this._user = user || {};
73 if (this._session) {
74 this._session.update({ user: user });
75 }
76 this._notifyScopeListeners();
77 return this;
78 };
79 /**
80 * @inheritDoc
81 */
82 Scope.prototype.getUser = function () {
83 return this._user;
84 };
85 /**
86 * @inheritDoc
87 */
88 Scope.prototype.getRequestSession = function () {
89 return this._requestSession;
90 };
91 /**
92 * @inheritDoc
93 */
94 Scope.prototype.setRequestSession = function (requestSession) {
95 this._requestSession = requestSession;
96 return this;
97 };
98 /**
99 * @inheritDoc
100 */
101 Scope.prototype.setTags = function (tags) {
102 this._tags = tslib_1.__assign(tslib_1.__assign({}, this._tags), tags);
103 this._notifyScopeListeners();
104 return this;
105 };
106 /**
107 * @inheritDoc
108 */
109 Scope.prototype.setTag = function (key, value) {
110 var _a;
111 this._tags = tslib_1.__assign(tslib_1.__assign({}, this._tags), (_a = {}, _a[key] = value, _a));
112 this._notifyScopeListeners();
113 return this;
114 };
115 /**
116 * @inheritDoc
117 */
118 Scope.prototype.setExtras = function (extras) {
119 this._extra = tslib_1.__assign(tslib_1.__assign({}, this._extra), extras);
120 this._notifyScopeListeners();
121 return this;
122 };
123 /**
124 * @inheritDoc
125 */
126 Scope.prototype.setExtra = function (key, extra) {
127 var _a;
128 this._extra = tslib_1.__assign(tslib_1.__assign({}, this._extra), (_a = {}, _a[key] = extra, _a));
129 this._notifyScopeListeners();
130 return this;
131 };
132 /**
133 * @inheritDoc
134 */
135 Scope.prototype.setFingerprint = function (fingerprint) {
136 this._fingerprint = fingerprint;
137 this._notifyScopeListeners();
138 return this;
139 };
140 /**
141 * @inheritDoc
142 */
143 Scope.prototype.setLevel = function (level) {
144 this._level = level;
145 this._notifyScopeListeners();
146 return this;
147 };
148 /**
149 * @inheritDoc
150 */
151 Scope.prototype.setTransactionName = function (name) {
152 this._transactionName = name;
153 this._notifyScopeListeners();
154 return this;
155 };
156 /**
157 * Can be removed in major version.
158 * @deprecated in favor of {@link this.setTransactionName}
159 */
160 Scope.prototype.setTransaction = function (name) {
161 return this.setTransactionName(name);
162 };
163 /**
164 * @inheritDoc
165 */
166 Scope.prototype.setContext = function (key, context) {
167 var _a;
168 if (context === null) {
169 // eslint-disable-next-line @typescript-eslint/no-dynamic-delete
170 delete this._contexts[key];
171 }
172 else {
173 this._contexts = tslib_1.__assign(tslib_1.__assign({}, this._contexts), (_a = {}, _a[key] = context, _a));
174 }
175 this._notifyScopeListeners();
176 return this;
177 };
178 /**
179 * @inheritDoc
180 */
181 Scope.prototype.setSpan = function (span) {
182 this._span = span;
183 this._notifyScopeListeners();
184 return this;
185 };
186 /**
187 * @inheritDoc
188 */
189 Scope.prototype.getSpan = function () {
190 return this._span;
191 };
192 /**
193 * @inheritDoc
194 */
195 Scope.prototype.getTransaction = function () {
196 var _a, _b, _c, _d;
197 // often, this span will be a transaction, but it's not guaranteed to be
198 var span = this.getSpan();
199 // try it the new way first
200 if ((_a = span) === null || _a === void 0 ? void 0 : _a.transaction) {
201 return (_b = span) === null || _b === void 0 ? void 0 : _b.transaction;
202 }
203 // fallback to the old way (known bug: this only finds transactions with sampled = true)
204 if ((_d = (_c = span) === null || _c === void 0 ? void 0 : _c.spanRecorder) === null || _d === void 0 ? void 0 : _d.spans[0]) {
205 return span.spanRecorder.spans[0];
206 }
207 // neither way found a transaction
208 return undefined;
209 };
210 /**
211 * @inheritDoc
212 */
213 Scope.prototype.setSession = function (session) {
214 if (!session) {
215 delete this._session;
216 }
217 else {
218 this._session = session;
219 }
220 this._notifyScopeListeners();
221 return this;
222 };
223 /**
224 * @inheritDoc
225 */
226 Scope.prototype.getSession = function () {
227 return this._session;
228 };
229 /**
230 * @inheritDoc
231 */
232 Scope.prototype.update = function (captureContext) {
233 if (!captureContext) {
234 return this;
235 }
236 if (typeof captureContext === 'function') {
237 var updatedScope = captureContext(this);
238 return updatedScope instanceof Scope ? updatedScope : this;
239 }
240 if (captureContext instanceof Scope) {
241 this._tags = tslib_1.__assign(tslib_1.__assign({}, this._tags), captureContext._tags);
242 this._extra = tslib_1.__assign(tslib_1.__assign({}, this._extra), captureContext._extra);
243 this._contexts = tslib_1.__assign(tslib_1.__assign({}, this._contexts), captureContext._contexts);
244 if (captureContext._user && Object.keys(captureContext._user).length) {
245 this._user = captureContext._user;
246 }
247 if (captureContext._level) {
248 this._level = captureContext._level;
249 }
250 if (captureContext._fingerprint) {
251 this._fingerprint = captureContext._fingerprint;
252 }
253 if (captureContext._requestSession) {
254 this._requestSession = captureContext._requestSession;
255 }
256 }
257 else if (utils_1.isPlainObject(captureContext)) {
258 // eslint-disable-next-line no-param-reassign
259 captureContext = captureContext;
260 this._tags = tslib_1.__assign(tslib_1.__assign({}, this._tags), captureContext.tags);
261 this._extra = tslib_1.__assign(tslib_1.__assign({}, this._extra), captureContext.extra);
262 this._contexts = tslib_1.__assign(tslib_1.__assign({}, this._contexts), captureContext.contexts);
263 if (captureContext.user) {
264 this._user = captureContext.user;
265 }
266 if (captureContext.level) {
267 this._level = captureContext.level;
268 }
269 if (captureContext.fingerprint) {
270 this._fingerprint = captureContext.fingerprint;
271 }
272 if (captureContext.requestSession) {
273 this._requestSession = captureContext.requestSession;
274 }
275 }
276 return this;
277 };
278 /**
279 * @inheritDoc
280 */
281 Scope.prototype.clear = function () {
282 this._breadcrumbs = [];
283 this._tags = {};
284 this._extra = {};
285 this._user = {};
286 this._contexts = {};
287 this._level = undefined;
288 this._transactionName = undefined;
289 this._fingerprint = undefined;
290 this._requestSession = undefined;
291 this._span = undefined;
292 this._session = undefined;
293 this._notifyScopeListeners();
294 return this;
295 };
296 /**
297 * @inheritDoc
298 */
299 Scope.prototype.addBreadcrumb = function (breadcrumb, maxBreadcrumbs) {
300 var maxCrumbs = typeof maxBreadcrumbs === 'number' ? Math.min(maxBreadcrumbs, MAX_BREADCRUMBS) : MAX_BREADCRUMBS;
301 // No data has been changed, so don't notify scope listeners
302 if (maxCrumbs <= 0) {
303 return this;
304 }
305 var mergedBreadcrumb = tslib_1.__assign({ timestamp: utils_1.dateTimestampInSeconds() }, breadcrumb);
306 this._breadcrumbs = tslib_1.__spread(this._breadcrumbs, [mergedBreadcrumb]).slice(-maxCrumbs);
307 this._notifyScopeListeners();
308 return this;
309 };
310 /**
311 * @inheritDoc
312 */
313 Scope.prototype.clearBreadcrumbs = function () {
314 this._breadcrumbs = [];
315 this._notifyScopeListeners();
316 return this;
317 };
318 /**
319 * Applies the current context and fingerprint to the event.
320 * Note that breadcrumbs will be added by the client.
321 * Also if the event has already breadcrumbs on it, we do not merge them.
322 * @param event Event
323 * @param hint May contain additional information about the original exception.
324 * @hidden
325 */
326 Scope.prototype.applyToEvent = function (event, hint) {
327 var _a;
328 if (this._extra && Object.keys(this._extra).length) {
329 event.extra = tslib_1.__assign(tslib_1.__assign({}, this._extra), event.extra);
330 }
331 if (this._tags && Object.keys(this._tags).length) {
332 event.tags = tslib_1.__assign(tslib_1.__assign({}, this._tags), event.tags);
333 }
334 if (this._user && Object.keys(this._user).length) {
335 event.user = tslib_1.__assign(tslib_1.__assign({}, this._user), event.user);
336 }
337 if (this._contexts && Object.keys(this._contexts).length) {
338 event.contexts = tslib_1.__assign(tslib_1.__assign({}, this._contexts), event.contexts);
339 }
340 if (this._level) {
341 event.level = this._level;
342 }
343 if (this._transactionName) {
344 event.transaction = this._transactionName;
345 }
346 // We want to set the trace context for normal events only if there isn't already
347 // a trace context on the event. There is a product feature in place where we link
348 // errors with transaction and it relies on that.
349 if (this._span) {
350 event.contexts = tslib_1.__assign({ trace: this._span.getTraceContext() }, event.contexts);
351 var transactionName = (_a = this._span.transaction) === null || _a === void 0 ? void 0 : _a.name;
352 if (transactionName) {
353 event.tags = tslib_1.__assign({ transaction: transactionName }, event.tags);
354 }
355 }
356 this._applyFingerprint(event);
357 event.breadcrumbs = tslib_1.__spread((event.breadcrumbs || []), this._breadcrumbs);
358 event.breadcrumbs = event.breadcrumbs.length > 0 ? event.breadcrumbs : undefined;
359 return this._notifyEventProcessors(tslib_1.__spread(getGlobalEventProcessors(), this._eventProcessors), event, hint);
360 };
361 /**
362 * This will be called after {@link applyToEvent} is finished.
363 */
364 Scope.prototype._notifyEventProcessors = function (processors, event, hint, index) {
365 var _this = this;
366 if (index === void 0) { index = 0; }
367 return new utils_1.SyncPromise(function (resolve, reject) {
368 var processor = processors[index];
369 if (event === null || typeof processor !== 'function') {
370 resolve(event);
371 }
372 else {
373 var result = processor(tslib_1.__assign({}, event), hint);
374 if (utils_1.isThenable(result)) {
375 void result
376 .then(function (final) { return _this._notifyEventProcessors(processors, final, hint, index + 1).then(resolve); })
377 .then(null, reject);
378 }
379 else {
380 void _this._notifyEventProcessors(processors, result, hint, index + 1)
381 .then(resolve)
382 .then(null, reject);
383 }
384 }
385 });
386 };
387 /**
388 * This will be called on every set call.
389 */
390 Scope.prototype._notifyScopeListeners = function () {
391 var _this = this;
392 // We need this check for this._notifyingListeners to be able to work on scope during updates
393 // If this check is not here we'll produce endless recursion when something is done with the scope
394 // during the callback.
395 if (!this._notifyingListeners) {
396 this._notifyingListeners = true;
397 this._scopeListeners.forEach(function (callback) {
398 callback(_this);
399 });
400 this._notifyingListeners = false;
401 }
402 };
403 /**
404 * Applies fingerprint from the scope to the event if there's one,
405 * uses message if there's one instead or get rid of empty fingerprint
406 */
407 Scope.prototype._applyFingerprint = function (event) {
408 // Make sure it's an array first and we actually have something in place
409 event.fingerprint = event.fingerprint
410 ? Array.isArray(event.fingerprint)
411 ? event.fingerprint
412 : [event.fingerprint]
413 : [];
414 // If we have something on the scope, then merge it with event
415 if (this._fingerprint) {
416 event.fingerprint = event.fingerprint.concat(this._fingerprint);
417 }
418 // If we have no data at all, remove empty array default
419 if (event.fingerprint && !event.fingerprint.length) {
420 delete event.fingerprint;
421 }
422 };
423 return Scope;
424}());
425exports.Scope = Scope;
426/**
427 * Returns the global event processors.
428 */
429function getGlobalEventProcessors() {
430 /* eslint-disable @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access */
431 var global = utils_1.getGlobalObject();
432 global.__SENTRY__ = global.__SENTRY__ || {};
433 global.__SENTRY__.globalEventProcessors = global.__SENTRY__.globalEventProcessors || [];
434 return global.__SENTRY__.globalEventProcessors;
435 /* eslint-enable @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access */
436}
437/**
438 * Add a EventProcessor to be kept globally.
439 * @param callback EventProcessor to add
440 */
441function addGlobalEventProcessor(callback) {
442 getGlobalEventProcessors().push(callback);
443}
444exports.addGlobalEventProcessor = addGlobalEventProcessor;
445//# sourceMappingURL=scope.js.map
\No newline at end of file