sessionflusher.js 3.6 KB

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