Skip to content

Conversation

typotter
Copy link

@typotter typotter commented Sep 26, 2025

Flags Feature: Enable method

Feature Flagging mobile SDK MVP spike
stacked on #2899
FFL-1117
FFL-1118

What does this PR do?

This PR implements the complete Flags feature initialization and client management APIs, bringing both Flags.enable() and FlagsClient up to the mobile API specification. The PR includes configuration management, multi-domain client support, and graceful degradation patterns.

Key Changes:

1. Flags.enable() Configuration

  • Enhanced FlagsConfiguration with customExposureEndpoint
  • Made configuration parameter optional with default configuration for convenience
  • Updated FlagsFeature to accept and store FlagsConfiguration for future client creation
  • Configuration is properly passed through to FlagsContext and network layer

2. FlagsClient Factory API

  • Implemented get() method with multi-tenant support: get(name: String = "default", sdkCore: SdkCore)
    • Auto-creates default client when name == "default"
    • Returns NOPClient for custom names not found (safe fallback)
  • Implemented Builder pattern for explicit client creation
    • Returns existing client with warning if duplicate requested
    • Never crashes - always returns valid FlagsClient (real or NOP)
  • Renamed setContext() to setEvaluationContext() for OpenFeature alignment

3. Multi-Client Management

  • Support for multiple SDK cores and multiple named clients per core
  • Lifecycle management with unregister() and clear() methods

Motivation

This change fully implements the mobile API specification for Feature Flagging:

// Feature initialization
Flags.enable()                                    // default config, default core
Flags.enable(flagsConfig)                         // custom config, default core
Flags.enable(flagsConfig, core)                   // advanced, custom core

// Client access
val client = FlagsClient.get()                    // get/create default client
val customClient = FlagsClient.get("custom")      // get custom named client (or NOP)
val newClient = FlagsClient.builder("name").build()        // explicitly create named client

// Flag evaluation
client.setEvaluationContext(context)              // set targeting context
val enabled = client.resolveBooleanValue("feature-key", false)

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)

@codecov-commenter
Copy link

codecov-commenter commented Sep 26, 2025

Codecov Report

❌ Patch coverage is 60.20942% with 76 lines in your changes missing coverage. Please review.
✅ Project coverage is 70.72%. Comparing base (264709b) to head (7890424).

Files with missing lines Patch % Lines
.../datadog/android/flags/featureflags/FlagsClient.kt 37.36% 45 Missing and 12 partials ⚠️
...flags/internal/persistence/FlagsStateSerializer.kt 75.00% 7 Missing ⚠️
...ernal/repository/net/DefaultFlagsNetworkManager.kt 12.50% 7 Missing ⚠️
...oid/flags/featureflags/internal/NoOpFlagsClient.kt 84.21% 2 Missing and 1 partial ⚠️
...lags/internal/repository/DefaultFlagsRepository.kt 0.00% 1 Missing ⚠️
...com/datadog/android/flags/internal/FlagsFeature.kt 95.00% 1 Missing ⚠️
Additional details and impacted files
@@                     Coverage Diff                      @@
##           feature/feature-flagging    #2900      +/-   ##
============================================================
- Coverage                     70.76%   70.72%   -0.04%     
============================================================
  Files                           834      834              
  Lines                         30340    30378      +38     
  Branches                       5128     5131       +3     
============================================================
+ Hits                          21469    21484      +15     
- Misses                         7415     7441      +26     
+ Partials                       1456     1453       -3     
Files with missing lines Coverage Δ
...src/main/kotlin/com/datadog/android/flags/Flags.kt 83.33% <100.00%> (+3.33%) ⬆️
...in/com/datadog/android/flags/FlagsConfiguration.kt 100.00% <100.00%> (ø)
.../flags/featureflags/internal/DatadogFlagsClient.kt 86.84% <100.00%> (+0.80%) ⬆️
...ureflags/internal/evaluation/EvaluationsManager.kt 89.29% <100.00%> (ø)
.../flags/featureflags/internal/model/FlagsContext.kt 100.00% <100.00%> (ø)
...lags/internal/repository/DefaultFlagsRepository.kt 48.65% <0.00%> (ø)
...com/datadog/android/flags/internal/FlagsFeature.kt 87.18% <95.00%> (+7.18%) ⬆️
...oid/flags/featureflags/internal/NoOpFlagsClient.kt 84.21% <84.21%> (-1.50%) ⬇️
...flags/internal/persistence/FlagsStateSerializer.kt 78.12% <75.00%> (-0.66%) ⬇️
...ernal/repository/net/DefaultFlagsNetworkManager.kt 54.39% <12.50%> (+3.15%) ⬆️
... and 1 more

... and 43 files with indirect coverage changes

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

@typotter typotter changed the base branch from develop to feature/feature-flagging September 26, 2025 04:35
@typotter typotter changed the title [FFL-1117] feat: pass default client configuration to flags enable [FFL-1117] feat: Flags.enable Sep 26, 2025
@typotter typotter changed the base branch from feature/feature-flagging to typo/FFL-1116-swap-classname-provider-client-client-client-manager-or-eliminate September 26, 2025 05:43
…ent-manager-or-eliminate' into typo/FFL-1117-pass-default-client-configuration-to-flags-enable
…ent-manager-or-eliminate' into typo/FFL-1117-pass-default-client-configuration-to-flags-enable
…ent-manager-or-eliminate' into typo/FFL-1117-pass-default-client-configuration-to-flags-enable
@typotter typotter changed the title [FFL-1117] feat: Flags.enable Flags.enable and FlagsClient APIs Oct 2, 2025
argumentCaptor<FlagsFeature> {
verify(mockSdkCore).registerFeature(capture())
// Verify the feature was created (implicit by successful registration)
assertThat(lastValue).isNotNull
Copy link
Member

Choose a reason for hiding this comment

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

this assertion is kind of useless, because if registerFeature was called, it means it was called with non-null value according to its signature which doesn't allow nullable type.

Copy link
Author

Choose a reason for hiding this comment

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

updated to check the feature's name.


// When
testedClient.setContext(fakeContext)
testedClient.setEvaluationContext(fakeContext)
Copy link
Member

Choose a reason for hiding this comment

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

comment is regarding verify below: instead of any we could actually capture the argument is verify its properties.

Copy link
Author

Choose a reason for hiding this comment

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

👍

Copy link
Member

@0xnm 0xnm left a comment

Choose a reason for hiding this comment

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

Resetting review status, because there is file which shouldn't be probably committed.

@typotter typotter force-pushed the typo/FFL-1117-pass-default-client-configuration-to-flags-enable branch from 0349f3e to cdebda3 Compare October 10, 2025 03:45
@typotter typotter requested a review from 0xnm October 10, 2025 05:41
Copy link
Author

@typotter typotter left a comment

Choose a reason for hiding this comment

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

alas, I have not been able to quite get through the merge conflicts from Jonathan's merges. tomorrow!

@typotter typotter changed the base branch from feature/feature-flagging to typo/site-extension October 10, 2025 16:21
Base automatically changed from typo/site-extension to feature/feature-flagging October 10, 2025 19:55
@typotter
Copy link
Author

/merge

@dd-devflow-routing-codex
Copy link

dd-devflow-routing-codex bot commented Oct 14, 2025

View all feedbacks in Devflow UI.

2025-10-14 15:19:52 UTC ℹ️ Start processing command /merge


2025-10-14 15:19:58 UTC ℹ️ MergeQueue: pull request added to the queue

The expected merge time in feature/feature-flagging is approximately 1h (p90).


2025-10-14 16:19:49 UTC ℹ️ MergeQueue: This merge request was merged

@dd-mergequeue dd-mergequeue bot merged commit 740290d into feature/feature-flagging Oct 14, 2025
26 checks passed
@dd-mergequeue dd-mergequeue bot deleted the typo/FFL-1117-pass-default-client-configuration-to-flags-enable branch October 14, 2025 16:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants