UNPKG

3.79 kBJavaScriptView Raw
1import { dropUndefinedKeys } from '@sentry/utils';
2import { getCurrentHub } from './hub.js';
3
4/**
5 * @inheritdoc
6 */
7class SessionFlusher {
8 __init() {this.flushTimeout = 60;}
9 __init2() {this._pendingAggregates = {};}
10
11 __init3() {this._isEnabled = true;}
12
13 constructor(client, attrs) {SessionFlusher.prototype.__init.call(this);SessionFlusher.prototype.__init2.call(this);SessionFlusher.prototype.__init3.call(this);
14 this._client = client;
15 // Call to setInterval, so that flush is called every 60 seconds
16 this._intervalId = setInterval(() => this.flush(), this.flushTimeout * 1000);
17 this._sessionAttrs = attrs;
18 }
19
20 /** Checks if `pendingAggregates` has entries, and if it does flushes them by calling `sendSession` */
21 flush() {
22 const sessionAggregates = this.getSessionAggregates();
23 if (sessionAggregates.aggregates.length === 0) {
24 return;
25 }
26 this._pendingAggregates = {};
27 this._client.sendSession(sessionAggregates);
28 }
29
30 /** Massages the entries in `pendingAggregates` and returns aggregated sessions */
31 getSessionAggregates() {
32 const aggregates = Object.keys(this._pendingAggregates).map((key) => {
33 return this._pendingAggregates[parseInt(key)];
34 });
35
36 const sessionAggregates = {
37 attrs: this._sessionAttrs,
38 aggregates,
39 };
40 return dropUndefinedKeys(sessionAggregates);
41 }
42
43 /** JSDoc */
44 close() {
45 clearInterval(this._intervalId);
46 this._isEnabled = false;
47 this.flush();
48 }
49
50 /**
51 * Wrapper function for _incrementSessionStatusCount that checks if the instance of SessionFlusher is enabled then
52 * fetches the session status of the request from `Scope.getRequestSession().status` on the scope and passes them to
53 * `_incrementSessionStatusCount` along with the start date
54 */
55 incrementSessionStatusCount() {
56 if (!this._isEnabled) {
57 return;
58 }
59 const scope = getCurrentHub().getScope();
60 const requestSession = scope && scope.getRequestSession();
61
62 if (requestSession && requestSession.status) {
63 this._incrementSessionStatusCount(requestSession.status, new Date());
64 // This is not entirely necessarily but is added as a safe guard to indicate the bounds of a request and so in
65 // case captureRequestSession is called more than once to prevent double count
66 if (scope) {
67 scope.setRequestSession(undefined);
68 }
69 /* eslint-enable @typescript-eslint/no-unsafe-member-access */
70 }
71 }
72
73 /**
74 * Increments status bucket in pendingAggregates buffer (internal state) corresponding to status of
75 * the session received
76 */
77 _incrementSessionStatusCount(status, date) {
78 // Truncate minutes and seconds on Session Started attribute to have one minute bucket keys
79 const sessionStartedTrunc = new Date(date).setSeconds(0, 0);
80 this._pendingAggregates[sessionStartedTrunc] = this._pendingAggregates[sessionStartedTrunc] || {};
81
82 // corresponds to aggregated sessions in one specific minute bucket
83 // for example, {"started":"2021-03-16T08:00:00.000Z","exited":4, "errored": 1}
84 const aggregationCounts = this._pendingAggregates[sessionStartedTrunc];
85 if (!aggregationCounts.started) {
86 aggregationCounts.started = new Date(sessionStartedTrunc).toISOString();
87 }
88
89 switch (status) {
90 case 'errored':
91 aggregationCounts.errored = (aggregationCounts.errored || 0) + 1;
92 return aggregationCounts.errored;
93 case 'ok':
94 aggregationCounts.exited = (aggregationCounts.exited || 0) + 1;
95 return aggregationCounts.exited;
96 default:
97 aggregationCounts.crashed = (aggregationCounts.crashed || 0) + 1;
98 return aggregationCounts.crashed;
99 }
100 }
101}
102
103export { SessionFlusher };
104//# sourceMappingURL=sessionflusher.js.map