Skip to content

[Feature flags] Send exposures as batches#2895

Merged
jonathanmos merged 9 commits into
feature/feature-flaggingfrom
jmoskovich/flags-feature-batching
Oct 9, 2025
Merged

[Feature flags] Send exposures as batches#2895
jonathanmos merged 9 commits into
feature/feature-flaggingfrom
jmoskovich/flags-feature-batching

Conversation

@jonathanmos

@jonathanmos jonathanmos commented Sep 25, 2025

Copy link
Copy Markdown
Member

What does this PR do?

This is part of the feature flags project.
• Takes the Flags Feature name from the core, to match the rest of our features
• GSON added as a transitive dependency.
• Writes feature flags exposures to batches and sends them to the endpoint using the core mechanism.
• Increases test coverage past 80% for the module.
• Exposures deduplication lrucache set at 4mb max size.
• Sending exposures batches is controlled by a configuration option in FlagsConfiguration of trackExposures that is set to default true.

Motivation

What inspired you to submit this pull request?

Additional Notes

Anything else we should know when reviewing?

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)

@jonathanmos
jonathanmos force-pushed the jmoskovich/flags-feature-batching branch from 48599ba to 50bbdd6 Compare September 25, 2025 08:46
@jonathanmos
jonathanmos force-pushed the jmoskovich/flags-feature-batching branch 2 times, most recently from 5f1386d to bedf595 Compare September 25, 2025 10:55
@codecov-commenter

codecov-commenter commented Sep 25, 2025

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 94.07895% with 9 lines in your changes missing coverage. Please review.
✅ Project coverage is 70.69%. Comparing base (b641740) to head (44bdded).

Files with missing lines Patch % Lines
.../flags/featureflags/internal/DatadogFlagsClient.kt 76.19% 3 Missing and 2 partials ⚠️
...com/datadog/android/flags/internal/FlagsFeature.kt 75.00% 2 Missing and 2 partials ⚠️
Additional details and impacted files
@@                     Coverage Diff                      @@
##           feature/feature-flagging    #2895      +/-   ##
============================================================
+ Coverage                     70.36%   70.69%   +0.33%     
============================================================
  Files                           826      830       +4     
  Lines                         30084    30203     +119     
  Branches                       5124     5128       +4     
============================================================
+ Hits                          21167    21349     +182     
+ Misses                         7465     7409      -56     
+ Partials                       1452     1445       -7     
Files with missing lines Coverage Δ
.../kotlin/com/datadog/android/api/feature/Feature.kt 100.00% <ø> (ø)
...src/main/kotlin/com/datadog/android/flags/Flags.kt 88.89% <100.00%> (+0.21%) ⬆️
...in/com/datadog/android/flags/FlagsConfiguration.kt 100.00% <100.00%> (ø)
...ernal/repository/net/DefaultFlagsNetworkManager.kt 49.22% <ø> (ø)
.../android/flags/internal/ExposureEventsProcessor.kt 100.00% <100.00%> (ø)
...adog/android/flags/internal/model/ExposureEvent.kt 100.00% <100.00%> (ø)
...roid/flags/internal/net/ExposuresRequestFactory.kt 100.00% <100.00%> (ø)
...lags/internal/storage/ExposureEventRecordWriter.kt 100.00% <100.00%> (ø)
...android/flags/internal/storage/NoOpRecordWriter.kt 100.00% <100.00%> (ø)
...com/datadog/android/flags/internal/FlagsFeature.kt 80.00% <75.00%> (+37.14%) ⬆️
... and 1 more

... and 35 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@jonathanmos jonathanmos changed the title Send exposures as batches [Feature flags] Send exposures as batches Sep 25, 2025
@jonathanmos
jonathanmos marked this pull request as ready for review September 29, 2025 12:43
@jonathanmos
jonathanmos requested review from a team as code owners September 29, 2025 12:43
typotter
typotter previously approved these changes Oct 1, 2025

@typotter typotter left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Looks great!
Just a couple small name/refactor comments.

@jonathanmos
jonathanmos force-pushed the jmoskovich/flags-feature-batching branch from 86c1e46 to 96114fc Compare October 5, 2025 10:29

@0xnm 0xnm left a comment

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 reviewed production files and left some comments.

private var enableExposureLogging: Boolean = false

/**
* Sets whether exposures should be logged to RUM. This is disabled by default.

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.

just curious: what is the impact if it is enabled? billing?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

You've got it. It's RUM ingestion and eventually, experiments ingestion events that would hit billing. The other impact is that feedback for Feature Flags won't be available in parts of the Datadog Feature Flags & Experimentation app, so the customer loses observability.

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.

We probably need to put more focus on explaining what it is, because it impacts billing, so it is kind of important parameter to change.

import com.google.gson.JsonElement
import com.google.gson.JsonObject

internal data class ExposureEvent(

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.

should we maybe simply create json schema locally and then generate event from there?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Added a todo to do this in another pr

Comment on lines +21 to +26
private data class CacheKey(
val targetingKey: String,
val flagName: String,
val allocationKey: String,
val variationKey: String
)

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.

with 4 unrelated properties making a cache key do we expect a high rate of cache miss?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The number of misses should be low once all of the Flags in an app have been evaluated for the first time.
targetingKey is likely to remain stable as it typically references the user. The length of the cache is essentially the number of Flags that are evaluated times the churn in assignment.
The allocationKey & variationKey only change if the evaluationContext changes is reset and the resulting flag assignment changes. The flux in assignment varies depending on the kind of feature flag (i.e. a rollout vs A/B test) but would generally be pretty stable during a user's session in the app. As a result, churn on Allocation and Variation would be very low.

typotter
typotter previously approved these changes Oct 6, 2025

@typotter typotter left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM

private var enableExposureLogging: Boolean = false

/**
* Sets whether exposures should be logged to RUM. This is disabled by default.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

You've got it. It's RUM ingestion and eventually, experiments ingestion events that would hit billing. The other impact is that feedback for Feature Flags won't be available in parts of the Datadog Feature Flags & Experimentation app, so the customer loses observability.

Comment on lines +21 to +26
private data class CacheKey(
val targetingKey: String,
val flagName: String,
val allocationKey: String,
val variationKey: String
)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The number of misses should be low once all of the Flags in an app have been evaluated for the first time.
targetingKey is likely to remain stable as it typically references the user. The length of the cache is essentially the number of Flags that are evaluated times the churn in assignment.
The allocationKey & variationKey only change if the evaluationContext changes is reset and the resulting flag assignment changes. The flux in assignment varies depending on the kind of feature flag (i.e. a rollout vs A/B test) but would generally be pretty stable during a user's session in the app. As a result, churn on Allocation and Variation would be very low.

@typotter typotter mentioned this pull request Oct 7, 2025
3 tasks
@jonathanmos
jonathanmos force-pushed the jmoskovich/flags-feature-batching branch from 16b6e3a to a1e7ee1 Compare October 8, 2025 12:07
@jonathanmos
jonathanmos force-pushed the jmoskovich/flags-feature-batching branch from e53c83c to 5e27688 Compare October 8, 2025 12:23
@jonathanmos
jonathanmos requested review from 0xnm and typotter October 8, 2025 13:30
Comment thread features/dd-sdk-android-flags/api/apiSurface Outdated
@jonathanmos
jonathanmos requested a review from 0xnm October 9, 2025 09:51
0xnm
0xnm previously approved these changes Oct 9, 2025
@jonathanmos
jonathanmos merged commit 09aacbf into feature/feature-flagging Oct 9, 2025
25 checks passed
@jonathanmos
jonathanmos deleted the jmoskovich/flags-feature-batching branch October 9, 2025 16:00
This was referenced Nov 4, 2025
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.

6 participants