From ef69d2eba4be80ddc23d5a5563b7833c61498d54 Mon Sep 17 00:00:00 2001 From: Daniel Oyewole Date: Fri, 23 Jan 2026 12:46:52 +0000 Subject: [PATCH 01/20] Add GitHub Action to build and publish SDK to GitHub Packages --- .github/workflows/publish.yml | 59 +++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 .github/workflows/publish.yml diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 0000000000..f0eb16de0c --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,59 @@ +name: Build and Publish SDK + +on: + push: + branches: + - main + tags: + - 'v*' + workflow_dispatch: + +jobs: + build-and-publish: + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '25.3.0' + registry-url: 'https://npm.pkg.github.com' + scope: '@multiverse-io' + + - name: Install dependencies + run: yarn install --frozen-lockfile + + - name: Build RUM package + run: yarn build:bundle packages/rum + + - name: Build Logs package + run: yarn build:bundle packages/logs + + - name: Prepare package for publishing + run: | + cd packages/rum + # Update package name to scoped version + node -e "const pkg=require('./package.json'); pkg.name='@multiverse-io/browser-rum'; pkg.publishConfig={registry:'https://npm.pkg.github.com'}; require('fs').writeFileSync('package.json', JSON.stringify(pkg, null, 2));" + + - name: Publish to GitHub Packages + run: | + cd packages/rum + npm publish + env: + NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Create Release (on tag) + if: startsWith(github.ref, 'refs/tags/') + uses: softprops/action-gh-release@v1 + with: + files: | + packages/rum/bundle/**/* + generate_release_notes: true + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} From db9c46567c3d55d9dc33dd5ca40acba488f02494 Mon Sep 17 00:00:00 2001 From: Daniel Oyewole Date: Fri, 23 Jan 2026 13:40:45 +0000 Subject: [PATCH 02/20] Fix GitHub Packages authentication --- .github/workflows/publish.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index f0eb16de0c..1f7039c03f 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -39,12 +39,15 @@ jobs: run: | cd packages/rum # Update package name to scoped version - node -e "const pkg=require('./package.json'); pkg.name='@multiverse-io/browser-rum'; pkg.publishConfig={registry:'https://npm.pkg.github.com'}; require('fs').writeFileSync('package.json', JSON.stringify(pkg, null, 2));" + node -e "const pkg=require('./package.json'); pkg.name='@multiverse-io/browser-rum'; pkg.publishConfig={registry:'https://npm.pkg.github.com', access:'public'}; require('fs').writeFileSync('package.json', JSON.stringify(pkg, null, 2));" + # Create .npmrc for authentication + echo "@multiverse-io:registry=https://npm.pkg.github.com" > .npmrc + echo "//npm.pkg.github.com/:_authToken=\${NODE_AUTH_TOKEN}" >> .npmrc - name: Publish to GitHub Packages run: | cd packages/rum - npm publish + npm publish --access public env: NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }} From e8b91cd5bf3886771654ed5a11320e94844899da Mon Sep 17 00:00:00 2001 From: Daniel Oyewole Date: Fri, 23 Jan 2026 13:52:49 +0000 Subject: [PATCH 03/20] Use PACKAGES_TOKEN for GitHub Packages authentication --- .github/workflows/publish.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 1f7039c03f..8b02f5723d 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -49,7 +49,7 @@ jobs: cd packages/rum npm publish --access public env: - NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + NODE_AUTH_TOKEN: ${{ secrets.PACKAGES_TOKEN || secrets.GITHUB_TOKEN }} - name: Create Release (on tag) if: startsWith(github.ref, 'refs/tags/') From 3537d9851654fe137dd6118c3cb268ea91c3af15 Mon Sep 17 00:00:00 2001 From: Daniel Oyewole Date: Fri, 23 Jan 2026 14:04:10 +0000 Subject: [PATCH 04/20] Remove DataDog CLA workflow (not needed for fork) --- .github/workflows/cla.yml | 52 --------------------------------------- 1 file changed, 52 deletions(-) delete mode 100644 .github/workflows/cla.yml diff --git a/.github/workflows/cla.yml b/.github/workflows/cla.yml deleted file mode 100644 index 631dcd4e89..0000000000 --- a/.github/workflows/cla.yml +++ /dev/null @@ -1,52 +0,0 @@ -name: 'CLA Assistant' -on: - issue_comment: - types: [created] - pull_request_target: - types: [opened, closed, synchronize] - merge_group: - types: [checks_requested] - -permissions: - contents: read - pull-requests: write - id-token: write # Needed to federate tokens. - actions: write - -jobs: - CLAAssistant: - runs-on: ubuntu-latest - steps: - - name: CLA already verified on PR - if: github.event_name == 'merge_group' - run: echo "CLA verification not needed for merge queue - already checked on PR" - - - uses: DataDog/dd-octo-sts-action@acaa02eee7e3bb0839e4272dacb37b8f3b58ba80 # v1.0.3 - if: github.event_name != 'merge_group' - id: octo-sts - with: - scope: DataDog/cla-signatures - policy: self.write-signatures-browser-sdk - - - name: 'CLA Assistant' - if: github.event_name != 'merge_group' && ((github.event.comment.body == 'recheck' || github.event.comment.body == 'I have read the CLA Document and I hereby sign the CLA') || github.event_name == 'pull_request_target') - uses: contributor-assistant/github-action@ca4a40a7d1004f18d9960b404b97e5f30a505a08 # v2.6.1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - PERSONAL_ACCESS_TOKEN: ${{ steps.octo-sts.outputs.token }} - with: - path-to-signatures: 'browser-sdk.json' - path-to-document: 'https://gist.github.com/bits-bot/55bdc97a4fdad52d97feb4d6c3d1d618' # Datadog CLA Document - branch: 'browser-sdk' - remote-repository-name: cla-signatures - remote-organization-name: DataDog - allowlist: renovate,renovate[bot] - - # the followings are the optional inputs - If the optional inputs are not given, then default values will be taken - #allowlist: user1,bot* - #create-file-commit-message: 'For example: Creating file for storing CLA Signatures' - #signed-commit-message: 'For example: $contributorName has signed the CLA in $owner/$repo#$pullRequestNo' - #custom-notsigned-prcomment: 'pull request comment with Introductory message to ask new contributors to sign' - #custom-pr-sign-comment: 'The signature to be committed in order to sign the CLA' - #custom-allsigned-prcomment: 'pull request comment when all contributors has signed, defaults to **CLA Assistant Lite bot** All Contributors have signed the CLA.' - #lock-pullrequest-aftermerge: false - if you don't want this bot to automatically lock the pull request after merging (default - true) From 225ae9c183f5c39d6f21623dbb9094e0252fd8f5 Mon Sep 17 00:00:00 2001 From: Daniel Oyewole Date: Fri, 23 Jan 2026 14:17:38 +0000 Subject: [PATCH 05/20] Temporarily allow workflow to run on all branches for testing --- .github/workflows/publish.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 8b02f5723d..c77253c266 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -3,7 +3,7 @@ name: Build and Publish SDK on: push: branches: - - main + - '**' # Temporary: Run on all branches for testing tags: - 'v*' workflow_dispatch: From 110afd8aa041c11e93bb10e152bb3728937f28f5 Mon Sep 17 00:00:00 2001 From: Daniel Oyewole Date: Fri, 23 Jan 2026 14:20:03 +0000 Subject: [PATCH 06/20] Fix build command - use yarn build:bundle without arguments --- .github/workflows/publish.yml | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index c77253c266..327d66a0ab 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -29,13 +29,10 @@ jobs: - name: Install dependencies run: yarn install --frozen-lockfile - - name: Build RUM package - run: yarn build:bundle packages/rum + - name: Build all packages + run: yarn build:bundle - - name: Build Logs package - run: yarn build:bundle packages/logs - - - name: Prepare package for publishing + - name: Prepare RUM package for publishing run: | cd packages/rum # Update package name to scoped version From 0491098b98818c4c2aee69f180cdcd983c2c9f5a Mon Sep 17 00:00:00 2001 From: Daniel Oyewole Date: Fri, 23 Jan 2026 14:38:53 +0000 Subject: [PATCH 07/20] Fix: Create .npmrc in publish step where NODE_AUTH_TOKEN is available --- .github/workflows/publish.yml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 327d66a0ab..0b1c13c407 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -37,13 +37,15 @@ jobs: cd packages/rum # Update package name to scoped version node -e "const pkg=require('./package.json'); pkg.name='@multiverse-io/browser-rum'; pkg.publishConfig={registry:'https://npm.pkg.github.com', access:'public'}; require('fs').writeFileSync('package.json', JSON.stringify(pkg, null, 2));" - # Create .npmrc for authentication - echo "@multiverse-io:registry=https://npm.pkg.github.com" > .npmrc - echo "//npm.pkg.github.com/:_authToken=\${NODE_AUTH_TOKEN}" >> .npmrc + env: + NODE_AUTH_TOKEN: ${{ secrets.PACKAGES_TOKEN || secrets.GITHUB_TOKEN }} - name: Publish to GitHub Packages run: | cd packages/rum + # Create .npmrc with auth token + echo "@multiverse-io:registry=https://npm.pkg.github.com" > .npmrc + echo "//npm.pkg.github.com/:_authToken=${NODE_AUTH_TOKEN}" >> .npmrc npm publish --access public env: NODE_AUTH_TOKEN: ${{ secrets.PACKAGES_TOKEN || secrets.GITHUB_TOKEN }} From e60dceca19fe8d728ae4e5733e332b7f3ce188c6 Mon Sep 17 00:00:00 2001 From: Daniel Oyewole Date: Fri, 23 Jan 2026 17:24:12 +0000 Subject: [PATCH 08/20] corrected yml file to be in line with MV versions --- .github/workflows/publish.yml | 61 -------------- .github/workflows/release-package.yml | 109 ++++++++++++++++++++++++++ 2 files changed, 109 insertions(+), 61 deletions(-) delete mode 100644 .github/workflows/publish.yml create mode 100644 .github/workflows/release-package.yml diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml deleted file mode 100644 index 0b1c13c407..0000000000 --- a/.github/workflows/publish.yml +++ /dev/null @@ -1,61 +0,0 @@ -name: Build and Publish SDK - -on: - push: - branches: - - '**' # Temporary: Run on all branches for testing - tags: - - 'v*' - workflow_dispatch: - -jobs: - build-and-publish: - runs-on: ubuntu-latest - permissions: - contents: read - packages: write - - steps: - - name: Checkout code - uses: actions/checkout@v4 - - - name: Setup Node.js - uses: actions/setup-node@v4 - with: - node-version: '25.3.0' - registry-url: 'https://npm.pkg.github.com' - scope: '@multiverse-io' - - - name: Install dependencies - run: yarn install --frozen-lockfile - - - name: Build all packages - run: yarn build:bundle - - - name: Prepare RUM package for publishing - run: | - cd packages/rum - # Update package name to scoped version - node -e "const pkg=require('./package.json'); pkg.name='@multiverse-io/browser-rum'; pkg.publishConfig={registry:'https://npm.pkg.github.com', access:'public'}; require('fs').writeFileSync('package.json', JSON.stringify(pkg, null, 2));" - env: - NODE_AUTH_TOKEN: ${{ secrets.PACKAGES_TOKEN || secrets.GITHUB_TOKEN }} - - - name: Publish to GitHub Packages - run: | - cd packages/rum - # Create .npmrc with auth token - echo "@multiverse-io:registry=https://npm.pkg.github.com" > .npmrc - echo "//npm.pkg.github.com/:_authToken=${NODE_AUTH_TOKEN}" >> .npmrc - npm publish --access public - env: - NODE_AUTH_TOKEN: ${{ secrets.PACKAGES_TOKEN || secrets.GITHUB_TOKEN }} - - - name: Create Release (on tag) - if: startsWith(github.ref, 'refs/tags/') - uses: softprops/action-gh-release@v1 - with: - files: | - packages/rum/bundle/**/* - generate_release_notes: true - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/release-package.yml b/.github/workflows/release-package.yml new file mode 100644 index 0000000000..96fd612177 --- /dev/null +++ b/.github/workflows/release-package.yml @@ -0,0 +1,109 @@ +name: Release Github Package + +on: + push: + branches: + - main + tags: + - v* + # Note: paths filter intentionally omitted for push events. + # Adding paths would break tag-triggered releases since tag pushes + # don't have file changes to match against. + pull_request: + types: + - opened + - synchronize + paths: + - 'packages/**' + - '.github/workflows/release-package.yml' + workflow_dispatch: + +concurrency: ${{ github.workflow }}-${{ github.ref }} + +env: + GITHUB_READ_PACKAGES_TOKEN: ${{ secrets.GITHUB_TOKEN }} + +jobs: + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: '25.3.0' + - run: yarn install --frozen-lockfile + - run: yarn lint + + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: '25.3.0' + - run: yarn install --frozen-lockfile + - run: yarn test:unit + + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: '25.3.0' + - run: yarn install --frozen-lockfile + - run: yarn build:bundle + + publish: + needs: + - lint + - test + - build + if: github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v') + runs-on: ubuntu-latest + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + permissions: + packages: write + contents: write + pull-requests: write + steps: + - uses: actions/checkout@v4 + with: + # Fetch all history and tags for proper versioning + fetch-depth: 0 + + - uses: actions/setup-node@v4 + with: + node-version: '25.3.0' + registry-url: https://npm.pkg.github.com/ + scope: '@multiverse-io' + + - run: yarn install --frozen-lockfile + - run: yarn build:bundle + + - name: Prepare RUM package for publishing + run: | + cd packages/rum + # Update package name to scoped version + node -e "const pkg=require('./package.json'); pkg.name='@multiverse-io/browser-rum'; pkg.publishConfig={registry:'https://npm.pkg.github.com', access:'public'}; require('fs').writeFileSync('package.json', JSON.stringify(pkg, null, 2));" + + - name: Publish to GitHub Packages + run: | + cd packages/rum + # Create .npmrc with auth token + echo "@multiverse-io:registry=https://npm.pkg.github.com" > .npmrc + echo "//npm.pkg.github.com/:_authToken=$NODE_AUTH_TOKEN" >> .npmrc + npm publish --access public + env: + NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Create Release (on tag) + if: startsWith(github.ref, 'refs/tags/') + uses: softprops/action-gh-release@v1 + with: + files: | + packages/rum/bundle/**/* + generate_release_notes: true + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} From db731f9c79307b135af4a65dc897892a2c8dd670 Mon Sep 17 00:00:00 2001 From: Daniel Oyewole Date: Fri, 23 Jan 2026 17:42:12 +0000 Subject: [PATCH 09/20] chore: remove DataDog Confluence workflow --- .github/workflows/changelog-to-confluence.yml | 29 ------------------- 1 file changed, 29 deletions(-) delete mode 100644 .github/workflows/changelog-to-confluence.yml diff --git a/.github/workflows/changelog-to-confluence.yml b/.github/workflows/changelog-to-confluence.yml deleted file mode 100644 index 152734ddb6..0000000000 --- a/.github/workflows/changelog-to-confluence.yml +++ /dev/null @@ -1,29 +0,0 @@ -name: Publish Changelog to Confluence -permissions: - contents: read -on: - push: - tags: - - 'v*.*.*' # Matches version tags like v1.0.0, v6.7.0, etc. -jobs: - publish: - runs-on: ubuntu-latest - steps: - - name: Checkout code - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - - - name: Prepare Only Changelog - run: | - mkdir -p publish_folder - cp CHANGELOG.md publish_folder/browser-sdk-changelog.md - echo "Publishing only CHANGELOG.md" - - - name: Publish Markdown to Confluence - uses: markdown-confluence/publish-action@7767a0a7f438bb1497ee7ffd7d3d685b81dfe700 # v5 - with: - confluenceBaseUrl: ${{ secrets.DATADOG_CONFLUENCE_BASE_URL }} - confluenceParentId: ${{ secrets.CONFLUENCE_PARENT_ID }} - atlassianUserName: ${{ secrets.CONFLUENCE_ROBOT_RUM_EMAIL }} - atlassianApiToken: ${{ secrets.CONFLUENCE_ROBOT_RUM_API_KEY }} - contentRoot: '.' - folderToPublish: 'publish_folder' From 60712bcfbf8cb1531e444065415278ba8518c2a9 Mon Sep 17 00:00:00 2001 From: Daniel Oyewole Date: Fri, 23 Jan 2026 17:46:03 +0000 Subject: [PATCH 10/20] feat: add prettier check for PRs, run full lint/test only on main/tags --- .github/workflows/release-package.yml | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/.github/workflows/release-package.yml b/.github/workflows/release-package.yml index 96fd612177..b6eff8fd5e 100644 --- a/.github/workflows/release-package.yml +++ b/.github/workflows/release-package.yml @@ -24,7 +24,21 @@ env: GITHUB_READ_PACKAGES_TOKEN: ${{ secrets.GITHUB_TOKEN }} jobs: + # Quick formatting check on PRs + format: + if: github.event_name == 'pull_request' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: '25.3.0' + - run: yarn install --frozen-lockfile + - run: yarn format + + # Full lint on main/tags only (test apps have inherited lint errors) lint: + if: github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v') runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 @@ -35,6 +49,7 @@ jobs: - run: yarn lint test: + if: github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v') runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 @@ -45,6 +60,7 @@ jobs: - run: yarn test:unit build: + if: github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v') runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 From 3bff5a13467a69b2fab10aab8a80ba150c2a3fb2 Mon Sep 17 00:00:00 2001 From: Daniel Oyewole Date: Fri, 23 Jan 2026 17:54:06 +0000 Subject: [PATCH 11/20] formatting chages --- .github/workflows/release-package.yml | 10 +++++----- .../core/src/boot/displayAlreadyInitializedError.ts | 5 ++++- .../logs/src/domain/contexts/rumInternalContext.ts | 4 +++- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/.github/workflows/release-package.yml b/.github/workflows/release-package.yml index b6eff8fd5e..9c6f5887bd 100644 --- a/.github/workflows/release-package.yml +++ b/.github/workflows/release-package.yml @@ -88,22 +88,22 @@ jobs: with: # Fetch all history and tags for proper versioning fetch-depth: 0 - + - uses: actions/setup-node@v4 with: node-version: '25.3.0' registry-url: https://npm.pkg.github.com/ scope: '@multiverse-io' - + - run: yarn install --frozen-lockfile - run: yarn build:bundle - + - name: Prepare RUM package for publishing run: | cd packages/rum # Update package name to scoped version node -e "const pkg=require('./package.json'); pkg.name='@multiverse-io/browser-rum'; pkg.publishConfig={registry:'https://npm.pkg.github.com', access:'public'}; require('fs').writeFileSync('package.json', JSON.stringify(pkg, null, 2));" - + - name: Publish to GitHub Packages run: | cd packages/rum @@ -113,7 +113,7 @@ jobs: npm publish --access public env: NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - + - name: Create Release (on tag) if: startsWith(github.ref, 'refs/tags/') uses: softprops/action-gh-release@v1 diff --git a/packages/core/src/boot/displayAlreadyInitializedError.ts b/packages/core/src/boot/displayAlreadyInitializedError.ts index 936b403d88..1e70532878 100644 --- a/packages/core/src/boot/displayAlreadyInitializedError.ts +++ b/packages/core/src/boot/displayAlreadyInitializedError.ts @@ -1,7 +1,10 @@ import type { InitConfiguration } from '../domain/configuration' import { display } from '../tools/display' -export function displayAlreadyInitializedError(sdkName: 'ATLAS_SDK_DD_RUM' | 'ATLAS_SDK_DD_LOGS', initConfiguration: InitConfiguration) { +export function displayAlreadyInitializedError( + sdkName: 'ATLAS_SDK_DD_RUM' | 'ATLAS_SDK_DD_LOGS', + initConfiguration: InitConfiguration +) { if (!initConfiguration.silentMultipleInit) { display.error(`${sdkName} is already initialized.`) } diff --git a/packages/logs/src/domain/contexts/rumInternalContext.ts b/packages/logs/src/domain/contexts/rumInternalContext.ts index ac15607756..3d485cb9a2 100644 --- a/packages/logs/src/domain/contexts/rumInternalContext.ts +++ b/packages/logs/src/domain/contexts/rumInternalContext.ts @@ -39,7 +39,9 @@ export function startRUMInternalContext(hooks: Hooks) { function getRUMInternalContext(startTime?: RelativeTime) { const willSyntheticsInjectRumResult = willSyntheticsInjectRum() - const rumSource = willSyntheticsInjectRumResult ? browserWindow.MV_SDK_ATLAS_SDK_DD_RUM_SYNTHETICS : browserWindow.ATLAS_SDK_DD_RUM + const rumSource = willSyntheticsInjectRumResult + ? browserWindow.MV_SDK_ATLAS_SDK_DD_RUM_SYNTHETICS + : browserWindow.ATLAS_SDK_DD_RUM const rumContext = getInternalContextFromRumGlobal(startTime, rumSource) if (rumContext) { From 2841505010f78f6f2f481bc318e2ae68b735df97 Mon Sep 17 00:00:00 2001 From: Daniel Oyewole Date: Fri, 23 Jan 2026 17:56:14 +0000 Subject: [PATCH 12/20] format readme --- FORK_README.md | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/FORK_README.md b/FORK_README.md index 8eef586946..830da54644 100644 --- a/FORK_README.md +++ b/FORK_README.md @@ -16,13 +16,13 @@ The challenge: When multiple applications on the same page try to use the standa // Ariel's DataDog (standard SDK) window.DD_RUM.init({ applicationId: 'ariel-app-id', - service: 'ariel' + service: 'ariel', }) // Atlas tries to use DataDog too window.DD_RUM.init({ applicationId: 'atlas-app-id', - service: 'atlas' + service: 'atlas', }) // ❌ This overwrites Ariel's instance! // ❌ Session tracking gets mixed between the two @@ -37,13 +37,13 @@ This fork renames all DataDog globals to use the `ATLAS_SDK` prefix, allowing At // Ariel's DataDog (standard SDK) window.DD_RUM.init({ applicationId: 'ariel-app-id', - service: 'ariel' + service: 'ariel', }) // Atlas DataDog (this fork) window.ATLAS_SDK_DD_RUM.init({ applicationId: 'atlas-app-id', - service: 'atlas' + service: 'atlas', }) // ✅ Both instances coexist peacefully // ✅ Separate session tracking @@ -55,6 +55,7 @@ window.ATLAS_SDK_DD_RUM.init({ All DataDog globals and storage keys have been renamed with the `ATLAS_SDK` prefix: ### Globals + - `window.DD_RUM` → `window.ATLAS_SDK_DD_RUM` - `window.DD_LOGS` → `window.ATLAS_SDK_DD_LOGS` - `window.DD_RUM_SYNTHETICS` → `window.ATLAS_SDK_DD_RUM_SYNTHETICS` @@ -62,17 +63,18 @@ All DataDog globals and storage keys have been renamed with the `ATLAS_SDK` pref - `window.DatadogEventBridge` → `window.AtlasSDKDatadogEventBridge` ### Storage Keys + - `_dd_s` → `_atlas_sdk_s` (session cookie) - `_dd_c` → `_atlas_sdk_c` (context storage prefix) - `_dd_test_` → `_atlas_sdk_test_` (localStorage test) ### Product Keys + - `rum` → `atlas-sdk-rum` - `logs` → `atlas-sdk-logs` This ensures complete isolation between Atlas's DataDog instance and any other DataDog instances on the same page. - ## Known Limitations As documented in [DataDog/browser-sdk#2994](https://github.com/DataDog/browser-sdk/issues/2994), some features cannot be fully separated between multiple instances: @@ -90,11 +92,13 @@ You may need to add filtering in your `beforeSend` hooks to prevent cross-pollut **Must be built with Node.js v22+ (we used v25.3.0)** Check your Node version: + ```bash node --version # Should be v22.x or higher ``` If you need to switch Node versions: + ```bash nvm use 25.3.0 # or the version specified in package.json ``` @@ -127,7 +131,6 @@ yarn test git push origin main ``` - ### Automated Rename (if needed) The renames follow a consistent pattern. If you need to reapply them after a merge, you can use find/replace: @@ -138,7 +141,6 @@ The renames follow a consistent pattern. If you need to reapply them after a mer - `'_dd_c'` → `'_atlas_sdk_c'` - etc. - ## Links - **Upstream Repository:** https://github.com/DataDog/browser-sdk From b9c37c8382c49a4b19e0ebbbde14fd75a5431f15 Mon Sep 17 00:00:00 2001 From: Daniel Oyewole Date: Mon, 26 Jan 2026 11:02:00 +0000 Subject: [PATCH 13/20] update yml for better follow MV pattern --- .github/workflows/release-package.yml | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/.github/workflows/release-package.yml b/.github/workflows/release-package.yml index 9c6f5887bd..f74eb4b469 100644 --- a/.github/workflows/release-package.yml +++ b/.github/workflows/release-package.yml @@ -24,21 +24,7 @@ env: GITHUB_READ_PACKAGES_TOKEN: ${{ secrets.GITHUB_TOKEN }} jobs: - # Quick formatting check on PRs - format: - if: github.event_name == 'pull_request' - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: '25.3.0' - - run: yarn install --frozen-lockfile - - run: yarn format - - # Full lint on main/tags only (test apps have inherited lint errors) lint: - if: github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v') runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 @@ -46,10 +32,10 @@ jobs: with: node-version: '25.3.0' - run: yarn install --frozen-lockfile + - run: yarn format - run: yarn lint test: - if: github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v') runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 @@ -60,7 +46,6 @@ jobs: - run: yarn test:unit build: - if: github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v') runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 From 3e2e408ea32fc25190080637b147e95951bb0fad Mon Sep 17 00:00:00 2001 From: Daniel Oyewole Date: Mon, 26 Jan 2026 11:08:30 +0000 Subject: [PATCH 14/20] eslint file for DD linter errors --- .eslintignore | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 .eslintignore diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000000..23a865a03f --- /dev/null +++ b/.eslintignore @@ -0,0 +1,11 @@ +# Exclude DataDog's test applications (contain inherited lint errors) +test/apps/** + +# Node modules +node_modules/ + +# Build outputs +**/bundle/** +**/cjs/** +**/esm/** +**/dist/** From 6f7515e5fddfddf76de7527190662aee095e8f55 Mon Sep 17 00:00:00 2001 From: Daniel Oyewole Date: Mon, 26 Jan 2026 11:13:38 +0000 Subject: [PATCH 15/20] eslintignore is deprecated --- .eslintignore | 11 ----------- eslint.config.mjs | 3 +-- 2 files changed, 1 insertion(+), 13 deletions(-) delete mode 100644 .eslintignore diff --git a/.eslintignore b/.eslintignore deleted file mode 100644 index 23a865a03f..0000000000 --- a/.eslintignore +++ /dev/null @@ -1,11 +0,0 @@ -# Exclude DataDog's test applications (contain inherited lint errors) -test/apps/** - -# Node modules -node_modules/ - -# Build outputs -**/bundle/** -**/cjs/** -**/esm/** -**/dist/** diff --git a/eslint.config.mjs b/eslint.config.mjs index 600ddf8f45..02b3a016c7 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -25,8 +25,7 @@ export default tseslint.config( 'packages/*/cjs', 'packages/*/esm', 'test/**/dist', - 'test/apps/react-heavy-spa', - 'test/apps/react-shopist-like', + 'test/apps/**', // Exclude all DataDog test apps (have inherited lint errors) 'sandbox', 'coverage', 'rum-events-format', From c9c33dc44b155dffcfa77a4c90b29c5fc4f2d368 Mon Sep 17 00:00:00 2001 From: Daniel Oyewole Date: Mon, 26 Jan 2026 11:21:44 +0000 Subject: [PATCH 16/20] update tests to accoutn for renames --- .../displayAlreadyInitializedError.spec.ts | 2 +- .../src/domain/contexts/accountContext.spec.ts | 4 ++-- .../src/domain/contexts/globalContext.spec.ts | 4 ++-- .../src/domain/contexts/userContext.spec.ts | 4 ++-- .../domain/session/oldCookiesMigration.spec.ts | 14 +++++++------- .../storeStrategies/sessionInCookie.spec.ts | 6 +++--- .../logs/src/domain/logsSessionManager.spec.ts | 14 +++++++------- .../src/domain/rumSessionManager.spec.ts | 18 +++++++++--------- 8 files changed, 33 insertions(+), 33 deletions(-) diff --git a/packages/core/src/boot/displayAlreadyInitializedError.spec.ts b/packages/core/src/boot/displayAlreadyInitializedError.spec.ts index ff2e83c782..d401301214 100644 --- a/packages/core/src/boot/displayAlreadyInitializedError.spec.ts +++ b/packages/core/src/boot/displayAlreadyInitializedError.spec.ts @@ -7,7 +7,7 @@ describe('displayAlreadyInitializedError', () => { const displayErrorSpy = spyOn(display, 'error') displayAlreadyInitializedError('ATLAS_SDK_DD_RUM', {} as InitConfiguration) expect(displayErrorSpy).toHaveBeenCalledTimes(1) - expect(displayErrorSpy).toHaveBeenCalledWith('DD_RUM is already initialized.') + expect(displayErrorSpy).toHaveBeenCalledWith('ATLAS_SDK_DD_RUM is already initialized.') }) it('should not display an error if the "silentMultipleInit" option is used', () => { diff --git a/packages/core/src/domain/contexts/accountContext.spec.ts b/packages/core/src/domain/contexts/accountContext.spec.ts index 3628e224a9..613140e91b 100644 --- a/packages/core/src/domain/contexts/accountContext.spec.ts +++ b/packages/core/src/domain/contexts/accountContext.spec.ts @@ -82,7 +82,7 @@ describe('account context across pages', () => { accountContext.setContext({ id: '123' }) expect(accountContext.getContext()).toEqual({ id: '123' }) - expect(localStorage.getItem('_dd_c_rum_4')).toBeNull() + expect(localStorage.getItem('_atlas_sdk_c_rum_4')).toBeNull() }) it('when enabled, should maintain the account in local storage', () => { @@ -94,6 +94,6 @@ describe('account context across pages', () => { accountContext.setContext({ id: 'foo', qux: 'qix' }) expect(accountContext.getContext()).toEqual({ id: 'foo', qux: 'qix' }) - expect(localStorage.getItem('_dd_c_some_product_key_4')).toBe('{"id":"foo","qux":"qix"}') + expect(localStorage.getItem('_atlas_sdk_c_some_product_key_4')).toBe('{"id":"foo","qux":"qix"}') }) }) diff --git a/packages/core/src/domain/contexts/globalContext.spec.ts b/packages/core/src/domain/contexts/globalContext.spec.ts index 35d0604fe6..6c5344b97c 100644 --- a/packages/core/src/domain/contexts/globalContext.spec.ts +++ b/packages/core/src/domain/contexts/globalContext.spec.ts @@ -70,7 +70,7 @@ describe('global context across pages', () => { globalContext.setContext({ id: '123' }) expect(globalContext.getContext()).toEqual({ id: '123' }) - expect(localStorage.getItem('_dd_c_some_product_key_2')).toBeNull() + expect(localStorage.getItem('_atlas_sdk_c_some_product_key_2')).toBeNull() }) it('when enabled, should maintain the global context in local storage', () => { @@ -83,6 +83,6 @@ describe('global context across pages', () => { globalContext.setContext({ id: 'foo', qux: 'qix' }) expect(globalContext.getContext()).toEqual({ id: 'foo', qux: 'qix' }) - expect(localStorage.getItem('_dd_c_some_product_key_2')).toBe('{"id":"foo","qux":"qix"}') + expect(localStorage.getItem('_atlas_sdk_c_some_product_key_2')).toBe('{"id":"foo","qux":"qix"}') }) }) diff --git a/packages/core/src/domain/contexts/userContext.spec.ts b/packages/core/src/domain/contexts/userContext.spec.ts index dd382ded57..9ef8fec6d3 100644 --- a/packages/core/src/domain/contexts/userContext.spec.ts +++ b/packages/core/src/domain/contexts/userContext.spec.ts @@ -138,7 +138,7 @@ describe('user context across pages', () => { userContext.setContext({ id: '123' }) expect(userContext.getContext()).toEqual({ id: '123' }) - expect(localStorage.getItem('_dd_c_some_product_key_1')).toBeNull() + expect(localStorage.getItem('_atlas_sdk_c_some_product_key_1')).toBeNull() }) it('when enabled, should maintain the user in local storage', () => { @@ -151,6 +151,6 @@ describe('user context across pages', () => { userContext.setContext({ id: 'foo', qux: 'qix' }) expect(userContext.getContext()).toEqual({ id: 'foo', qux: 'qix' }) - expect(localStorage.getItem('_dd_c_some_product_key_1')).toBe('{"id":"foo","qux":"qix"}') + expect(localStorage.getItem('_atlas_sdk_c_some_product_key_1')).toBe('{"id":"foo","qux":"qix"}') }) }) diff --git a/packages/core/src/domain/session/oldCookiesMigration.spec.ts b/packages/core/src/domain/session/oldCookiesMigration.spec.ts index 1404733549..d7fc139aef 100644 --- a/packages/core/src/domain/session/oldCookiesMigration.spec.ts +++ b/packages/core/src/domain/session/oldCookiesMigration.spec.ts @@ -26,11 +26,11 @@ describe('old cookies migration', () => { }) it('should not touch current cookie', () => { - setCookie(SESSION_STORE_KEY, 'id=abcde&rum=0&logs=1&expire=1234567890', SESSION_EXPIRATION_DELAY) + setCookie(SESSION_STORE_KEY, 'id=abcde&atlas-sdk-rum=0&atlas-sdk-logs=1&expire=1234567890', SESSION_EXPIRATION_DELAY) tryOldCookiesMigration(sessionStoreStrategy) - expect(getCookie(SESSION_STORE_KEY)).toBe('id=abcde&rum=0&logs=1&expire=1234567890') + expect(getCookie(SESSION_STORE_KEY)).toBe('id=abcde&atlas-sdk-rum=0&atlas-sdk-logs=1&expire=1234567890') }) it('should create new cookie from old cookie values', () => { @@ -41,8 +41,8 @@ describe('old cookies migration', () => { tryOldCookiesMigration(sessionStoreStrategy) expect(getSessionState(SESSION_STORE_KEY).id).toBe('abcde') - expect(getSessionState(SESSION_STORE_KEY).rum).toBe('0') - expect(getSessionState(SESSION_STORE_KEY).logs).toBe('1') + expect(getSessionState(SESSION_STORE_KEY)['atlas-sdk-rum']).toBe('0') + expect(getSessionState(SESSION_STORE_KEY)['atlas-sdk-logs']).toBe('1') expect(getSessionState(SESSION_STORE_KEY).expire).toMatch(/\d+/) }) @@ -51,7 +51,7 @@ describe('old cookies migration', () => { tryOldCookiesMigration(sessionStoreStrategy) expect(getSessionState(SESSION_STORE_KEY).id).not.toBeDefined() - expect(getSessionState(SESSION_STORE_KEY).rum).toBe('0') + expect(getSessionState(SESSION_STORE_KEY)['atlas-sdk-rum']).toBe('0') expect(getSessionState(SESSION_STORE_KEY).expire).toMatch(/\d+/) }) @@ -69,8 +69,8 @@ describe('old cookies migration', () => { tryOldCookiesMigration(sessionStoreStrategy) expect(getSessionState(SESSION_STORE_KEY).id).toBe('abcde') - expect(getSessionState(SESSION_STORE_KEY).rum).toBe('0') - expect(getSessionState(SESSION_STORE_KEY).logs).toBe('1') + expect(getSessionState(SESSION_STORE_KEY)['atlas-sdk-rum']).toBe('0') + expect(getSessionState(SESSION_STORE_KEY)['atlas-sdk-logs']).toBe('1') expect(getSessionState(SESSION_STORE_KEY).expire).toMatch(/\d+/) }) }) diff --git a/packages/core/src/domain/session/storeStrategies/sessionInCookie.spec.ts b/packages/core/src/domain/session/storeStrategies/sessionInCookie.spec.ts index bd92ebd330..653738e0c7 100644 --- a/packages/core/src/domain/session/storeStrategies/sessionInCookie.spec.ts +++ b/packages/core/src/domain/session/storeStrategies/sessionInCookie.spec.ts @@ -131,7 +131,7 @@ describe('session in cookie strategy', () => { const calls = cookieSetSpy.calls.all() const lastCall = calls[calls.length - 1] - expect(lastCall.args[0]).toMatch(/^_dd_s=id=123&c=1/) + expect(lastCall.args[0]).toMatch(/^_atlas_sdk_s=id=123&c=1/) }) it('should not encode cookie options in the cookie value if the session is empty (deleting the cookie)', () => { @@ -142,14 +142,14 @@ describe('session in cookie strategy', () => { }) it('should return the correct session state from the cookies', () => { - spyOnProperty(document, 'cookie', 'get').and.returnValue('_dd_s=id=123&c=0;_dd_s=id=456&c=1;_dd_s=id=789&c=2') + spyOnProperty(document, 'cookie', 'get').and.returnValue('_atlas_sdk_s=id=123&c=0;_atlas_sdk_s=id=456&c=1;_atlas_sdk_s=id=789&c=2') const cookieStorageStrategy = setupCookieStrategy({ usePartitionedCrossSiteSessionCookie: true, ...config }) expect(cookieStorageStrategy.retrieveSession()).toEqual({ id: '456' }) }) it('should return the session state from the first cookie if there is no match', () => { - spyOnProperty(document, 'cookie', 'get').and.returnValue('_dd_s=id=123&c=0;_dd_s=id=789&c=2') + spyOnProperty(document, 'cookie', 'get').and.returnValue('_atlas_sdk_s=id=123&c=0;_atlas_sdk_s=id=789&c=2') const cookieStorageStrategy = setupCookieStrategy({ usePartitionedCrossSiteSessionCookie: true, ...config }) expect(cookieStorageStrategy.retrieveSession()).toEqual({ id: '123' }) diff --git a/packages/logs/src/domain/logsSessionManager.spec.ts b/packages/logs/src/domain/logsSessionManager.spec.ts index b0b03a76f0..3b192ec4f1 100644 --- a/packages/logs/src/domain/logsSessionManager.spec.ts +++ b/packages/logs/src/domain/logsSessionManager.spec.ts @@ -52,7 +52,7 @@ describe('logs session manager', () => { }) it('when tracked should keep existing tracking type and session id', () => { - setCookie(SESSION_STORE_KEY, 'id=abcdef&logs=1', DURATION) + setCookie(SESSION_STORE_KEY, 'id=abcdef&atlas-sdk-logs=1', DURATION) startLogsSessionManagerWithDefaults() @@ -61,7 +61,7 @@ describe('logs session manager', () => { }) it('when not tracked should keep existing tracking type', () => { - setCookie(SESSION_STORE_KEY, 'logs=0', DURATION) + setCookie(SESSION_STORE_KEY, 'atlas-sdk-logs=0', DURATION) startLogsSessionManagerWithDefaults() @@ -83,19 +83,19 @@ describe('logs session manager', () => { describe('findTrackedSession', () => { it('should return the current active session', () => { - setCookie(SESSION_STORE_KEY, 'id=abcdef&logs=1', DURATION) + setCookie(SESSION_STORE_KEY, 'id=abcdef&atlas-sdk-logs=1', DURATION) const logsSessionManager = startLogsSessionManagerWithDefaults() expect(logsSessionManager.findTrackedSession()!.id).toBe('abcdef') }) it('should return undefined if the session is not tracked', () => { - setCookie(SESSION_STORE_KEY, 'id=abcdef&logs=0', DURATION) + setCookie(SESSION_STORE_KEY, 'id=abcdef&atlas-sdk-logs=0', DURATION) const logsSessionManager = startLogsSessionManagerWithDefaults() expect(logsSessionManager.findTrackedSession()).toBeUndefined() }) it('should not return the current session if it has expired by default', () => { - setCookie(SESSION_STORE_KEY, 'id=abcdef&logs=1', DURATION) + setCookie(SESSION_STORE_KEY, 'id=abcdef&atlas-sdk-logs=1', DURATION) const logsSessionManager = startLogsSessionManagerWithDefaults() clock.tick(10 * ONE_SECOND) expireCookie() @@ -111,10 +111,10 @@ describe('logs session manager', () => { }) it('should return session corresponding to start time', () => { - setCookie(SESSION_STORE_KEY, 'id=foo&logs=1', DURATION) + setCookie(SESSION_STORE_KEY, 'id=foo&atlas-sdk-logs=1', DURATION) const logsSessionManager = startLogsSessionManagerWithDefaults() clock.tick(10 * ONE_SECOND) - setCookie(SESSION_STORE_KEY, 'id=bar&logs=1', DURATION) + setCookie(SESSION_STORE_KEY, 'id=bar&atlas-sdk-logs=1', DURATION) // simulate a click to renew the session document.dispatchEvent(createNewEvent(DOM_EVENT.CLICK)) clock.tick(STORAGE_POLL_DELAY) diff --git a/packages/rum-core/src/domain/rumSessionManager.spec.ts b/packages/rum-core/src/domain/rumSessionManager.spec.ts index 29f92fc158..922d93bd19 100644 --- a/packages/rum-core/src/domain/rumSessionManager.spec.ts +++ b/packages/rum-core/src/domain/rumSessionManager.spec.ts @@ -85,7 +85,7 @@ describe('rum session manager', () => { }) it('when tracked should keep existing session type and id', () => { - setCookie(SESSION_STORE_KEY, 'id=abcdef&rum=1', DURATION) + setCookie(SESSION_STORE_KEY, 'id=abcdef&atlas-sdk-rum=1', DURATION) startRumSessionManagerWithDefaults() @@ -96,7 +96,7 @@ describe('rum session manager', () => { }) it('when not tracked should keep existing session type', () => { - setCookie(SESSION_STORE_KEY, 'rum=0', DURATION) + setCookie(SESSION_STORE_KEY, 'atlas-sdk-rum=0', DURATION) startRumSessionManagerWithDefaults() @@ -106,7 +106,7 @@ describe('rum session manager', () => { }) it('should renew on activity after expiration', () => { - setCookie(SESSION_STORE_KEY, 'id=abcdef&rum=1', DURATION) + setCookie(SESSION_STORE_KEY, 'id=abcdef&atlas-sdk-rum=1', DURATION) startRumSessionManagerWithDefaults({ configuration: { sessionSampleRate: 100, sessionReplaySampleRate: 100 } }) @@ -127,13 +127,13 @@ describe('rum session manager', () => { describe('findSession', () => { it('should return the current session', () => { - setCookie(SESSION_STORE_KEY, 'id=abcdef&rum=1', DURATION) + setCookie(SESSION_STORE_KEY, 'id=abcdef&atlas-sdk-rum=1', DURATION) const rumSessionManager = startRumSessionManagerWithDefaults() expect(rumSessionManager.findTrackedSession()!.id).toBe('abcdef') }) it('should return undefined if the session is not tracked', () => { - setCookie(SESSION_STORE_KEY, 'id=abcdef&rum=0', DURATION) + setCookie(SESSION_STORE_KEY, 'id=abcdef&atlas-sdk-rum=0', DURATION) const rumSessionManager = startRumSessionManagerWithDefaults() expect(rumSessionManager.findTrackedSession()).toBe(undefined) }) @@ -146,7 +146,7 @@ describe('rum session manager', () => { }) it('should return session corresponding to start time', () => { - setCookie(SESSION_STORE_KEY, 'id=abcdef&rum=1', DURATION) + setCookie(SESSION_STORE_KEY, 'id=abcdef&atlas-sdk-rum=1', DURATION) const rumSessionManager = startRumSessionManagerWithDefaults() clock.tick(10 * ONE_SECOND) expireCookie() @@ -156,19 +156,19 @@ describe('rum session manager', () => { }) it('should return session TRACKED_WITH_SESSION_REPLAY', () => { - setCookie(SESSION_STORE_KEY, 'id=abcdef&rum=1', DURATION) + setCookie(SESSION_STORE_KEY, 'id=abcdef&atlas-sdk-rum=1', DURATION) const rumSessionManager = startRumSessionManagerWithDefaults() expect(rumSessionManager.findTrackedSession()!.sessionReplay).toBe(SessionReplayState.SAMPLED) }) it('should return session TRACKED_WITHOUT_SESSION_REPLAY', () => { - setCookie(SESSION_STORE_KEY, 'id=abcdef&rum=2', DURATION) + setCookie(SESSION_STORE_KEY, 'id=abcdef&atlas-sdk-rum=2', DURATION) const rumSessionManager = startRumSessionManagerWithDefaults() expect(rumSessionManager.findTrackedSession()!.sessionReplay).toBe(SessionReplayState.OFF) }) it('should update current entity when replay recording is forced', () => { - setCookie(SESSION_STORE_KEY, 'id=abcdef&rum=2', DURATION) + setCookie(SESSION_STORE_KEY, 'id=abcdef&atlas-sdk-rum=2', DURATION) const rumSessionManager = startRumSessionManagerWithDefaults() rumSessionManager.setForcedReplay() From f57b8928b5e5f59476676f4bf821aa08aba171da Mon Sep 17 00:00:00 2001 From: Daniel Oyewole Date: Mon, 26 Jan 2026 11:32:48 +0000 Subject: [PATCH 17/20] syntax and format --- .../domain/session/oldCookiesMigration.spec.ts | 18 +++++++++++------- .../src/domain/session/oldCookiesMigration.ts | 4 ++-- .../storeStrategies/sessionInCookie.spec.ts | 4 +++- .../logs/src/domain/logsSessionManager.spec.ts | 14 +++++++------- packages/logs/src/domain/logsSessionManager.ts | 2 +- .../src/domain/rumSessionManager.spec.ts | 18 +++++++++--------- .../rum-core/src/domain/rumSessionManager.ts | 2 +- 7 files changed, 34 insertions(+), 28 deletions(-) diff --git a/packages/core/src/domain/session/oldCookiesMigration.spec.ts b/packages/core/src/domain/session/oldCookiesMigration.spec.ts index d7fc139aef..985e6462ae 100644 --- a/packages/core/src/domain/session/oldCookiesMigration.spec.ts +++ b/packages/core/src/domain/session/oldCookiesMigration.spec.ts @@ -26,11 +26,15 @@ describe('old cookies migration', () => { }) it('should not touch current cookie', () => { - setCookie(SESSION_STORE_KEY, 'id=abcde&atlas-sdk-rum=0&atlas-sdk-logs=1&expire=1234567890', SESSION_EXPIRATION_DELAY) + setCookie( + SESSION_STORE_KEY, + 'id=abcde&atlas_sdk_rum=0&atlas_sdk_logs=1&expire=1234567890', + SESSION_EXPIRATION_DELAY + ) tryOldCookiesMigration(sessionStoreStrategy) - expect(getCookie(SESSION_STORE_KEY)).toBe('id=abcde&atlas-sdk-rum=0&atlas-sdk-logs=1&expire=1234567890') + expect(getCookie(SESSION_STORE_KEY)).toBe('id=abcde&atlas_sdk_rum=0&atlas_sdk_logs=1&expire=1234567890') }) it('should create new cookie from old cookie values', () => { @@ -41,8 +45,8 @@ describe('old cookies migration', () => { tryOldCookiesMigration(sessionStoreStrategy) expect(getSessionState(SESSION_STORE_KEY).id).toBe('abcde') - expect(getSessionState(SESSION_STORE_KEY)['atlas-sdk-rum']).toBe('0') - expect(getSessionState(SESSION_STORE_KEY)['atlas-sdk-logs']).toBe('1') + expect(getSessionState(SESSION_STORE_KEY)['atlas_sdk_rum']).toBe('0') + expect(getSessionState(SESSION_STORE_KEY)['atlas_sdk_logs']).toBe('1') expect(getSessionState(SESSION_STORE_KEY).expire).toMatch(/\d+/) }) @@ -51,7 +55,7 @@ describe('old cookies migration', () => { tryOldCookiesMigration(sessionStoreStrategy) expect(getSessionState(SESSION_STORE_KEY).id).not.toBeDefined() - expect(getSessionState(SESSION_STORE_KEY)['atlas-sdk-rum']).toBe('0') + expect(getSessionState(SESSION_STORE_KEY)['atlas_sdk_rum']).toBe('0') expect(getSessionState(SESSION_STORE_KEY).expire).toMatch(/\d+/) }) @@ -69,8 +73,8 @@ describe('old cookies migration', () => { tryOldCookiesMigration(sessionStoreStrategy) expect(getSessionState(SESSION_STORE_KEY).id).toBe('abcde') - expect(getSessionState(SESSION_STORE_KEY)['atlas-sdk-rum']).toBe('0') - expect(getSessionState(SESSION_STORE_KEY)['atlas-sdk-logs']).toBe('1') + expect(getSessionState(SESSION_STORE_KEY)['atlas_sdk_rum']).toBe('0') + expect(getSessionState(SESSION_STORE_KEY)['atlas_sdk_logs']).toBe('1') expect(getSessionState(SESSION_STORE_KEY).expire).toMatch(/\d+/) }) }) diff --git a/packages/core/src/domain/session/oldCookiesMigration.ts b/packages/core/src/domain/session/oldCookiesMigration.ts index a91afe7e6b..090c512e74 100644 --- a/packages/core/src/domain/session/oldCookiesMigration.ts +++ b/packages/core/src/domain/session/oldCookiesMigration.ts @@ -9,8 +9,8 @@ export const OLD_RUM_COOKIE_NAME = '_atlas_sdk_r' export const OLD_LOGS_COOKIE_NAME = '_atlas_sdk_l' // duplicate values to avoid dependency issues -export const RUM_SESSION_KEY = 'atlas-sdk-rum' -export const LOGS_SESSION_KEY = 'atlas-sdk-logs' +export const RUM_SESSION_KEY = 'atlas_sdk_rum' +export const LOGS_SESSION_KEY = 'atlas_sdk_logs' /** * This migration should remain in the codebase as long as older versions are available/live diff --git a/packages/core/src/domain/session/storeStrategies/sessionInCookie.spec.ts b/packages/core/src/domain/session/storeStrategies/sessionInCookie.spec.ts index 653738e0c7..d2f4412329 100644 --- a/packages/core/src/domain/session/storeStrategies/sessionInCookie.spec.ts +++ b/packages/core/src/domain/session/storeStrategies/sessionInCookie.spec.ts @@ -142,7 +142,9 @@ describe('session in cookie strategy', () => { }) it('should return the correct session state from the cookies', () => { - spyOnProperty(document, 'cookie', 'get').and.returnValue('_atlas_sdk_s=id=123&c=0;_atlas_sdk_s=id=456&c=1;_atlas_sdk_s=id=789&c=2') + spyOnProperty(document, 'cookie', 'get').and.returnValue( + '_atlas_sdk_s=id=123&c=0;_atlas_sdk_s=id=456&c=1;_atlas_sdk_s=id=789&c=2' + ) const cookieStorageStrategy = setupCookieStrategy({ usePartitionedCrossSiteSessionCookie: true, ...config }) expect(cookieStorageStrategy.retrieveSession()).toEqual({ id: '456' }) diff --git a/packages/logs/src/domain/logsSessionManager.spec.ts b/packages/logs/src/domain/logsSessionManager.spec.ts index 3b192ec4f1..ffbc4fe0e8 100644 --- a/packages/logs/src/domain/logsSessionManager.spec.ts +++ b/packages/logs/src/domain/logsSessionManager.spec.ts @@ -52,7 +52,7 @@ describe('logs session manager', () => { }) it('when tracked should keep existing tracking type and session id', () => { - setCookie(SESSION_STORE_KEY, 'id=abcdef&atlas-sdk-logs=1', DURATION) + setCookie(SESSION_STORE_KEY, 'id=abcdef&atlas_sdk_logs=1', DURATION) startLogsSessionManagerWithDefaults() @@ -61,7 +61,7 @@ describe('logs session manager', () => { }) it('when not tracked should keep existing tracking type', () => { - setCookie(SESSION_STORE_KEY, 'atlas-sdk-logs=0', DURATION) + setCookie(SESSION_STORE_KEY, 'atlas_sdk_logs=0', DURATION) startLogsSessionManagerWithDefaults() @@ -83,19 +83,19 @@ describe('logs session manager', () => { describe('findTrackedSession', () => { it('should return the current active session', () => { - setCookie(SESSION_STORE_KEY, 'id=abcdef&atlas-sdk-logs=1', DURATION) + setCookie(SESSION_STORE_KEY, 'id=abcdef&atlas_sdk_logs=1', DURATION) const logsSessionManager = startLogsSessionManagerWithDefaults() expect(logsSessionManager.findTrackedSession()!.id).toBe('abcdef') }) it('should return undefined if the session is not tracked', () => { - setCookie(SESSION_STORE_KEY, 'id=abcdef&atlas-sdk-logs=0', DURATION) + setCookie(SESSION_STORE_KEY, 'id=abcdef&atlas_sdk_logs=0', DURATION) const logsSessionManager = startLogsSessionManagerWithDefaults() expect(logsSessionManager.findTrackedSession()).toBeUndefined() }) it('should not return the current session if it has expired by default', () => { - setCookie(SESSION_STORE_KEY, 'id=abcdef&atlas-sdk-logs=1', DURATION) + setCookie(SESSION_STORE_KEY, 'id=abcdef&atlas_sdk_logs=1', DURATION) const logsSessionManager = startLogsSessionManagerWithDefaults() clock.tick(10 * ONE_SECOND) expireCookie() @@ -111,10 +111,10 @@ describe('logs session manager', () => { }) it('should return session corresponding to start time', () => { - setCookie(SESSION_STORE_KEY, 'id=foo&atlas-sdk-logs=1', DURATION) + setCookie(SESSION_STORE_KEY, 'id=foo&atlas_sdk_logs=1', DURATION) const logsSessionManager = startLogsSessionManagerWithDefaults() clock.tick(10 * ONE_SECOND) - setCookie(SESSION_STORE_KEY, 'id=bar&atlas-sdk-logs=1', DURATION) + setCookie(SESSION_STORE_KEY, 'id=bar&atlas_sdk_logs=1', DURATION) // simulate a click to renew the session document.dispatchEvent(createNewEvent(DOM_EVENT.CLICK)) clock.tick(STORAGE_POLL_DELAY) diff --git a/packages/logs/src/domain/logsSessionManager.ts b/packages/logs/src/domain/logsSessionManager.ts index cbaba60d51..b0f70a1508 100644 --- a/packages/logs/src/domain/logsSessionManager.ts +++ b/packages/logs/src/domain/logsSessionManager.ts @@ -2,7 +2,7 @@ import type { RelativeTime, TrackingConsentState } from '@datadog/browser-core' import { Observable, performDraw, SESSION_NOT_TRACKED, startSessionManager } from '@datadog/browser-core' import type { LogsConfiguration } from './configuration' -export const LOGS_SESSION_KEY = 'atlas-sdk-logs' +export const LOGS_SESSION_KEY = 'atlas_sdk_logs' export interface LogsSessionManager { findTrackedSession: (startTime?: RelativeTime, options?: { returnInactive: boolean }) => LogsSession | undefined diff --git a/packages/rum-core/src/domain/rumSessionManager.spec.ts b/packages/rum-core/src/domain/rumSessionManager.spec.ts index 922d93bd19..24774b2eea 100644 --- a/packages/rum-core/src/domain/rumSessionManager.spec.ts +++ b/packages/rum-core/src/domain/rumSessionManager.spec.ts @@ -85,7 +85,7 @@ describe('rum session manager', () => { }) it('when tracked should keep existing session type and id', () => { - setCookie(SESSION_STORE_KEY, 'id=abcdef&atlas-sdk-rum=1', DURATION) + setCookie(SESSION_STORE_KEY, 'id=abcdef&atlas_sdk_rum=1', DURATION) startRumSessionManagerWithDefaults() @@ -96,7 +96,7 @@ describe('rum session manager', () => { }) it('when not tracked should keep existing session type', () => { - setCookie(SESSION_STORE_KEY, 'atlas-sdk-rum=0', DURATION) + setCookie(SESSION_STORE_KEY, 'atlas_sdk_rum=0', DURATION) startRumSessionManagerWithDefaults() @@ -106,7 +106,7 @@ describe('rum session manager', () => { }) it('should renew on activity after expiration', () => { - setCookie(SESSION_STORE_KEY, 'id=abcdef&atlas-sdk-rum=1', DURATION) + setCookie(SESSION_STORE_KEY, 'id=abcdef&atlas_sdk_rum=1', DURATION) startRumSessionManagerWithDefaults({ configuration: { sessionSampleRate: 100, sessionReplaySampleRate: 100 } }) @@ -127,13 +127,13 @@ describe('rum session manager', () => { describe('findSession', () => { it('should return the current session', () => { - setCookie(SESSION_STORE_KEY, 'id=abcdef&atlas-sdk-rum=1', DURATION) + setCookie(SESSION_STORE_KEY, 'id=abcdef&atlas_sdk_rum=1', DURATION) const rumSessionManager = startRumSessionManagerWithDefaults() expect(rumSessionManager.findTrackedSession()!.id).toBe('abcdef') }) it('should return undefined if the session is not tracked', () => { - setCookie(SESSION_STORE_KEY, 'id=abcdef&atlas-sdk-rum=0', DURATION) + setCookie(SESSION_STORE_KEY, 'id=abcdef&atlas_sdk_rum=0', DURATION) const rumSessionManager = startRumSessionManagerWithDefaults() expect(rumSessionManager.findTrackedSession()).toBe(undefined) }) @@ -146,7 +146,7 @@ describe('rum session manager', () => { }) it('should return session corresponding to start time', () => { - setCookie(SESSION_STORE_KEY, 'id=abcdef&atlas-sdk-rum=1', DURATION) + setCookie(SESSION_STORE_KEY, 'id=abcdef&atlas_sdk_rum=1', DURATION) const rumSessionManager = startRumSessionManagerWithDefaults() clock.tick(10 * ONE_SECOND) expireCookie() @@ -156,19 +156,19 @@ describe('rum session manager', () => { }) it('should return session TRACKED_WITH_SESSION_REPLAY', () => { - setCookie(SESSION_STORE_KEY, 'id=abcdef&atlas-sdk-rum=1', DURATION) + setCookie(SESSION_STORE_KEY, 'id=abcdef&atlas_sdk_rum=1', DURATION) const rumSessionManager = startRumSessionManagerWithDefaults() expect(rumSessionManager.findTrackedSession()!.sessionReplay).toBe(SessionReplayState.SAMPLED) }) it('should return session TRACKED_WITHOUT_SESSION_REPLAY', () => { - setCookie(SESSION_STORE_KEY, 'id=abcdef&atlas-sdk-rum=2', DURATION) + setCookie(SESSION_STORE_KEY, 'id=abcdef&atlas_sdk_rum=2', DURATION) const rumSessionManager = startRumSessionManagerWithDefaults() expect(rumSessionManager.findTrackedSession()!.sessionReplay).toBe(SessionReplayState.OFF) }) it('should update current entity when replay recording is forced', () => { - setCookie(SESSION_STORE_KEY, 'id=abcdef&atlas-sdk-rum=2', DURATION) + setCookie(SESSION_STORE_KEY, 'id=abcdef&atlas_sdk_rum=2', DURATION) const rumSessionManager = startRumSessionManagerWithDefaults() rumSessionManager.setForcedReplay() diff --git a/packages/rum-core/src/domain/rumSessionManager.ts b/packages/rum-core/src/domain/rumSessionManager.ts index 33232d0a32..27480dcadd 100644 --- a/packages/rum-core/src/domain/rumSessionManager.ts +++ b/packages/rum-core/src/domain/rumSessionManager.ts @@ -18,7 +18,7 @@ export const enum SessionType { CI_TEST = 'ci_test', } -export const RUM_SESSION_KEY = 'atlas-sdk-rum' +export const RUM_SESSION_KEY = 'atlas_sdk_rum' export interface RumSessionManager { findTrackedSession: (startTime?: RelativeTime) => RumSession | undefined From 4bd58834a10d8cbd283b5c276a4d6fbf367d03e7 Mon Sep 17 00:00:00 2001 From: Daniel Oyewole Date: Mon, 26 Jan 2026 11:46:01 +0000 Subject: [PATCH 18/20] refactor: update old cookie names for session management --- packages/core/src/domain/session/oldCookiesMigration.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/core/src/domain/session/oldCookiesMigration.ts b/packages/core/src/domain/session/oldCookiesMigration.ts index 090c512e74..8525c6e9d8 100644 --- a/packages/core/src/domain/session/oldCookiesMigration.ts +++ b/packages/core/src/domain/session/oldCookiesMigration.ts @@ -4,9 +4,9 @@ import { SESSION_STORE_KEY } from './storeStrategies/sessionStoreStrategy' import type { SessionState } from './sessionState' import { expandSessionState, isSessionStarted } from './sessionState' -export const OLD_SESSION_COOKIE_NAME = '_atlas_sdk' -export const OLD_RUM_COOKIE_NAME = '_atlas_sdk_r' -export const OLD_LOGS_COOKIE_NAME = '_atlas_sdk_l' +export const OLD_SESSION_COOKIE_NAME = '_dd' +export const OLD_RUM_COOKIE_NAME = '_dd_r' +export const OLD_LOGS_COOKIE_NAME = '_dd_l' // duplicate values to avoid dependency issues export const RUM_SESSION_KEY = 'atlas_sdk_rum' From 33c1f46c7982b86e9a3f6f9f5eeb448339434d18 Mon Sep 17 00:00:00 2001 From: Daniel Oyewole Date: Mon, 26 Jan 2026 13:11:27 +0000 Subject: [PATCH 19/20] update the regex to allow underscores in the key for the name changes --- packages/core/src/domain/session/sessionStateValidation.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/src/domain/session/sessionStateValidation.ts b/packages/core/src/domain/session/sessionStateValidation.ts index 08573cb336..2828049df4 100644 --- a/packages/core/src/domain/session/sessionStateValidation.ts +++ b/packages/core/src/domain/session/sessionStateValidation.ts @@ -1,4 +1,4 @@ -export const SESSION_ENTRY_REGEXP = /^([a-zA-Z]+)=([a-z0-9-]+)$/ +export const SESSION_ENTRY_REGEXP = /^([a-zA-Z_]+)=([a-z0-9-]+)$/ export const SESSION_ENTRY_SEPARATOR = '&' export function isValidSessionString(sessionString: string | undefined | null): sessionString is string { From ed75a7bdad631f0449f1895ac05540c6684e6682 Mon Sep 17 00:00:00 2001 From: Daniel Oyewole Date: Mon, 26 Jan 2026 13:17:21 +0000 Subject: [PATCH 20/20] more ranmes! --- packages/logs/src/boot/startLogs.spec.ts | 6 +++--- packages/logs/src/domain/assembly.spec.ts | 10 +++++----- .../src/domain/contexts/rumInternalContext.spec.ts | 8 ++++---- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/packages/logs/src/boot/startLogs.spec.ts b/packages/logs/src/boot/startLogs.spec.ts index 781fdbc73a..f367ddc6b8 100644 --- a/packages/logs/src/boot/startLogs.spec.ts +++ b/packages/logs/src/boot/startLogs.spec.ts @@ -41,7 +41,7 @@ interface Rum { } declare global { interface Window { - DD_RUM?: Rum + ATLAS_SDK_DD_RUM?: Rum MV_SDK_ATLAS_SDK_DD_RUM_SYNTHETICS?: Rum } } @@ -87,7 +87,7 @@ describe('logs', () => { }) afterEach(() => { - delete window.DD_RUM + delete window.ATLAS_SDK_DD_RUM stopSessionManager() }) @@ -287,7 +287,7 @@ describe('logs', () => { it('RUM context should take precedence over global context', () => { const { handleLog, logger, globalContext } = startLogsWithDefaults() - window.DD_RUM = { + window.ATLAS_SDK_DD_RUM = { getInternalContext: () => ({ view: { url: 'from-rum-context' } }), } globalContext.setContext({ view: { url: 'from-global-context' } }) diff --git a/packages/logs/src/domain/assembly.spec.ts b/packages/logs/src/domain/assembly.spec.ts index 760e98ddf4..5769c260f2 100644 --- a/packages/logs/src/domain/assembly.spec.ts +++ b/packages/logs/src/domain/assembly.spec.ts @@ -48,13 +48,13 @@ describe('startLogsAssembly', () => { hooks = createHooks() startRUMInternalContext(hooks) startLogsAssembly(configuration, lifeCycle, hooks, () => COMMON_CONTEXT, noop) - window.DD_RUM = { + window.ATLAS_SDK_DD_RUM = { getInternalContext: noop, } }) afterEach(() => { - delete window.DD_RUM + delete window.ATLAS_SDK_DD_RUM serverLogs = [] }) @@ -84,7 +84,7 @@ describe('startLogsAssembly', () => { describe('contexts inclusion', () => { it('should include message context', () => { - spyOn(window.DD_RUM!, 'getInternalContext').and.returnValue({ + spyOn(window.ATLAS_SDK_DD_RUM!, 'getInternalContext').and.returnValue({ view: { url: 'http://from-rum-context.com', id: 'view-id' }, }) @@ -133,7 +133,7 @@ describe('startLogsAssembly', () => { }) it('should include rum internal context related to the error time', () => { - window.DD_RUM = { + window.ATLAS_SDK_DD_RUM = { getInternalContext(startTime) { return { foo: startTime === 1234 ? 'b' : 'a' } }, @@ -147,7 +147,7 @@ describe('startLogsAssembly', () => { }) it('should include RUM context', () => { - window.DD_RUM = { + window.ATLAS_SDK_DD_RUM = { getInternalContext() { return { view: { url: 'http://from-rum-context.com', id: 'view-id' } } }, diff --git a/packages/logs/src/domain/contexts/rumInternalContext.spec.ts b/packages/logs/src/domain/contexts/rumInternalContext.spec.ts index 4f35b8ad00..fed73c423d 100644 --- a/packages/logs/src/domain/contexts/rumInternalContext.spec.ts +++ b/packages/logs/src/domain/contexts/rumInternalContext.spec.ts @@ -28,7 +28,7 @@ describe('startRUMInternalContext', () => { }) it('returns undefined if the global variable does not have a `getInternalContext` method', () => { - window.DD_RUM = {} as any + window.ATLAS_SDK_DD_RUM = {} as any const defaultLogsEventAttributes = hooks.triggerHook(HookNames.Assemble, { startTime: 0 as RelativeTime, }) @@ -36,7 +36,7 @@ describe('startRUMInternalContext', () => { }) it('returns the internal context from the `getInternalContext` method', () => { - window.DD_RUM = { + window.ATLAS_SDK_DD_RUM = { getInternalContext: () => ({ foo: 'bar' }), } const defaultLogsEventAttributes = hooks.triggerHook(HookNames.Assemble, { @@ -64,7 +64,7 @@ describe('startRUMInternalContext', () => { describe('assemble telemetry hook', () => { it('should set internal context', () => { - window.DD_RUM = { + window.ATLAS_SDK_DD_RUM = { getInternalContext: () => ({ application_id: '123', view: { id: '456' }, user_action: { id: '789' } }), } const defaultRumEventAttributes = hooks.triggerHook(HookNames.AssembleTelemetry, { @@ -79,7 +79,7 @@ describe('startRUMInternalContext', () => { }) it('should not set internal context if the RUM instance is not present', () => { - window.DD_RUM = { + window.ATLAS_SDK_DD_RUM = { getInternalContext: () => undefined, } const defaultRumEventAttributes = hooks.triggerHook(HookNames.AssembleTelemetry, {