Skip to content

RUM-17009: Preserve application attribution without an active RUM session - #3970

Draft
kikoveiga wants to merge 1 commit into
developfrom
kikoveiga/RUM-17009/preserve-rum-application-id
Draft

kikoveiga wants to merge 1 commit into
developfrom
kikoveiga/RUM-17009/preserve-rum-application-id

Conversation

@kikoveiga

@kikoveiga kikoveiga commented Oct 9, 2026 •

Copy link
Copy Markdown
Collaborator

What does this PR do?

Preserve application attribution before and between RUM sessions. RumContext requires the configured applicationId; sessionId, sessionState and sessionStartReason are nullable. When no session is available, the monitor publishes an application-only context and clears stale session, view and action correlation.

  • Telemetry takes the application ID directly from configuration and omits absent session information.
  • Native logs, traces and WebView logs retain application attribution without a session. Session-dependent RUM events, WebView RUM/replay events and metrics require session information.
  • Failed event processing publishes an application-only fallback. WebView correlation can recover when session context becomes available again.
  • Replay uploads reject records with missing, blank, non-string or zero-UUID application/session/view IDs.
  • Core delivers a shallow copy of the feature-context map to registered receivers, so subsequent map updates do not change previously delivered snapshots.

Motivation

RUM-17009: Android PR #3304 cleared the entire RUM context to prevent zero-UUID session correlation in logs and traces. That also removed application attribution when sessions ended. This change preserves application identity while keeping absent session correlation out of events.

The telemetry approach aligns with iOS PR #3095: application identity comes from configuration, independently of session state. Android also updates its shared context model; the iOS PR leaves that model unchanged.

Additional Notes

Targets develop, which now includes the shared-context extraction (#4019) and reader migration (#4027). This PR contains the lifecycle changes on top of those merged changes.

No customer-facing API changes. The SDK-internal RumContext constructor and field nullability change. Legacy flat fields remain published for cross-platform compatibility; an application-only snapshot publishes only the application ID alongside the typed context. NULL_UUID remains for legacy boundaries and required schema fallbacks, but no longer represents an absent session in the internal RUM context.

Validation against the latest develop: Core, Internal, Logs, Profiling, RUM, Session Replay, Trace, WebView and Flags unit tests; Trace and OkHttp JVM integration suites; generated-file checks; and instrumented integration test compilation passed. Formatting and Detekt also passed during rebase validation. Device tests were not run.

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)

@datadog-prod-us1-6

datadog-prod-us1-6 Bot commented Oct 9, 2026 •

Copy link
Copy Markdown

Pipelines  Tests

🎉 All green!

🧪 All tests passed
❄️ No new flaky tests detected

🎯 Code Coverage (details)
• Patch Coverage: 82.99%
• Overall Coverage: 71.83% (+0.04%)

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

@kikoveiga
kikoveiga force-pushed the kikoveiga/RUM-17009/preserve-rum-application-id branch 7 times, most recently from 7166051 to 83930b2 Compare October 14, 2026 13:24
@kikoveiga

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 14, 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-10-21T15:00:07.480220Z d15a144 New commits
🔒 Security Review ✅ Completed 2026-10-21T14:53:07.867061Z d15a144 New commits
ℹ️ 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

Copy link
Copy Markdown

🛡️ Codex Security Review · Automatically triggered

Security review completed. No security issues were found in this pull request.

Reviewed commit: 83930b2f31

View security finding report

Only the user who started this review can view the report in Codex.

ℹ️ About Codex security reviews in GitHub

This is an experimental Codex feature. Security reviews are triggered when:

  • You comment "@codex security review"
  • A regular code review gets triggered (for example, "@codex review" or when a PR is opened), and you’re opted in so security review runs alongside code review

Once complete, Codex will leave suggestions, or a comment if no findings are found.

@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: 83930b2f31

ℹ️ 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".

@kikoveiga
kikoveiga force-pushed the kikoveiga/RUM-17009/preserve-rum-application-id branch from 83930b2 to c29b60b Compare October 14, 2026 13:45
@kikoveiga
kikoveiga marked this pull request as ready for review October 14, 2026 14:01
@kikoveiga
kikoveiga requested review from a team as code owners October 14, 2026 14:01
@kikoveiga kikoveiga added the ready-for-human-review All agentic review feedback was addressed and PR is ready for the human review. label Oct 14, 2026

@datadog-prod-us1-6 datadog-prod-us1-6 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.

Bits Code Review: FAIL

Resources that finish before the first RUM session skip completion bookkeeping, leaving pending counters positive and preventing stopped view/session scopes from completing. Both successful-resource and resource-error paths need the dropped-event notification.

Open Bits AI session

🤖 Bits Code Review · Commit c29b60b

Comment on lines +252 to +253
@Suppress("UnsafeThirdPartyFunctionCall") // currentContext is non-null
val contextSnapshot = HashMap(currentContext)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

is it just for an additional guard? onContextUpdate argument for the context is of Map type, so it is not mutable unless receiver tries to cast to the mutable map explicitly (unlikely, I think).

as a price to pay - extra object allocation and iteration to copy.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Map prevents writes through that reference, but the producer still mutates the underlying object. Session replay retains that reference, for example, so subsequent updates change its previous context too.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

but the producer still mutates the underlying object. Session replay retains that reference, for example, so subsequent updates change its previous context too.

can you point to the code you are referencing? HashMap(currentContext) is also only top-level copy, not the deep one.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

SessionReplayRumContextProvider.onContextUpdate() retains the map with rumContext = context. On the next update, publishRumContext() clears and repopulates that same map before notifying receivers, so previousViewId already contains the new value and the view change is missed.

Yes it's a shallow snapshot. I think it's enough for this issue because the IDs are immutable strings and the producer replaces top-level entries.

Comment on lines +15 to +23
val applicationId: String = NULL_UUID,
val sessionId: String = NULL_UUID,
val applicationId: String,
val sessionId: String? = null,
val isSessionActive: Boolean = false,
val viewId: String? = null,
val viewName: String? = null,
val viewUrl: String? = null,
val actionId: String? = null,
val sessionState: RumSessionScope.State = RumSessionScope.State.NOT_TRACKED,
val sessionStartReason: RumSessionScope.StartReason = RumSessionScope.StartReason.USER_APP_LAUNCH,
val sessionState: RumSessionScope.State? = null,
val sessionStartReason: RumSessionScope.StartReason? = null,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

what is the benefit of dropping NULL_UUID and RumSessionScope.State.NOT_TRACKED here?

maybe we can extract RumContext into dd-sdk-android-internal, so that all modules can access it directly and use properties/methods specific to this class instead of relying on the generic types (e.g. strings, nulls)?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Dropping NULL_UUID lets us represent "RUM configured, no session" explicitly: applicationId is still required, while session information is nullable. NOT_TRACKED still describes an existing sampled-out session, while null means no session exists. WDYT?

I agree, we could extract a shared immutable RUM context, I will do it in a follow-up PR.

@0xnm 0xnm Oct 21, 2026 •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I agree, we could extract a shared immutable RUM context, I will do it in a follow-up PR.

Please start it first instead. This change is quote significant, we cannot let it land in develop with a follow-up PRs.

I also don't agree with making most important properties nullable, it feels wrong and brings a lot of changes - this is already surfaced by the number of if you had to introduce in this PR.

Comment on lines +242 to +246
val sessionId = rumContext.sessionId
if (sessionId == null) {
sent = true
return
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

it seems this change is not related and should be (if valid) in a standalone PR?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

This follows from making sessionId nullable, while actions require it. This is just some defensive handling.

val rulePsr = resourceAttributes.remove(RumAttributes.RULE_PSR) as? Number

val rumContext = getRumContext()
val sessionId = rumContext.sessionId

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

same here

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Same as my comment above, in the meantime also added the eventDropped call as suggested by Bits.

@kikoveiga
kikoveiga force-pushed the kikoveiga/RUM-17009/preserve-rum-application-id branch from c29b60b to 476770c Compare October 20, 2026 16:49

@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: 476770c908

ℹ️ 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".

@kikoveiga
kikoveiga force-pushed the kikoveiga/RUM-17009/preserve-rum-application-id branch 2 times, most recently from a86ed21 to 214cf44 Compare October 21, 2026 11:25
@kikoveiga
kikoveiga requested a review from a team as a code owner October 21, 2026 11:25

@datadog-prod-us1-6 datadog-prod-us1-6 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.

Bits Code Review: PASS

More details

Application-only context preserves application attribution while session-dependent consumers guard against absent session identifiers. The completed static review identified no reportable regression across context publication, telemetry, logs, tracing, WebView, and replay.

Was this helpful? React 👍 or 👎

Open Bits AI session

🤖 Bits Code Review · Commit 214cf44

@kikoveiga
kikoveiga force-pushed the kikoveiga/RUM-17009/preserve-rum-application-id branch from 214cf44 to d15a144 Compare October 21, 2026 14:41
@kikoveiga
kikoveiga changed the base branch from develop to kikoveiga/RUM-17009/extract-shared-rum-context October 21, 2026 14:41
@kikoveiga
kikoveiga added this pull request to stack #4023 October 21, 2026 14:42

@datadog-prod-us1-6 datadog-prod-us1-6 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.

Bits Code Review: PASS

More details

Application-only contexts retain application identity while clearing session, view, and action correlation. The static review found no actionable regression in lifecycle handling or affected consumers.

Was this helpful? React 👍 or 👎

Open Bits AI session

🤖 Bits Code Review · Commit d15a144

@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: d15a144958

ℹ️ 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 +52 to +53
val applicationId: String,
val sessionId: String? = null,

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 published RumContext API

Making applicationId mandatory removes the public no-argument constructor (<init>()V) shown as deleted in dd-sdk-android-internal.api; the nullable changes to sessionId, session metadata, and fromFeatureContext also alter the Kotlin source contract. Because dd-sdk-android-internal is a published artifact, a separately versioned consumer compiled against RumContext() will fail with NoSuchMethodError after upgrading this AAR, despite the PR stating that it makes no public API changes. Preserve the existing signatures and introduce the application-only representation through a compatibility-preserving API.

AGENTS.md reference: AGENTS.md:L106-L106

Useful? React with 👍 / 👎.

@kikoveiga
kikoveiga marked this pull request as draft October 22, 2026 10:15
@kikoveiga
kikoveiga force-pushed the kikoveiga/RUM-17009/preserve-rum-application-id branch from d15a144 to 50df67a Compare October 22, 2026 10:49
@kikoveiga
kikoveiga removed this pull request from stack #4023 October 22, 2026 10:52
@kikoveiga
kikoveiga changed the base branch from kikoveiga/RUM-17009/extract-shared-rum-context to kikoveiga/RUM-19153/use-typed-rum-context October 22, 2026 10:54
@kikoveiga
kikoveiga added this pull request to stack #4028 October 22, 2026 10:55
@kikoveiga
kikoveiga force-pushed the kikoveiga/RUM-17009/preserve-rum-application-id branch from 50df67a to 4a812cc Compare October 23, 2026 08:53
Base automatically changed from kikoveiga/RUM-19153/use-typed-rum-context to develop October 26, 2026 12:12
@kikoveiga
kikoveiga force-pushed the kikoveiga/RUM-17009/preserve-rum-application-id branch 5 times, most recently from ff79b64 to 8b82ed9 Compare October 27, 2026 16:13
…sion

Preserve the application context and group optional session metadata into a typed snapshot. Migrate readers and fixtures while retaining legacy feature-context fields for cross-platform consumers.

Ref: RUM-17009
@kikoveiga
kikoveiga force-pushed the kikoveiga/RUM-17009/preserve-rum-application-id branch from 8b82ed9 to b0cd265 Compare October 27, 2026 17:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ready-for-human-review All agentic review feedback was addressed and PR is ready for the human review.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants