UNPKG

18.3 kBJavaScriptView Raw
1Object.defineProperty(exports, "__esModule", { value: true });
2var tslib_1 = require("tslib");
3var utils_1 = require("@sentry/utils");
4var flags_1 = require("./flags");
5var scope_1 = require("./scope");
6var session_1 = require("./session");
7/**
8 * API compatibility version of this hub.
9 *
10 * WARNING: This number should only be increased when the global interface
11 * changes and new methods are introduced.
12 *
13 * @hidden
14 */
15exports.API_VERSION = 4;
16/**
17 * Default maximum number of breadcrumbs added to an event. Can be overwritten
18 * with {@link Options.maxBreadcrumbs}.
19 */
20var DEFAULT_BREADCRUMBS = 100;
21/**
22 * @inheritDoc
23 */
24var Hub = /** @class */ (function () {
25 /**
26 * Creates a new instance of the hub, will push one {@link Layer} into the
27 * internal stack on creation.
28 *
29 * @param client bound to the hub.
30 * @param scope bound to the hub.
31 * @param version number, higher number means higher priority.
32 */
33 function Hub(client, scope, _version) {
34 if (scope === void 0) { scope = new scope_1.Scope(); }
35 if (_version === void 0) { _version = exports.API_VERSION; }
36 this._version = _version;
37 /** Is a {@link Layer}[] containing the client and scope */
38 this._stack = [{}];
39 this.getStackTop().scope = scope;
40 if (client) {
41 this.bindClient(client);
42 }
43 }
44 /**
45 * @inheritDoc
46 */
47 Hub.prototype.isOlderThan = function (version) {
48 return this._version < version;
49 };
50 /**
51 * @inheritDoc
52 */
53 Hub.prototype.bindClient = function (client) {
54 var top = this.getStackTop();
55 top.client = client;
56 if (client && client.setupIntegrations) {
57 client.setupIntegrations();
58 }
59 };
60 /**
61 * @inheritDoc
62 */
63 Hub.prototype.pushScope = function () {
64 // We want to clone the content of prev scope
65 var scope = scope_1.Scope.clone(this.getScope());
66 this.getStack().push({
67 client: this.getClient(),
68 scope: scope,
69 });
70 return scope;
71 };
72 /**
73 * @inheritDoc
74 */
75 Hub.prototype.popScope = function () {
76 if (this.getStack().length <= 1)
77 return false;
78 return !!this.getStack().pop();
79 };
80 /**
81 * @inheritDoc
82 */
83 Hub.prototype.withScope = function (callback) {
84 var scope = this.pushScope();
85 try {
86 callback(scope);
87 }
88 finally {
89 this.popScope();
90 }
91 };
92 /**
93 * @inheritDoc
94 */
95 Hub.prototype.getClient = function () {
96 return this.getStackTop().client;
97 };
98 /** Returns the scope of the top stack. */
99 Hub.prototype.getScope = function () {
100 return this.getStackTop().scope;
101 };
102 /** Returns the scope stack for domains or the process. */
103 Hub.prototype.getStack = function () {
104 return this._stack;
105 };
106 /** Returns the topmost scope layer in the order domain > local > process. */
107 Hub.prototype.getStackTop = function () {
108 return this._stack[this._stack.length - 1];
109 };
110 /**
111 * @inheritDoc
112 */
113 // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/explicit-module-boundary-types
114 Hub.prototype.captureException = function (exception, hint) {
115 var eventId = (this._lastEventId = hint && hint.event_id ? hint.event_id : utils_1.uuid4());
116 var finalHint = hint;
117 // If there's no explicit hint provided, mimic the same thing that would happen
118 // in the minimal itself to create a consistent behavior.
119 // We don't do this in the client, as it's the lowest level API, and doing this,
120 // would prevent user from having full control over direct calls.
121 if (!hint) {
122 var syntheticException = void 0;
123 try {
124 throw new Error('Sentry syntheticException');
125 }
126 catch (exception) {
127 syntheticException = exception;
128 }
129 finalHint = {
130 originalException: exception,
131 syntheticException: syntheticException,
132 };
133 }
134 this._invokeClient('captureException', exception, tslib_1.__assign(tslib_1.__assign({}, finalHint), { event_id: eventId }));
135 return eventId;
136 };
137 /**
138 * @inheritDoc
139 */
140 Hub.prototype.captureMessage = function (message, level, hint) {
141 var eventId = (this._lastEventId = hint && hint.event_id ? hint.event_id : utils_1.uuid4());
142 var finalHint = hint;
143 // If there's no explicit hint provided, mimic the same thing that would happen
144 // in the minimal itself to create a consistent behavior.
145 // We don't do this in the client, as it's the lowest level API, and doing this,
146 // would prevent user from having full control over direct calls.
147 if (!hint) {
148 var syntheticException = void 0;
149 try {
150 throw new Error(message);
151 }
152 catch (exception) {
153 syntheticException = exception;
154 }
155 finalHint = {
156 originalException: message,
157 syntheticException: syntheticException,
158 };
159 }
160 this._invokeClient('captureMessage', message, level, tslib_1.__assign(tslib_1.__assign({}, finalHint), { event_id: eventId }));
161 return eventId;
162 };
163 /**
164 * @inheritDoc
165 */
166 Hub.prototype.captureEvent = function (event, hint) {
167 var eventId = hint && hint.event_id ? hint.event_id : utils_1.uuid4();
168 if (event.type !== 'transaction') {
169 this._lastEventId = eventId;
170 }
171 this._invokeClient('captureEvent', event, tslib_1.__assign(tslib_1.__assign({}, hint), { event_id: eventId }));
172 return eventId;
173 };
174 /**
175 * @inheritDoc
176 */
177 Hub.prototype.lastEventId = function () {
178 return this._lastEventId;
179 };
180 /**
181 * @inheritDoc
182 */
183 Hub.prototype.addBreadcrumb = function (breadcrumb, hint) {
184 var _a = this.getStackTop(), scope = _a.scope, client = _a.client;
185 if (!scope || !client)
186 return;
187 // eslint-disable-next-line @typescript-eslint/unbound-method
188 var _b = (client.getOptions && client.getOptions()) || {}, _c = _b.beforeBreadcrumb, beforeBreadcrumb = _c === void 0 ? null : _c, _d = _b.maxBreadcrumbs, maxBreadcrumbs = _d === void 0 ? DEFAULT_BREADCRUMBS : _d;
189 if (maxBreadcrumbs <= 0)
190 return;
191 var timestamp = utils_1.dateTimestampInSeconds();
192 var mergedBreadcrumb = tslib_1.__assign({ timestamp: timestamp }, breadcrumb);
193 var finalBreadcrumb = beforeBreadcrumb
194 ? utils_1.consoleSandbox(function () { return beforeBreadcrumb(mergedBreadcrumb, hint); })
195 : mergedBreadcrumb;
196 if (finalBreadcrumb === null)
197 return;
198 scope.addBreadcrumb(finalBreadcrumb, maxBreadcrumbs);
199 };
200 /**
201 * @inheritDoc
202 */
203 Hub.prototype.setUser = function (user) {
204 var scope = this.getScope();
205 if (scope)
206 scope.setUser(user);
207 };
208 /**
209 * @inheritDoc
210 */
211 Hub.prototype.setTags = function (tags) {
212 var scope = this.getScope();
213 if (scope)
214 scope.setTags(tags);
215 };
216 /**
217 * @inheritDoc
218 */
219 Hub.prototype.setExtras = function (extras) {
220 var scope = this.getScope();
221 if (scope)
222 scope.setExtras(extras);
223 };
224 /**
225 * @inheritDoc
226 */
227 Hub.prototype.setTag = function (key, value) {
228 var scope = this.getScope();
229 if (scope)
230 scope.setTag(key, value);
231 };
232 /**
233 * @inheritDoc
234 */
235 Hub.prototype.setExtra = function (key, extra) {
236 var scope = this.getScope();
237 if (scope)
238 scope.setExtra(key, extra);
239 };
240 /**
241 * @inheritDoc
242 */
243 // eslint-disable-next-line @typescript-eslint/no-explicit-any
244 Hub.prototype.setContext = function (name, context) {
245 var scope = this.getScope();
246 if (scope)
247 scope.setContext(name, context);
248 };
249 /**
250 * @inheritDoc
251 */
252 Hub.prototype.configureScope = function (callback) {
253 var _a = this.getStackTop(), scope = _a.scope, client = _a.client;
254 if (scope && client) {
255 callback(scope);
256 }
257 };
258 /**
259 * @inheritDoc
260 */
261 Hub.prototype.run = function (callback) {
262 var oldHub = makeMain(this);
263 try {
264 callback(this);
265 }
266 finally {
267 makeMain(oldHub);
268 }
269 };
270 /**
271 * @inheritDoc
272 */
273 Hub.prototype.getIntegration = function (integration) {
274 var client = this.getClient();
275 if (!client)
276 return null;
277 try {
278 return client.getIntegration(integration);
279 }
280 catch (_oO) {
281 flags_1.IS_DEBUG_BUILD && utils_1.logger.warn("Cannot retrieve integration " + integration.id + " from the current Hub");
282 return null;
283 }
284 };
285 /**
286 * @inheritDoc
287 */
288 Hub.prototype.startSpan = function (context) {
289 return this._callExtensionMethod('startSpan', context);
290 };
291 /**
292 * @inheritDoc
293 */
294 Hub.prototype.startTransaction = function (context, customSamplingContext) {
295 return this._callExtensionMethod('startTransaction', context, customSamplingContext);
296 };
297 /**
298 * @inheritDoc
299 */
300 Hub.prototype.traceHeaders = function () {
301 return this._callExtensionMethod('traceHeaders');
302 };
303 /**
304 * @inheritDoc
305 */
306 Hub.prototype.captureSession = function (endSession) {
307 if (endSession === void 0) { endSession = false; }
308 // both send the update and pull the session from the scope
309 if (endSession) {
310 return this.endSession();
311 }
312 // only send the update
313 this._sendSessionUpdate();
314 };
315 /**
316 * @inheritDoc
317 */
318 Hub.prototype.endSession = function () {
319 var layer = this.getStackTop();
320 var scope = layer && layer.scope;
321 var session = scope && scope.getSession();
322 if (session) {
323 session.close();
324 }
325 this._sendSessionUpdate();
326 // the session is over; take it off of the scope
327 if (scope) {
328 scope.setSession();
329 }
330 };
331 /**
332 * @inheritDoc
333 */
334 Hub.prototype.startSession = function (context) {
335 var _a = this.getStackTop(), scope = _a.scope, client = _a.client;
336 var _b = (client && client.getOptions()) || {}, release = _b.release, environment = _b.environment;
337 // Will fetch userAgent if called from browser sdk
338 var global = utils_1.getGlobalObject();
339 var userAgent = (global.navigator || {}).userAgent;
340 var session = new session_1.Session(tslib_1.__assign(tslib_1.__assign(tslib_1.__assign({ release: release,
341 environment: environment }, (scope && { user: scope.getUser() })), (userAgent && { userAgent: userAgent })), context));
342 if (scope) {
343 // End existing session if there's one
344 var currentSession = scope.getSession && scope.getSession();
345 if (currentSession && currentSession.status === 'ok') {
346 currentSession.update({ status: 'exited' });
347 }
348 this.endSession();
349 // Afterwards we set the new session on the scope
350 scope.setSession(session);
351 }
352 return session;
353 };
354 /**
355 * Sends the current Session on the scope
356 */
357 Hub.prototype._sendSessionUpdate = function () {
358 var _a = this.getStackTop(), scope = _a.scope, client = _a.client;
359 if (!scope)
360 return;
361 var session = scope.getSession && scope.getSession();
362 if (session) {
363 if (client && client.captureSession) {
364 client.captureSession(session);
365 }
366 }
367 };
368 /**
369 * Internal helper function to call a method on the top client if it exists.
370 *
371 * @param method The method to call on the client.
372 * @param args Arguments to pass to the client function.
373 */
374 // eslint-disable-next-line @typescript-eslint/no-explicit-any
375 Hub.prototype._invokeClient = function (method) {
376 var _a;
377 var args = [];
378 for (var _i = 1; _i < arguments.length; _i++) {
379 args[_i - 1] = arguments[_i];
380 }
381 var _b = this.getStackTop(), scope = _b.scope, client = _b.client;
382 if (client && client[method]) {
383 // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any
384 (_a = client)[method].apply(_a, tslib_1.__spread(args, [scope]));
385 }
386 };
387 /**
388 * Calls global extension method and binding current instance to the function call
389 */
390 // @ts-ignore Function lacks ending return statement and return type does not include 'undefined'. ts(2366)
391 // eslint-disable-next-line @typescript-eslint/no-explicit-any
392 Hub.prototype._callExtensionMethod = function (method) {
393 var args = [];
394 for (var _i = 1; _i < arguments.length; _i++) {
395 args[_i - 1] = arguments[_i];
396 }
397 var carrier = getMainCarrier();
398 var sentry = carrier.__SENTRY__;
399 if (sentry && sentry.extensions && typeof sentry.extensions[method] === 'function') {
400 return sentry.extensions[method].apply(this, args);
401 }
402 flags_1.IS_DEBUG_BUILD && utils_1.logger.warn("Extension method " + method + " couldn't be found, doing nothing.");
403 };
404 return Hub;
405}());
406exports.Hub = Hub;
407/**
408 * Returns the global shim registry.
409 *
410 * FIXME: This function is problematic, because despite always returning a valid Carrier,
411 * it has an optional `__SENTRY__` property, which then in turn requires us to always perform an unnecessary check
412 * at the call-site. We always access the carrier through this function, so we can guarantee that `__SENTRY__` is there.
413 **/
414function getMainCarrier() {
415 var carrier = utils_1.getGlobalObject();
416 carrier.__SENTRY__ = carrier.__SENTRY__ || {
417 extensions: {},
418 hub: undefined,
419 };
420 return carrier;
421}
422exports.getMainCarrier = getMainCarrier;
423/**
424 * Replaces the current main hub with the passed one on the global object
425 *
426 * @returns The old replaced hub
427 */
428function makeMain(hub) {
429 var registry = getMainCarrier();
430 var oldHub = getHubFromCarrier(registry);
431 setHubOnCarrier(registry, hub);
432 return oldHub;
433}
434exports.makeMain = makeMain;
435/**
436 * Returns the default hub instance.
437 *
438 * If a hub is already registered in the global carrier but this module
439 * contains a more recent version, it replaces the registered version.
440 * Otherwise, the currently registered hub will be returned.
441 */
442function getCurrentHub() {
443 // Get main carrier (global for every environment)
444 var registry = getMainCarrier();
445 // If there's no hub, or its an old API, assign a new one
446 if (!hasHubOnCarrier(registry) || getHubFromCarrier(registry).isOlderThan(exports.API_VERSION)) {
447 setHubOnCarrier(registry, new Hub());
448 }
449 // Prefer domains over global if they are there (applicable only to Node environment)
450 if (utils_1.isNodeEnv()) {
451 return getHubFromActiveDomain(registry);
452 }
453 // Return hub that lives on a global object
454 return getHubFromCarrier(registry);
455}
456exports.getCurrentHub = getCurrentHub;
457/**
458 * Returns the active domain, if one exists
459 * @deprecated No longer used; remove in v7
460 * @returns The domain, or undefined if there is no active domain
461 */
462// eslint-disable-next-line deprecation/deprecation
463function getActiveDomain() {
464 flags_1.IS_DEBUG_BUILD && utils_1.logger.warn('Function `getActiveDomain` is deprecated and will be removed in a future version.');
465 var sentry = getMainCarrier().__SENTRY__;
466 return sentry && sentry.extensions && sentry.extensions.domain && sentry.extensions.domain.active;
467}
468exports.getActiveDomain = getActiveDomain;
469/**
470 * Try to read the hub from an active domain, and fallback to the registry if one doesn't exist
471 * @returns discovered hub
472 */
473function getHubFromActiveDomain(registry) {
474 try {
475 var sentry = getMainCarrier().__SENTRY__;
476 var activeDomain = sentry && sentry.extensions && sentry.extensions.domain && sentry.extensions.domain.active;
477 // If there's no active domain, just return global hub
478 if (!activeDomain) {
479 return getHubFromCarrier(registry);
480 }
481 // If there's no hub on current domain, or it's an old API, assign a new one
482 if (!hasHubOnCarrier(activeDomain) || getHubFromCarrier(activeDomain).isOlderThan(exports.API_VERSION)) {
483 var registryHubTopStack = getHubFromCarrier(registry).getStackTop();
484 setHubOnCarrier(activeDomain, new Hub(registryHubTopStack.client, scope_1.Scope.clone(registryHubTopStack.scope)));
485 }
486 // Return hub that lives on a domain
487 return getHubFromCarrier(activeDomain);
488 }
489 catch (_Oo) {
490 // Return hub that lives on a global object
491 return getHubFromCarrier(registry);
492 }
493}
494/**
495 * This will tell whether a carrier has a hub on it or not
496 * @param carrier object
497 */
498function hasHubOnCarrier(carrier) {
499 return !!(carrier && carrier.__SENTRY__ && carrier.__SENTRY__.hub);
500}
501/**
502 * This will create a new {@link Hub} and add to the passed object on
503 * __SENTRY__.hub.
504 * @param carrier object
505 * @hidden
506 */
507function getHubFromCarrier(carrier) {
508 return utils_1.getGlobalSingleton('hub', function () { return new Hub(); }, carrier);
509}
510exports.getHubFromCarrier = getHubFromCarrier;
511/**
512 * This will set passed {@link Hub} on the passed object's __SENTRY__.hub attribute
513 * @param carrier object
514 * @param hub Hub
515 * @returns A boolean indicating success or failure
516 */
517function setHubOnCarrier(carrier, hub) {
518 if (!carrier)
519 return false;
520 var __SENTRY__ = (carrier.__SENTRY__ = carrier.__SENTRY__ || {});
521 __SENTRY__.hub = hub;
522 return true;
523}
524exports.setHubOnCarrier = setHubOnCarrier;
525//# sourceMappingURL=hub.js.map
\No newline at end of file