Skip to content

feat: add anonymous_id user enrichment to RUM and Logs#151

Draft
kikoveiga wants to merge 1 commit into
developfrom
add-anonymous-id-user-enrichment
Draft

feat: add anonymous_id user enrichment to RUM and Logs#151
kikoveiga wants to merge 1 commit into
developfrom
add-anonymous-id-user-enrichment

Conversation

@kikoveiga

@kikoveiga kikoveiga commented May 13, 2026

Copy link
Copy Markdown
Contributor

Supersedes #145 by @asdftamir: opened here internally so the CI and Codex review can run.

What does this PR do?

Adds browser-SDK-style anonymous_id enrichment to the Roku SDK so RUM and Logs events can be tied back to a stable, anonymous device identity across both sessions and channel launches.

  • New trackAnonymousUser init configuration flag (default true).
  • At init time, if no anonymous_id is persisted in the Roku registry (section "datadog", key "anonymous_id"), generate one via roDeviceInfo.GetRandomUUID() and persist it back to the registry. This mirrors browser-sdk's cookie behavior — the id survives channel relaunches and reboots, scoped per-channel.
  • When trackAnonymousUser: false is passed at init, any previously persisted anonymous_id is removed from the registry so the identifier does not outlive the integrator's consent signal.
  • New getDatadogUserInfo(global) helper enriches usr payloads with anonymous_id only when not already set by the user, and only when tracking is enabled.
  • All usr: payload builders in Logs and RUM (view, action, error, resource, vital) now go through the helper.
  • New library/source/identityStorage.bs module wraps registry read/write/delete so future identity values can be persisted the same way.

Motivation

Mirror the behavior already shipped in browser-sdk so anonymous Roku sessions are attributable and consistent with other Datadog SDKs. The same precedence rules apply: a user-provided anonymous_id always wins over the SDK-generated one, and explicit user opt-out (trackAnonymousUser: false) disables enrichment entirely and clears any persisted id. Persistence in the Roku registry is the closest analogue to a browser cookie: per-channel-sandboxed, survives reboots.

Additional Notes

  • Tests added in test/source/tests/Test__datadog.bs cover the three precedence cases (enrich, preserve user value, opt-out) plus registry cleanup on trackAnonymousUser: false.
  • Tests in test/source/tests/logs/Test__LogsAgent.bs verify the helper is wired into log payloads.
  • Tests in test/source/tests/rum/Test__datadog.bs cover registry reuse (WhenInitialize_WithRegistryValue_ThenReuseAnonymousId) and first-launch generation/persistence (WhenInitialize_WithEmptyRegistry_ThenGenerateAndPersistAnonymousId). The shared TearDown clears the registry key for isolation.
  • dist/ is regenerated and included in the commits, consistent with the repo's existing workflow.
  • No linked Issue yet — happy to open one if the team prefers per CONTRIBUTING.md.

Review checklist (to be filled by reviewers)

  • Feature or bugfix MUST have appropriate tests (unit, integration, e2e)
  • Make sure you discussed the feature or bugfix with the maintaining team in an Issue
  • Make sure each commit and the PR mention the Issue number (cf the CONTRIBUTING doc)

🤖 Generated with Claude Code

@kikoveiga kikoveiga requested a review from a team as a code owner May 13, 2026 14:28

@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: 4d07789047

ℹ️ 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 thread library/source/datadogSdk.bs Outdated
Comment on lines +116 to +117
if (not trackAnonymousUser)
clearDatadogAnonymousId()

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Scrub cached last-view user data on opt-out

When a channel previously ran with anonymous tracking enabled, sendViewUpdate now persists the last view event with usr.anonymous_id for crash recovery. If the next launch passes trackAnonymousUser: false after a reportable crash, this branch only clears the registry, while RumCrashReporterTask.sendCrashReportFromViewEventFile still reads the cached _last_view_* event and copies lastViewEvent.usr into the crash payload. That lets the old anonymous id be uploaded after the integrator has opted out, so the opt-out path also needs to remove or scrub cached last-view events before crash reporting can send them.

Useful? React with 👍 / 👎.

@kikoveiga kikoveiga force-pushed the add-anonymous-id-user-enrichment branch from 4d07789 to 71c68d8 Compare May 13, 2026 15:44
@kikoveiga kikoveiga requested a review from a team as a code owner May 13, 2026 15:44
@kikoveiga kikoveiga marked this pull request as draft May 13, 2026 15:45
Mirror the browser SDK's anonymous-user tracking on Roku.

- Add the `trackAnonymousUser` init config flag (default `true`).
- Resolve a stable `anonymousId` once at init, before any agent/task
  starts: read it from the Roku registry (section "datadog", key
  "anonymous_id") or generate one with GetRandomUUID() and persist it,
  so it survives channel relaunches. Disabling tracking clears the
  persisted id. Stored in the immutable global `datadogAnonymousId`.
- Add `identityStorage.bs` (registry read/write/clear helpers).
- `getDatadogUserInfo(userInfo, anonymousId)` enriches the `usr` payload
  with `anonymous_id` only when the integrator hasn't supplied one,
  shallow-copying so the shared global user info is never mutated.
- Route all `usr:` builders (logs, view, action, error, resource, vital)
  through the helper.

Performance: the helper takes already-read values instead of touching
the global node, so callers cache `anonymousId` once rather than reading
it per event. On the RumAgent Task thread every `m.global` read is a
cross-thread rendezvous; LogsAgent keeps its observer-cached `usr` path
and reads no globals per log.

Tests: getDatadogUserInfo enrichment/passthrough/mutation-safety,
identityStorage registry round-trip, RUM view-event enrichment, and
LogsAgent anonymous_id behavior. Docs added to README.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@kikoveiga kikoveiga force-pushed the add-anonymous-id-user-enrichment branch from 71c68d8 to 0a732ac Compare June 16, 2026 18:01
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