@cloudcare/browser-core 1.1.3 → 1.2.1

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 (134) hide show
  1. package/cjs/{cookie.js → browser/cookie.js} +6 -37
  2. package/cjs/browser/fetchObservable.js +91 -0
  3. package/cjs/browser/xhrObservable.js +118 -0
  4. package/cjs/configuration/configuration.js +70 -0
  5. package/cjs/configuration/transportConfiguration.js +64 -0
  6. package/cjs/console/consoleObservable.js +84 -0
  7. package/cjs/dataMap.js +26 -21
  8. package/cjs/error/trackRuntimeError.js +27 -0
  9. package/cjs/helper/catchUserErrors.js +20 -0
  10. package/cjs/helper/contextHistory.js +134 -0
  11. package/cjs/helper/createEventRateLimiter.js +47 -0
  12. package/cjs/helper/deviceInfo.js +8 -25
  13. package/cjs/helper/display.js +31 -0
  14. package/cjs/helper/enums.js +28 -2
  15. package/cjs/helper/errorTools.js +63 -2
  16. package/cjs/helper/instrumentMethod.js +93 -0
  17. package/cjs/helper/lifeCycle.js +5 -3
  18. package/cjs/helper/observable.js +40 -2
  19. package/cjs/helper/tools.js +185 -9
  20. package/cjs/index.js +153 -23
  21. package/cjs/init.js +17 -27
  22. package/cjs/report/reportObservable.js +112 -0
  23. package/cjs/session/sessionConstants.js +13 -0
  24. package/cjs/session/sessionCookieStore.js +188 -0
  25. package/cjs/session/sessionManagement.js +96 -0
  26. package/cjs/session/sessionStore.js +150 -0
  27. package/cjs/synthetics/syntheticsWorkerValues.js +32 -0
  28. package/cjs/synthetics/usr.js +32 -0
  29. package/cjs/tracekit/computeStackTrace.js +73 -563
  30. package/cjs/tracekit/index.js +3 -15
  31. package/cjs/tracekit/tracekit.js +113 -0
  32. package/cjs/transport/batch.js +332 -0
  33. package/cjs/transport/httpRequest.js +112 -0
  34. package/cjs/transport/index.js +29 -0
  35. package/cjs/transport/sendWithRetryStrategy.js +177 -0
  36. package/cjs/transport/startBatchWithReplica.js +24 -0
  37. package/esm/{cookie.js → browser/cookie.js} +4 -35
  38. package/esm/browser/fetchObservable.js +77 -0
  39. package/esm/browser/xhrObservable.js +106 -0
  40. package/esm/configuration/configuration.js +55 -0
  41. package/esm/configuration/transportConfiguration.js +54 -0
  42. package/esm/console/consoleObservable.js +70 -0
  43. package/esm/dataMap.js +26 -21
  44. package/esm/error/trackRuntimeError.js +16 -0
  45. package/esm/helper/catchUserErrors.js +12 -0
  46. package/esm/helper/contextHistory.js +106 -0
  47. package/esm/helper/createEventRateLimiter.js +38 -0
  48. package/esm/helper/deviceInfo.js +6 -25
  49. package/esm/helper/display.js +21 -0
  50. package/esm/helper/enums.js +25 -1
  51. package/esm/helper/errorTools.js +58 -3
  52. package/esm/helper/instrumentMethod.js +81 -0
  53. package/esm/helper/lifeCycle.js +5 -3
  54. package/esm/helper/observable.js +39 -3
  55. package/esm/helper/tools.js +147 -1
  56. package/esm/index.js +17 -7
  57. package/esm/init.js +17 -22
  58. package/esm/report/reportObservable.js +98 -0
  59. package/esm/session/sessionConstants.js +3 -0
  60. package/esm/session/sessionCookieStore.js +168 -0
  61. package/esm/session/sessionManagement.js +78 -0
  62. package/esm/session/sessionStore.js +139 -0
  63. package/esm/synthetics/syntheticsWorkerValues.js +15 -0
  64. package/esm/synthetics/usr.js +18 -0
  65. package/esm/tracekit/computeStackTrace.js +73 -557
  66. package/esm/tracekit/index.js +1 -1
  67. package/esm/tracekit/tracekit.js +103 -0
  68. package/esm/transport/batch.js +316 -0
  69. package/esm/transport/httpRequest.js +104 -0
  70. package/esm/transport/index.js +3 -0
  71. package/esm/transport/sendWithRetryStrategy.js +165 -0
  72. package/esm/transport/startBatchWithReplica.js +15 -0
  73. package/package.json +2 -2
  74. package/src/.DS_Store +0 -0
  75. package/src/{cookie.js → browser/cookie.js} +6 -34
  76. package/src/browser/fetchObservable.js +86 -0
  77. package/src/browser/xhrObservable.js +102 -0
  78. package/src/configuration/configuration.js +61 -0
  79. package/src/configuration/transportConfiguration.js +42 -0
  80. package/src/console/consoleObservable.js +65 -0
  81. package/src/dataMap.js +26 -21
  82. package/src/error/trackRuntimeError.js +19 -0
  83. package/src/helper/catchUserErrors.js +12 -0
  84. package/src/helper/contextHistory.js +85 -0
  85. package/src/helper/createEventRateLimiter.js +37 -0
  86. package/src/helper/deviceInfo.js +5 -51
  87. package/src/helper/display.js +21 -0
  88. package/src/helper/enums.js +38 -14
  89. package/src/helper/errorTools.js +76 -12
  90. package/src/helper/instrumentMethod.js +97 -0
  91. package/src/helper/lifeCycle.js +5 -3
  92. package/src/helper/observable.js +33 -2
  93. package/src/helper/tools.js +135 -4
  94. package/src/index.js +18 -7
  95. package/src/init.js +17 -18
  96. package/src/report/reportObservable.js +113 -0
  97. package/src/session/sessionConstants.js +3 -0
  98. package/src/session/sessionCookieStore.js +159 -0
  99. package/src/session/sessionManagement.js +89 -0
  100. package/src/session/sessionStore.js +139 -0
  101. package/src/synthetics/syntheticsWorkerValues.js +22 -0
  102. package/src/synthetics/usr.js +18 -0
  103. package/src/tracekit/computeStackTrace.js +75 -551
  104. package/src/tracekit/index.js +1 -1
  105. package/src/tracekit/tracekit.js +100 -0
  106. package/src/transport/batch.js +289 -0
  107. package/src/transport/httpRequest.js +109 -0
  108. package/src/transport/index.js +3 -0
  109. package/src/transport/sendWithRetryStrategy.js +186 -0
  110. package/src/transport/startBatchWithReplica.js +26 -0
  111. package/cjs/configuration.js +0 -193
  112. package/cjs/errorCollection.js +0 -167
  113. package/cjs/fetchProxy.js +0 -161
  114. package/cjs/helper/errorFilter.js +0 -47
  115. package/cjs/sessionManagement.js +0 -221
  116. package/cjs/tracekit/report.js +0 -289
  117. package/cjs/transport.js +0 -373
  118. package/cjs/xhrProxy.js +0 -122
  119. package/esm/configuration.js +0 -176
  120. package/esm/errorCollection.js +0 -141
  121. package/esm/fetchProxy.js +0 -115
  122. package/esm/helper/errorFilter.js +0 -38
  123. package/esm/sessionManagement.js +0 -195
  124. package/esm/tracekit/report.js +0 -273
  125. package/esm/transport.js +0 -357
  126. package/esm/xhrProxy.js +0 -110
  127. package/src/configuration.js +0 -161
  128. package/src/errorCollection.js +0 -170
  129. package/src/fetchProxy.js +0 -108
  130. package/src/helper/errorFilter.js +0 -38
  131. package/src/sessionManagement.js +0 -224
  132. package/src/tracekit/report.js +0 -284
  133. package/src/transport.js +0 -380
  134. package/src/xhrProxy.js +0 -106
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cloudcare/browser-core",
3
- "version": "1.1.3",
3
+ "version": "1.2.1",
4
4
  "main": "cjs/index.js",
5
5
  "module": "esm/index.js",
6
6
  "scripts": {
@@ -20,5 +20,5 @@
20
20
  "author": "dataflux",
21
21
  "license": "MIT",
22
22
  "description": "DataFlux RUM Web 端数据指标监控",
23
- "gitHead": "8cd2d38961b7663bde39072730de22bcf4ba9c2b"
23
+ "gitHead": "e8411cbf5448e90b81a5e902c54cceb44e6e2501"
24
24
  }
package/src/.DS_Store CHANGED
Binary file
@@ -1,38 +1,5 @@
1
- import { findCommaSeparatedValue, UUID, ONE_SECOND } from './helper/tools'
1
+ import { findCommaSeparatedValue, UUID, ONE_SECOND } from '../helper/tools'
2
2
  export var COOKIE_ACCESS_DELAY = ONE_SECOND
3
- export function cacheCookieAccess(name, options) {
4
- var timeout
5
- var cache
6
- var hasCache = false
7
-
8
- var cacheAccess = function () {
9
- hasCache = true
10
- window.clearTimeout(timeout)
11
- timeout = window.setTimeout(function () {
12
- hasCache = false
13
- }, COOKIE_ACCESS_DELAY)
14
- }
15
-
16
- return {
17
- get: function () {
18
- if (hasCache) {
19
- return cache
20
- }
21
- cache = getCookie(name)
22
- cacheAccess()
23
- return cache
24
- },
25
- set: function (value, expireDelay) {
26
- setCookie(name, value, expireDelay, options)
27
- cache = value
28
- cacheAccess()
29
- },
30
- clearCache: function() {
31
- window.clearTimeout(timeout)
32
- hasCache = false
33
- },
34
- }
35
- }
36
3
 
37
4
  export function setCookie(name, value, expireDelay, options) {
38
5
  var date = new Date()
@@ -57,6 +24,11 @@ export function getCookie(name) {
57
24
  return findCommaSeparatedValue(document.cookie, name)
58
25
  }
59
26
 
27
+ export function deleteCookie(name, options) {
28
+ setCookie(name, '', 0, options)
29
+ }
30
+
31
+
60
32
  export function areCookiesAuthorized(options) {
61
33
  if (document.cookie === undefined || document.cookie === null) {
62
34
  return false
@@ -0,0 +1,86 @@
1
+ import { instrumentMethod } from '../helper/instrumentMethod'
2
+ import { Observable } from '../helper/observable'
3
+ import { elapsed, clocksNow, timeStampNow } from '../helper/tools'
4
+ import { normalizeUrl } from '../helper/urlPolyfill'
5
+
6
+ var fetchObservable
7
+
8
+ export function initFetchObservable() {
9
+ if (!fetchObservable) {
10
+ fetchObservable = createFetchObservable()
11
+ }
12
+ return fetchObservable
13
+ }
14
+
15
+ function createFetchObservable() {
16
+ var observable = new Observable(function() {
17
+ if (!window.fetch) {
18
+ return
19
+ }
20
+
21
+ var fetchMethod = instrumentMethod(
22
+ window,
23
+ 'fetch',
24
+ function(originalFetch) {
25
+ return function (input, init) {
26
+ var responsePromise
27
+ var context = beforeSend(observable, input, init)
28
+ if (context) {
29
+ responsePromise = originalFetch.call(this, context.input, context.init)
30
+ afterSend(observable, responsePromise, context)
31
+ } else {
32
+ responsePromise = originalFetch.call(this, input, init)
33
+ }
34
+ return responsePromise
35
+ }
36
+ }
37
+ )
38
+ return fetchMethod.stop
39
+ })
40
+
41
+ return observable
42
+ }
43
+
44
+ function beforeSend(observable, input, init) {
45
+ var method = (init && init.method) || (typeof input === 'object' && input.method) || 'GET'
46
+ var url = normalizeUrl((typeof input === 'object' && input.url) || input)
47
+ var startClocks = clocksNow()
48
+
49
+ var context = {
50
+ state: 'start',
51
+ init: init,
52
+ input: input,
53
+ method: method,
54
+ startClocks: startClocks,
55
+ url: url,
56
+ }
57
+
58
+ observable.notify(context)
59
+
60
+ return context
61
+ }
62
+
63
+ function afterSend(
64
+ observable,
65
+ responsePromise,
66
+ startContext
67
+ ) {
68
+ var reportFetch = function(response) {
69
+ var context = startContext
70
+ context.state = 'complete'
71
+ context.duration = elapsed(context.startClocks.timeStamp, timeStampNow())
72
+ if ('stack' in response || response instanceof Error) {
73
+ context.status = 0
74
+ context.isAborted = response instanceof DOMException && response.code === DOMException.ABORT_ERR
75
+ context.error = response
76
+ observable.notify(context)
77
+ } else if ('status' in response) {
78
+ context.response = response
79
+ context.responseType = response.type
80
+ context.status = response.status
81
+ context.isAborted = false
82
+ observable.notify(context)
83
+ }
84
+ }
85
+ responsePromise.then(reportFetch, reportFetch)
86
+ }
@@ -0,0 +1,102 @@
1
+ import { instrumentMethodAndCallOriginal } from '../helper/instrumentMethod'
2
+ import { Observable } from '../helper/observable'
3
+ import { normalizeUrl } from '../helper/urlPolyfill'
4
+ import { shallowClone, elapsed, relativeNow, clocksNow, timeStampNow, UUID } from '../helper/tools'
5
+
6
+ var xhrObservable
7
+ var xhrContexts = {}
8
+ var DATA_FLUX_REQUEST_ID_KEY = '_DATAFLUX_REQUEST_UUID'
9
+ export function initXhrObservable() {
10
+ if (!xhrObservable) {
11
+ xhrObservable = createXhrObservable()
12
+ }
13
+ return xhrObservable
14
+ }
15
+
16
+ function createXhrObservable() {
17
+ var observable = new Observable(function(){
18
+ var openInstrumentMethod = instrumentMethodAndCallOriginal(XMLHttpRequest.prototype, 'open', {
19
+ before: openXhr,
20
+ })
21
+
22
+ var sendInstrumentMethod = instrumentMethodAndCallOriginal(XMLHttpRequest.prototype, 'send', {
23
+ before: function() {
24
+ sendXhr.call(this, observable)
25
+ },
26
+ })
27
+
28
+ var abortInstrumentMethod = instrumentMethodAndCallOriginal(XMLHttpRequest.prototype, 'abort', {
29
+ before:abortXhr,
30
+ })
31
+
32
+ return function() {
33
+ openInstrumentMethod.stop()
34
+ sendInstrumentMethod.stop()
35
+ abortInstrumentMethod.stop()
36
+ }
37
+ })
38
+ return observable
39
+ }
40
+
41
+ function openXhr(method, url) {
42
+ var requestUUID = this[DATA_FLUX_REQUEST_ID_KEY] || UUID()
43
+ this[DATA_FLUX_REQUEST_ID_KEY] = requestUUID
44
+ xhrContexts[requestUUID] = {
45
+ state: 'open',
46
+ method: method,
47
+ url: normalizeUrl(String(url)),
48
+ }
49
+ }
50
+
51
+ function sendXhr(observable) {
52
+ var context = xhrContexts[this[DATA_FLUX_REQUEST_ID_KEY]]
53
+ if (!context) {
54
+ return
55
+ }
56
+ var startContext = context
57
+ startContext.state = 'start'
58
+ startContext.startTime = relativeNow()
59
+ startContext.startClocks = clocksNow()
60
+ startContext.isAborted = false
61
+ startContext.xhr = this
62
+ var hasBeenReported = false
63
+ var onreadyStateChangeInstrumentMethod = instrumentMethodAndCallOriginal(this, 'onreadystatechange', {
64
+ before: function() {
65
+ if (this.readyState === XMLHttpRequest.DONE) {
66
+ // Try to report the XHR as soon as possible, because the XHR may be mutated by the
67
+ // application during a future event. For example, Angular is calling .abort() on
68
+ // completed requests during a onreadystatechange event, so the status becomes '0'
69
+ // before the request is collected.
70
+ onEnd.call(this)
71
+
72
+ }
73
+ },
74
+ })
75
+
76
+ var onEnd = function() {
77
+ this.removeEventListener('loadend', onEnd)
78
+ onreadyStateChangeInstrumentMethod.stop()
79
+ if (hasBeenReported) {
80
+ return
81
+ }
82
+ hasBeenReported = true
83
+ var completeContext = context
84
+ completeContext.state = 'complete'
85
+ completeContext.duration = elapsed(startContext.startClocks.timeStamp, timeStampNow())
86
+ completeContext.status = this.status
87
+ observable.notify(shallowClone(completeContext))
88
+ clearRequestId.call(this)
89
+ }
90
+ this.addEventListener('loadend', onEnd)
91
+ observable.notify(startContext)
92
+ }
93
+ function clearRequestId() {
94
+ delete xhrContexts[this[DATA_FLUX_REQUEST_ID_KEY]]
95
+ delete this[DATA_FLUX_REQUEST_ID_KEY]
96
+ }
97
+ function abortXhr() {
98
+ var context = xhrContexts[this[DATA_FLUX_REQUEST_ID_KEY]]
99
+ if (context) {
100
+ context.isAborted = true
101
+ }
102
+ }
@@ -0,0 +1,61 @@
1
+ import { getCurrentSite } from '../browser/cookie'
2
+ import { catchUserErrors } from '../helper/catchUserErrors'
3
+ import { display } from '../helper/display'
4
+ import { assign, isPercentage, ONE_KIBI_BYTE, ONE_SECOND, isNullUndefinedDefaultValue } from '../helper/tools'
5
+ import { computeTransportConfiguration } from './transportConfiguration'
6
+ export function validateAndBuildConfiguration(initConfiguration){
7
+ if (initConfiguration.sampleRate !== undefined && !isPercentage(initConfiguration.sampleRate)) {
8
+ display.error('Sample Rate should be a number between 0 and 100')
9
+ return
10
+ }
11
+ return assign(
12
+ {
13
+ beforeSend:
14
+ initConfiguration.beforeSend && catchUserErrors(initConfiguration.beforeSend, 'beforeSend threw an error:'),
15
+ cookieOptions: buildCookieOptions(initConfiguration),
16
+ sampleRate: isNullUndefinedDefaultValue(initConfiguration.sampleRate, 100),
17
+ service: initConfiguration.service,
18
+ version: initConfiguration.version,
19
+ env: initConfiguration.env,
20
+ silentMultipleInit: !!initConfiguration.silentMultipleInit,
21
+
22
+ /**
23
+ * beacon payload max queue size implementation is 64kb
24
+ * ensure that we leave room for logs, rum and potential other users
25
+ */
26
+ batchBytesLimit: 16 * ONE_KIBI_BYTE,
27
+
28
+ eventRateLimiterThreshold: 3000,
29
+
30
+ /**
31
+ * flush automatically, aim to be lower than ALB connection timeout
32
+ * to maximize connection reuse.
33
+ */
34
+ flushTimeout: 30 * ONE_SECOND,
35
+
36
+ /**
37
+ * Logs intake limit
38
+ */
39
+ batchMessagesLimit: 50,
40
+ messageBytesLimit: 256 * ONE_KIBI_BYTE,
41
+ },
42
+ computeTransportConfiguration(initConfiguration)
43
+ )
44
+ }
45
+
46
+ export function buildCookieOptions(initConfiguration) {
47
+ var cookieOptions = {}
48
+
49
+ cookieOptions.secure = mustUseSecureCookie(initConfiguration)
50
+ cookieOptions.crossSite = !!initConfiguration.useCrossSiteSessionCookie
51
+
52
+ if (initConfiguration.trackSessionAcrossSubdomains) {
53
+ cookieOptions.domain = getCurrentSite()
54
+ }
55
+
56
+ return cookieOptions
57
+ }
58
+
59
+ function mustUseSecureCookie(initConfiguration) {
60
+ return !!initConfiguration.useSecureSessionCookie || !!initConfiguration.useCrossSiteSessionCookie
61
+ }
@@ -0,0 +1,42 @@
1
+ import { isFunction, isBoolean, some } from '../helper/tools'
2
+ var TRIM_REGIX = /^\s+|\s+$/g
3
+ function getDatakitUrl(url) {
4
+ if (url.lastIndexOf('/') === url.length - 1) return trim(url) + 'v1/write/rum'
5
+ return trim(url) + '/v1/write/rum'
6
+ }
7
+ function trim(str) {
8
+ return str.replace(TRIM_REGIX, '')
9
+ }
10
+ function getLogsEndPoint(url) {
11
+ if (url.lastIndexOf('/') === url.length - 1)
12
+ return trim(url) + 'v1/write/logging'
13
+ return trim(url) + '/v1/write/logging'
14
+ }
15
+ export function computeTransportConfiguration(initConfiguration) {
16
+ var isIntakeUrl = function(url) { return false }
17
+ if ('isIntakeUrl' in initConfiguration && isFunction(initConfiguration.isIntakeUrl) && isBoolean(initConfiguration.isIntakeUrl())) {
18
+ isIntakeUrl = initConfiguration.isIntakeUrl
19
+ }
20
+ var isServerError = function(request) { return false }
21
+ if ('isServerError' in initConfiguration && isFunction(initConfiguration.isServerError) && isBoolean(initConfiguration.isServerError())) {
22
+ isServerError = initConfiguration.isServerError
23
+ }
24
+ return {
25
+ datakitUrl: getDatakitUrl(
26
+ initConfiguration.datakitUrl || initConfiguration.datakitOrigin
27
+ ),
28
+ logsEndpoint: getLogsEndPoint(initConfiguration.datakitOrigin),
29
+ isIntakeUrl: isIntakeUrl,
30
+ isServerError: isServerError
31
+ }
32
+
33
+ }
34
+ export function isIntakeRequest(url, configuration) {
35
+ // return haveSameOrigin(url, configuration.datakitUrl)
36
+ var notTakeRequest = [configuration.datakitUrl]
37
+ if (configuration.logsEndpoint) {
38
+ notTakeRequest.push(configuration.logsEndpoint)
39
+ }
40
+ // datakit 地址,log 地址,以及客户自定义过滤方法定义url
41
+ return some(notTakeRequest, function(takeUrl) { return url.indexOf(takeUrl) === 0 }) || configuration.isIntakeUrl(url)
42
+ }
@@ -0,0 +1,65 @@
1
+ import { computeStackTrace } from '../tracekit'
2
+ import { createHandlingStack, formatErrorMessage, toStackTraceString } from '../helper/errorTools'
3
+ import { mergeObservables, Observable } from '../helper/observable'
4
+ import { find, jsonStringify, map } from '../helper/tools'
5
+ import { ConsoleApiName } from '../helper/display'
6
+
7
+
8
+ var consoleObservablesByApi = {}
9
+
10
+ export function initConsoleObservable(apis) {
11
+ var consoleObservables = map(apis, function(api) {
12
+ if (!consoleObservablesByApi[api]) {
13
+ consoleObservablesByApi[api] = createConsoleObservable(api)
14
+ }
15
+ return consoleObservablesByApi[api]
16
+ })
17
+
18
+ return mergeObservables.apply(this, consoleObservables)
19
+ }
20
+
21
+ /* eslint-disable no-console */
22
+ function createConsoleObservable(api) {
23
+ var observable = new Observable(function(){
24
+ var originalConsoleApi = console[api]
25
+ console[api] = function() {
26
+ var params = [].slice.call(arguments)
27
+ originalConsoleApi.apply(console, arguments)
28
+ var handlingStack = createHandlingStack()
29
+ observable.notify(buildConsoleLog(params, api, handlingStack))
30
+ }
31
+ return function() {
32
+ console[api] = originalConsoleApi
33
+ }
34
+ })
35
+ return observable
36
+ }
37
+
38
+ function buildConsoleLog(params, api, handlingStack) {
39
+ // Todo: remove console error prefix in the next major version
40
+ var message = map(params, function(param) { return formatConsoleParameters(param) }).join(' ')
41
+ var stack
42
+
43
+ if (api === ConsoleApiName.error) {
44
+ var firstErrorParam = find(params, function(param) { return param instanceof Error })
45
+ stack = firstErrorParam ? toStackTraceString(computeStackTrace(firstErrorParam)) : undefined
46
+ message = 'console error: '+ message
47
+ }
48
+
49
+ return {
50
+ api: api,
51
+ message: message,
52
+ stack: stack,
53
+ handlingStack: handlingStack,
54
+ }
55
+ }
56
+
57
+ function formatConsoleParameters(param) {
58
+ if (typeof param === 'string') {
59
+ return param
60
+ }
61
+ if (param instanceof Error) {
62
+ return formatErrorMessage(computeStackTrace(param))
63
+ }
64
+ return jsonStringify(param, undefined, 2)
65
+ }
package/src/dataMap.js CHANGED
@@ -1,11 +1,12 @@
1
1
  import { RumEventType } from './helper/enums'
2
2
  export var commonTags = {
3
+ action_id: 'action.id',
3
4
  sdk_name: '_dd.sdk_name',
4
5
  sdk_version: '_dd.sdk_version',
5
6
  app_id: 'application.id',
6
- env: '_dd.env',
7
- service: '_dd.service',
8
- version: '_dd.version',
7
+ env: 'env',
8
+ service: 'service',
9
+ version: 'version',
9
10
  userid: 'user.id',
10
11
  user_email: 'user.email',
11
12
  user_name: 'user.name',
@@ -92,27 +93,31 @@ export var dataMap = {
92
93
  error: {
93
94
  type: RumEventType.ERROR,
94
95
  tags: {
96
+ error_id: 'error.id',
95
97
  trace_id: '_dd.trace_id',
96
98
  span_id: '_dd.span_id',
97
99
  error_source: 'error.source',
98
100
  error_type: 'error.type',
99
- error_handling: 'error.handling',
100
- resource_url: 'error.resource.url',
101
- resource_url_host: 'error.resource.url_host',
102
- resource_url_path: 'error.resource.url_path',
103
- resource_url_path_group: 'error.resource.url_path_group',
104
- resource_status: 'error.resource.status',
105
- resource_status_group: 'error.resource.status_group',
106
- resource_method: 'error.resource.method',
101
+ error_handling: 'error.handling'
102
+ // resource_url: 'error.resource.url',
103
+ // resource_url_host: 'error.resource.url_host',
104
+ // resource_url_path: 'error.resource.url_path',
105
+ // resource_url_path_group: 'error.resource.url_path_group',
106
+ // resource_status: 'error.resource.status',
107
+ // resource_status_group: 'error.resource.status_group',
108
+ // resource_method: 'error.resource.method'
107
109
  },
108
110
  fields: {
109
111
  error_message: ['string', 'error.message'],
110
- error_stack: ['string', 'error.stack']
112
+ error_stack: ['string', 'error.stack'],
113
+ error_causes: ['string', 'error.causes']
111
114
  }
112
115
  },
113
116
  long_task: {
114
117
  type: RumEventType.LONG_TASK,
115
- tags: {},
118
+ tags: {
119
+ long_task_id: 'long_task.id'
120
+ },
116
121
  fields: {
117
122
  duration: 'long_task.duration'
118
123
  }
@@ -120,7 +125,6 @@ export var dataMap = {
120
125
  action: {
121
126
  type: RumEventType.ACTION,
122
127
  tags: {
123
- action_id: 'action.id',
124
128
  action_name: 'action.target.name',
125
129
  action_type: 'action.type'
126
130
  },
@@ -128,6 +132,7 @@ export var dataMap = {
128
132
  duration: 'action.loading_time',
129
133
  action_error_count: 'action.error.count',
130
134
  action_resource_count: 'action.resource.count',
135
+ action_frustration_types: 'action.frustration.type',
131
136
  action_long_task_count: 'action.long_task.count'
132
137
  }
133
138
  },
@@ -136,13 +141,13 @@ export var dataMap = {
136
141
  tags: {
137
142
  error_source: 'error.source',
138
143
  error_type: 'error.type',
139
- error_resource_url: 'resource.url',
140
- error_resource_url_host: 'resource.url_host',
141
- error_resource_url_path: 'resource.url_path',
142
- error_resource_url_path_group: 'resource.url_path_group',
143
- error_resource_status: 'resource.status',
144
- error_resource_status_group: 'resource.status_group',
145
- error_resource_method: 'resource.method',
144
+ error_resource_url: 'http.url',
145
+ error_resource_url_host: 'http.url_host',
146
+ error_resource_url_path: 'http.url_path',
147
+ error_resource_url_path_group: 'http.url_path_group',
148
+ error_resource_status: 'http.status_code',
149
+ error_resource_status_group: 'http.status_group',
150
+ error_resource_method: 'http.method',
146
151
  action_id: 'user_action.id',
147
152
  service: 'service',
148
153
  status: 'status'
@@ -0,0 +1,19 @@
1
+ import { ErrorSource, computeRawError } from '../helper/errorTools'
2
+ import { clocksNow } from '../helper/tools'
3
+ import { ErrorHandling } from '../helper/enums'
4
+ import { startUnhandledErrorCollection } from '../tracekit'
5
+
6
+ export function trackRuntimeError(errorObservable) {
7
+ return startUnhandledErrorCollection(function (stackTrace, originalError) {
8
+ errorObservable.notify(
9
+ computeRawError({
10
+ stackTrace: stackTrace,
11
+ originalError: originalError,
12
+ startClocks: clocksNow(),
13
+ nonErrorPrefix: 'Uncaught',
14
+ source: ErrorSource.SOURCE,
15
+ handling: ErrorHandling.UNHANDLED
16
+ })
17
+ )
18
+ })
19
+ }
@@ -0,0 +1,12 @@
1
+ import { display } from './display'
2
+
3
+ export function catchUserErrors(fn, errorMsg) {
4
+ return function() {
5
+ var args = [].slice.call(arguments)
6
+ try {
7
+ return fn.apply(this, args)
8
+ } catch (err) {
9
+ display.error(errorMsg, err)
10
+ }
11
+ }
12
+ }
@@ -0,0 +1,85 @@
1
+ import { relativeNow, ONE_MINUTE, filter, map} from './tools'
2
+
3
+ var END_OF_TIMES = Infinity
4
+
5
+ export var CLEAR_OLD_CONTEXTS_INTERVAL = ONE_MINUTE
6
+ export function ContextHistory(expireDelay) {
7
+ this.expireDelay = expireDelay
8
+ this.entries = []
9
+ var _this = this
10
+ this.clearOldContextsInterval = setInterval(function(){
11
+ _this.clearOldContexts()
12
+ }, CLEAR_OLD_CONTEXTS_INTERVAL);
13
+ }
14
+ ContextHistory.prototype.add = function(context, startTime) {
15
+ var _this = this
16
+ var entry = {
17
+ context: context,
18
+ startTime: startTime,
19
+ endTime: END_OF_TIMES,
20
+ remove: function() {
21
+ var index = _this.entries.indexOf(entry)
22
+ if (index >= 0) {
23
+ _this.entries.splice(index, 1)
24
+ }
25
+ },
26
+ close: function(endTime){
27
+ entry.endTime = endTime
28
+ },
29
+ }
30
+ this.entries.unshift(entry)
31
+ return entry
32
+ }
33
+ ContextHistory.prototype.find = function(startTime) {
34
+ if (typeof startTime === 'undefined') {
35
+ startTime = END_OF_TIMES
36
+ }
37
+ for (var entry of this.entries) {
38
+ if (entry.startTime <= startTime) {
39
+ if (startTime <= entry.endTime) {
40
+ return entry.context
41
+ }
42
+ break
43
+ }
44
+ }
45
+ }
46
+ /**
47
+ * Helper function to close the currently active context, if any. This method assumes that entries
48
+ * are not overlapping.
49
+ */
50
+ ContextHistory.prototype.closeActive = function(endTime) {
51
+ var latestEntry = this.entries[0]
52
+ if (latestEntry && latestEntry.endTime === END_OF_TIMES) {
53
+ latestEntry.close(endTime)
54
+ }
55
+ }
56
+ /**
57
+ * Return all contexts that were active during `startTime`, or all currently active contexts if no
58
+ * `startTime` is provided.
59
+ */
60
+ ContextHistory.prototype.findAll = function(startTime){
61
+ if (typeof startTime === 'undefined') {
62
+ startTime = END_OF_TIMES
63
+ }
64
+ var result = filter(this.entries, function(entry) { return entry.startTime <= startTime && startTime <= entry.endTime })
65
+ return map(result, function(entry) { return entry.context })
66
+ }
67
+ /**
68
+ * Remove all entries from this collection.
69
+ */
70
+ ContextHistory.prototype.reset = function () {
71
+ this.entries = []
72
+ }
73
+ /**
74
+ * Stop internal garbage collection of past entries.
75
+ */
76
+ ContextHistory.prototype.stop = function() {
77
+ clearInterval(this.clearOldContextsInterval)
78
+ }
79
+ ContextHistory.prototype.clearOldContexts = function() {
80
+ var oldTimeThreshold = relativeNow() - this.expireDelay
81
+ while (this.entries.length > 0 && this.entries[this.entries.length - 1].endTime < oldTimeThreshold) {
82
+ this.entries.pop()
83
+ }
84
+ }
85
+
@@ -0,0 +1,37 @@
1
+ import { ErrorSource } from './errorTools'
2
+ import { clocksNow, ONE_MINUTE } from './tools'
3
+ export function createEventRateLimiter(
4
+ eventType,
5
+ limit,
6
+ onLimitReached
7
+ ) {
8
+ var eventCount = 0
9
+ var allowNextEvent = false
10
+ return {
11
+ isLimitReached: function() {
12
+ if (eventCount === 0) {
13
+ setTimeout(function(){
14
+ eventCount = 0
15
+ }, ONE_MINUTE)
16
+ }
17
+ eventCount += 1
18
+ if (eventCount <= limit || allowNextEvent) {
19
+ allowNextEvent = false
20
+ return false
21
+ }
22
+ if (eventCount === limit + 1) {
23
+ allowNextEvent = true
24
+ try {
25
+ onLimitReached({
26
+ message: 'Reached max number of ' + eventType +'s by minute: ' + limit,
27
+ source: ErrorSource.AGENT,
28
+ startClocks: clocksNow(),
29
+ })
30
+ } finally {
31
+ allowNextEvent = false
32
+ }
33
+ }
34
+ return true
35
+ }
36
+ }
37
+ }