@cloudcare/browser-core 1.2.11 → 2.0.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 (61) hide show
  1. package/cjs/browser/fetchObservable.js +3 -4
  2. package/cjs/browser/htmlDomUtils.js +45 -0
  3. package/cjs/browser/pageExitObservable.js +72 -0
  4. package/cjs/configuration/configuration.js +8 -0
  5. package/cjs/configuration/transportConfiguration.js +7 -0
  6. package/cjs/dataMap.js +12 -4
  7. package/cjs/helper/deviceInfo.js +44 -2
  8. package/cjs/helper/enums.js +3 -0
  9. package/cjs/helper/getZoneJsOriginalValue.js +34 -0
  10. package/cjs/helper/instrumentMethod.js +7 -1
  11. package/cjs/helper/lifeCycle.js +2 -6
  12. package/cjs/helper/readBytesFromStream.js +74 -0
  13. package/cjs/helper/tools.js +123 -46
  14. package/cjs/index.js +52 -0
  15. package/cjs/session/sessionStore.js +1 -1
  16. package/cjs/transport/batch.js +7 -44
  17. package/cjs/transport/httpRequest.js +4 -2
  18. package/cjs/transport/sendWithRetryStrategy.js +8 -8
  19. package/cjs/transport/startBatchWithReplica.js +2 -2
  20. package/esm/browser/fetchObservable.js +3 -4
  21. package/esm/browser/htmlDomUtils.js +26 -0
  22. package/esm/browser/pageExitObservable.js +57 -0
  23. package/esm/configuration/configuration.js +5 -0
  24. package/esm/configuration/transportConfiguration.js +7 -0
  25. package/esm/dataMap.js +9 -2
  26. package/esm/helper/contextHistory.js +1 -1
  27. package/esm/helper/deviceInfo.js +44 -2
  28. package/esm/helper/enums.js +3 -0
  29. package/esm/helper/getZoneJsOriginalValue.js +27 -0
  30. package/esm/helper/instrumentMethod.js +6 -1
  31. package/esm/helper/lifeCycle.js +2 -6
  32. package/esm/helper/readBytesFromStream.js +67 -0
  33. package/esm/helper/tools.js +99 -44
  34. package/esm/index.js +4 -0
  35. package/esm/session/sessionStore.js +1 -1
  36. package/esm/transport/batch.js +8 -45
  37. package/esm/transport/httpRequest.js +4 -2
  38. package/esm/transport/sendWithRetryStrategy.js +8 -8
  39. package/esm/transport/startBatchWithReplica.js +2 -2
  40. package/package.json +2 -2
  41. package/src/browser/fetchObservable.js +21 -17
  42. package/src/browser/htmlDomUtils.js +35 -0
  43. package/src/browser/pageExitObservable.js +70 -0
  44. package/src/configuration/configuration.js +6 -0
  45. package/src/configuration/transportConfiguration.js +30 -6
  46. package/src/dataMap.js +9 -2
  47. package/src/helper/contextHistory.js +1 -1
  48. package/src/helper/deviceInfo.js +39 -3
  49. package/src/helper/enums.js +40 -37
  50. package/src/helper/getZoneJsOriginalValue.js +27 -0
  51. package/src/helper/instrumentMethod.js +40 -50
  52. package/src/helper/lifeCycle.js +2 -7
  53. package/src/helper/readBytesFromStream.js +69 -0
  54. package/src/helper/tools.js +112 -43
  55. package/src/index.js +4 -1
  56. package/src/session/sessionStore.js +27 -24
  57. package/src/synthetics/syntheticsWorkerValues.js +11 -7
  58. package/src/transport/batch.js +70 -81
  59. package/src/transport/httpRequest.js +25 -25
  60. package/src/transport/sendWithRetryStrategy.js +14 -9
  61. package/src/transport/startBatchWithReplica.js +11 -5
@@ -13,7 +13,7 @@ export function initFetchObservable() {
13
13
  }
14
14
 
15
15
  function createFetchObservable() {
16
- var observable = new Observable(function() {
16
+ var observable = new Observable(function () {
17
17
  if (!window.fetch) {
18
18
  return
19
19
  }
@@ -21,19 +21,23 @@ function createFetchObservable() {
21
21
  var fetchMethod = instrumentMethod(
22
22
  window,
23
23
  'fetch',
24
- function(originalFetch) {
24
+ function (originalFetch) {
25
25
  return function (input, init) {
26
26
  var responsePromise
27
27
  var context = beforeSend(observable, input, init)
28
28
  if (context) {
29
- responsePromise = originalFetch.call(this, context.input, context.init)
29
+ responsePromise = originalFetch.call(
30
+ this,
31
+ context.input,
32
+ context.init
33
+ )
30
34
  afterSend(observable, responsePromise, context)
31
35
  } else {
32
36
  responsePromise = originalFetch.call(this, input, init)
33
37
  }
34
38
  return responsePromise
35
39
  }
36
- }
40
+ }
37
41
  )
38
42
  return fetchMethod.stop
39
43
  })
@@ -42,7 +46,10 @@ function createFetchObservable() {
42
46
  }
43
47
 
44
48
  function beforeSend(observable, input, init) {
45
- var method = (init && init.method) || (typeof input === 'object' && input.method) || 'GET'
49
+ var method =
50
+ (init && init.method) ||
51
+ (typeof input === 'object' && input.method) ||
52
+ 'GET'
46
53
  var url = normalizeUrl((typeof input === 'object' && input.url) || input)
47
54
  var startClocks = clocksNow()
48
55
 
@@ -52,7 +59,7 @@ function beforeSend(observable, input, init) {
52
59
  input: input,
53
60
  method: method,
54
61
  startClocks: startClocks,
55
- url: url,
62
+ url: url
56
63
  }
57
64
 
58
65
  observable.notify(context)
@@ -60,27 +67,24 @@ function beforeSend(observable, input, init) {
60
67
  return context
61
68
  }
62
69
 
63
- function afterSend(
64
- observable,
65
- responsePromise,
66
- startContext
67
- ) {
68
- var reportFetch = function(response) {
70
+ function afterSend(observable, responsePromise, startContext) {
71
+ var reportFetch = function (response) {
69
72
  var context = startContext
70
- context.state = 'complete'
71
- context.duration = elapsed(context.startClocks.timeStamp, timeStampNow())
73
+ context.state = 'resolve'
74
+ // context.duration = elapsed(context.startClocks.timeStamp, timeStampNow())
72
75
  if ('stack' in response || response instanceof Error) {
73
76
  context.status = 0
74
- context.isAborted = response instanceof DOMException && response.code === DOMException.ABORT_ERR
77
+ context.isAborted =
78
+ response instanceof DOMException &&
79
+ response.code === DOMException.ABORT_ERR
75
80
  context.error = response
76
- observable.notify(context)
77
81
  } else if ('status' in response) {
78
82
  context.response = response
79
83
  context.responseType = response.type
80
84
  context.status = response.status
81
85
  context.isAborted = false
82
- observable.notify(context)
83
86
  }
87
+ observable.notify(context)
84
88
  }
85
89
  responsePromise.then(reportFetch, reportFetch)
86
90
  }
@@ -0,0 +1,35 @@
1
+ export function isTextNode(node) {
2
+ return node.nodeType === Node.TEXT_NODE
3
+ }
4
+
5
+ export function isCommentNode(node) {
6
+ return node.nodeType === Node.COMMENT_NODE
7
+ }
8
+
9
+ export function isElementNode(node) {
10
+ return node.nodeType === Node.ELEMENT_NODE
11
+ }
12
+
13
+ export function isNodeShadowHost(node) {
14
+ return isElementNode(node) && Boolean(node.shadowRoot)
15
+ }
16
+
17
+ export function isNodeShadowRoot(node) {
18
+ var shadowRoot = node
19
+ return (
20
+ !!shadowRoot.host &&
21
+ shadowRoot.nodeType === Node.DOCUMENT_FRAGMENT_NODE &&
22
+ isElementNode(shadowRoot.host)
23
+ )
24
+ }
25
+
26
+ export function getChildNodes(node) {
27
+ return isNodeShadowHost(node) ? node.shadowRoot.childNodes : node.childNodes
28
+ }
29
+
30
+ /**
31
+ * Return `host` in case if the current node is a shadow root otherwise will return the `parentNode`
32
+ */
33
+ export function getParentNode(node) {
34
+ return isNodeShadowRoot(node) ? node.host : node.parentNode
35
+ }
@@ -0,0 +1,70 @@
1
+ import { Observable } from '../helper/observable'
2
+ import {
3
+ addEventListener,
4
+ addEventListeners,
5
+ includes,
6
+ values
7
+ } from '../helper/tools'
8
+ import { DOM_EVENT } from '../helper/enums'
9
+ export var PageExitReason = {
10
+ HIDDEN: 'visibility_hidden',
11
+ UNLOADING: 'before_unload',
12
+ PAGEHIDE: 'page_hide',
13
+ FROZEN: 'page_frozen'
14
+ }
15
+
16
+ export function createPageExitObservable() {
17
+ var observable = new Observable(function () {
18
+ /**
19
+ * Only event that guarantee to fire on mobile devices when the page transitions to background state
20
+ * (e.g. when user switches to a different application, goes to homescreen, etc), or is being unloaded.
21
+ */
22
+ var visibilityChangeListener = addEventListeners(
23
+ document,
24
+ [DOM_EVENT.VISIBILITY_CHANGE, DOM_EVENT.FREEZE, DOM_EVENT.PAGE_HIDE],
25
+ function (event) {
26
+ if (
27
+ event.type === DOM_EVENT.VISIBILITY_CHANGE &&
28
+ document.visibilityState === 'hidden'
29
+ ) {
30
+ /**
31
+ * Only event that guarantee to fire on mobile devices when the page transitions to background state
32
+ * (e.g. when user switches to a different application, goes to homescreen, etc), or is being unloaded.
33
+ */
34
+ observable.notify({ reason: PageExitReason.HIDDEN })
35
+ } else if (event.type === DOM_EVENT.FREEZE) {
36
+ /**
37
+ * After transitioning in background a tab can be freezed to preserve resources. (cf: https://developer.chrome.com/blog/page-lifecycle-api)
38
+ * Allow to collect events happening between hidden and frozen state.
39
+ */
40
+ observable.notify({ reason: PageExitReason.FROZEN })
41
+ }
42
+ },
43
+ { capture: true }
44
+ )
45
+
46
+ /**
47
+ * Safari does not support yet to send a request during:
48
+ * - a visibility change during doc unload (cf: https://bugs.webkit.org/show_bug.cgi?id=194897)
49
+ * - a page hide transition (cf: https://bugs.webkit.org/show_bug.cgi?id=188329)
50
+ */
51
+ var beforeUnloadListener = addEventListener(
52
+ window,
53
+ DOM_EVENT.BEFORE_UNLOAD,
54
+ function () {
55
+ observable.notify({ reason: PageExitReason.UNLOADING })
56
+ }
57
+ )
58
+
59
+ return function () {
60
+ visibilityChangeListener.stop()
61
+ beforeUnloadListener.stop()
62
+ }
63
+ })
64
+
65
+ return observable
66
+ }
67
+
68
+ export function isPageExitReason(reason) {
69
+ return includes(values(PageExitReason), reason)
70
+ }
@@ -9,6 +9,12 @@ import {
9
9
  isNullUndefinedDefaultValue
10
10
  } from '../helper/tools'
11
11
  import { computeTransportConfiguration } from './transportConfiguration'
12
+
13
+ export var DefaultPrivacyLevel = {
14
+ ALLOW: 'allow',
15
+ MASK: 'mask',
16
+ MASK_USER_INPUT: 'mask-user-input'
17
+ }
12
18
  export function validateAndBuildConfiguration(initConfiguration) {
13
19
  if (
14
20
  initConfiguration.sampleRate !== undefined &&
@@ -12,13 +12,31 @@ function getLogsEndPoint(url) {
12
12
  return trim(url) + 'v1/write/logging'
13
13
  return trim(url) + '/v1/write/logging'
14
14
  }
15
+ function getSessionReplayEndPoint(url) {
16
+ // return 'http://localhost:3002/write_data'
17
+ if (url.lastIndexOf('/') === url.length - 1)
18
+ return trim(url) + 'v1/write/rum/replay'
19
+ return trim(url) + '/v1/write/rum/replay'
20
+ }
15
21
  export function computeTransportConfiguration(initConfiguration) {
16
- var isIntakeUrl = function(url) { return false }
17
- if ('isIntakeUrl' in initConfiguration && isFunction(initConfiguration.isIntakeUrl) && isBoolean(initConfiguration.isIntakeUrl())) {
22
+ var isIntakeUrl = function (url) {
23
+ return false
24
+ }
25
+ if (
26
+ 'isIntakeUrl' in initConfiguration &&
27
+ isFunction(initConfiguration.isIntakeUrl) &&
28
+ isBoolean(initConfiguration.isIntakeUrl())
29
+ ) {
18
30
  isIntakeUrl = initConfiguration.isIntakeUrl
19
31
  }
20
- var isServerError = function(request) { return false }
21
- if ('isServerError' in initConfiguration && isFunction(initConfiguration.isServerError) && isBoolean(initConfiguration.isServerError())) {
32
+ var isServerError = function (request) {
33
+ return false
34
+ }
35
+ if (
36
+ 'isServerError' in initConfiguration &&
37
+ isFunction(initConfiguration.isServerError) &&
38
+ isBoolean(initConfiguration.isServerError())
39
+ ) {
22
40
  isServerError = initConfiguration.isServerError
23
41
  }
24
42
  return {
@@ -26,10 +44,12 @@ export function computeTransportConfiguration(initConfiguration) {
26
44
  initConfiguration.datakitUrl || initConfiguration.datakitOrigin
27
45
  ),
28
46
  logsEndpoint: getLogsEndPoint(initConfiguration.datakitOrigin),
47
+ sessionReplayEndPoint: getSessionReplayEndPoint(
48
+ initConfiguration.datakitOrigin
49
+ ),
29
50
  isIntakeUrl: isIntakeUrl,
30
51
  isServerError: isServerError
31
52
  }
32
-
33
53
  }
34
54
  export function isIntakeRequest(url, configuration) {
35
55
  // return haveSameOrigin(url, configuration.datakitUrl)
@@ -38,5 +58,9 @@ export function isIntakeRequest(url, configuration) {
38
58
  notTakeRequest.push(configuration.logsEndpoint)
39
59
  }
40
60
  // datakit 地址,log 地址,以及客户自定义过滤方法定义url
41
- return some(notTakeRequest, function(takeUrl) { return url.indexOf(takeUrl) === 0 }) || configuration.isIntakeUrl(url)
61
+ return (
62
+ some(notTakeRequest, function (takeUrl) {
63
+ return url.indexOf(takeUrl) === 0
64
+ }) || configuration.isIntakeUrl(url)
65
+ )
42
66
  }
package/src/dataMap.js CHANGED
@@ -1,6 +1,5 @@
1
1
  import { RumEventType } from './helper/enums'
2
2
  export var commonTags = {
3
- action_id: 'action.id',
4
3
  sdk_name: '_dd.sdk_name',
5
4
  sdk_version: '_dd.sdk_version',
6
5
  app_id: 'application.id',
@@ -13,6 +12,7 @@ export var commonTags = {
13
12
  session_id: 'session.id',
14
13
  session_type: 'session.type',
15
14
  session_sampling: 'session.is_sampling',
15
+ session_has_replay: 'session.has_replay',
16
16
  is_signin: 'user.is_signin',
17
17
  os: 'device.os',
18
18
  os_version: 'device.os_version',
@@ -32,6 +32,10 @@ export var commonTags = {
32
32
  view_path_group: 'view.path_group',
33
33
  view_url_query: 'view.url_query'
34
34
  }
35
+ export var commonFields = {
36
+ action_id: 'action.id',
37
+ view_in_foreground: 'view.in_foreground'
38
+ }
35
39
  // 需要用双引号将字符串类型的field value括起来, 这里有数组标示[string, path]
36
40
  export var dataMap = {
37
41
  view: {
@@ -42,6 +46,7 @@ export var dataMap = {
42
46
  is_active: 'view.is_active'
43
47
  },
44
48
  fields: {
49
+ session_replay_stats: '_dd.replay_stats',
45
50
  view_error_count: 'view.error.count',
46
51
  view_resource_count: 'view.resource.count',
47
52
  view_long_task_count: 'view.long_task.count',
@@ -62,7 +67,9 @@ export var dataMap = {
62
67
  time_to_interactive: 'view.tti',
63
68
  dom: 'view.dom',
64
69
  dom_ready: 'view.dom_ready',
65
- time_spent: 'view.time_spent'
70
+ time_spent: 'view.time_spent',
71
+ in_foreground_periods: 'view.in_foreground_periods',
72
+ frustration_count: 'view.frustration.count'
66
73
  }
67
74
  },
68
75
  resource: {
@@ -1,4 +1,4 @@
1
- import { relativeNow, ONE_MINUTE, filter, map, each } from './tools'
1
+ import { relativeNow, ONE_MINUTE, filter, map } from './tools'
2
2
 
3
3
  var END_OF_TIMES = Infinity
4
4
 
@@ -247,9 +247,45 @@ var MethodLibrary = {
247
247
  },
248
248
  // 获取网络状态
249
249
  getNetwork: function () {
250
- var netWork =
251
- navigator && navigator.connection && navigator.connection.effectiveType
252
- return netWork
250
+ var connection =
251
+ window.navigator.connection ||
252
+ window.navigator.mozConnection ||
253
+ window.navigator.webkitConnection
254
+ var result = 'unknown'
255
+ var type = connection ? connection.type || connection.effectiveType : null
256
+ if (type && typeof type === 'string') {
257
+ switch (type) {
258
+ // possible type values
259
+ case 'bluetooth':
260
+ case 'cellular':
261
+ result = 'cellular'
262
+ break
263
+ case 'none':
264
+ result = 'none'
265
+ break
266
+ case 'ethernet':
267
+ case 'wifi':
268
+ case 'wimax':
269
+ result = 'wifi'
270
+ break
271
+ case 'other':
272
+ case 'unknown':
273
+ result = 'unknown'
274
+ break
275
+ // possible effectiveType values
276
+ case 'slow-2g':
277
+ case '2g':
278
+ case '3g':
279
+ result = 'cellular'
280
+ break
281
+ case '4g':
282
+ result = 'wifi'
283
+ break
284
+ default:
285
+ break
286
+ }
287
+ }
288
+ return result
253
289
  },
254
290
  // 获取当前语言
255
291
  getLanguage: function () {
@@ -1,34 +1,37 @@
1
1
  export var DOM_EVENT = {
2
2
  BEFORE_UNLOAD: 'beforeunload',
3
- CLICK : 'click',
4
- DBL_CLICK : 'dblclick',
5
- KEY_DOWN : 'keydown',
6
- LOAD : 'load',
7
- POP_STATE : 'popstate',
8
- SCROLL : 'scroll',
9
- TOUCH_START : 'touchstart',
10
- TOUCH_END : 'touchend',
11
- TOUCH_MOVE : 'touchmove',
12
- VISIBILITY_CHANGE : 'visibilitychange',
13
- DOM_CONTENT_LOADED : 'DOMContentLoaded',
14
- POINTER_DOWN : 'pointerdown',
15
- POINTER_UP : 'pointerup',
16
- POINTER_CANCEL : 'pointercancel',
17
- HASH_CHANGE : 'hashchange',
18
- PAGE_HIDE : 'pagehide',
19
- MOUSE_DOWN : 'mousedown',
20
- MOUSE_UP : 'mouseup',
21
- MOUSE_MOVE : 'mousemove',
22
- FOCUS : 'focus',
23
- BLUR : 'blur',
24
- CONTEXT_MENU : 'contextmenu',
25
- RESIZE : 'resize',
26
- CHANGE : 'change',
27
- INPUT : 'input',
28
- PLAY : 'play',
29
- PAUSE : 'pause',
30
- SECURITY_POLICY_VIOLATION : 'securitypolicyviolation',
31
- SELECTION_CHANGE : 'selectionchange',
3
+ CLICK: 'click',
4
+ DBL_CLICK: 'dblclick',
5
+ KEY_DOWN: 'keydown',
6
+ LOAD: 'load',
7
+ POP_STATE: 'popstate',
8
+ SCROLL: 'scroll',
9
+ TOUCH_START: 'touchstart',
10
+ TOUCH_END: 'touchend',
11
+ TOUCH_MOVE: 'touchmove',
12
+ VISIBILITY_CHANGE: 'visibilitychange',
13
+ PAGE_SHOW: 'pageshow',
14
+ FREEZE: 'freeze',
15
+ RESUME: 'resume',
16
+ DOM_CONTENT_LOADED: 'DOMContentLoaded',
17
+ POINTER_DOWN: 'pointerdown',
18
+ POINTER_UP: 'pointerup',
19
+ POINTER_CANCEL: 'pointercancel',
20
+ HASH_CHANGE: 'hashchange',
21
+ PAGE_HIDE: 'pagehide',
22
+ MOUSE_DOWN: 'mousedown',
23
+ MOUSE_UP: 'mouseup',
24
+ MOUSE_MOVE: 'mousemove',
25
+ FOCUS: 'focus',
26
+ BLUR: 'blur',
27
+ CONTEXT_MENU: 'contextmenu',
28
+ RESIZE: 'resize',
29
+ CHANGE: 'change',
30
+ INPUT: 'input',
31
+ PLAY: 'play',
32
+ PAUSE: 'pause',
33
+ SECURITY_POLICY_VIOLATION: 'securitypolicyviolation',
34
+ SELECTION_CHANGE: 'selectionchange'
32
35
  }
33
36
  export var ResourceType = {
34
37
  DOCUMENT: 'document',
@@ -48,9 +51,9 @@ export var ActionType = {
48
51
  CUSTOM: 'custom'
49
52
  }
50
53
  export var FrustrationType = {
51
- RAGE_CLICK :'rage_click',
52
- ERROR_CLICK :'error_click',
53
- DEAD_CLICK :'dead_click',
54
+ RAGE_CLICK: 'rage_click',
55
+ ERROR_CLICK: 'error_click',
56
+ DEAD_CLICK: 'dead_click'
54
57
  }
55
58
  export var RumEventType = {
56
59
  ACTION: 'action',
@@ -61,9 +64,9 @@ export var RumEventType = {
61
64
  LOGGER: 'logger'
62
65
  }
63
66
 
64
- export var ViewLoadingType = {
67
+ export var ViewLoadingType = {
65
68
  INITIAL_LOAD: 'initial_load',
66
- ROUTE_CHANGE: 'route_change',
69
+ ROUTE_CHANGE: 'route_change'
67
70
  }
68
71
  export var RequestType = {
69
72
  FETCH: ResourceType.FETCH,
@@ -76,9 +79,9 @@ export var TraceType = {
76
79
  ZIPKIN_SINGLE_HEADER: 'zipkin_single_header',
77
80
  W3C_TRACEPARENT: 'w3c_traceparent',
78
81
  SKYWALKING_V3: 'skywalking_v3',
79
- JAEGER: 'jaeger',
82
+ JAEGER: 'jaeger'
80
83
  }
81
84
  export var ErrorHandling = {
82
85
  HANDLED: 'handled',
83
- UNHANDLED: 'unhandled',
84
- }
86
+ UNHANDLED: 'unhandled'
87
+ }
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Gets the original value for a DOM API that was potentially patched by Zone.js.
3
+ *
4
+ * Zone.js[1] is a library that patches a bunch of JS and DOM APIs. It usually stores the original
5
+ * value of the patched functions/constructors/methods in a hidden property prefixed by
6
+ * __zone_symbol__.
7
+ *
8
+ * In multiple occasions, we observed that Zone.js is the culprit of important issues leading to
9
+ * browser resource exhaustion (memory leak, high CPU usage). This method is used as a workaround to
10
+ * use the original DOM API instead of the one patched by Zone.js.
11
+ *
12
+ * [1]: https://github.com/angular/angular/tree/main/packages/zone.js
13
+ */
14
+ export function getZoneJsOriginalValue(target, name) {
15
+ var browserWindow = window
16
+ var original
17
+ if (
18
+ browserWindow.Zone &&
19
+ typeof browserWindow.Zone.__symbol__ === 'function'
20
+ ) {
21
+ original = target[browserWindow.Zone.__symbol__(name)]
22
+ }
23
+ if (!original) {
24
+ original = target[name]
25
+ }
26
+ return original
27
+ }
@@ -1,10 +1,6 @@
1
1
  import { noop } from './tools'
2
-
3
- export function instrumentMethod(
4
- object,
5
- method,
6
- instrumentationFactory
7
- ) {
2
+ import { getZoneJsOriginalValue } from './getZoneJsOriginalValue'
3
+ export function instrumentMethod(object, method, instrumentationFactory) {
8
4
  var original = object[method]
9
5
 
10
6
  var instrumentation = instrumentationFactory(original)
@@ -18,62 +14,52 @@ export function instrumentMethod(
18
14
  }
19
15
  object[method] = instrumentationWrapper
20
16
  return {
21
- stop: function() {
17
+ stop: function () {
22
18
  if (object[method] === instrumentationWrapper) {
23
19
  object[method] = original
24
20
  } else {
25
21
  instrumentation = original
26
22
  }
27
- },
23
+ }
28
24
  }
29
25
  }
30
26
 
31
- export function instrumentMethodAndCallOriginal(
32
- object,
33
- method,
34
- aliasOption
35
- ) {
36
- return instrumentMethod(
37
- object,
38
- method,
39
- function(original) {
40
- return function () {
41
- var result
42
- if (aliasOption && aliasOption.before) {
43
- aliasOption.before.apply(this, arguments)
44
- }
45
- if (typeof original === 'function') {
46
- // eslint-disable-next-line @typescript-eslint/no-unsafe-call
47
- result = original.apply(this, arguments)
48
- }
49
- if (aliasOption && aliasOption.after) {
50
- aliasOption.after.apply(this, arguments)
51
- }
52
- return result
27
+ export function instrumentMethodAndCallOriginal(object, method, aliasOption) {
28
+ return instrumentMethod(object, method, function (original) {
29
+ return function () {
30
+ var result
31
+ if (aliasOption && aliasOption.before) {
32
+ aliasOption.before.apply(this, arguments)
33
+ }
34
+ if (typeof original === 'function') {
35
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-call
36
+ result = original.apply(this, arguments)
37
+ }
38
+ if (aliasOption && aliasOption.after) {
39
+ aliasOption.after.apply(this, arguments)
53
40
  }
41
+ return result
54
42
  }
55
-
56
- )
43
+ })
57
44
  }
58
45
 
59
- export function instrumentSetter(
60
- object,
61
- property,
62
- after
63
- ) {
46
+ export function instrumentSetter(object, property, after) {
64
47
  var originalDescriptor = Object.getOwnPropertyDescriptor(object, property)
65
- if (!originalDescriptor || !originalDescriptor.set || !originalDescriptor.configurable) {
48
+ if (
49
+ !originalDescriptor ||
50
+ !originalDescriptor.set ||
51
+ !originalDescriptor.configurable
52
+ ) {
66
53
  return { stop: noop }
67
54
  }
68
-
69
- var instrumentation = function(thisObject, value) {
55
+ // Using the patched `setTimeout` from Zone.js triggers a rendering loop in some Angular
56
+ // component, see issue RUMF-1443
57
+ var setTimeout = getZoneJsOriginalValue(window, 'setTimeout')
58
+ var instrumentation = function (thisObject, value) {
70
59
  // put hooked setter into event loop to avoid of set latency
71
- setTimeout(
72
- function() {
73
- after(thisObject, value)
74
- },
75
- 0
76
- )
60
+ setTimeout(function () {
61
+ after(thisObject, value)
62
+ }, 0)
77
63
  }
78
64
 
79
65
  var instrumentationWrapper = function (value) {
@@ -82,16 +68,20 @@ export function instrumentSetter(
82
68
  }
83
69
 
84
70
  Object.defineProperty(object, property, {
85
- set: instrumentationWrapper,
71
+ set: instrumentationWrapper
86
72
  })
87
73
 
88
74
  return {
89
- stop: function() {
90
- if (Object.getOwnPropertyDescriptor(object, property) && Object.getOwnPropertyDescriptor(object, property).set === instrumentationWrapper) {
75
+ stop: function () {
76
+ if (
77
+ Object.getOwnPropertyDescriptor(object, property) &&
78
+ Object.getOwnPropertyDescriptor(object, property).set ===
79
+ instrumentationWrapper
80
+ ) {
91
81
  Object.defineProperty(object, property, originalDescriptor)
92
82
  } else {
93
83
  instrumentation = noop
94
84
  }
95
- },
85
+ }
96
86
  }
97
87
  }
@@ -1,28 +1,23 @@
1
1
  import { each, filter } from './tools'
2
2
  export var LifeCycleEventType = {
3
3
  PERFORMANCE_ENTRIES_COLLECTED: 'PERFORMANCE_ENTRIES_COLLECTED',
4
- AUTO_ACTION_CREATED: 'AUTO_ACTION_CREATED',
5
4
  AUTO_ACTION_COMPLETED: 'AUTO_ACTION_COMPLETED',
6
5
  VIEW_CREATED: 'VIEW_CREATED',
7
6
  VIEW_UPDATED: 'VIEW_UPDATED',
8
7
  VIEW_ENDED: 'VIEW_ENDED',
9
8
  SESSION_RENEWED: 'SESSION_RENEWED',
10
9
  SESSION_EXPIRED: 'SESSION_EXPIRED',
11
- DOM_MUTATED: 'DOM_MUTATED',
12
- BEFORE_UNLOAD: 'BEFORE_UNLOAD',
10
+ PAGE_EXITED: 'PAGE_EXITED',
13
11
  REQUEST_STARTED: 'REQUEST_STARTED',
14
12
  REQUEST_COMPLETED: 'REQUEST_COMPLETED',
15
13
  RAW_RUM_EVENT_COLLECTED: 'RAW_RUM_EVENT_COLLECTED',
16
14
  RUM_EVENT_COLLECTED: 'RUM_EVENT_COLLECTED',
17
15
  RAW_ERROR_COLLECTED: 'RAW_ERROR_COLLECTED',
18
- RECORD_STARTED: 'RECORD_STARTED',
19
- RECORD_STOPPED: 'RECORD_STOPPED',
20
16
  RAW_LOG_COLLECTED: 'RAW_LOG_COLLECTED',
21
17
  LOG_COLLECTED: 'LOG_COLLECTED'
22
18
  }
23
-
24
19
  export function LifeCycle() {
25
- this.callbacks = []
20
+ this.callbacks = {}
26
21
  }
27
22
  LifeCycle.prototype = {
28
23
  notify: function (eventType, data) {