@pratham.raval/browser-core 6.22.3 → 6.22.5

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 (147) hide show
  1. package/README.md +1 -1
  2. package/cjs/boot/displayAlreadyInitializedError.d.ts +1 -1
  3. package/cjs/boot/init.d.ts +1 -1
  4. package/cjs/browser/cookie.d.ts +10 -0
  5. package/cjs/browser/cookie.js +13 -0
  6. package/cjs/browser/cookie.js.map +1 -1
  7. package/cjs/domain/configuration/configuration.js +4 -4
  8. package/cjs/domain/configuration/configuration.js.map +1 -1
  9. package/cjs/domain/configuration/endpointBuilder.js +16 -24
  10. package/cjs/domain/configuration/endpointBuilder.js.map +1 -1
  11. package/cjs/domain/configuration/transportConfiguration.js +5 -15
  12. package/cjs/domain/configuration/transportConfiguration.js.map +1 -1
  13. package/cjs/domain/intakeSites.d.ts +1 -7
  14. package/cjs/domain/intakeSites.js +2 -8
  15. package/cjs/domain/intakeSites.js.map +1 -1
  16. package/cjs/domain/session/oldCookiesMigration.d.ts +1 -1
  17. package/cjs/domain/session/oldCookiesMigration.js +1 -1
  18. package/cjs/domain/session/sessionManager.d.ts +1 -0
  19. package/cjs/domain/session/sessionManager.js +24 -6
  20. package/cjs/domain/session/sessionManager.js.map +1 -1
  21. package/cjs/domain/session/sessionState.js +2 -8
  22. package/cjs/domain/session/sessionState.js.map +1 -1
  23. package/cjs/domain/session/sessionStore.d.ts +1 -1
  24. package/cjs/domain/session/sessionStore.js +5 -1
  25. package/cjs/domain/session/sessionStore.js.map +1 -1
  26. package/cjs/domain/session/storeStrategies/sessionInCookie.d.ts +5 -1
  27. package/cjs/domain/session/storeStrategies/sessionInCookie.js +52 -3
  28. package/cjs/domain/session/storeStrategies/sessionInCookie.js.map +1 -1
  29. package/cjs/domain/session/storeStrategies/sessionInLocalStorage.d.ts +2 -0
  30. package/cjs/domain/session/storeStrategies/sessionInLocalStorage.js +1 -0
  31. package/cjs/domain/session/storeStrategies/sessionInLocalStorage.js.map +1 -1
  32. package/cjs/domain/session/storeStrategies/sessionStoreStrategy.d.ts +1 -1
  33. package/cjs/domain/session/storeStrategies/sessionStoreStrategy.js +1 -1
  34. package/cjs/domain/synthetics/syntheticsWorkerValues.d.ts +6 -6
  35. package/cjs/domain/synthetics/syntheticsWorkerValues.js +6 -6
  36. package/cjs/domain/synthetics/syntheticsWorkerValues.js.map +1 -1
  37. package/cjs/domain/tags.js +6 -5
  38. package/cjs/domain/tags.js.map +1 -1
  39. package/cjs/domain/telemetry/telemetry.js +4 -5
  40. package/cjs/domain/telemetry/telemetry.js.map +1 -1
  41. package/cjs/domain/telemetry/telemetryEvent.types.d.ts +1 -1
  42. package/cjs/index.d.ts +1 -1
  43. package/cjs/index.js +3 -2
  44. package/cjs/index.js.map +1 -1
  45. package/cjs/tools/display.js +1 -1
  46. package/cjs/tools/display.js.map +1 -1
  47. package/cjs/tools/experimentalFeatures.d.ts +2 -1
  48. package/cjs/tools/experimentalFeatures.js +1 -0
  49. package/cjs/tools/experimentalFeatures.js.map +1 -1
  50. package/cjs/tools/utils/browserDetection.d.ts +2 -0
  51. package/cjs/tools/utils/browserDetection.js +20 -0
  52. package/cjs/tools/utils/browserDetection.js.map +1 -1
  53. package/cjs/tools/utils/stringUtils.d.ts +15 -0
  54. package/cjs/tools/utils/stringUtils.js +36 -0
  55. package/cjs/tools/utils/stringUtils.js.map +1 -1
  56. package/cjs/transport/httpRequest.d.ts +1 -0
  57. package/cjs/transport/httpRequest.js +26 -4
  58. package/cjs/transport/httpRequest.js.map +1 -1
  59. package/cjs/transport/index.d.ts +1 -1
  60. package/cjs/transport/index.js +2 -1
  61. package/cjs/transport/index.js.map +1 -1
  62. package/esm/boot/displayAlreadyInitializedError.d.ts +1 -1
  63. package/esm/boot/init.d.ts +1 -1
  64. package/esm/browser/cookie.d.ts +10 -0
  65. package/esm/browser/cookie.js +13 -1
  66. package/esm/browser/cookie.js.map +1 -1
  67. package/esm/domain/configuration/configuration.js +5 -5
  68. package/esm/domain/configuration/configuration.js.map +1 -1
  69. package/esm/domain/configuration/endpointBuilder.js +16 -24
  70. package/esm/domain/configuration/endpointBuilder.js.map +1 -1
  71. package/esm/domain/configuration/transportConfiguration.js +6 -16
  72. package/esm/domain/configuration/transportConfiguration.js.map +1 -1
  73. package/esm/domain/intakeSites.d.ts +1 -7
  74. package/esm/domain/intakeSites.js +1 -7
  75. package/esm/domain/intakeSites.js.map +1 -1
  76. package/esm/domain/session/oldCookiesMigration.d.ts +1 -1
  77. package/esm/domain/session/oldCookiesMigration.js +1 -1
  78. package/esm/domain/session/sessionManager.d.ts +1 -0
  79. package/esm/domain/session/sessionManager.js +25 -7
  80. package/esm/domain/session/sessionManager.js.map +1 -1
  81. package/esm/domain/session/sessionState.js +2 -8
  82. package/esm/domain/session/sessionState.js.map +1 -1
  83. package/esm/domain/session/sessionStore.d.ts +1 -1
  84. package/esm/domain/session/sessionStore.js +5 -1
  85. package/esm/domain/session/sessionStore.js.map +1 -1
  86. package/esm/domain/session/storeStrategies/sessionInCookie.d.ts +5 -1
  87. package/esm/domain/session/storeStrategies/sessionInCookie.js +53 -4
  88. package/esm/domain/session/storeStrategies/sessionInCookie.js.map +1 -1
  89. package/esm/domain/session/storeStrategies/sessionInLocalStorage.d.ts +2 -0
  90. package/esm/domain/session/storeStrategies/sessionInLocalStorage.js +1 -1
  91. package/esm/domain/session/storeStrategies/sessionInLocalStorage.js.map +1 -1
  92. package/esm/domain/session/storeStrategies/sessionStoreStrategy.d.ts +1 -1
  93. package/esm/domain/session/storeStrategies/sessionStoreStrategy.js +1 -1
  94. package/esm/domain/synthetics/syntheticsWorkerValues.d.ts +6 -6
  95. package/esm/domain/synthetics/syntheticsWorkerValues.js +6 -6
  96. package/esm/domain/synthetics/syntheticsWorkerValues.js.map +1 -1
  97. package/esm/domain/tags.js +6 -5
  98. package/esm/domain/tags.js.map +1 -1
  99. package/esm/domain/telemetry/telemetry.js +4 -5
  100. package/esm/domain/telemetry/telemetry.js.map +1 -1
  101. package/esm/domain/telemetry/telemetryEvent.types.d.ts +1 -1
  102. package/esm/index.d.ts +1 -1
  103. package/esm/index.js +1 -1
  104. package/esm/index.js.map +1 -1
  105. package/esm/tools/display.js +1 -1
  106. package/esm/tools/display.js.map +1 -1
  107. package/esm/tools/experimentalFeatures.d.ts +2 -1
  108. package/esm/tools/experimentalFeatures.js +1 -0
  109. package/esm/tools/experimentalFeatures.js.map +1 -1
  110. package/esm/tools/utils/browserDetection.d.ts +2 -0
  111. package/esm/tools/utils/browserDetection.js +18 -0
  112. package/esm/tools/utils/browserDetection.js.map +1 -1
  113. package/esm/tools/utils/stringUtils.d.ts +15 -0
  114. package/esm/tools/utils/stringUtils.js +35 -0
  115. package/esm/tools/utils/stringUtils.js.map +1 -1
  116. package/esm/transport/httpRequest.d.ts +1 -0
  117. package/esm/transport/httpRequest.js +25 -4
  118. package/esm/transport/httpRequest.js.map +1 -1
  119. package/esm/transport/index.d.ts +1 -1
  120. package/esm/transport/index.js +1 -1
  121. package/esm/transport/index.js.map +1 -1
  122. package/package.json +4 -6
  123. package/src/boot/displayAlreadyInitializedError.ts +1 -1
  124. package/src/boot/init.ts +1 -1
  125. package/src/browser/cookie.ts +19 -1
  126. package/src/domain/configuration/configuration.ts +4 -4
  127. package/src/domain/configuration/endpointBuilder.ts +17 -27
  128. package/src/domain/configuration/transportConfiguration.ts +6 -18
  129. package/src/domain/intakeSites.ts +2 -17
  130. package/src/domain/session/oldCookiesMigration.ts +1 -1
  131. package/src/domain/session/sessionManager.ts +28 -7
  132. package/src/domain/session/sessionState.ts +2 -7
  133. package/src/domain/session/sessionStore.ts +6 -2
  134. package/src/domain/session/storeStrategies/sessionInCookie.ts +66 -4
  135. package/src/domain/session/storeStrategies/sessionInLocalStorage.ts +1 -1
  136. package/src/domain/session/storeStrategies/sessionStoreStrategy.ts +1 -1
  137. package/src/domain/synthetics/syntheticsWorkerValues.ts +9 -9
  138. package/src/domain/tags.ts +6 -6
  139. package/src/domain/telemetry/telemetry.ts +5 -5
  140. package/src/domain/telemetry/telemetryEvent.types.ts +1 -1
  141. package/src/index.ts +1 -0
  142. package/src/tools/display.ts +1 -1
  143. package/src/tools/experimentalFeatures.ts +1 -0
  144. package/src/tools/utils/browserDetection.ts +26 -0
  145. package/src/tools/utils/stringUtils.ts +34 -0
  146. package/src/transport/httpRequest.ts +31 -5
  147. package/src/transport/index.ts +1 -1
@@ -46,6 +46,7 @@ export interface RetryInfo {
46
46
  count: number;
47
47
  lastFailureStatus: number;
48
48
  }
49
+ export declare function setCurrentSite(site: string | undefined): void;
49
50
  export declare function createHttpRequest<Body extends Payload = Payload>(endpointBuilders: EndpointBuilder[], bytesLimit: number, reportError: (error: RawError) => void): HttpRequest<Body>;
50
51
  export declare function fetchKeepAliveStrategy(endpointBuilder: EndpointBuilder, bytesLimit: number, payload: Payload, onResponse?: (r: HttpResponse) => void): void;
51
52
  export declare function fetchStrategy(endpointBuilder: EndpointBuilder, payload: Payload, onResponse?: (r: HttpResponse) => void): void;
@@ -1,6 +1,11 @@
1
1
  import { monitor, monitorError } from '../tools/monitor';
2
2
  import { Observable } from '../tools/observable';
3
+ import { getDetailedBrowserName } from '../tools/utils/browserDetection';
3
4
  import { newRetryState, sendWithRetryStrategy } from './sendWithRetryStrategy';
5
+ let currentSite;
6
+ export function setCurrentSite(site) {
7
+ currentSite = site;
8
+ }
4
9
  export function createHttpRequest(endpointBuilders, bytesLimit, reportError) {
5
10
  const observable = new Observable();
6
11
  const retryState = newRetryState();
@@ -49,9 +54,15 @@ export function fetchKeepAliveStrategy(endpointBuilder, bytesLimit, payload, onR
49
54
  const canUseKeepAlive = isKeepAliveSupported() && payload.bytesCount < bytesLimit;
50
55
  if (canUseKeepAlive) {
51
56
  const fetchUrl = endpointBuilder.build('fetch-keepalive', payload);
52
- fetch(fetchUrl, { method: 'POST', body: payload.data, keepalive: true, mode: 'cors' })
53
- .then(monitor((response) => onResponse === null || onResponse === void 0 ? void 0 : onResponse({ status: response.status, type: response.type })))
54
- .catch(monitor(() => fetchStrategy(endpointBuilder, payload, onResponse)));
57
+ const headers = buildRequestHeaders(fetchUrl);
58
+ fetch(fetchUrl, { method: 'POST', body: payload.data, keepalive: true, mode: 'cors', headers })
59
+ .then(monitor((response) => {
60
+ onResponse === null || onResponse === void 0 ? void 0 : onResponse({ status: response.status, type: response.type });
61
+ }))
62
+ .catch(monitor((error) => {
63
+ fetchStrategy(endpointBuilder, payload, onResponse);
64
+ onResponse === null || onResponse === void 0 ? void 0 : onResponse({ status: 0 });
65
+ }));
55
66
  }
56
67
  else {
57
68
  fetchStrategy(endpointBuilder, payload, onResponse);
@@ -59,7 +70,8 @@ export function fetchKeepAliveStrategy(endpointBuilder, bytesLimit, payload, onR
59
70
  }
60
71
  export function fetchStrategy(endpointBuilder, payload, onResponse) {
61
72
  const fetchUrl = endpointBuilder.build('fetch', payload);
62
- fetch(fetchUrl, { method: 'POST', body: payload.data, mode: 'cors' })
73
+ const headers = buildRequestHeaders(fetchUrl);
74
+ fetch(fetchUrl, { method: 'POST', body: payload.data, mode: 'cors', headers })
63
75
  .then(monitor((response) => onResponse === null || onResponse === void 0 ? void 0 : onResponse({ status: response.status, type: response.type })))
64
76
  .catch(monitor(() => onResponse === null || onResponse === void 0 ? void 0 : onResponse({ status: 0 })));
65
77
  }
@@ -72,4 +84,13 @@ function isKeepAliveSupported() {
72
84
  return false;
73
85
  }
74
86
  }
87
+ function buildRequestHeaders(url) {
88
+ const headers = {};
89
+ // dynamically match your RUM SDK endpoint host
90
+ // "site" comes from init() call, so this automatically adjusts
91
+ if (currentSite && url) {
92
+ headers['X-Browser-Name'] = getDetailedBrowserName();
93
+ }
94
+ return headers;
95
+ }
75
96
  //# sourceMappingURL=httpRequest.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"httpRequest.js","sourceRoot":"","sources":["../../src/transport/httpRequest.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"httpRequest.js","sourceRoot":"","sources":["../../src/transport/httpRequest.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  export type { BandwidthStats, HttpRequest, HttpRequestEvent, Payload, RetryInfo } from './httpRequest';
2
- export { createHttpRequest } from './httpRequest';
2
+ export { createHttpRequest, setCurrentSite } from './httpRequest';
3
3
  export type { BrowserWindowWithEventBridge, DatadogEventBridge } from './eventBridge';
4
4
  export { canUseEventBridge, bridgeSupports, getEventBridge, BridgeCapability } from './eventBridge';
5
5
  export { createBatch } from './batch';
@@ -1,4 +1,4 @@
1
- export { createHttpRequest } from './httpRequest';
1
+ export { createHttpRequest, setCurrentSite } from './httpRequest';
2
2
  export { canUseEventBridge, bridgeSupports, getEventBridge } from './eventBridge';
3
3
  export { createBatch } from './batch';
4
4
  export { createFlushController } from './flushController';
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/transport/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAA;AAEjD,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,cAAc,EAAoB,MAAM,eAAe,CAAA;AACnG,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AAErC,OAAO,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/transport/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AAEjE,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,cAAc,EAAoB,MAAM,eAAe,CAAA;AACnG,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AAErC,OAAO,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pratham.raval/browser-core",
3
- "version": "6.22.3",
3
+ "version": "6.22.5",
4
4
  "license": "Apache-2.0",
5
5
  "main": "cjs/index.js",
6
6
  "module": "esm/index.js",
@@ -13,11 +13,6 @@
13
13
  "build:esm": "rm -rf esm && tsc -p tsconfig.esm.json && yarn replace-build-env esm",
14
14
  "replace-build-env": "node ../../scripts/build/replace-build-env.ts"
15
15
  },
16
- "repository": {
17
- "type": "git",
18
- "url": "https://github.com/DataDog/browser-sdk.git",
19
- "directory": "packages/core"
20
- },
21
16
  "devDependencies": {
22
17
  "@types/pako": "2.0.4",
23
18
  "pako": "2.1.0"
@@ -27,5 +22,8 @@
27
22
  },
28
23
  "publishConfig": {
29
24
  "access": "public"
25
+ },
26
+ "dependencies": {
27
+ "ua-parser-js": "2.0.8"
30
28
  }
31
29
  }
@@ -1,7 +1,7 @@
1
1
  import type { InitConfiguration } from '../domain/configuration'
2
2
  import { display } from '../tools/display'
3
3
 
4
- export function displayAlreadyInitializedError(sdkName: 'DD_RUM' | 'DD_LOGS', initConfiguration: InitConfiguration) {
4
+ export function displayAlreadyInitializedError(sdkName: 'MD_RUM' | 'MD_LOGS', initConfiguration: InitConfiguration) {
5
5
  if (!initConfiguration.silentMultipleInit) {
6
6
  display.error(`${sdkName} is already initialized.`)
7
7
  }
package/src/boot/init.ts CHANGED
@@ -12,7 +12,7 @@ export interface PublicApi {
12
12
  version: string
13
13
 
14
14
  /**
15
- * For CDN async setup: Early RUM API calls must be wrapped in the `window.DD_RUM.onReady()` callback. This ensures the code only gets executed once the SDK is properly loaded.
15
+ * For CDN async setup: Early RUM API calls must be wrapped in the `window.MD_RUM.onReady()` callback. This ensures the code only gets executed once the SDK is properly loaded.
16
16
  *
17
17
  * See [CDN async setup](https://docs.datadoghq.com/real_user_monitoring/browser/#cdn-async) for further information.
18
18
  */
@@ -1,6 +1,11 @@
1
1
  import { display } from '../tools/display'
2
2
  import { ONE_MINUTE, ONE_SECOND } from '../tools/utils/timeUtils'
3
- import { findCommaSeparatedValue, findCommaSeparatedValues, generateUUID } from '../tools/utils/stringUtils'
3
+ import {
4
+ findAllCommaSeparatedValues,
5
+ findCommaSeparatedValue,
6
+ findCommaSeparatedValues,
7
+ generateUUID,
8
+ } from '../tools/utils/stringUtils'
4
9
  import { buildUrl } from '../tools/utils/urlPolyfill'
5
10
 
6
11
  export interface CookieOptions {
@@ -21,15 +26,28 @@ export function setCookie(name: string, value: string, expireDelay: number = 0,
21
26
  document.cookie = `${name}=${value};${expires};path=/;samesite=${sameSite}${domain}${secure}${partitioned}`
22
27
  }
23
28
 
29
+ /**
30
+ * Returns the value of the cookie with the given name
31
+ * If there are multiple cookies with the same name, returns the first one
32
+ */
24
33
  export function getCookie(name: string) {
25
34
  return findCommaSeparatedValue(document.cookie, name)
26
35
  }
27
36
 
37
+ /**
38
+ * Returns all the values of the cookies with the given name
39
+ */
40
+ export function getCookies(name: string): string[] {
41
+ return findAllCommaSeparatedValues(document.cookie).get(name) || []
42
+ }
43
+
28
44
  let initCookieParsed: Map<string, string> | undefined
29
45
 
30
46
  /**
31
47
  * Returns a cached value of the cookie. Use this during SDK initialization (and whenever possible)
32
48
  * to avoid accessing document.cookie multiple times.
49
+ *
50
+ * ⚠️ If there are multiple cookies with the same name, returns the LAST one (unlike `getCookie()`)
33
51
  */
34
52
  export function getInitCookie(name: string) {
35
53
  if (!initCookieParsed) {
@@ -342,9 +342,9 @@ function isString(tag: unknown, tagName: string): tag is string | undefined | nu
342
342
  return true
343
343
  }
344
344
 
345
- function isDatadogSite(site: unknown) {
346
- if (site && typeof site === 'string' && !/(datadog|ddog|datad0g|dd0g)/.test(site)) {
347
- display.error(`Site should be a valid Datadog site. ${MORE_DETAILS} ${DOCS_ORIGIN}/getting_started/site/.`)
345
+ function isValidSite(site: unknown) {
346
+ if (site !== undefined && site !== null && typeof site !== 'string') {
347
+ display.error('Site must be a non-null string')
348
348
  return false
349
349
  }
350
350
  return true
@@ -376,7 +376,7 @@ export function validateAndBuildConfiguration(
376
376
  }
377
377
 
378
378
  if (
379
- !isDatadogSite(initConfiguration.site) ||
379
+ !isValidSite(initConfiguration.site) ||
380
380
  !isSampleRate(initConfiguration.sessionSampleRate, 'Session') ||
381
381
  !isSampleRate(initConfiguration.telemetrySampleRate, 'Telemetry') ||
382
382
  !isSampleRate(initConfiguration.telemetryConfigurationSampleRate, 'Telemetry Configuration') ||
@@ -2,7 +2,7 @@ import type { Payload } from '../../transport'
2
2
  import { timeStampNow } from '../../tools/utils/timeUtils'
3
3
  import { normalizeUrl } from '../../tools/utils/urlPolyfill'
4
4
  import { generateUUID } from '../../tools/utils/stringUtils'
5
- import { INTAKE_SITE_FED_STAGING, INTAKE_SITE_US1, PCI_INTAKE_HOST_US1 } from '../intakeSites'
5
+
6
6
  import type { InitConfiguration } from './configuration'
7
7
 
8
8
  // replaced at build time
@@ -48,36 +48,26 @@ function createEndpointUrlWithParametersBuilder(
48
48
  const proxy = initConfiguration.proxy
49
49
  if (typeof proxy === 'string') {
50
50
  const normalizedProxyUrl = normalizeUrl(proxy)
51
- return (parameters) => `${normalizedProxyUrl}?ddforward=${encodeURIComponent(`${path}?${parameters}`)}`
51
+ return (parameters) => `${normalizedProxyUrl}?mdforward=${encodeURIComponent(`${path}?${parameters}`)}`
52
52
  }
53
53
  if (typeof proxy === 'function') {
54
54
  return (parameters) => proxy({ path, parameters })
55
55
  }
56
56
  const host = buildEndpointHost(trackType, initConfiguration)
57
- return (parameters) => `https://${host}${path}?${parameters}`
57
+ // return (parameters) => `https://${host}${path}?${parameters}`
58
+ return (parameters) => `${host}${path}?${parameters}`
58
59
  }
59
60
 
60
61
  export function buildEndpointHost(
61
62
  trackType: TrackType,
62
63
  initConfiguration: InitConfiguration & { usePciIntake?: boolean }
63
64
  ) {
64
- const { site = INTAKE_SITE_US1, internalAnalyticsSubdomain } = initConfiguration
65
-
66
- if (trackType === 'logs' && initConfiguration.usePciIntake && site === INTAKE_SITE_US1) {
67
- return PCI_INTAKE_HOST_US1
68
- }
69
-
70
- if (internalAnalyticsSubdomain && site === INTAKE_SITE_US1) {
71
- return `${internalAnalyticsSubdomain}.${INTAKE_SITE_US1}`
72
- }
73
-
74
- if (site === INTAKE_SITE_FED_STAGING) {
75
- return `http-intake.logs.${site}`
76
- }
65
+ const { site = 'localhost' } = initConfiguration
77
66
 
78
- const domainParts = site.split('.')
79
- const extension = domainParts.pop()
80
- return `browser-intake-${domainParts.join('-')}.${extension!}`
67
+ // Use the site directly as the host
68
+ // If site includes a port, use it as-is
69
+ // If no port is specified, the default HTTPS port 443 will be used automatically
70
+ return site
81
71
  }
82
72
 
83
73
  /**
@@ -92,22 +82,22 @@ function buildEndpointParameters(
92
82
  extraParameters: string[] = []
93
83
  ) {
94
84
  const parameters = [
95
- `ddsource=${source}`,
96
- `dd-api-key=${clientToken}`,
97
- `dd-evp-origin-version=${encodeURIComponent(__BUILD_ENV__SDK_VERSION__)}`,
98
- 'dd-evp-origin=browser',
99
- `dd-request-id=${generateUUID()}`,
85
+ `mdsource=${source}`,
86
+ `md-api-key=${clientToken}`,
87
+ `md-evp-origin-version=${encodeURIComponent(__BUILD_ENV__SDK_VERSION__)}`,
88
+ 'md-evp-origin=browser',
89
+ `md-request-id=${generateUUID()}`,
100
90
  ].concat(extraParameters)
101
91
 
102
92
  if (encoding) {
103
- parameters.push(`dd-evp-encoding=${encoding}`)
93
+ parameters.push(`md-evp-encoding=${encoding}`)
104
94
  }
105
95
 
106
96
  if (trackType === 'rum') {
107
- parameters.push(`batch_time=${timeStampNow()}`, `_dd.api=${api}`)
97
+ parameters.push(`batch_time=${timeStampNow()}`, `_md.api=${api}`)
108
98
 
109
99
  if (retry) {
110
- parameters.push(`_dd.retry_count=${retry.count}`, `_dd.retry_after=${retry.lastFailureStatus}`)
100
+ parameters.push(`_md.retry_count=${retry.count}`, `_md.retry_after=${retry.lastFailureStatus}`)
111
101
  }
112
102
  }
113
103
 
@@ -1,5 +1,5 @@
1
1
  import type { Site } from '../intakeSites'
2
- import { INTAKE_SITE_US1, INTAKE_URL_PARAMETERS } from '../intakeSites'
2
+ import { INTAKE_URL_PARAMETERS } from '../intakeSites'
3
3
  import type { InitConfiguration } from './configuration'
4
4
  import type { EndpointBuilder } from './endpointBuilder'
5
5
  import { createEndpointBuilder } from './endpointBuilder'
@@ -22,7 +22,7 @@ export interface ReplicaConfiguration {
22
22
  }
23
23
 
24
24
  export function computeTransportConfiguration(initConfiguration: InitConfiguration): TransportConfiguration {
25
- const site = initConfiguration.site || INTAKE_SITE_US1
25
+ const site = initConfiguration.site || 'localhost'
26
26
  const source = validateSource(initConfiguration.source)
27
27
 
28
28
  const endpointBuilders = computeEndpointBuilders({ ...initConfiguration, site, source })
@@ -54,22 +54,10 @@ function computeEndpointBuilders(initConfiguration: InitConfiguration) {
54
54
  }
55
55
 
56
56
  function computeReplicaConfiguration(initConfiguration: InitConfiguration): ReplicaConfiguration | undefined {
57
- if (!initConfiguration.replica) {
58
- return
59
- }
60
-
61
- const replicaConfiguration: InitConfiguration = {
62
- ...initConfiguration,
63
- site: INTAKE_SITE_US1,
64
- clientToken: initConfiguration.replica.clientToken,
65
- }
66
-
67
- return {
68
- logsEndpointBuilder: createEndpointBuilder(replicaConfiguration, 'logs'),
69
- rumEndpointBuilder: createEndpointBuilder(replicaConfiguration, 'rum', [
70
- `application.id=${initConfiguration.replica.applicationId}`,
71
- ]),
72
- }
57
+ // Disable replica configuration for custom endpoints to avoid duplicate requests
58
+ // The replica feature was designed for Datadog's internal use and causes unwanted duplicates
59
+ // when using custom endpoints
60
+ return undefined
73
61
  }
74
62
 
75
63
  export function isIntakeUrl(url: string): boolean {
@@ -1,17 +1,2 @@
1
- export type Site =
2
- | 'datadoghq.com'
3
- | 'us3.datadoghq.com'
4
- | 'us5.datadoghq.com'
5
- | 'datadoghq.eu'
6
- | 'ddog-gov.com'
7
- | 'ap1.datadoghq.com'
8
- | 'ap2.datadoghq.com'
9
-
10
- export const INTAKE_SITE_STAGING: Site = 'datad0g.com' as Site
11
- export const INTAKE_SITE_FED_STAGING: Site = 'dd0g-gov.com' as Site
12
- export const INTAKE_SITE_US1: Site = 'datadoghq.com'
13
- export const INTAKE_SITE_EU1: Site = 'datadoghq.eu'
14
- export const INTAKE_SITE_US1_FED: Site = 'ddog-gov.com'
15
-
16
- export const PCI_INTAKE_HOST_US1 = 'pci.browser-intake-datadoghq.com'
17
- export const INTAKE_URL_PARAMETERS = ['ddsource', 'dd-api-key', 'dd-request-id']
1
+ export type Site = string
2
+ export const INTAKE_URL_PARAMETERS = ['mdsource', 'md-api-key', 'md-request-id']
@@ -4,7 +4,7 @@ import { SESSION_STORE_KEY } from './storeStrategies/sessionStoreStrategy'
4
4
  import type { SessionState } from './sessionState'
5
5
  import { expandSessionState, isSessionStarted } from './sessionState'
6
6
 
7
- export const OLD_SESSION_COOKIE_NAME = '_dd'
7
+ export const OLD_SESSION_COOKIE_NAME = '_md'
8
8
  export const OLD_RUM_COOKIE_NAME = '_dd_r'
9
9
  export const OLD_LOGS_COOKIE_NAME = '_dd_l'
10
10
 
@@ -14,12 +14,13 @@ import { getCurrentSite } from '../../browser/cookie'
14
14
  import { ExperimentalFeature, isExperimentalFeatureEnabled } from '../../tools/experimentalFeatures'
15
15
  import { findLast } from '../../tools/utils/polyfills'
16
16
  import { monitorError } from '../../tools/monitor'
17
- import { SESSION_NOT_TRACKED, SESSION_TIME_OUT_DELAY } from './sessionConstants'
17
+ import { SESSION_NOT_TRACKED, SESSION_TIME_OUT_DELAY, SessionPersistence } from './sessionConstants'
18
18
  import { startSessionStore } from './sessionStore'
19
19
  import type { SessionState } from './sessionState'
20
20
  import { toSessionState } from './sessionState'
21
21
  import { retrieveSessionCookie } from './storeStrategies/sessionInCookie'
22
22
  import { SESSION_STORE_KEY } from './storeStrategies/sessionStoreStrategy'
23
+ import { retrieveSessionFromLocalStorage } from './storeStrategies/sessionInLocalStorage'
23
24
 
24
25
  export interface SessionManager<TrackingType extends string> {
25
26
  findSession: (
@@ -38,6 +39,7 @@ export interface SessionContext<TrackingType extends string> extends Context {
38
39
  trackingType: TrackingType
39
40
  isReplayForced: boolean
40
41
  anonymousId: string | undefined
42
+ created: string | undefined
41
43
  }
42
44
 
43
45
  export const VISIBILITY_CHECK_DELAY = ONE_MINUTE
@@ -91,7 +93,7 @@ export function startSessionManager<TrackingType extends string>(
91
93
  if (trackingConsentState.isGranted()) {
92
94
  sessionStore.expandOrRenewSession()
93
95
  } else {
94
- sessionStore.expire()
96
+ sessionStore.expire(false)
95
97
  }
96
98
  })
97
99
 
@@ -107,13 +109,14 @@ export function startSessionManager<TrackingType extends string>(
107
109
  const session = sessionStore.getSession()
108
110
 
109
111
  if (!session) {
110
- reportUnexpectedSessionState().catch(() => void 0) // Ignore errors
112
+ reportUnexpectedSessionState(configuration).catch(() => void 0) // Ignore errors
111
113
 
112
114
  return {
113
115
  id: 'invalid',
114
116
  trackingType: SESSION_NOT_TRACKED as TrackingType,
115
117
  isReplayForced: false,
116
118
  anonymousId: undefined,
119
+ created: undefined,
117
120
  }
118
121
  }
119
122
 
@@ -122,6 +125,7 @@ export function startSessionManager<TrackingType extends string>(
122
125
  trackingType: session[productKey] as TrackingType,
123
126
  isReplayForced: !!session.forcedReplay,
124
127
  anonymousId: session.anonymousId,
128
+ created: session.created,
125
129
  }
126
130
  }
127
131
 
@@ -172,16 +176,33 @@ function trackResume(configuration: Configuration, cb: () => void) {
172
176
  stopCallbacks.push(stop)
173
177
  }
174
178
 
175
- async function reportUnexpectedSessionState() {
176
- const rawSession = retrieveSessionCookie()
179
+ async function reportUnexpectedSessionState(configuration: Configuration) {
180
+ const sessionStoreStrategyType = configuration.sessionStoreStrategyType
181
+ if (!sessionStoreStrategyType) {
182
+ return
183
+ }
184
+
185
+ let rawSession
186
+ let cookieContext
187
+
188
+ if (sessionStoreStrategyType.type === SessionPersistence.COOKIE) {
189
+ rawSession = retrieveSessionCookie(sessionStoreStrategyType.cookieOptions)
190
+
191
+ cookieContext = {
192
+ cookie: await getSessionCookies(),
193
+ currentDomain: `${window.location.protocol}//${window.location.hostname}`,
194
+ }
195
+ } else {
196
+ rawSession = retrieveSessionFromLocalStorage()
197
+ }
177
198
  // monitor-until: forever, could be handy to troubleshoot issues until session manager rework
178
199
  addTelemetryDebug('Unexpected session state', {
200
+ sessionStoreStrategyType: sessionStoreStrategyType.type,
179
201
  session: rawSession,
180
202
  isSyntheticsTest: isSyntheticsTest(),
181
203
  createdTimestamp: rawSession?.created,
182
204
  expireTimestamp: rawSession?.expire,
183
- cookie: await getSessionCookies(),
184
- currentDomain: `${window.location.protocol}//${window.location.hostname}`,
205
+ ...cookieContext,
185
206
  })
186
207
  }
187
208
 
@@ -1,7 +1,6 @@
1
1
  import { isEmptyObject } from '../../tools/utils/objectUtils'
2
2
  import { objectEntries } from '../../tools/utils/polyfills'
3
3
  import { dateNow } from '../../tools/utils/timeUtils'
4
- import { generateUUID } from '../../tools/utils/stringUtils'
5
4
  import type { Configuration } from '../configuration'
6
5
  import { SESSION_EXPIRATION_DELAY, SESSION_TIME_OUT_DELAY } from './sessionConstants'
7
6
  import { isValidSessionString, SESSION_ENTRY_REGEXP, SESSION_ENTRY_SEPARATOR } from './sessionStateValidation'
@@ -23,12 +22,8 @@ export function getExpiredSessionState(
23
22
  const expiredSessionState: SessionState = {
24
23
  isExpired: EXPIRED,
25
24
  }
26
- if (configuration.trackAnonymousUser) {
27
- if (previousSessionState?.anonymousId) {
28
- expiredSessionState.anonymousId = previousSessionState?.anonymousId
29
- } else {
30
- expiredSessionState.anonymousId = generateUUID()
31
- }
25
+ if (configuration.trackAnonymousUser && previousSessionState?.anonymousId) {
26
+ expiredSessionState.anonymousId = previousSessionState?.anonymousId
32
27
  }
33
28
  return expiredSessionState
34
29
  }
@@ -26,7 +26,7 @@ export interface SessionStore {
26
26
  renewObservable: Observable<void>
27
27
  expireObservable: Observable<void>
28
28
  sessionStateUpdateObservable: Observable<{ previousState: SessionState; newState: SessionState }>
29
- expire: () => void
29
+ expire: (hasConsent?: boolean) => void
30
30
  stop: () => void
31
31
  updateSessionState: (state: Partial<SessionState>) => void
32
32
  }
@@ -170,6 +170,7 @@ export function startSessionStore<TrackingType extends string>(
170
170
  {
171
171
  process: (sessionState) => {
172
172
  if (isSessionInNotStartedState(sessionState)) {
173
+ sessionState.anonymousId = generateUUID()
173
174
  return getExpiredSessionState(sessionState, configuration)
174
175
  }
175
176
  },
@@ -231,8 +232,11 @@ export function startSessionStore<TrackingType extends string>(
231
232
  expireObservable,
232
233
  sessionStateUpdateObservable,
233
234
  restartSession: startSession,
234
- expire: () => {
235
+ expire: (hasConsent?: boolean) => {
235
236
  cancelExpandOrRenewSession()
237
+ if (hasConsent === false && sessionCache) {
238
+ delete sessionCache.anonymousId
239
+ }
236
240
  sessionStoreStrategy.expireSession(sessionCache)
237
241
  synchronizeSession(getExpiredSessionState(sessionCache, configuration))
238
242
  },
@@ -1,6 +1,8 @@
1
+ import { isExperimentalFeatureEnabled, ExperimentalFeature } from '../../../tools/experimentalFeatures'
2
+ import { isEmptyObject } from '../../../tools/utils/objectUtils'
1
3
  import { isChromium } from '../../../tools/utils/browserDetection'
2
4
  import type { CookieOptions } from '../../../browser/cookie'
3
- import { getCurrentSite, areCookiesAuthorized, getCookie, setCookie } from '../../../browser/cookie'
5
+ import { getCurrentSite, areCookiesAuthorized, getCookies, setCookie, getCookie } from '../../../browser/cookie'
4
6
  import type { InitConfiguration, Configuration } from '../../configuration'
5
7
  import { tryOldCookiesMigration } from '../oldCookiesMigration'
6
8
  import {
@@ -14,6 +16,8 @@ import { toSessionString, toSessionState, getExpiredSessionState } from '../sess
14
16
  import type { SessionStoreStrategy, SessionStoreStrategyType } from './sessionStoreStrategy'
15
17
  import { SESSION_STORE_KEY } from './sessionStoreStrategy'
16
18
 
19
+ const SESSION_COOKIE_VERSION = 0
20
+
17
21
  export function selectCookieStrategy(initConfiguration: InitConfiguration): SessionStoreStrategyType | undefined {
18
22
  const cookieOptions = buildCookieOptions(initConfiguration)
19
23
  return cookieOptions && areCookiesAuthorized(cookieOptions)
@@ -30,7 +34,7 @@ export function initCookieStrategy(configuration: Configuration, cookieOptions:
30
34
  isLockEnabled: isChromium(),
31
35
  persistSession: (sessionState: SessionState) =>
32
36
  storeSessionCookie(cookieOptions, configuration, sessionState, SESSION_EXPIRATION_DELAY),
33
- retrieveSession: retrieveSessionCookie,
37
+ retrieveSession: () => retrieveSessionCookie(cookieOptions),
34
38
  expireSession: (sessionState: SessionState) =>
35
39
  storeSessionCookie(
36
40
  cookieOptions,
@@ -51,15 +55,34 @@ function storeSessionCookie(
51
55
  sessionState: SessionState,
52
56
  defaultTimeout: number
53
57
  ) {
58
+ let sessionStateString = toSessionString(sessionState)
59
+
60
+ if (isExperimentalFeatureEnabled(ExperimentalFeature.ENCODE_COOKIE_OPTIONS)) {
61
+ sessionStateString = toSessionString({
62
+ ...sessionState,
63
+ // deleting a cookie is writing a new cookie with an empty value
64
+ // we don't want to store the cookie options in this case otherwise the cookie will not be deleted
65
+ ...(!isEmptyObject(sessionState) ? { c: encodeCookieOptions(options) } : {}),
66
+ })
67
+ }
68
+
54
69
  setCookie(
55
70
  SESSION_STORE_KEY,
56
- toSessionString(sessionState),
71
+ sessionStateString,
57
72
  configuration.trackAnonymousUser ? SESSION_COOKIE_EXPIRATION_DELAY : defaultTimeout,
58
73
  options
59
74
  )
60
75
  }
61
76
 
62
- export function retrieveSessionCookie(): SessionState {
77
+ /**
78
+ * Retrieve the session state from the cookie that was set with the same cookie options
79
+ * If there is no match, return the first cookie, because that's how `getCookie()` works
80
+ */
81
+ export function retrieveSessionCookie(cookieOptions: CookieOptions): SessionState {
82
+ if (isExperimentalFeatureEnabled(ExperimentalFeature.ENCODE_COOKIE_OPTIONS)) {
83
+ return retrieveSessionCookieFromEncodedCookie(cookieOptions)
84
+ }
85
+
63
86
  const sessionString = getCookie(SESSION_STORE_KEY)
64
87
  const sessionState = toSessionState(sessionString)
65
88
  return sessionState
@@ -83,3 +106,42 @@ export function buildCookieOptions(initConfiguration: InitConfiguration): Cookie
83
106
 
84
107
  return cookieOptions
85
108
  }
109
+
110
+ function encodeCookieOptions(cookieOptions: CookieOptions): string {
111
+ const domainCount = cookieOptions.domain ? cookieOptions.domain.split('.').length - 1 : 0
112
+
113
+ /* eslint-disable no-bitwise */
114
+ let byte = 0
115
+ byte |= SESSION_COOKIE_VERSION << 5 // Store version in upper 3 bits
116
+ byte |= domainCount << 1 // Store domain count in next 4 bits
117
+ byte |= cookieOptions.crossSite ? 1 : 0 // Store useCrossSiteScripting in next bit
118
+ /* eslint-enable no-bitwise */
119
+
120
+ return byte.toString(16) // Convert to hex string
121
+ }
122
+
123
+ /**
124
+ * Retrieve the session state from the cookie that was set with the same cookie options.
125
+ * If there is no match, fallback to the first cookie, (because that's how `getCookie()` works)
126
+ * and this allows to keep the current session id when we release this feature.
127
+ */
128
+ function retrieveSessionCookieFromEncodedCookie(cookieOptions: CookieOptions): SessionState {
129
+ const cookies = getCookies(SESSION_STORE_KEY)
130
+ const opts = encodeCookieOptions(cookieOptions)
131
+
132
+ let sessionState: SessionState | undefined
133
+
134
+ // reverse the cookies so that if there is no match, the cookie returned is the first one
135
+ for (const cookie of cookies.reverse()) {
136
+ sessionState = toSessionState(cookie)
137
+
138
+ if (sessionState.c === opts) {
139
+ break
140
+ }
141
+ }
142
+
143
+ // remove the cookie options from the session state as this is not part of the session state
144
+ delete sessionState?.c
145
+
146
+ return sessionState ?? {}
147
+ }
@@ -34,7 +34,7 @@ function persistInLocalStorage(sessionState: SessionState) {
34
34
  localStorage.setItem(SESSION_STORE_KEY, toSessionString(sessionState))
35
35
  }
36
36
 
37
- function retrieveSessionFromLocalStorage(): SessionState {
37
+ export function retrieveSessionFromLocalStorage(): SessionState {
38
38
  const sessionString = localStorage.getItem(SESSION_STORE_KEY)
39
39
  return toSessionState(sessionString)
40
40
  }
@@ -2,7 +2,7 @@ import type { CookieOptions } from '../../../browser/cookie'
2
2
  import type { SessionPersistence } from '../sessionConstants'
3
3
  import type { SessionState } from '../sessionState'
4
4
 
5
- export const SESSION_STORE_KEY = '_dd_s'
5
+ export const SESSION_STORE_KEY = '_md_s'
6
6
 
7
7
  export type SessionStoreStrategyType =
8
8
  | { type: typeof SessionPersistence.COOKIE; cookieOptions: CookieOptions }