Skip to content

[FFL-1720] Evaluation Logging: Storage & Network Infrastructure#3146

Open
typotter wants to merge 14 commits intographite-base/3146from
typo/FFL-1720-pr3-storage-network
Open

[FFL-1720] Evaluation Logging: Storage & Network Infrastructure#3146
typotter wants to merge 14 commits intographite-base/3146from
typo/FFL-1720-pr3-storage-network

Conversation

@typotter
Copy link
Contributor

@typotter typotter commented Jan 22, 2026

🥞 Evaluation Logging Stacked Pull Requests 🥞

🔲 Integration & Configuration (PR #3147)
👉 Storage & Network Infrastructure (this PR)
☑️ 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?

Implements the infrastructure for persisting evaluation events to disk and uploading them to Datadog's intake endpoint. Connects the aggregation engine (PR #3145) to the SDK Core's storage and network layer.

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)

  • 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)

Copy link
Contributor Author

typotter commented Jan 22, 2026

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.
Learn more

This stack of pull requests is managed by Graphite. Learn more about stacking.

@typotter typotter force-pushed the typo/FFL-1720-pr2-aggregation branch from 95f4c0a to a0e7df9 Compare January 22, 2026 16:29
@typotter typotter force-pushed the typo/FFL-1720-pr3-storage-network branch 2 times, most recently from 7ceef6b to 7c8d6b7 Compare January 22, 2026 21:27
@datadog-official

This comment has been minimized.

@typotter typotter mentioned this pull request Jan 27, 2026
3 tasks
@typotter typotter force-pushed the typo/FFL-1720-pr2-aggregation branch 2 times, most recently from 968dc68 to 80c8de7 Compare January 28, 2026 06:55
@typotter typotter force-pushed the typo/FFL-1720-pr3-storage-network branch from 7c8d6b7 to a195a29 Compare January 28, 2026 06:56
@typotter typotter force-pushed the typo/FFL-1720-pr2-aggregation branch from 2eb16ca to 0cfb30a Compare January 28, 2026 07:27
@typotter typotter force-pushed the typo/FFL-1720-pr3-storage-network branch from a195a29 to 4f4c253 Compare January 28, 2026 07:35
@typotter typotter force-pushed the typo/FFL-1720-pr2-aggregation branch from 0cfb30a to 141cded Compare January 28, 2026 07:50
@codecov-commenter
Copy link

codecov-commenter commented Jan 28, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 70.92%. Comparing base (66b62f4) to head (3a685c2).

Additional details and impacted files
@@                  Coverage Diff                   @@
##           graphite-base/3146    #3146      +/-   ##
======================================================
- Coverage               70.98%   70.92%   -0.06%     
======================================================
  Files                     905      906       +1     
  Lines                   33319    33353      +34     
  Branches                 5619     5623       +4     
======================================================
+ Hits                    23650    23654       +4     
- Misses                   8097     8127      +30     
  Partials                 1572     1572              
Files with missing lines Coverage Δ
...id/flags/internal/net/EvaluationsRequestFactory.kt 100.00% <100.00%> (+25.00%) ⬆️
...gs/internal/storage/EvaluationEventRecordWriter.kt 100.00% <100.00%> (ø)

... and 36 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 force-pushed the typo/FFL-1720-pr2-aggregation branch from 141cded to 4bfc37e Compare January 28, 2026 16:33
@typotter typotter force-pushed the typo/FFL-1720-pr3-storage-network branch from 4f4c253 to df51ceb Compare January 28, 2026 16:35
@typotter typotter force-pushed the typo/FFL-1720-pr2-aggregation branch from 4bfc37e to 550f9f0 Compare January 28, 2026 17:05
@typotter typotter force-pushed the typo/FFL-1720-pr3-storage-network branch from 3618528 to cce61c1 Compare January 28, 2026 23:04
@typotter typotter marked this pull request as ready for review January 29, 2026 05:56
@typotter typotter requested a review from a team as a code owner January 29, 2026 05:56
@typotter typotter mentioned this pull request Jan 30, 2026
3 tasks
@typotter typotter force-pushed the typo/FFL-1720-pr2-aggregation branch from 4b1cbc1 to 7e2293e Compare January 30, 2026 17:36
@typotter typotter force-pushed the typo/FFL-1720-pr3-storage-network branch from 8813c89 to 56da165 Compare January 30, 2026 20:54
@typotter typotter force-pushed the typo/FFL-1720-pr2-aggregation branch from 512a272 to e0d2ae7 Compare February 2, 2026 04:47
@typotter typotter force-pushed the typo/FFL-1720-pr3-storage-network branch from 56da165 to 5ba6fec Compare February 2, 2026 04:47
@typotter typotter requested a review from 0xnm February 2, 2026 05:00
@typotter typotter force-pushed the typo/FFL-1720-pr3-storage-network branch 3 times, most recently from e84dada to fb01eef Compare February 2, 2026 06:20
@typotter typotter changed the base branch from typo/FFL-1720-pr2-aggregation to graphite-base/3146 February 2, 2026 18:39
@typotter typotter force-pushed the typo/FFL-1720-pr3-storage-network branch from fb01eef to 3a685c2 Compare February 2, 2026 18:47
}

@Test
fun `M preserve batch data order W create() { multiple batch events }`(
Copy link
Member

Choose a reason for hiding this comment

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

does it actually matter? should we preserve the order?

* to the EVP intake endpoint by the SDK Core's upload mechanism.
*/
internal class EvaluationEventRecordWriter(private val sdkCore: FeatureSdkCore) : EvaluationEventWriter {
override fun writeAll(events: List<FlagEvaluation>) {
Copy link
Member

Choose a reason for hiding this comment

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

nit: maybe can be just write

Comment on lines +104 to +123
fun `M use write context W writeAll() { events provided }`(
@Forgery event: FlagEvaluation
) {
// Given
whenever(mockSdkCore.getFeature(Feature.FLAGS_EVALUATIONS_FEATURE_NAME)).thenReturn(mockFeature)
whenever(mockFeature.withWriteContext(any(), any()))
.thenAnswer { invocation ->
val callback = invocation.getArgument<(DatadogContext, EventWriteScope) -> Unit>(1)
val mockContext = mock<DatadogContext>()
callback.invoke(mockContext) { writerScope ->
writerScope.invoke(mockEventBatchWriter)
}
}

// When
testedWriter.writeAll(listOf(event))

// Then - should use withWriteContext
verify(mockFeature).withWriteContext(any(), any())
}
Copy link
Member

Choose a reason for hiding this comment

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

I'm not sure this test makes sense, we already assert that events are written in the tests above

}

@Test
fun `M serialize events correctly W writeAll() { events with all fields }`() {
Copy link
Member

Choose a reason for hiding this comment

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

I would suggest to start creating tests in the reliability/single-fit for that kind, it is a better place to verify E2E functionality.

}

@Test
fun `M write event with UTF-8 encoding W writeAll() { event provided }`(
Copy link
Member

Choose a reason for hiding this comment

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

same for this test

internal class EvaluationEventRecordWriter(private val sdkCore: FeatureSdkCore) : EvaluationEventWriter {
override fun writeAll(events: List<FlagEvaluation>) {
if (events.isEmpty()) return

Copy link
Member

Choose a reason for hiding this comment

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

one more thing: it is better to wrap a code block below synchronized(this) to avoid race condition when the same batch is accessed

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.

5 participants