[FFL-1720] Evaluation Logging: Integration#3147
[FFL-1720] Evaluation Logging: Integration#3147typotter wants to merge 9 commits intotypo/FFL-1720-pr3-storage-networkfrom
Conversation
10e6149 to
5a11e3d
Compare
fa56eda to
a83f2d5
Compare
|
Warning This pull request is not mergeable via GitHub because a downstack PR is open. Once all requirements are satisfied, merge this PR as a stack on Graphite.
This stack of pull requests is managed by Graphite. Learn more about stacking. |
5a11e3d to
1c2b043
Compare
7ceef6b to
7c8d6b7
Compare
1c2b043 to
cc350e3
Compare
...d-sdk-android-flags/src/main/kotlin/com/datadog/android/flags/internal/DatadogFlagsClient.kt
Show resolved
Hide resolved
3618528 to
cce61c1
Compare
8813c89 to
56da165
Compare
cc350e3 to
8c8b89d
Compare
e84dada to
fb01eef
Compare
8c8b89d to
14f24f6
Compare
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## typo/FFL-1720-pr3-storage-network #3147 +/- ##
=====================================================================
- Coverage 70.92% 70.86% -0.06%
=====================================================================
Files 906 906
Lines 33353 33430 +77
Branches 5623 5643 +20
=====================================================================
+ Hits 23654 23690 +36
- Misses 8127 8166 +39
- Partials 1572 1574 +2
🚀 New features to boost your workflow:
|
This comment has been minimized.
This comment has been minimized.
Integrates the evaluation logging feature end-to-end, enabling it in the SDK. Configuration (FlagsConfiguration): - Add trackEvaluations(enabled: Boolean) - default true (EVALLOG.12) - Add useCustomEvaluationEndpoint(endpoint: String) - for testing/proxies - Add evaluationFlushInterval(intervalMs: Long) - configurable 1-60s, default 10s - Validation: interval coerced to valid range Lifecycle (FlagsFeature): - Initialize evaluation processor on onInitialize() when trackEvaluations enabled - Creates scheduled executor for periodic flushing - Creates evaluation writer (EvaluationEventRecordWriter) - Schedules periodic flush task - Clean up on onStop(): - Flush remaining evaluations via processor.stop() - Clean up processor and writer references - Renamed processor → exposureProcessor for clarity - Renamed dataWriter → exposureWriter for clarity Integration (DatadogFlagsClient): - Accept both exposureProcessor and evaluationProcessor (optional) - Add writeEvaluationEvent() method to log evaluations - Track ALL evaluations when trackEvaluations enabled: - Success evaluations in trackResolution() - Error evaluations via new trackErrorResolution() method - Error evaluations create synthetic PrecomputedFlag with ERROR reason Factory (FlagsClient): - Pass both processors to DatadogFlagsClient constructor Test Updates: - DatadogFlagsClientTest: Update all instantiations to pass both processors - FlagsFeatureTest: Update to test dual processor initialization - Add mock for createScheduledExecutorService() EVALLOG compliance: Enables evaluation logging (2, 3, 4, 5, 8, 10, 11, 12, 13) Zero user-facing breaking changes - all new options have defaults.
fb01eef to
3a685c2
Compare
cccb7f9 to
03a8d8d
Compare
| internal class FlagsFeature( | ||
| private val sdkCore: FeatureSdkCore, | ||
| internal val flagsConfiguration: FlagsConfiguration, | ||
| internal val evaluationsFeature: EvaluationsFeature? = null |
There was a problem hiding this comment.
Having it as a property just to be read in the FlagsClient setup without a real usage inside FlagsFeature may look a bit confusing. Maybe simply get it in the FlagsClient.Builder.build as it is done for the FlagsFeature?
| doLog = false, | ||
| allocationKey = "", | ||
| variationKey = "", | ||
| extraLogging = org.json.JSONObject(), |
There was a problem hiding this comment.
| extraLogging = org.json.JSONObject(), | |
| extraLogging = JSONObject(), |
We then need to have it as a static object instead of creating the same object all the time. But only if it is not supposed to be mutated during the downstream processing.
|
|
||
| // Get initial service from DatadogContext | ||
| val internalSdkCore = sdkCore as? InternalSdkCore | ||
| val initialService = internalSdkCore?.getDatadogContext()?.service |
There was a problem hiding this comment.
We should avoid doing this since it is a blocking call and may slow down SDK initialization.
What prevents from reading RUM context and SDK context during the event write stage? I believe it is evaluation aggregation where we write data to the disk only after some time.
Normally, service doesn't change during the SDK core lifetime, because there is no way to set if after SDK is initialized, so it can be read actually during the event write phase, not here.

🥞 Evaluation Logging Stacked Pull Requests 🥞
👉 Integration & Configuration (this PR)
☑️ Storage & Network Infrastructure (PR #3146)
☑️ Aggregation Engine & Test Utilities (PR #3145)
☑️ FlagEvaluation Schema (PR #3166)
☑️ Event Schema & Data Models (PR #3144)
☑️ Evaluations Subfeature (PR #3159)
⎿
feature/flags-evaluations-logging(feature branch)Datadog Internal
🎟️ Ticket: FFL-1720 - Implement Evaluation Logging for Android SDK
What does this PR do?
Wires the evaluation logging feature end-to-end by connecting the
EvaluationsFeatureto the flag evaluation flow. This is the final PR that enables evaluation logging in the Flags SDK.Motivation
We need to implement Evaluation Logging to provide comprehensive visibility into all feature flag evaluations, including defaults, errors, and successful matches. This goes beyond exposure logging by capturing aggregated metrics about evaluation frequency, error rates, and runtime default usage across all flags.
Additional Notes
Review checklist (to be filled by reviewers)