@newrelic/browser-agent 1.258.2 → 1.260.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (132) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/dist/cjs/cdn/polyfills.js +3 -1
  3. package/dist/cjs/common/constants/env.cdn.js +1 -1
  4. package/dist/cjs/common/constants/env.npm.js +1 -1
  5. package/dist/cjs/common/drain/drain.js +1 -1
  6. package/dist/cjs/common/harvest/harvest-scheduler.js +4 -2
  7. package/dist/cjs/common/session/session-entity.js +8 -1
  8. package/dist/cjs/common/timing/time-keeper.js +9 -30
  9. package/dist/cjs/features/ajax/constants.js +3 -2
  10. package/dist/cjs/features/jserrors/instrument/index.js +3 -4
  11. package/dist/cjs/features/metrics/aggregate/index.js +0 -8
  12. package/dist/cjs/features/page_view_event/aggregate/index.js +8 -6
  13. package/dist/cjs/features/session_replay/aggregate/index.js +31 -36
  14. package/dist/cjs/features/session_replay/constants.js +5 -2
  15. package/dist/cjs/features/session_replay/instrument/index.js +53 -13
  16. package/dist/cjs/features/session_replay/shared/recorder.js +8 -1
  17. package/dist/cjs/features/session_replay/shared/utils.js +3 -5
  18. package/dist/cjs/features/session_trace/aggregate/index.js +181 -527
  19. package/dist/cjs/features/session_trace/aggregate/trace/node.js +19 -0
  20. package/dist/cjs/features/session_trace/aggregate/trace/storage.js +289 -0
  21. package/dist/cjs/features/session_trace/constants.js +3 -2
  22. package/dist/cjs/features/session_trace/instrument/index.js +7 -3
  23. package/dist/cjs/features/utils/aggregate-base.js +1 -0
  24. package/dist/cjs/features/utils/feature-gates.js +17 -0
  25. package/dist/cjs/features/utils/instrument-base.js +2 -1
  26. package/dist/cjs/loaders/agent-base.js +4 -0
  27. package/dist/cjs/loaders/api/api-methods.js +1 -1
  28. package/dist/cjs/loaders/api/api.js +2 -2
  29. package/dist/cjs/loaders/configure/configure.js +1 -0
  30. package/dist/esm/cdn/polyfills.js +3 -1
  31. package/dist/esm/common/constants/env.cdn.js +1 -1
  32. package/dist/esm/common/constants/env.npm.js +1 -1
  33. package/dist/esm/common/drain/drain.js +1 -1
  34. package/dist/esm/common/harvest/harvest-scheduler.js +4 -2
  35. package/dist/esm/common/session/session-entity.js +8 -1
  36. package/dist/esm/common/timing/time-keeper.js +9 -30
  37. package/dist/esm/features/ajax/constants.js +2 -1
  38. package/dist/esm/features/jserrors/instrument/index.js +3 -4
  39. package/dist/esm/features/metrics/aggregate/index.js +0 -8
  40. package/dist/esm/features/page_view_event/aggregate/index.js +8 -6
  41. package/dist/esm/features/session_replay/aggregate/index.js +32 -37
  42. package/dist/esm/features/session_replay/constants.js +4 -1
  43. package/dist/esm/features/session_replay/instrument/index.js +54 -14
  44. package/dist/esm/features/session_replay/shared/recorder.js +8 -1
  45. package/dist/esm/features/session_replay/shared/utils.js +4 -6
  46. package/dist/esm/features/session_trace/aggregate/index.js +182 -527
  47. package/dist/esm/features/session_trace/aggregate/trace/node.js +12 -0
  48. package/dist/esm/features/session_trace/aggregate/trace/storage.js +282 -0
  49. package/dist/esm/features/session_trace/constants.js +2 -1
  50. package/dist/esm/features/session_trace/instrument/index.js +7 -3
  51. package/dist/esm/features/utils/aggregate-base.js +1 -0
  52. package/dist/esm/features/utils/feature-gates.js +11 -0
  53. package/dist/esm/features/utils/instrument-base.js +3 -2
  54. package/dist/esm/loaders/agent-base.js +4 -0
  55. package/dist/esm/loaders/api/api-methods.js +1 -1
  56. package/dist/esm/loaders/api/api.js +2 -2
  57. package/dist/esm/loaders/configure/configure.js +1 -0
  58. package/dist/types/common/harvest/harvest-scheduler.d.ts +1 -0
  59. package/dist/types/common/harvest/harvest-scheduler.d.ts.map +1 -1
  60. package/dist/types/common/session/session-entity.d.ts.map +1 -1
  61. package/dist/types/common/timing/time-keeper.d.ts +2 -0
  62. package/dist/types/common/timing/time-keeper.d.ts.map +1 -1
  63. package/dist/types/features/ajax/constants.d.ts +1 -0
  64. package/dist/types/features/ajax/constants.d.ts.map +1 -1
  65. package/dist/types/features/jserrors/instrument/index.d.ts.map +1 -1
  66. package/dist/types/features/metrics/aggregate/index.d.ts.map +1 -1
  67. package/dist/types/features/page_view_event/aggregate/index.d.ts +2 -0
  68. package/dist/types/features/page_view_event/aggregate/index.d.ts.map +1 -1
  69. package/dist/types/features/session_replay/aggregate/index.d.ts +1 -1
  70. package/dist/types/features/session_replay/aggregate/index.d.ts.map +1 -1
  71. package/dist/types/features/session_replay/constants.d.ts +3 -0
  72. package/dist/types/features/session_replay/instrument/index.d.ts +0 -1
  73. package/dist/types/features/session_replay/instrument/index.d.ts.map +1 -1
  74. package/dist/types/features/session_replay/shared/recorder.d.ts.map +1 -1
  75. package/dist/types/features/session_replay/shared/utils.d.ts +1 -1
  76. package/dist/types/features/session_replay/shared/utils.d.ts.map +1 -1
  77. package/dist/types/features/session_trace/aggregate/index.d.ts +39 -52
  78. package/dist/types/features/session_trace/aggregate/index.d.ts.map +1 -1
  79. package/dist/types/features/session_trace/aggregate/trace/node.d.ts +12 -0
  80. package/dist/types/features/session_trace/aggregate/trace/node.d.ts.map +1 -0
  81. package/dist/types/features/session_trace/aggregate/trace/storage.d.ts +43 -0
  82. package/dist/types/features/session_trace/aggregate/trace/storage.d.ts.map +1 -0
  83. package/dist/types/features/session_trace/constants.d.ts +1 -0
  84. package/dist/types/features/session_trace/constants.d.ts.map +1 -1
  85. package/dist/types/features/session_trace/instrument/index.d.ts.map +1 -1
  86. package/dist/types/features/utils/aggregate-base.d.ts +1 -0
  87. package/dist/types/features/utils/aggregate-base.d.ts.map +1 -1
  88. package/dist/types/features/utils/feature-gates.d.ts +2 -0
  89. package/dist/types/features/utils/feature-gates.d.ts.map +1 -0
  90. package/dist/types/features/utils/instrument-base.d.ts.map +1 -1
  91. package/dist/types/loaders/agent-base.d.ts +1 -0
  92. package/dist/types/loaders/agent-base.d.ts.map +1 -1
  93. package/dist/types/loaders/configure/configure.d.ts.map +1 -1
  94. package/package.json +1 -1
  95. package/src/cdn/polyfills.js +2 -0
  96. package/src/common/drain/drain.js +1 -1
  97. package/src/common/harvest/harvest-scheduler.js +4 -2
  98. package/src/common/session/session-entity.js +3 -1
  99. package/src/common/timing/time-keeper.js +9 -30
  100. package/src/features/ajax/constants.js +2 -0
  101. package/src/features/jserrors/instrument/index.js +3 -4
  102. package/src/features/metrics/aggregate/index.js +0 -8
  103. package/src/features/page_view_event/aggregate/index.js +9 -5
  104. package/src/features/session_replay/aggregate/index.js +30 -39
  105. package/src/features/session_replay/constants.js +4 -0
  106. package/src/features/session_replay/instrument/index.js +48 -8
  107. package/src/features/session_replay/shared/__mocks__/utils.js +0 -1
  108. package/src/features/session_replay/shared/recorder.js +8 -1
  109. package/src/features/session_replay/shared/utils.js +4 -7
  110. package/src/features/session_trace/aggregate/index.js +157 -493
  111. package/src/features/session_trace/aggregate/trace/node.js +12 -0
  112. package/src/features/session_trace/aggregate/trace/storage.js +287 -0
  113. package/src/features/session_trace/constants.js +1 -0
  114. package/src/features/session_trace/instrument/index.js +7 -2
  115. package/src/features/utils/__mocks__/feature-gates.js +1 -0
  116. package/src/features/utils/aggregate-base.js +1 -0
  117. package/src/features/utils/feature-gates.js +11 -0
  118. package/src/features/utils/instrument-base.js +3 -2
  119. package/src/loaders/agent-base.js +4 -0
  120. package/src/loaders/api/api-methods.js +1 -1
  121. package/src/loaders/api/api.js +2 -2
  122. package/src/loaders/configure/configure.js +1 -0
  123. package/dist/cjs/features/session_replay/shared/replay-mode.js +0 -28
  124. package/dist/cjs/features/utils/handler-cache.js +0 -70
  125. package/dist/esm/features/session_replay/shared/replay-mode.js +0 -23
  126. package/dist/esm/features/utils/handler-cache.js +0 -63
  127. package/dist/types/features/session_replay/shared/replay-mode.d.ts +0 -9
  128. package/dist/types/features/session_replay/shared/replay-mode.d.ts.map +0 -1
  129. package/dist/types/features/utils/handler-cache.d.ts +0 -23
  130. package/dist/types/features/utils/handler-cache.d.ts.map +0 -1
  131. package/src/features/session_replay/shared/replay-mode.js +0 -23
  132. package/src/features/utils/handler-cache.js +0 -65
@@ -53,3 +53,7 @@ export const ABORT_REASONS = {
53
53
  }
54
54
  /** Reserved room for query param attrs */
55
55
  export const QUERY_PARAM_PADDING = 5000
56
+
57
+ export const TRIGGERS = {
58
+ API: 'api'
59
+ }
@@ -12,11 +12,13 @@
12
12
  import { handle } from '../../../common/event-emitter/handle'
13
13
  import { DEFAULT_KEY, MODE, PREFIX } from '../../../common/session/constants'
14
14
  import { InstrumentBase } from '../../utils/instrument-base'
15
- import { FEATURE_NAME, SR_EVENT_EMITTER_TYPES } from '../constants'
16
- import { isPreloadAllowed } from '../shared/utils'
15
+ import { hasReplayPrerequisite, isPreloadAllowed } from '../shared/utils'
16
+ import { FEATURE_NAME, SR_EVENT_EMITTER_TYPES, TRIGGERS } from '../constants'
17
17
 
18
18
  export class Instrument extends InstrumentBase {
19
19
  static featureName = FEATURE_NAME
20
+
21
+ #mode
20
22
  constructor (agentIdentifier, aggregator, auto = true) {
21
23
  super(agentIdentifier, aggregator, FEATURE_NAME, auto)
22
24
  let session
@@ -25,8 +27,13 @@ export class Instrument extends InstrumentBase {
25
27
  session = JSON.parse(localStorage.getItem(`${PREFIX}_${DEFAULT_KEY}`))
26
28
  } catch (err) { }
27
29
 
30
+ if (hasReplayPrerequisite(agentIdentifier)) {
31
+ this.ee.on('recordReplay', () => this.#apiStartOrRestartReplay())
32
+ }
33
+
28
34
  if (this.#canPreloadRecorder(session)) {
29
- this.#startRecording(session?.sessionReplayMode)
35
+ this.#mode = session?.sessionReplayMode
36
+ this.#preloadStartRecording()
30
37
  } else {
31
38
  this.importAggregator()
32
39
  }
@@ -58,11 +65,44 @@ export class Instrument extends InstrumentBase {
58
65
  }
59
66
  }
60
67
 
61
- async #startRecording (mode) {
62
- const { Recorder } = (await import(/* webpackChunkName: "recorder" */'../shared/recorder'))
63
- this.recorder = new Recorder({ mode, agentIdentifier: this.agentIdentifier, ee: this.ee })
64
- this.recorder.startRecording()
65
- this.abortHandler = this.recorder.stopRecording
68
+ #alreadyStarted = false
69
+ /**
70
+ * This func is use for early pre-load recording prior to replay feature (agg) being loaded onto the page. It should only setup once, including if already called and in-progress.
71
+ */
72
+ async #preloadStartRecording (trigger) {
73
+ if (this.#alreadyStarted) return
74
+ this.#alreadyStarted = true
75
+
76
+ try {
77
+ const { Recorder } = (await import(/* webpackChunkName: "recorder" */'../shared/recorder'))
78
+
79
+ // If startReplay() has been used by this point, we must record in full mode regardless of session preload:
80
+ // Note: recorder starts here with w/e the mode is at this time, but this may be changed later (see #apiStartOrRestartReplay else-case)
81
+ this.recorder ??= new Recorder({ mode: this.#mode, agentIdentifier: this.agentIdentifier, trigger, ee: this.ee })
82
+ this.recorder.startRecording()
83
+ this.abortHandler = this.recorder.stopRecording
84
+ } catch (e) {}
66
85
  this.importAggregator({ recorder: this.recorder, errorNoticed: this.errorNoticed })
67
86
  }
87
+
88
+ /**
89
+ * Called whenever startReplay API is used. That could occur any time, pre or post load.
90
+ */
91
+ #apiStartOrRestartReplay () {
92
+ if (this.featAggregate) { // post-load; there's possibly already an ongoing recording
93
+ if (this.featAggregate.mode !== MODE.FULL) this.featAggregate.initializeRecording(MODE.FULL, true)
94
+ } else { // pre-load
95
+ this.#mode = MODE.FULL
96
+ this.#preloadStartRecording(TRIGGERS.API)
97
+ // There's a race here wherein either:
98
+ // a. Recorder has not been initialized, and we've set the enforced mode, so we're good, or;
99
+ // b. Record has been initialized, possibly with the "wrong" mode, so we have to correct that + restart.
100
+ if (this.recorder && this.recorder.parent.mode !== MODE.FULL) {
101
+ this.recorder.parent.mode = MODE.FULL
102
+ this.recorder.stopRecording()
103
+ this.recorder.startRecording()
104
+ this.abortHandler = this.recorder.stopRecording
105
+ }
106
+ }
107
+ }
68
108
  }
@@ -1,2 +1 @@
1
- export const enableSessionTracking = jest.fn()
2
1
  export const canImportReplayAgg = jest.fn()
@@ -86,7 +86,14 @@ export class Recorder {
86
86
  inlineStylesheet: inline_stylesheet,
87
87
  inlineImages: inline_images,
88
88
  collectFonts: collect_fonts,
89
- checkoutEveryNms: CHECKOUT_MS[this.parent.mode]
89
+ checkoutEveryNms: CHECKOUT_MS[this.parent.mode],
90
+ /** Emits errors thrown by rrweb directly before bubbling them up to the window */
91
+ errorHandler: (err) => {
92
+ /** capture rrweb errors as "internal" errors only */
93
+ this.parent.ee.emit('internal-error', [err])
94
+ /** returning true informs rrweb to swallow the error instead of throwing it to the window */
95
+ return true
96
+ }
90
97
  })
91
98
 
92
99
  this.stopRecording = () => {
@@ -1,13 +1,10 @@
1
1
  import { getConfigurationValue, originals } from '../../../common/config/config'
2
- import { isBrowserScope, originTime } from '../../../common/constants/runtime'
2
+ import { canEnableSessionTracking } from '../../utils/feature-gates'
3
+ import { originTime } from '../../../common/constants/runtime'
3
4
 
4
- export function enableSessionTracking (agentId) {
5
- return isBrowserScope && getConfigurationValue(agentId, 'privacy.cookies_enabled') === true
6
- }
7
-
8
- function hasReplayPrerequisite (agentId) {
5
+ export function hasReplayPrerequisite (agentId) {
9
6
  return !!originals.MO && // Session Replay cannot work without Mutation Observer
10
- enableSessionTracking(agentId) && // requires session tracking to be running (hence "session" replay...)
7
+ canEnableSessionTracking(agentId) && // requires session tracking to be running (hence "session" replay...)
11
8
  getConfigurationValue(agentId, 'session_trace.enabled') === true // Session Replay as of now is tightly coupled with Session Trace in the UI
12
9
  }
13
10