Repository navigation
Conversation
|
|
🎉 All green!🧪 All tests passed 🔗 Commit SHA: d3cec03 | Docs | View more details | Give us feedback! |
5a23492 to
5fcbf37
Compare
2512fe2 to
1844814
Compare
5fcbf37 to
7b19f61
Compare
1844814 to
91a38de
Compare
There was a problem hiding this comment.
🟡 Changes recommended
Cycle assertions currently accept duplicate evaluations aggregated into a single event.
1 open finding
What changed in this PR
Adds telemetry validation to the dependent-flag evaluation coverage from #8049, with SDK activation remaining in #8050.
Changes:
- Adds evaluation-event extraction and telemetry matching.
- Checks graph telemetry, memoization, short-circuiting, and exposure rollback.
- Adds matcher self-tests and documents assertion timing.
| File | Description |
|---|---|
| tests/parametric/test_ffe/test-case-dependent-flags.json | Defines expected graph telemetry. |
| tests/ffe/utils/evaluations.py | Extracts evaluation events by flag and subject. |
| tests/ffe/utils/dependent_flags.py | Adds telemetry event matching. |
| tests/ffe/test_tests.py | Tests success and error matching. |
| tests/ffe/test_dependent_flags.py | Validates captured graph telemetry. |
| tests/ffe/README.md | Documents post-teardown telemetry assertions. |
🧠 Review effort: Balanced
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
7b19f61 to
36c286e
Compare
91a38de to
35e691d
Compare
36c286e to
e36f568
Compare
35e691d to
b9eaaf4
Compare
e36f568 to
deec34b
Compare
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
7b6040f to
bfa4296
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: c83c9287c6
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
a4767e8 to
2d637a9
Compare
Consume canonical dependent-suite expectations to assert graph evaluation events, exposure rollback, memoization, and short-circuit behavior without local fixture overlays. Environment: Datadog workspace Co-Authored-By: Codex GPT-5 <noreply@localhost>
Keep feature suites lazy and use corpus-owned drain markers with unambiguous telemetry correlation. Environment: Datadog workspace Co-Authored-By: Codex GPT-5 <noreply@localhost>
Honor logical evaluation counts and drain readiness retries before capturing corpus telemetry. Environment: Datadog workspace Co-Authored-By: Codex GPT-5 <noreply@localhost>
| complete = all(marker_events.values()) | ||
| for targeting_key, cases in grouped_cases.items(): | ||
| expected = _expected_events_for_cases(cases, platform) | ||
| if expected is None: |
There was a problem hiding this comment.
🤖 Comment from Claude working with Aaron Silverman:
[P2] Cases without expectations skip the telemetry check here, and the shared suite has gaps that this harness inherits.
- Six of the 14 cases have no
expectations, so the harness performs no telemetry assertions for them:dependent-direct,dependent-transitive,dependent-memoized,dependent-atomic-error,dependent-over-depthanddependent-cycle. For example, an SDK that sends the leaf exposure before the missing prerequisite abortsdependent-atomic-errorstill passes. - No case covers a configuration that contains a disabled prerequisite. The design forbids adding one; a case would pin what SDKs do if one arrives anyway.
- No case covers a prerequisite with
doLog: false, or a root withdoLog: falsewhose prerequisite logs. Exposure logging applies per flag. - No case covers a rule that matches but whose allocation selects no split, so the root falls through.
- No case covers non-
STRINGprerequisites (BOOLEAN,JSON). These check that the comparison uses the variant key, not the value. - Only
dependent-memoizedexercises a successfulNOT_ONE_OFcomparison, and it has no telemetry expectations. - No case covers the default depth (no
evaluatorParams) or an invalidmaxDependencyDepth. These need their own suite directories, becauseevaluatorParamsapplies to the whole configuration.
The suite lives in ffe-system-test-data. Expectations and cases added to the existing suite directory reach this harness once its snapshot is refreshed. New suite directories (for example, for depth limits) also need wiring here, because this module hard-codes the dependent-flags suite path. Until then, these telemetry assertions and configuration scenarios are missing from the shared suite.
| return events | ||
|
|
||
|
|
||
| def ffe_events_for_target( |
There was a problem hiding this comment.
🤖 Comment from Claude working with Aaron Silverman:
[P2] Three ways the dependent-flags telemetry check can pass when it should fail.
- Events without a matching identifier are dropped.
ffe_events_for_targetkeeps only events whose identifier (subject.idfor exposures,targeting_keyfor evaluation events) matches the raw key orsha256_<hex>. For a case with a targeting key, a forbidden prerequisite exposure with no subject, or with a key in another format, is never compared, sonoUnmatchedEventsstill passes. - Typos in
expectationsweaken the check without an error. A misspellednoUnmatchedEventturns off exact mode. A misspelledexposurekey makes the expected exposure list empty while exact mode stays on._count: trueis accepted as 1. - Remote Config bit 50 is never asserted.
Capabilities.FFE_FLAG_DEPENDENT_FLAG_VARIANT_KEY_V1is registered, but no test reads it. The test agent serves the dependent configuration to every SDK, so an otherwise correct SDK passes this test without advertising bit 50. Per the dependent-flags design, capability-gated delivery would then omit dependent flags for it.
I confirmed the first two by running the helper functions directly on synthetic events.
Suggested changes (sketches; I did not run them in the harness):
Suggested code
# Extend the existing import from utils.dd_constants with Capabilities.
# In test_ffe_dependent_flags, before _assert_evaluation_cases:
test_agent.assert_rc_capabilities({Capabilities.FFE_FLAG_DEPENDENT_FLAG_VARIANT_KEY_V1})Suggested code
_EXPECTATION_KEYS = frozenset({"exposures", "evaluationEvents", "noUnmatchedEvents"})
_MATCHER_KEYS = frozenset({"_count", "_skip", "_include", "allocation", "errorCode", "flag", "runtimeDefaultUsed", "variant"})
def _validate_expectations(case):
exp = case["expectations"]
assert isinstance(exp, dict) and exp.keys() <= _EXPECTATION_KEYS, f"unknown expectation keys: {sorted(exp)}"
assert type(exp.get("noUnmatchedEvents", False)) is bool
for kind in ("exposures", "evaluationEvents"):
for matcher in exp.get(kind, []):
assert isinstance(matcher, dict), f"{kind} matcher must be an object"
assert matcher.keys() <= _MATCHER_KEYS, f"unknown {kind} matcher fields {sorted(matcher.keys() - _MATCHER_KEYS)}"
# Call it for each case that has "expectations", before Remote Config setup.Also change isinstance(count, int) to type(count) is int, and fail on events that no case targeting key (or the drain and readiness markers) can claim.
| if "features" in case["result"] | ||
| ] | ||
| DEPENDENT_FLAGS_UFC_DATA, DEPENDENT_FLAGS_TEST_CASE_FILES = _load_dependent_flags_suite() | ||
| DEPENDENT_FLAGS_UFC_PATH, DEPENDENT_FLAGS_TEST_CASE_FILES = _load_evaluation_suite( |
There was a problem hiding this comment.
🤖 Comment from Claude working with Aaron Silverman:
Heads up: three per-SDK activation PRs that build on this one enable the dependent-flags test for SDK versions that are already released and likely do not implement the feature.
| Activation PR | Manifest gate for test_ffe_dependent_flags |
Effect |
|---|---|---|
| #8050 (Node.js) | *ref_5_77_0 |
enabled for released Node.js versions from 5.77.0 on |
| #8230 (.NET) | v3.57.0-dev |
enabled for released .NET 3.57.0 |
| #8231 (PHP) | v1.26.0-dev |
enabled for released PHP 1.26.x |
The Node.js tracer, .NET and PHP implementation PRs for this feature (DataDog/dd-trace-js#10749, DataDog/dd-trace-dotnet#9589, DataDog/dd-trace-php#4421) have not merged, and Node.js 6.23.0, .NET 3.57.0 and PHP 1.26.2 are published releases. So these gates would likely run the test against released SDKs that do not implement dependent flags. Gate each on the first version that will contain the feature, or keep missing_feature on main and use the branch override for branch CI. Also, #8050, #8231 and #8235 target SDK branches that have no PR (for Node.js, a branch other than DataDog/dd-trace-js#10749).
Refresh the dependent flag telemetry tests against current system-tests main. Environment: Datadog workspace Co-Authored-By: Codex GPT-5 <noreply@localhost>

Motivation
#8260 has landed the canonical rules-based corpus and feature-suite import on
main. This PR makes the existing dynamic-evaluation harness consume optional telemetry expectations through the same suite-directory-driven execution path used for result assertions. Core cases, dependent flags, and later feature suites therefore share one runner while retaining separate manifest activation nodes.Changes
ffe_events_from_requestshelper to distinguish an explicit null targeting key from no filter and to filter already-decoded events by raw or hashed targeting key_skip/_includeannotationsdoLog=trueflag as the post-batch marker and wait for both telemetry writers before checking event absence or exact countstest_ffe_flag_evaluationandtest_ffe_dependent_flagsas separate manifest activation nodes; each node differs only in the suite directory supplied to the common harnessffe-system-test-dataValidation:
./format.sh— passed, including repository-wide mypy, import policy, Ruff, YAML, parser, shell, and fixture checksgit diff --check— passedtests/test_the_test/test_ffe_split_features.pyinvocation could not start because the localsystem_tests/weblogimage is absent; no test-harness tests were addedStack:
main; test(ffe): import canonical feature suites #8260 and test(ffe): register dependent flag RC capability #8293 are mergedWorkflow
system-tests-reviewers: ask one of your coworkers familiar with the tested feature.system-tests-core(slack)🚀 Once your PR is reviewed and the CI green, you can merge it!
🛟 #apm-shared-testing 🛟