Skip to content

🐛 [devext] support v7 session cookie and expose anonymous ID / account context - #4960

Open
mormubis wants to merge 7 commits into
mainfrom
adlrb/devext-v7-cookie
Open

🐛 [devext] support v7 session cookie and expose anonymous ID / account context#4960
mormubis wants to merge 7 commits into
mainfrom
adlrb/devext-v7-cookie

Conversation

@mormubis

@mormubis mormubis commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

Motivation

SDK v7 renamed the session cookie from _dd_s to _dd_s_v2, so the extension was showing empty session data for any v7 app. v7 also added an aid (anonymous ID) field in the cookie and a getAccount() API that the extension wasn't exposing. Jira: RUM-17172.

Changes

In useSdkInfos.ts, cookie reading no longer tries to detect which SDK major is running. The version string can't do that reliably: local dev builds always report version: "dev" regardless of which major is checked out, so a v6 dev build and a v7 dev build look identical. Instead, it reads both _dd_s and _dd_s_v2, and keeps whichever holds the more recently created valid session, since only an actively running SDK writes fresh data under its own cookie name.

Both cookie names can also have duplicates under the same name (e.g. after changing trackSessionAcrossSubdomains or usePartitionedCrossSiteSessionCookie, or with v6's betaEncodeCookieOptions). The SDK picks the right one by matching a c marker encoded in the cookie value against its current config. findMatchingCookieValue() replicates that matching for both cookie names, so the extension doesn't just grab the first duplicate.

The aid cookie field is mapped to anonymousId for readability. Added getAccount() calls for both RUM and Logs.

In infosTab.tsx, anonymous ID shows under the cookie section, account under RUM and Logs. endSession() also expires _dd_s_v2, but only if it already exists — unconditionally writing it on a v6 page would create a phantom cookie that shadows the real v6 session on next load.

Test instructions

  1. yarn dev, open http://localhost:8080, open the Infos tab. Session data should show, including the anonymous ID.
  2. DD_RUM.setAccount({ id: 'test' }) in the console. Account should appear under RUM.
  3. Click "End current session". _dd_s_v2 should be expired in Application → Cookies, and reloading starts a new session.
  4. In the console, manually write a fresh _dd_s (e.g. document.cookie = '_dd_s=id=v6&created=' + Date.now() + '&expire=9999999999999; path=/') while a stale _dd_s_v2 is still present. The Infos tab should now read from _dd_s, since it holds the more recently created session.
  5. Set two _dd_s_v2 cookies with different c values by hand (or reuse ones left over from changing trackSessionAcrossSubdomains between reloads) and confirm the extension shows the one matching the SDK's current config, not just the first one found.

Checklist

  • Tested locally
  • Tested on staging
  • Added unit tests for this change.
  • Added e2e/integration tests for this change.
  • Updated documentation and/or relevant AGENTS.md file

Comment thread developer-extension/src/panel/hooks/useSdkInfos.ts Outdated
@datadog-prod-us1-3

datadog-prod-us1-3 Bot commented Aug 18, 2026

Copy link
Copy Markdown

Tests

🎉 All green!

🧪 All tests passed
❄️ No new flaky tests detected

🎯 Code Coverage (details)
Patch Coverage: 100.00%
Overall Coverage: 77.22% (+0.00%)

This comment will be updated automatically if new data arrives.
🔗 Commit SHA: 248ec33 | Docs | View more details | Give us feedback!

@mormubis
mormubis force-pushed the adlrb/devext-v7-cookie branch from 5eb1c53 to 8af253c Compare August 18, 2026 10:46
@cit-pr-commenter-54b7da

Copy link
Copy Markdown

Bundles Sizes Evolution

📦 Bundle Name Base Size Local Size 𝚫 𝚫% Status
Rum 181.27 KiB 181.27 KiB 0 B 0.00%
Rum Profiler 8.43 KiB 8.43 KiB 0 B 0.00%
Rum Recorder 21.12 KiB 21.12 KiB 0 B 0.00%
Logs 57.50 KiB 57.50 KiB 0 B 0.00%
Rum Salesforce N/A 139.22 KiB N/A N/A N/A
Rum Slim 139.21 KiB 139.21 KiB 0 B 0.00%
Worker 22.96 KiB 22.96 KiB 0 B 0.00%
Rum Shopify N/A 200.99 KiB N/A N/A N/A
Rum-shopify Profiler N/A 8.43 KiB N/A N/A N/A
Rum-shopify Recorder N/A 3.72 KiB N/A N/A N/A

@mormubis
mormubis marked this pull request as ready for review August 19, 2026 09:54
@mormubis
mormubis requested a review from a team as a code owner August 19, 2026 09:54
@mormubis
mormubis marked this pull request as draft August 19, 2026 09:54

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 8af253ce64

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +89 to +90
.find(([cookieName]) => cookieName === name)
?.[1]

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Match the active v7 cookie by its configuration marker

issue: When multiple _dd_s_v2 cookies are visible, such as after changing trackSessionAcrossSubdomains or partitioned-cookie settings, this returns the first value regardless of its c marker. The v7 SDK deliberately selects the cookie whose marker matches its current cookie options in sessionInCookie.ts, so the extension can display and link to a stale or unrelated session instead of the one the SDK is using.

Useful? React with 👍 / 👎.

Comment thread developer-extension/src/panel/components/tabs/infosTab.tsx
Comment thread developer-extension/src/panel/hooks/useSdkInfos.ts
The SDK version string cannot identify which cookie name is active: local
dev builds always report 'dev' regardless of which major is checked out, so
a v6 and a v7 dev build are indistinguishable. Read both names and keep
whichever holds the more recently created valid session instead.

Also apply c marker matching to _dd_s, not just _dd_s_v2, since v6 with
betaEncodeCookieOptions could also write duplicates under that name.
@mormubis
mormubis marked this pull request as ready for review September 4, 2026 14:07
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 4, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-04T14:12:08.882001Z 248ec33 Draft marked ready
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 248ec3378f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +96 to +99
const domain = config?.domain
const crossSite = config?.usePartitionedCrossSiteSessionCookie ? 1 : 0
const domainCount = domain ? domain.split('.').length - 1 : 0
const expectedC = ((domainCount << 1) | crossSite).toString(16)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Derive the marker from the actual cookie domain

issue: When trackSessionAcrossSubdomains is enabled, getInitConfiguration() exposes that boolean but no computed domain property; the SDK derives the domain internally with getCurrentSite(). Consequently domainCount remains zero here, the expected c marker does not match the active cross-subdomain cookie, and the fallback can display a stale duplicate. Fresh evidence in this revision is the new marker-matching implementation's direct read of the nonexistent config.domain value.

Useful? React with 👍 / 👎.

Comment on lines +129 to +132
const cookieRawValue =
v2Session && v6Session
? (Number(v2Session.created) >= Number(v6Session.created) ? v2RawValue : v6RawValue)
: (v2RawValue ?? v6RawValue)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Select the cookie whose parsed session is valid

issue: When _dd_s_v2 contains an expiration tombstone such as isExpired=1 while a v6 SDK has an active _dd_s cookie, v2Session is correctly parsed as invalid but this fallback still selects v2RawValue merely because it is defined. The Infos tab then loses the active v6 session ID and links; choose between the validated sessions rather than the raw values.

Useful? React with 👍 / 👎.

`
document.cookie = '_dd_s=isExpired=1; expires=${expires}; path=/'
if (document.cookie.includes('_dd_s_v2=')) {
document.cookie = '_dd_s_v2=isExpired=1; expires=${expires}; path=/'

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve the anonymous ID when ending a v7 session

issue: On the default v7 configuration where anonymous-user tracking is enabled, replacing _dd_s_v2 with only isExpired=1 discards its aid. The SDK's own stopSession() path deliberately carries that value into the expired state so the anonymous identity persists across session renewal; clicking “End current session” instead assigns a new anonymous identity on the next interaction. Include the existing aid in the tombstone.

Useful? React with 👍 / 👎.

Comment on lines +129 to +132
const cookieRawValue =
v2Session && v6Session
? (Number(v2Session.created) >= Number(v6Session.created) ? v2RawValue : v6RawValue)
: (v2RawValue ?? v6RawValue)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Determine freshness from session expiry instead of creation

issue: When both cookie names contain IDs—for example, a v6 session starts, the same origin briefly loads v7, and then returns to v6 within the original session—the abandoned v7 cookie always wins because its fixed created timestamp is newer. Active sessions update expire, not created, and this parser also accepts an elapsed expire, so the stale cookie can continue shadowing the session used by the currently running SDK long after it stopped being refreshed; use the SDK version when reliable or compare active expiry/freshness instead.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant