Skip to content

feat(openfeature): support dependent flags on Python delivery paths - #21346

Open
hhan2024 wants to merge 14 commits into
helen/dependent-flags-python-rcfrom
helen/python-dependent-flags-support
Open

hhan2024 wants to merge 14 commits into
helen/dependent-flags-python-rcfrom
helen/python-dependent-flags-support

Conversation

@hhan2024

@hhan2024 hhan2024 commented Oct 28, 2026 •

Copy link
Copy Markdown

Description

Enables variant-key prerequisite flag evaluation for Python server applications using agentless HTTP or Agent Remote Configuration. Agentless delivery advertises cap_dependent-flags-variant-key=v1; Agent RC advertises capability bit 50.

Each root call records reached prerequisites once, including errors and prerequisites on rejected paths. Exposure events require the selected allocation's doLog and membership in the successful dependency path. Root and prerequisite exposures are staged until all OpenFeature application hooks succeed; failed calls neither enqueue exposures nor populate the deduplication cache. Re-entrant and overlapping calls retain independent batches, and direct provider calls preserve their existing reporting behavior.

Pins libdatadog to cb3bfba0d51adba06f9afca32841573fa7bad0b3 from #2748, including error records for depth-rejected prerequisites, the public trace constructor/diagnostics updates, and current main's trace-stats session-token fix. PyO3 and its build dependencies are aligned to 0.30, which that native baseline requires; deprecated extraction opt-out annotations are removed because opt-out is now the default. Preserves per-root memoization, caller-default behavior on dependency failures, entry-time consent, and independent-flag compatibility. Native allocation metadata remains lazily constructed.

Validation

  • Full OpenFeature suite, Python 3.11: OpenFeature 0.8.4 1,265 passed, 3 skipped; OpenFeature 0.10 1,268 passed.
  • All 31 native Rust tests, exact native CI Clippy/format commands, startup smoke, and repository lint passed.
  • The asynchronous-client rollback/retry regression is included in both full OpenFeature runs.
  • Regressions cover later-hook rollback without cache admission, successful retries, re-entrant and overlapping evaluations, before-hook failures, depth-limit error events, fallback exposure eligibility, rejected paths, and deduplication.
  • Tyler Potter's shared telemetry harness, system-tests #8051, passed against the earlier consumer revision and its rebuilt native extension: 1 passed, exercising all 14 canonical dependent-flag cases. The blocking built-wheel CI job reruns it for the updated native pin.
  • Adds a blocking GitLab job that runs that suite against the built wheel and uses -F so the unreleased-feature declaration cannot hide failures. The job pins harness commit d3cec0314166889cf31555252c94d94b9140c4d8; existing system-test jobs retain their pins. Release-wide activation remains in system-tests #8233.
  • Native-resolution benchmarks against previous PR head 878c1b75c72d7b524236e374f25ed530d0bee694 completed with 60 samples per configuration: static 602 ± 21 ns → 606 ± 40 ns; targeting 653 ± 44 ns → 652 ± 47 ns (mean ± standard deviation). Neither configuration reports a significant regression. Samples overlap and show shared-host jitter; these measure the independent native binding, not the provider hook lifecycle. Artifacts: run 5cd6eaa3-2ab5-4d48-9f86-dd8dac28d146.
  • Repository lint checks, targeted typing, type-comment checks, and whitespace checks pass. Import analysis finds no cycles and no new dependency-direction violations.

Compatibility and remaining validation

Stacked on #21336 and consumes libdatadog #2748. The native revision is unreleased and the source-build Rust minimum is 1.91.1. Replace the temporary pin with an approved merged revision before release. Local suite coverage is Linux x86_64 / Python 3.11, plus the optimized benchmark wheel on Python 3.12; release-wheel and supported-platform validation remains with CI. The system-test run used the documented local-source mount, while the added CI job consumes release wheels.

Evaluate prerequisites with ordered memoized native evaluation and preserve eligible exposures across agentless and Agent Remote Configuration delivery.

Environment: Datadog workspace

Co-Authored-By: Codex GPT-6 <noreply@localhost>
@cit-pr-commenter-54b7da

cit-pr-commenter-54b7da Bot commented Oct 28, 2026 •

Copy link
Copy Markdown

Codeowners resolved as

Resolved from the full PR diff against helen/dependent-flags-python-rc using the target branch CODEOWNERS file.
CODEOWNERS team requests not listed below are not required by the current file set.

.github/CODEOWNERS                                                      @DataDog/python-guild @DataDog/apm-core-python
.github/workflows/system-tests.yml                                      @DataDog/python-guild @DataDog/apm-core-python
.gitlab-ci.yml                                                          @DataDog/python-guild @DataDog/apm-core-python
.gitlab/benchmarks/slos/feature-flagging-and-experimentation-sdk.yml    @DataDog/feature-flagging-and-experimentation-sdk
.gitlab/system-tests.yml                                                @DataDog/python-guild @DataDog/apm-core-python
benchmarks/Dockerfile                                                   @DataDog/apm-core-python
benchmarks/openfeature_resolution/config.yaml                           @DataDog/apm-core-python
benchmarks/openfeature_resolution/scenario.py                           @DataDog/apm-core-python
benchmarks/suitespec.yml                                                @DataDog/apm-core-python
ddtrace/internal/native/_native.pyi                                     @DataDog/apm-core-python
ddtrace/internal/openfeature/_agentless_source.py                       @DataDog/feature-flagging-and-experimentation-sdk
ddtrace/internal/openfeature/_exposure_hook.py                          @DataDog/feature-flagging-and-experimentation-sdk
ddtrace/internal/openfeature/_native.py                                 @DataDog/feature-flagging-and-experimentation-sdk
ddtrace/internal/openfeature/_provider.py                               @DataDog/feature-flagging-and-experimentation-sdk
releasenotes/notes/openfeature-dependent-flags-725402cf9da064ca.yaml    @DataDog/apm-python
setup.py                                                                @DataDog/python-guild
src/native/Cargo.lock                                                   @DataDog/apm-core-python
src/native/Cargo.toml                                                   @DataDog/apm-core-python
src/native/crashtracker.rs                                              @DataDog/profiling-python @DataDog/apm-core-python
src/native/ffe.rs                                                       @DataDog/feature-flagging-and-experimentation-sdk
src/native/py_string.rs                                                 @DataDog/apm-core-python
src/native/remote_config.rs                                             @DataDog/apm-core-python
tests/openfeature/test_agentless_poller.py                              @DataDog/feature-flagging-and-experimentation-sdk
tests/openfeature/test_dependent_flag_delivery.py                       @DataDog/feature-flagging-and-experimentation-sdk
tests/openfeature/test_dependent_flags.py                               @DataDog/feature-flagging-and-experimentation-sdk
tests/openfeature/test_flag_eval_evp_hook.py                            @DataDog/feature-flagging-and-experimentation-sdk
tests/openfeature/test_native_resolution.py                             @DataDog/feature-flagging-and-experimentation-sdk
tests/openfeature/test_provider_exposure.py                             @DataDog/feature-flagging-and-experimentation-sdk
tests/openfeature/test_remoteconfig.py                                  @DataDog/feature-flagging-and-experimentation-sdk

@cit-pr-commenter-54b7da

cit-pr-commenter-54b7da Bot commented Oct 28, 2026 •

Copy link
Copy Markdown

Dependency direction analysis

⚠️ Existing dependency direction violations

There are 104 dependency direction violations that already exist on the base branch and have not been changed by this PR.

Show existing violations (showing 5 of 104 highest severity)
ddtrace.internal.tracemethods -×-> ddtrace.trace  (internal-core -> product:tracing, score=122)
ddtrace.aiguard._api_client -×-> ddtrace.trace  (product:aiguard -> product:tracing, score=120)
ddtrace.llmobs._integrations.bedrock -×-> ddtrace.trace  (product:llmobs -> product:tracing, score=120)
ddtrace.llmobs._integrations.langchain -×-> ddtrace.trace  (product:llmobs -> product:tracing, score=120)
ddtrace.llmobs._integrations.bedrock_agents -×-> ddtrace.trace  (product:llmobs -> product:tracing, score=120)

To see all violations, download the layers-base.json and layers-pr.json artifacts from this CI job and run:

uv run --script scripts/import-analysis/layers.py compare layers-base.json layers-pr.json

@datadog-datadog-prod-us1

datadog-datadog-prod-us1 Bot commented Oct 28, 2026 •

Copy link
Copy Markdown
Contributor

Pipelines  Tests

✨ Unblock PR with BitsAI

❌ Errors

Your PR has failed checks. Please review the issues below and take necessary action before merging.

🚦 4 Pipeline jobs failed

System Tests | tracer-release / parametric / parametric (1) — ❌ 15 tests failed

View more details · View in GitHub Actions

❌ tests.parametric.test_ffe.test_configuration_sources.Test_Feature_Flag_Configuration_Source_Cold_Failure_And_Recovery.test_bad_to_good_cold_recovery[server-e... from system_tests_suite
mock FFE agentless backend status did not reach expected state: bad_to_good 500 to 200 recovery; status={&#39;requests_total&#39;: 0, &#39;in_flight&#39;: 0, &#39;max_in_flight&#39;: 0, &#39;last_path&#39;: None, &#39;last_if_none_match&#39;: None, &#39;observed_dd_api_key&#39;: None, &#39;last_status_code&#39;: None, &#39;status_codes&#39;: []}
❌ tests.parametric.test_ffe.test_configuration_sources.Test_Feature_Flag_Configuration_Source_Cold_Failure_And_Recovery.test_bad_to_unchanged_cold_preserves_no... from system_tests_suite
mock FFE agentless backend status did not reach expected state: bad_to_unchanged 500 to 304 cold sequence; status={&#39;requests_total&#39;: 0, &#39;in_flight&#39;: 0, &#39;max_in_flight&#39;: 0, &#39;last_path&#39;: None, &#39;last_if_none_match&#39;: None, &#39;observed_dd_api_key&#39;: None, &#39;last_status_code&#39;: None, &#39;status_codes&#39;: []}
↳ and 13 more — View all
DDCI - DataDog/dd-trace-py | system-tests parametric — 🔧 Needs a code fix, caused by this PR

View more details · View in DDCI

DataDog/apm-reliability/dd-trace-py | system-tests parametric — 🔄 Retry may pass, looks flaky

View more details · View in GitLab

View all 4 failed jobs.

ℹ️ Info

No other issues found (see more)

❄️ No new flaky tests detected

Useful? React with 👍 / 👎

This comment will be updated automatically if new data arrives.
🔗 Commit SHA: 06a741f | Docs | View more details | Give us feedback!

Preserve the independent-flag evaluation path while retaining prerequisite evaluation and exposure records.

Environment: Datadog workspace

Co-Authored-By: Codex GPT-6 <noreply@localhost>
@pr-commenter

pr-commenter Bot commented Oct 28, 2026 •

Copy link
Copy Markdown

Benchmarks

Benchmark execution time: 2026-11-06 23:01:08

Comparing candidate commit 06a741f in PR branch helen/python-dependent-flags-support with baseline commit 12e0e8c in branch helen/dependent-flags-python-rc.

📊 Benchmarking dashboard

Found 12 performance improvements and 0 performance regressions! Performance is the same for 604 metrics, 10 unstable metrics, 1 flaky benchmarks without significant changes.

Explanation

This is an A/B test comparing a candidate commit's performance against that of a baseline commit. Performance changes are noted in the tables below as:

  • 🟩 = significantly better candidate vs. baseline
  • 🟥 = significantly worse candidate vs. baseline

We compute a confidence interval (CI) over the relative difference of means between metrics from the candidate and baseline commits, considering the baseline as the reference.

If the CI is entirely outside the configured SIGNIFICANT_IMPACT_THRESHOLD (or the deprecated UNCONFIDENCE_THRESHOLD), the change is considered significant.

Feel free to reach out to #apm-benchmarking-platform on Slack if you have any questions.

More details about the CI and significant changes

You can imagine this CI as a range of values that is likely to contain the true difference of means between the candidate and baseline commits.

CIs of the difference of means are often centered around 0%, because often changes are not that big:

---------------------------------(------|---^--------)-------------------------------->
                              -0.6%    0%  0.3%     +1.2%
                                 |          |        |
         lower bound of the CI --'          |        |
sample mean (center of the CI) -------------'        |
         upper bound of the CI ----------------------'

As described above, a change is considered significant if the CI is entirely outside the configured SIGNIFICANT_IMPACT_THRESHOLD (or the deprecated UNCONFIDENCE_THRESHOLD).

For instance, for an execution time metric, this confidence interval indicates a significantly worse performance:

----------------------------------------|---------|---(---------^---------)---------->
                                       0%        1%  1.3%      2.2%      3.1%
                                                  |   |         |         |
       significant impact threshold --------------'   |         |         |
                      lower bound of CI --------------'         |         |
       sample mean (center of the CI) --------------------------'         |
                      upper bound of CI ----------------------------------'

scenario:coreapiscenario-core_dispatch_exception_no_listeners

  • 🟩 execution_time [-39.312ns; -31.348ns] or [-17.625%; -14.055%]

scenario:coreapiscenario-core_dispatch_no_args_no_listeners

  • 🟩 execution_time [-42.605ns; -34.631ns] or [-19.125%; -15.546%]

scenario:coreapiscenario-core_dispatch_no_listeners

  • 🟩 execution_time [-38.061ns; -29.832ns] or [-17.015%; -13.336%]

scenario:coreapiscenario-core_dispatch_with_results_no_listeners

  • 🟩 execution_time [-41.636ns; -33.108ns] or [-18.781%; -14.934%]

scenario:coreapiscenario-has_listeners_no_listeners

  • 🟩 execution_time [-41.716ns; -33.111ns] or [-19.781%; -15.700%]

scenario:coreapiscenario-has_listeners_with_listeners

  • 🟩 execution_time [-42.600ns; -33.086ns] or [-18.964%; -14.729%]

scenario:httppropagationextract-empty_headers

  • 🟩 execution_time [-101.610ns; -90.539ns] or [-13.165%; -11.731%]

scenario:httppropagationextract-wsgi_empty_headers

  • 🟩 execution_time [-106.149ns; -96.513ns] or [-13.713%; -12.468%]

scenario:httppropagationextract-wsgi_invalid_span_id_header

  • 🟩 execution_time [-102.288ns; -88.502ns] or [-13.210%; -11.429%]

scenario:otelspan-add-tags

  • 🟩 execution_time [-12.546ms; -11.601ms] or [-8.966%; -8.291%]

scenario:rand-rand128bits

  • 🟩 execution_time [-22.107ns; -19.290ns] or [-11.417%; -9.962%]

scenario:rand-rand64bits

  • 🟩 execution_time [-14.213ns; -12.428ns] or [-11.710%; -10.239%]

Unstable benchmarks

These benchmarks have a confidence interval too wide to call a change; treat them as noise rather than signal.

scenario:coreapiscenario-context_with_data_listeners

  • unstable execution_time [-690.474ns; +766.910ns] or [-6.468%; +7.184%]

scenario:coreapiscenario-core_dispatch_1_listener

  • unstable execution_time [-70.117ns; +1.414ns] or [-10.202%; +0.206%]

scenario:coreapiscenario-core_dispatch_50_listeners

  • unstable execution_time [-1683.416ns; +2157.437ns] or [-8.472%; +10.857%]

scenario:coreapiscenario-core_dispatch_exception_listeners

  • unstable execution_time [-2257.070ns; +1426.405ns] or [-11.551%; +7.300%]

scenario:coreapiscenario-core_dispatch_listeners

  • unstable execution_time [-379.980ns; +376.851ns] or [-8.886%; +8.812%]

scenario:coreapiscenario-core_dispatch_no_args_listeners

  • unstable execution_time [-220.917ns; +231.783ns] or [-8.194%; +8.597%]

scenario:coreapiscenario-core_dispatch_with_results_1_listener

  • unstable execution_time [-167.027ns; +8.745ns] or [-11.931%; +0.625%]

scenario:coreapiscenario-core_dispatch_with_results_50_listeners

  • unstable execution_time [-6.819µs; +2.542µs] or [-13.653%; +5.089%]

scenario:coreapiscenario-core_dispatch_with_results_listeners

  • unstable execution_time [-1433.810ns; +484.190ns] or [-13.521%; +4.566%]

scenario:packagesupdateimporteddependencies-import_many_stdlib_cached

  • unstable execution_time [-60.502µs; +50.149µs] or [-10.255%; +8.501%]

Known flaky benchmarks

These benchmarks are marked as flaky and will not trigger a failure. Modify FLAKY_BENCHMARKS_REGEX to control which benchmarks are marked as flaky.

Known flaky benchmarks without significant changes:

  • scenario:packagespackageforrootmodulemapping-cache_off

Comment thread src/native/ffe.rs Resolved
Comment thread src/native/ffe.rs Resolved
Pin the shared harness revision that registers RC capability bit 50, fixing parametric capability validation failures in GitHub and GitLab CI.

System-tests fix: DataDog/system-tests#8293

Environment: Datadog workspace

Co-Authored-By: Codex GPT-6 <noreply@localhost>
Keep configuration delivery enabled when native capability discovery raises, and include the effective capability header in agentless startup diagnostics. Cover reporter failures in both delivery paths and supported/unsupported startup diagnostics.

Environment: Datadog workspace

Co-Authored-By: Codex GPT-6 <noreply@localhost>
@hhan2024
hhan2024 marked this pull request as ready for review November 2, 2026 17:40
@hhan2024
hhan2024 requested review from a team as code owners November 2, 2026 17:40
@hhan2024
hhan2024 requested review from juanjux and vlad-scherbich and removed request for a team November 2, 2026 17:40
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Nov 2, 2026 •

Copy link
Copy Markdown
Codex Review Summary: ✅ Completed

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-11-06T22:43:08.359610Z 06a741f New commits
🔒 Security Review ✅ Completed 2026-11-06T22:43:13.054643Z 06a741f New commits
ℹ️ 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" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1007b76502

ℹ️ 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".

@datadog-datadog-prod-us1 datadog-datadog-prod-us1 Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Bits Code Review: PASS

More details

The pinned libdatadog evaluator internals were unavailable for inspection, so prerequisite evaluation semantics and runtime delivery behavior remain unverified.

Was this helpful? React 👍 or 👎

Open Bits AI session

🤖 Bits Code Review · Commit 1007b76

@leoromanovsky

leoromanovsky commented Nov 2, 2026 •

Copy link
Copy Markdown
Contributor

FFE reviewer selection

Reviewers: @sameerank

Why: Dependent Flags — The PR turns on prerequisite (dependent) flag evaluation in the Python SDK. Reviewers come from the matched pod.

🤖 Automated selection.

Selection details

Initiative: project / dependent-flags

Why this match: The PR turns on prerequisite (dependent) flag evaluation in the Python SDK. The native binding now advertises dependent-flag-variant-key-v1 and returns per-prerequisite evaluation records. The provider records each prerequisite evaluation it reaches and reports exposures only for prerequisites that contributed to the assignment. Agentless HTTP and Remote Configuration delivery send the capability. Package-manager pin changes only support this work.

Why these owners: Eligible reviewers have already approved the current head; no additional reviewers are needed for the responsibilities those approvals cover.

  • @sameerank — floating (dependent-flags): Coverage and knowledge sharing. Covers: openfeature-architecture. Existing review coverage preserved.

Additional review: openfeature-architecture — The PR changes shared provider and native contracts beyond dependent-flag logic. Every flag resolution now goes through eval_flag_with_trace instead of get_assignment, with a measured 9–10% overhead. The ResolutionDetails native result type gains a new field. The tracer/native capability handshake is now fail-safe, so a failing reporter advertises no capabilities for both agentless and RC sources. The provider's evaluation, metrics and exposure paths gain extra per-prerequisite event emission. Coverage: @sameerank. Evidence: src/native/ffe.rs, ddtrace/internal/openfeature/_native.py, ddtrace/internal/openfeature/_provider.py

The PR author was excluded. Existing reviewers and teams were preserved.

Debug or fix a problem

Workflow run · Bits Code session

  • Wrong project or pod? Clarify this PR’s purpose, or correct the reviewer registry and publish the change. Sheet edits take effect after publication.
  • Need another reviewer now? Request them in GitHub. This workflow only adds requests and keeps existing reviewers.
  • Stuck beyond five minutes or failed? Inspect the run’s failed step and available Bits session. After fixing the cause, rerun the workflow with this PR URL and dry_run=false. Unchanged completed runs are skipped. If the receipt says needs_reconciliation or a write outcome is uncertain, ask the workflow owner to reconcile GitHub and the receipt before retrying; do not delete the lock blindly.
  • Report a problem: Comment on the reviewer-routing skill PR with this PR URL, the workflow run link, and the expected initiative or reviewer correction.
Evidence and run details

✅ Complete — reviewer coverage verified. The workflow checked pending requests or submitted reviews on the evaluated head.

Generated asynchronously by the FFE reviewer-routing workflow.

Changed paths: src/native/ffe.rs, ddtrace/internal/openfeature/_provider.py, ddtrace/internal/openfeature/_agentless_source.py, ddtrace/internal/native/_native.pyi, tests/openfeature/test_dependent_flags.py, tests/openfeature/test_dependent_flag_delivery.py

Evaluated head: 1007b7650260496aa15e6516a7e80bb403d0c6c2

Registry revision: revision:fe6a8bb4-aeba-4b6e-af89-db919eb47638

Pinned skill source: 7e3283c602f6b18a7e3e623eecb52d3a9c091a2e

Instructions: workflow-injected snapshot (no plugin loaded)

Instruction snapshot SHA-256: 52ed8cb68675dde1a47addaefe4a9500891c24014abf7dade6dfe38cf836c1d2

Comment thread .github/workflows/system-tests.yml Resolved
hhan2024 and others added 2 commits November 3, 2026 22:49
Keep independent evaluations compatible with older native results, cover both consent transitions, use the merged system-tests pin, and register measured native-resolution benchmark gates.

Environment: Datadog workspace

Co-Authored-By: Codex GPT-6 <noreply@localhost>
Set native-resolution limits about 10% above measured CI candidate means and record the calibration pipeline, preserving regression gates for both configurations.

Environment: Datadog workspace

Co-Authored-By: Codex GPT-6 <noreply@localhost>

hhan2024 commented Nov 4, 2026

Copy link
Copy Markdown
Author

Calibrated the new native-resolution gates in 5554077 from CI release-wheel measurements, rather than workspace A/A timings.

The raw artifacts from benchmark job 2209594150 compare stacked baseline 12e0e8c with candidate 59d7347 on the same runner:

Configuration Baseline mean ± SD Candidate mean ± SD Change New absolute SLO
Static 800.12 ± 15.78 ns 858.97 ± 11.30 ns +58.85 ns / +7.36% 950 ns
Targeting 855.21 ± 27.30 ns 912.62 ± 9.96 ns +57.41 ns / +6.71% 1,010 ns

Each configuration has 60 samples per wheel; sample-size and autocorrelation warnings still apply. The platform's unchanged summary should not obscure the measured increase in the raw samples.

This accepts the already documented independent-flag cost of the dependent-evaluator upgrade and prerequisite trace support. The native independent-flag fast path remains enabled. The old 800/850 ns limits were at or below the CI baseline; the new limits retain about 10.6% headroom above the CI candidate and continue to gate both configurations. This follow-up changes only the two thresholds and calibration comments.

Full repository lint checks and generated CI validation pass. A fresh pipeline will rerun the benchmark jobs before the gate; the gate is not being bypassed.

hhan2024 commented Nov 4, 2026

Copy link
Copy Markdown
Author

Fresh verification on 5554077 completed: OpenFeature benchmark job and check-slo-breaches both pass.

The gate reports static resolution 851.017–856.481 ns < 950 ns and targeting 914.175–920.739 ns < 1,010 ns. Functional test child pipeline 150033308 also passed.

This resolves the benchmark-limit failure by CI calibration. It does not eliminate the native performance cost: the fresh raw means compare baseline/candidate 793.50 → 853.75 ns for static (+7.59%) and 848.97 → 917.46 ns for targeting (+8.07%).

Build allocation metadata only when requested and restore the original independent-resolution benchmark limits.

Environment: Datadog workspace

Co-Authored-By: Codex GPT-6 <noreply@localhost>
Comment thread src/native/Cargo.toml Outdated
# Keep libdatadog crates on one mainline revision to share native types.
# This adds prerequisite evaluation and its Remote Configuration capability:
# https://github.com/DataDog/libdatadog/pull/2748
libdd-ffe = { git = "https://github.com/DataDog/libdatadog", rev = "1cf7834903025181d51480bc6a5a6a174e4e7b47", optional = true, features = ["pyo3"] }

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🤖 Comment from Claude working with Aaron Silverman:

Heads up: This pin would regress main and does not match the current DataDog/libdatadog#2748 head. Please keep this PR unmerged until DataDog/libdatadog#2748 is merged and released.

Suggested order: rebase DataDog/libdatadog#2748 on libdatadog main (which brings in f42b3ab), merge and release it. Then pin all crates here to that release and update the tests that encode 1cf7834 behavior.

Comment thread src/native/ffe.rs Resolved
typotter and others added 4 commits November 4, 2026 15:57
## Description

Move direct UFC dependent-flags negotiation from the capabilities header
to the `cap_dependent-flags-variant-key=v1` query parameter. Existing
endpoint query parameters are preserved, and the end-to-end local
delivery fixture now selects dependent configurations from that
parameter while Remote Config negotiation remains unchanged.

## Testing

- Python AST parsing and `git diff --check` pass.
- The mandated OpenFeature test runner could not execute: its image pull
filled the workspace filesystem, and environment setup failed with
`ENOSPC` before tests started.

## Risks

Scoped to agentless UFC request construction and its local delivery
fixture. Reverting this PR restores the header transport.

## Additional Notes

No release note: this corrects the transport contract within the
unmerged dependent-flags base PR and does not independently expose a
released customer feature.
Stage graph exposures per evaluation and publish/cache them only after successful finalization. Preserve prerequisite evaluations on failures, consume the corrected native depth telemetry, and activate shared dependency telemetry system tests in CI.

Environment: Datadog workspace

Co-Authored-By: Codex GPT-6 <noreply@localhost>
Verify asynchronous OpenFeature clients preserve prerequisite evaluation events while discarding failed graph exposures and cache admission on both supported SDK versions.

Environment: Datadog workspace

Co-Authored-By: Codex GPT-6 <noreply@localhost>
Run feature tests before the shared after-script exchanges credentials and tags the job. Preserve framework tagging on both jobs without requiring an API key before the dependent-flag test starts.

Environment: Datadog workspace

Co-Authored-By: Codex GPT-6 <noreply@localhost>
Use the updated prerequisite evaluator and current main fixes, align PyO3 with its native dependencies, and preserve extraction behavior under PyO3 0.30.

Environment: Datadog workspace

Co-Authored-By: Codex GPT-6 <noreply@localhost>
@hhan2024
hhan2024 requested a review from a team as a code owner November 6, 2026 22:37
@hhan2024
hhan2024 requested a review from taegyunkim November 6, 2026 22:37

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 06a741f0c7

ℹ️ 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".

Comment on lines +326 to +328
parameter = _dependent_flags_variant_key_parameter()
if parameter is None:
return urlunsplit(("", "", self._request_path, self._request_query, "")) or "/"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Strip unsupported capability parameters from custom URLs

When an older native extension is used with a custom endpoint that already contains cap_dependent-flags-variant-key=v1, the parameter is None branch returns the original query unchanged, so the request still advertises dependent-flag support even though capability discovery explicitly reported none. The server may then return a dependent configuration that the loaded evaluator cannot process; parse and remove this parameter regardless of support, and append v1 only when the evaluator advertises it.

Useful? React with 👍 / 👎.

@datadog-datadog-prod-us1 datadog-datadog-prod-us1 Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Bits Code Review: FAIL

A fork during exposure publication can permanently stall flag evaluation in the child. The same provider-wide lock also lets slow exposure delivery block concurrent cached evaluations.

Open Bits AI session

🤖 Bits Code Review · Commit 06a741f

self._exposure_cache: LRUCache[
tuple[str, str], tuple[typing.Optional[str], typing.Optional[str], typing.Optional[int]]
] = LRUCache(maxsize=65536)
self._exposure_lock = RLock()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2 Reset the exposure lock after fork

If another application thread holds this lock when the process forks, the child inherits a locked primitive whose owner no longer exists. Subsequent exposure-producing evaluations, including cache hits, can hang indefinitely. The imported RLock is a plain _thread.RLock, and this provider never resets it after fork. Use forksafe.RLock and update its import.

React: 👍 useful · 👎 wrong · 😕 unclear · 👀 right, but not acting on it

What each reaction means
  • 👍 Useful: correct, and you're fixing it or will.
  • 👎 Wrong: the finding is incorrect, for example the bug can't happen or the code was misread.
  • 😕 Unclear: you can't tell what it means or why it matters.
  • 👀 Right, not acting: correct, but intended, out of scope for this PR, a known risk, or too minor.

🤖 Bits Code Review · Open Bits AI session

with self._exposure_lock:
if self._exposure_cache.get(key, None) == value:
return
get_exposure_writer().enqueue(event)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2 Keep synchronous delivery outside the exposure cache lock

ExposureWriter.enqueue() synchronously flushes over HTTP when buffering another event would exceed the 5 MiB payload limit. Holding the provider-wide lock across enqueue makes concurrent exposure-producing evaluations wait for delivery timeouts and retries, including cached flag/subject pairs that previously bypassed the writer. Keep blocking delivery outside the cache lock while preserving concurrent deduplication and admission only after successful enqueue.

React: 👍 useful · 👎 wrong · 😕 unclear · 👀 right, but not acting on it

What each reaction means
  • 👍 Useful: correct, and you're fixing it or will.
  • 👎 Wrong: the finding is incorrect, for example the bug can't happen or the code was misread.
  • 😕 Unclear: you can't tell what it means or why it matters.
  • 👀 Right, not acting: correct, but intended, out of scope for this PR, a known risk, or too minor.

🤖 Bits Code Review · Open Bits AI session

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

crucible: reviewing A Crucible review has started; this PR has reviewer attention.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants