dd-sdk-android
dd-sdk-android copied to clipboard
feat: Openfeature Provider implementation powered by DD Flags
What does this PR do?
This PR adds a new OpenFeature provider module (dd-sdk-android-flags-openfeature) that integrates the Datadog Feature Flags SDK with the OpenFeature API, enabling developers to use standardized feature flag management while leveraging Datadog's observability platform.
Key components:
- DatadogFlagsProvider: OpenFeature FeatureProvider implementation that adapts the OpenFeature API to Datadog's FlagsClient
- Type Converters: Bidirectional conversion between OpenFeature Values and JSON types, preserving type information
- Factory Methods: Three factory methods (
create(),create(name),create(name, sdkCore)) for flexible provider instantiation, parallelingFlagsClient'screatemethods - Extension Function:
FlagsClient.asOpenFeatureProvider()for convenient wrapping of existing clients - Static-Context Paradigm: Implements OpenFeature's static-context model with global context management
Motivation
Why OpenFeature Integration?
- Standardization: OpenFeature provides a vendor-neutral, community-driven specification for feature flagging
- Ecosystem: Enables integration with OpenFeature-compatible tools and libraries
- Migration Path: Allows customers to adopt OpenFeature API while using Datadog as the backend
- Multi-Vendor: Customers can switch between feature flag providers without code changes
Additional Notes
Architecture Decisions
Static-Context Paradigm
- This provider implements the static-context paradigm per OpenFeature spec
- Global context is set via
OpenFeatureAPI.setEvaluationContext() - Per-evaluation (invocation) contexts are not supported - OpenFeature spec does not support invocation contexts in static-paradigm providers
Type Conversion Strategy
- JSON → OpenFeature Value: Intelligent type promotion (e.g., Long within Int range becomes Value.Integer)
- OpenFeature Value → JSON: Preserves type information (Integer→Int, Boolean→Boolean)
- Null Handling:
JSONObject.NULLsentinel values are converted toValue.Null - Special Values: Handles NaN, Infinity, nested structures, large collections
Error Handling
- Specific exception catching (JSONException, ClassCastException, IllegalStateException)
- Appropriate OpenFeature error codes (PARSE_ERROR, TYPE_MISMATCH, GENERAL)
- Graceful degradation - returns default values on errors
- Comprehensive logging for debugging
Thread Safety
- Provider methods are thread-safe, delegating coordination to FlagsClient
- No synchronization locks (upstream FlagsClient handles concurrency)
Implementation Details
Module Structure:
dd-sdk-android-flags-openfeature/
├── DatadogFlagsProvider.kt # Main provider implementation
├── FlagsClientExt.kt # Extension function
└── internal/adapters/
├── Converters.kt # Context & error code converters
└── ValueConverters.kt # JSON ↔ OpenFeature Value converters
Test Coverage:
- new unit tests
CI/CD Integration:
- Added to detekt pipeline (
:features:dd-sdk-android-flags-openfeature:customDetektRules) - Publishing configured (
publish:release-flags-openfeature) - License compliance updated (Apache-2.0 for OpenFeature)
Known Limitations & Future Work
TODO FFL-1442: Implement observe() method for provider state observation
- Requires upstream changes in flags module to expose FlagsClient state changes
- Currently uses default implementation (returns empty Flow)
Manual Testing:
val provider = DatadogFlagsProvider.create()
OpenFeatureAPI.setProviderAndWait(provider)
val client = OpenFeatureAPI.getClient()
val isEnabled = client.getBooleanValue("my-feature", 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 Report
:x: Patch coverage is 47.23247% with 143 lines in your changes missing coverage. Please review.
:white_check_mark: Project coverage is 70.86%. Comparing base (6c2f8ab) to head (ef411d2).
Additional details and impacted files
@@ Coverage Diff @@
## feature/flags-ofeat #2998 +/- ##
=======================================================
- Coverage 71.10% 70.86% -0.24%
=======================================================
Files 860 865 +5
Lines 31311 31565 +254
Branches 5275 5334 +59
=======================================================
+ Hits 22263 22368 +105
- Misses 7556 7673 +117
- Partials 1492 1524 +32
| Files with missing lines | Coverage Δ | |
|---|---|---|
| ...atadog/android/flags/openfeature/FlagsClientExt.kt | 100.00% <100.00%> (ø) |
|
| ...tadog/android/flags/internal/DatadogFlagsClient.kt | 88.41% <100.00%> (-1.30%) |
:arrow_down: |
| ...id/flags/internal/evaluation/EvaluationsManager.kt | 91.18% <93.33%> (+1.89%) |
:arrow_up: |
| ...lags/internal/repository/DefaultFlagsRepository.kt | 64.00% <0.00%> (-1.31%) |
:arrow_down: |
| ...om/datadog/android/flags/model/FlagsClientState.kt | 83.33% <83.33%> (ø) |
|
| .../datadog/android/flags/internal/NoOpFlagsClient.kt | 93.10% <50.00%> (-6.90%) |
:arrow_down: |
| ...atadog/android/flags/internal/FlagsStateManager.kt | 86.36% <86.36%> (ø) |
|
| ...in/kotlin/com/datadog/android/flags/FlagsClient.kt | 35.59% <0.00%> (-2.59%) |
:arrow_down: |
| .../flags/openfeature/internal/adapters/Converters.kt | 57.14% <57.14%> (ø) |
|
| ...s/openfeature/internal/adapters/ValueConverters.kt | 68.52% <68.52%> (ø) |
|
| ... and 1 more |
:rocket: New features to boost your workflow:
- :snowflake: Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
🎯 Code Coverage
• Patch Coverage: 100.00%
• Total Coverage: 71.03% (-0.22%)
View detailed report
🔗 Commit SHA: ef411d2 | Docs | Datadog PR Page | Was this helpful? Give us feedback!