Skip to content

feat(ffe): expose prerequisite evaluations through C FFI - #2791

Open
hhan2024 wants to merge 2 commits into
helen/ffe-dependent-flags-evaluatorfrom
helen/dependent-flags-sdk-ffi
Open

hhan2024 wants to merge 2 commits into
helen/ffe-dependent-flags-evaluatorfrom
helen/dependent-flags-sdk-ffi

Conversation

@hhan2024

@hhan2024 hhan2024 commented Nov 3, 2026 •

Copy link
Copy Markdown
Contributor

Ruby calls the shared Rust feature-flag evaluator through its existing C extension and libdatadog's C FFI. The evaluator can now evaluate prerequisite flags, but the C FFI currently drops those prerequisite observations when converting the result into a resolution handle. Ruby therefore cannot report the prerequisite evaluations and eligible exposures associated with a dependent-flag assignment.

This PR carries those observations across the C FFI boundary so dd-trace-rb #6613 can consume them:

Ruby OpenFeature provider
  ↕ Ruby C extension                       dd-trace-rb #6613
  ↕ libdatadog C FFI prerequisite accessors this PR
  ↕ Shared Rust dependent-flag evaluator   libdatadog #2748

The accessors expose each reached prerequisite's flag key, evaluation result (including errors), and exposure eligibility. The Ruby integration uses these results to report prerequisite evaluation counts/metrics and eligible exposures, respecting the evaluator's decisions about which prerequisites contributed to the assignment. Each child result is independently owned and remains valid after the root result and configuration are freed.

This is an extension of the native bridge used by Ruby; it does not introduce a standalone C feature-flagging SDK. Dependent-flag evaluation logic lives in #2748. Ruby-side capability advertisement, result consumption, and telemetry are implemented in dd-trace-rb #6613.

Stacked on #2748; this diff contains only the FFI integration and its tests. Ruby's release dependency must be updated to a published libdatadog package containing both PRs before default installations can enable dependent-flag support.

Updated on #2748 at cb3bfba0d51adba06f9afca32841573fa7bad0b3, which includes main at 7195c2d and the trace-stats session-token fix. The merge preserves split feature metadata together with prerequisite observations.

Validation: 12 FFI unit tests and doc tests; cargo check, Clippy and formatting; AST checks (existing repository warnings); C FFI ownership example compiled and passed through cargo ffi-test --skip-build --filter ffe_dependencies. An earlier Ruby consumer run passed 991 OpenFeature examples against a clean local build; the updated native stack has been validated with the FFI suite and a freshly built C ownership example.

Expose owned prerequisite results and exposure eligibility for server SDK integrations.

Environment: Datadog workspace

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

github-actions Bot commented Nov 3, 2026 •

Copy link
Copy Markdown
Contributor

📚 Documentation Check Results

⚠️ 541 documentation warning(s) found

📦 libdd-ffe-ffi - 541 warning(s)


Updated: 2026-11-06 22:29:09 UTC | Commit: 6d41925 | missing-docs job results

@github-actions

github-actions Bot commented Nov 3, 2026 •

Copy link
Copy Markdown
Contributor

🔒 Cargo Deny Results

⚠️ 6 issue(s) found, showing only errors (advisories, bans, sources)

📦 libdd-ffe-ffi - 6 error(s)

Show output
info: syncing channel updates for 1.91.1-x86_64-unknown-linux-gnu
info: latest update on 2025-11-10 for version 1.91.1 (ed61e7d7e 2025-11-07)
info: downloading 6 components
warn: the missing active toolchain `1.91.1-x86_64-unknown-linux-gnu` has been auto-installed
warn: this might cause rustup commands to take longer time to finish than expected
info: you may opt out with `RUSTUP_AUTO_INSTALL=0` or `rustup set auto-install disable`
error[unmaintained]: Bincode is unmaintained
   ┌─ /home/runner/work/libdatadog/libdatadog/Cargo.lock:25:1
   │
25 │ bincode 1.3.3 registry+https://github.com/rust-lang/crates.io-index
   │ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ unmaintained advisory detected
   │
   ├ ID: RUSTSEC-2025-0141
   ├ Advisory: https://rustsec.org/advisories/RUSTSEC-2025-0141
   ├ Due to a doxxing and harassment incident, the bincode team has taken the decision to cease development permanently.
     
     The team considers version 1.3.3 a complete version of bincode that is not in need of any updates.
     
     ## Alternatives to consider
     
     * [wincode](https://crates.io/crates/wincode)
     * [postcard](https://crates.io/crates/postcard)
     * [bitcode](https://crates.io/crates/bitcode)
     * [rkyv](https://crates.io/crates/rkyv)
   ├ Announcement: https://git.sr.ht/~stygianentity/bincode/tree/v3.0/item/README.md
   ├ Solution: No safe upgrade is available!
   ├ bincode v1.3.3
     └── (dev) libdd-ffe v2.0.0
         └── libdd-ffe-ffi v1.0.2

error[vulnerability]: TLS 1.3 handshake messages incorrectly accepted across encryption level boundaries
    ┌─ /home/runner/work/libdatadog/libdatadog/Cargo.lock:199:1
    │
199 │ rustls 0.23.37 registry+https://github.com/rust-lang/crates.io-index
    │ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ security vulnerability detected
    │
    ├ ID: RUSTSEC-2026-0285
    ├ Advisory: https://rustsec.org/advisories/RUSTSEC-2026-0285
    ├ Rustls accepted TLS 1.3 handshake messages sent at the wrong encryption level
      when they followed a key-changing message in the same record. For example,
      a plaintext `EncryptedExtensions` message packed into the same record as the
      `ServerHello` was accepted.
      
      RFC 8446 section 5.1 requires that handshake messages do not span key changes,
      and that implementations terminate the connection with an "unexpected_message"
      alert if they do.
      
      The handshake transcript is still authenticated, so a network-position attacker
      cannot use this to alter or complete a handshake; the practical effect is that
      a peer could send handshake messages that should be encrypted in plaintext
      without rustls rejecting the connection.
      
      This is functionally the same bug as Go's
      [GO-2026-4340](https://pkg.go.dev/vuln/GO-2026-4340) (CVE-2025-61730).
    ├ Announcement: https://github.com/rustls/rustls/pull/3265
    ├ Solution: Upgrade to >=0.23.45 (try `cargo update -p rustls`)
    ├ rustls v0.23.37
      ├── hyper-rustls v0.27.7
      │   └── libdd-common v9.0.0
      │       ├── libdd-capabilities-impl v8.0.0
      │       │   ├── (dev) libdd-ffe v2.0.0
      │       │   │   └── libdd-ffe-ffi v1.0.2
      │       │   └── libdd-remote-config v8.0.0
      │       │       ├── libdd-ffe v2.0.0 (*)
      │       │       └── (dev) libdd-remote-config v8.0.0 (*)
      │       ├── libdd-common-ffi v48.0.0
      │       │   └── libdd-ffe-ffi v1.0.2 (*)
      │       ├── libdd-ffe v2.0.0 (*)
      │       └── libdd-remote-config v8.0.0 (*)
      ├── libdd-common v9.0.0 (*)
      ├── rustls-platform-verifier v0.6.2
      │   └── libdd-common v9.0.0 (*)
      └── tokio-rustls v0.26.0
          ├── hyper-rustls v0.27.7 (*)
          └── (dev) libdd-common v9.0.0 (*)

error[vulnerability]: `Debug` impls for client session values expose TLS secrets
    ┌─ /home/runner/work/libdatadog/libdatadog/Cargo.lock:199:1
    │
199 │ rustls 0.23.37 registry+https://github.com/rust-lang/crates.io-index
    │ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ security vulnerability detected
    │
    ├ ID: RUSTSEC-2026-0346
    ├ Advisory: https://rustsec.org/advisories/RUSTSEC-2026-0346
    ├ The `Debug` implementations of `Tls12ClientSessionValue` and
      `Tls13ClientSessionValue` were derived, and so included the TLS 1.2 master
      secret or TLS 1.3 resumption PSK in their output.
      
      Custom `ClientSessionStore` implementations that format these values with
      `Debug` (for example, when logging) could disclose these secrets to readers of
      the logs. This conflicts with rustls's
      [key-material redaction policy](https://github.com/rustls/rustls/blob/99f2358cae2954837dbb866faf6727de75489ab9/SECURITY.md#boundary-public-api).
      
      Ordinary connection and built-in session cache `Debug` output is redacted and
      is not affected.
    ├ Announcement: https://github.com/rustls/rustls/pull/3299
    ├ Solution: Upgrade to >=0.23.46 (try `cargo update -p rustls`)
    ├ rustls v0.23.37
      ├── hyper-rustls v0.27.7
      │   └── libdd-common v9.0.0
      │       ├── libdd-capabilities-impl v8.0.0
      │       │   ├── (dev) libdd-ffe v2.0.0
      │       │   │   └── libdd-ffe-ffi v1.0.2
      │       │   └── libdd-remote-config v8.0.0
      │       │       ├── libdd-ffe v2.0.0 (*)
      │       │       └── (dev) libdd-remote-config v8.0.0 (*)
      │       ├── libdd-common-ffi v48.0.0
      │       │   └── libdd-ffe-ffi v1.0.2 (*)
      │       ├── libdd-ffe v2.0.0 (*)
      │       └── libdd-remote-config v8.0.0 (*)
      ├── libdd-common v9.0.0 (*)
      ├── rustls-platform-verifier v0.6.2
      │   └── libdd-common v9.0.0 (*)
      └── tokio-rustls v0.26.0
          ├── hyper-rustls v0.27.7 (*)
          └── (dev) libdd-common v9.0.0 (*)

error[vulnerability]: Brotli certificate decompression can allocate up to 1 GiB before authentication
    ┌─ /home/runner/work/libdatadog/libdatadog/Cargo.lock:199:1
    │
199 │ rustls 0.23.37 registry+https://github.com/rust-lang/crates.io-index
    │ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ security vulnerability detected
    │
    ├ ID: RUSTSEC-2026-0348
    ├ Advisory: https://rustsec.org/advisories/RUSTSEC-2026-0348
    ├ The built-in Brotli certificate decompressor (enabled by the non-default
      `brotli` crate feature) bounded the size of the decompressed output, but
      accepted a peer-selected history window. Brotli's large-window extension was
      enabled, so a five-byte header could cause an allocation of 1 GiB. A peer can
      abort a process whose allocator cannot satisfy that request.
      
      No trusted certificate is required by the attacker. Affected configurations are:
      
      - clients that enable the `brotli` feature and connect to a malicious server, and
      - servers that enable the `brotli` feature and request client certificates.
      
      Applications that do not enable the `brotli` feature are not affected.
    ├ Announcement: https://github.com/rustls/rustls/pull/3297
    ├ Solution: Upgrade to >=0.23.46 (try `cargo update -p rustls`)
    ├ rustls v0.23.37
      ├── hyper-rustls v0.27.7
      │   └── libdd-common v9.0.0
      │       ├── libdd-capabilities-impl v8.0.0
      │       │   ├── (dev) libdd-ffe v2.0.0
      │       │   │   └── libdd-ffe-ffi v1.0.2
      │       │   └── libdd-remote-config v8.0.0
      │       │       ├── libdd-ffe v2.0.0 (*)
      │       │       └── (dev) libdd-remote-config v8.0.0 (*)
      │       ├── libdd-common-ffi v48.0.0
      │       │   └── libdd-ffe-ffi v1.0.2 (*)
      │       ├── libdd-ffe v2.0.0 (*)
      │       └── libdd-remote-config v8.0.0 (*)
      ├── libdd-common v9.0.0 (*)
      ├── rustls-platform-verifier v0.6.2
      │   └── libdd-common v9.0.0 (*)
      └── tokio-rustls v0.26.0
          ├── hyper-rustls v0.27.7 (*)
          └── (dev) libdd-common v9.0.0 (*)

error[vulnerability]: Unauthenticated ServerHello can downgrade later connections to classical key exchange
    ┌─ /home/runner/work/libdatadog/libdatadog/Cargo.lock:199:1
    │
199 │ rustls 0.23.37 registry+https://github.com/rust-lang/crates.io-index
    │ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ security vulnerability detected
    │
    ├ ID: RUSTSEC-2026-0349
    ├ Advisory: https://rustsec.org/advisories/RUSTSEC-2026-0349
    ├ The client recorded the server-selected key exchange group for each server
      name when processing the ServerHello, before the server was authenticated.
      This record is used to predict which key share to send in future ClientHellos
      to that server name.
      
      A network attacker can answer one connection attempt with a ServerHello
      selecting X25519, and then close the connection. Later ClientHellos for that
      name carry only an X25519 key share, while `supported_groups` still lists
      X25519MLKEM768 first. If the genuine server accepts that share rather than
      sending a HelloRetryRequest for its preferred hybrid group, the handshake
      completes with classical-only key exchange and no error. This persists for as
      long as the entry stays in the client's session store.
      
      The impact is loss of post-quantum confidentiality for affected connections
      ("harvest now, decrypt later"). There is no key compromise and no
      authentication bypass.
      
      The following are not affected:
      
      - connections to servers which send a HelloRetryRequest for their preferred group,
      - clients with resumption disabled (as nothing is stored), and
      - other server names.
      
      This behaviour is discussed in
      [draft-ietf-tls-key-share-prediction](https://www.ietf.org/archive/id/draft-ietf-tls-key-share-prediction-01.html#name-security-considerations),
      so the practical impact depends largely on server policy.
    ├ Announcement: https://github.com/rustls/rustls/pull/3355
    ├ Solution: Upgrade to >=0.23.46 (try `cargo update -p rustls`)
    ├ rustls v0.23.37
      ├── hyper-rustls v0.27.7
      │   └── libdd-common v9.0.0
      │       ├── libdd-capabilities-impl v8.0.0
      │       │   ├── (dev) libdd-ffe v2.0.0
      │       │   │   └── libdd-ffe-ffi v1.0.2
      │       │   └── libdd-remote-config v8.0.0
      │       │       ├── libdd-ffe v2.0.0 (*)
      │       │       └── (dev) libdd-remote-config v8.0.0 (*)
      │       ├── libdd-common-ffi v48.0.0
      │       │   └── libdd-ffe-ffi v1.0.2 (*)
      │       ├── libdd-ffe v2.0.0 (*)
      │       └── libdd-remote-config v8.0.0 (*)
      ├── libdd-common v9.0.0 (*)
      ├── rustls-platform-verifier v0.6.2
      │   └── libdd-common v9.0.0 (*)
      └── tokio-rustls v0.26.0
          ├── hyper-rustls v0.27.7 (*)
          └── (dev) libdd-common v9.0.0 (*)

error[unsound]: `AsyncFd::new` and related constructors violate I/O safety
    ┌─ /home/runner/work/libdatadog/libdatadog/Cargo.lock:250:1
    │
250 │ tokio 1.49.0 registry+https://github.com/rust-lang/crates.io-index
    │ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ unsound advisory detected
    │
    ├ ID: RUSTSEC-2026-0386
    ├ Advisory: https://rustsec.org/advisories/RUSTSEC-2026-0386
    ├ `tokio::io::unix::AsyncFd` provides safe constructors (`new`, `with_interest`, `try_new`, and `try_with_interest`) that accept any `T: AsRawFd` rather than requiring proof of ownership or validity of the file descriptor. Because `RawFd` implements `AsRawFd`, safe code can construct an `AsyncFd` from an arbitrary or closed file descriptor, or close/replace the underlying file descriptor while the `AsyncFd` is still alive.
      
      This violates I/O safety in two ways:
      
      1. `AsyncFd<T>` implements `AsFd` for all `T: AsRawFd` by calling `BorrowedFd::borrow_raw(self.as_raw_fd())`, allowing safe code to obtain an arbitrary `BorrowedFd<'_>` without owning the file descriptor.
      2. Tokio's I/O driver stores a pointer to an internal allocation in the `epoll`/`kqueue` user data for registered file descriptors. If the underlying file descriptor is duplicated and then closed while an `AsyncFd` is alive, and the OS reuses that file descriptor number for a another IO resource on the same runtime, dropping the first `AsyncFd` deregisters the reused file descriptor number and frees the first while the original file description remains registered in `epoll`, leading to a use-after-free when a readiness event fires.
      
      Starting in Tokio 1.51.6, 1.53.3, and 1.54.0, `AsyncFd::new`, `AsyncFd::with_interest`, `AsyncFd::try_new`, and `AsyncFd::try_with_interest` are deprecated in favor of the `unsafe` constructors `AsyncFd::register` and `AsyncFd::register_with_interest`. Callers must ensure that the file descriptor remains valid, open, and unchanged for the lifetime of the `AsyncFd`.
    ├ Announcement: https://github.com/tokio-rs/tokio/pull/8587
    ├ Solution: Upgrade to >=1.51.6, <1.52.0 OR >=1.53.3 (try `cargo update -p tokio`)
    ├ tokio v1.49.0
      ├── h2 v0.4.19
      │   └── hyper v1.11.1
      │       ├── httpmock v0.8.0-alpha.1
      │       │   └── (dev) libdd-ffe v2.0.0
      │       │       └── libdd-ffe-ffi v1.0.2
      │       ├── hyper-rustls v0.27.7
      │       │   └── libdd-common v9.0.0
      │       │       ├── libdd-capabilities-impl v8.0.0
      │       │       │   ├── (dev) libdd-ffe v2.0.0 (*)
      │       │       │   └── libdd-remote-config v8.0.0
      │       │       │       ├── libdd-ffe v2.0.0 (*)
      │       │       │       └── (dev) libdd-remote-config v8.0.0 (*)
      │       │       ├── libdd-common-ffi v48.0.0
      │       │       │   └── libdd-ffe-ffi v1.0.2 (*)
      │       │       ├── libdd-ffe v2.0.0 (*)
      │       │       └── libdd-remote-config v8.0.0 (*)
      │       ├── hyper-util v0.1.17
      │       │   ├── httpmock v0.8.0-alpha.1 (*)
      │       │   ├── hyper-rustls v0.27.7 (*)
      │       │   ├── libdd-common v9.0.0 (*)
      │       │   └── libdd-remote-config v8.0.0 (*)
      │       ├── libdd-common v9.0.0 (*)
      │       ├── libdd-common-ffi v48.0.0 (*)
      │       └── libdd-remote-config v8.0.0 (*)
      ├── httpmock v0.8.0-alpha.1 (*)
      ├── hyper v1.11.1 (*)
      ├── hyper-rustls v0.27.7 (*)
      ├── hyper-util v0.1.17 (*)
      ├── (dev) libdd-capabilities-impl v8.0.0 (*)
      ├── (dev) libdd-common v9.0.0 (*)
      ├── (dev) libdd-ffe v2.0.0 (*)
      ├── libdd-remote-config v8.0.0 (*)
      ├── (dev) libdd-trace-protobuf v5.1.1
      │   └── libdd-remote-config v8.0.0 (*)
      ├── tokio-rustls v0.26.0
      │   ├── hyper-rustls v0.27.7 (*)
      │   └── (dev) libdd-common v9.0.0 (*)
      ├── tokio-util v0.7.12
      │   ├── h2 v0.4.19 (*)
      │   └── libdd-remote-config v8.0.0 (*)
      └── (dev) tools v48.0.0
          └── (dev) libdd-common v9.0.0 (*)

advisories FAILED, bans ok, sources ok

Updated: 2026-11-06 22:30:10 UTC | Commit: 6d41925 | dependency-check job results

@datadog-official

datadog-official Bot commented Nov 3, 2026 •

Copy link
Copy Markdown

Pipelines  Tests

🎉 All green!

🧪 All tests passed
❄️ No new flaky tests detected

🎯 Code Coverage (details)
• Patch Coverage: 84.76%
• Overall Coverage: 70.38% (-9.91%)

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

@pr-commenter

pr-commenter Bot commented Nov 3, 2026 •

Copy link
Copy Markdown

Benchmarks

Comparison

Benchmark execution time: 2026-11-06 22:37:23

Comparing candidate commit d816927 in PR branch helen/dependent-flags-sdk-ffi with baseline commit cb3bfba in branch helen/ffe-dependent-flags-evaluator.

📊 Benchmarking dashboard

Found 0 performance improvements and 0 performance regressions! Performance is the same for 17 metrics, 0 unstable metrics.

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 ----------------------------------'

Candidate

Candidate benchmark details

Group 1

cpu_model git_commit_sha git_commit_date git_branch
Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz d816927 1794003979 helen/dependent-flags-sdk-ffi
scenario metric min mean ± sd median ± mad p75 p95 p99 max peak_to_median_ratio skewness kurtosis cv sem runs sample_size
flagevaluation_evp/payloads/scale/2500flags_500users_20fields execution_time 34.545ms 34.710ms ± 0.067ms 34.700ms ± 0.045ms 34.760ms 34.818ms 34.854ms 34.863ms 0.47% 0.159 -0.206 0.19% 0.009ms 1 50
flagevaluation_evp/payloads/scale/2500flags_500users_20fields throughput 71709.469op/s 72024.866op/s ± 139.050op/s 72045.335op/s ± 93.814op/s 72114.163op/s 72193.207op/s 72335.723op/s 72368.586op/s 0.45% -0.149 -0.201 0.19% 19.665op/s 1 50
flagevaluation_evp/payloads/stress/10flags_1000users_250fields execution_time 181.875ms 183.639ms ± 0.856ms 183.934ms ± 0.600ms 184.054ms 184.684ms 184.978ms 185.064ms 0.61% -0.465 -0.821 0.46% 0.171ms 1 25
flagevaluation_evp/payloads/stress/10flags_1000users_250fields throughput 5403.531op/s 5445.591op/s ± 25.435op/s 5436.719op/s ± 17.687op/s 5465.261op/s 5486.328op/s 5495.885op/s 5498.285op/s 1.13% 0.478 -0.814 0.46% 5.087op/s 1 25
flagevaluation_evp/payloads/typical/100flags_50users_10fields execution_time 844.126µs 845.899µs ± 0.824µs 845.961µs ± 0.645µs 846.495µs 847.282µs 847.490µs 847.636µs 0.20% -0.070 -0.710 0.10% 0.082µs 1 100
flagevaluation_evp/payloads/typical/100flags_50users_10fields throughput 117975.198op/s 118217.561op/s ± 115.152op/s 118208.707op/s ± 90.183op/s 118301.467op/s 118418.472op/s 118451.192op/s 118465.762op/s 0.22% 0.074 -0.710 0.10% 11.515op/s 1 100
scenario metric 95% CI mean Shapiro-Wilk pvalue Ljung-Box pvalue (lag=1) Dip test pvalue
flagevaluation_evp/payloads/scale/2500flags_500users_20fields execution_time [34.692ms; 34.729ms] or [-0.054%; +0.054%] None None None
flagevaluation_evp/payloads/scale/2500flags_500users_20fields throughput [71986.324op/s; 72063.408op/s] or [-0.054%; +0.054%] None None None
flagevaluation_evp/payloads/stress/10flags_1000users_250fields execution_time [183.303ms; 183.974ms] or [-0.183%; +0.183%] None None None
flagevaluation_evp/payloads/stress/10flags_1000users_250fields throughput [5435.620op/s; 5455.561op/s] or [-0.183%; +0.183%] None None None
flagevaluation_evp/payloads/typical/100flags_50users_10fields execution_time [845.737µs; 846.060µs] or [-0.019%; +0.019%] None None None
flagevaluation_evp/payloads/typical/100flags_50users_10fields throughput [118194.992op/s; 118240.131op/s] or [-0.019%; +0.019%] None None None

Group 2

cpu_model git_commit_sha git_commit_date git_branch
Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz d816927 1794003979 helen/dependent-flags-sdk-ffi
scenario metric min mean ± sd median ± mad p75 p95 p99 max peak_to_median_ratio skewness kurtosis cv sem runs sample_size
flagevaluation_evp/coalescer/scale/2500flags_500users_20fields execution_time 31.262ms 31.470ms ± 0.135ms 31.465ms ± 0.057ms 31.525ms 31.570ms 31.914ms 32.230ms 2.43% 3.479 18.343 0.42% 0.019ms 1 50
flagevaluation_evp/coalescer/scale/2500flags_500users_20fields throughput 77566.702op/s 79442.047op/s ± 335.802op/s 79454.621op/s ± 144.840op/s 79585.102op/s 79794.473op/s 79961.249op/s 79970.373op/s 0.65% -3.375 17.652 0.42% 47.490op/s 1 50
flagevaluation_evp/coalescer/stress/10flags_1000users_250fields execution_time 190.119ms 190.816ms ± 0.887ms 190.492ms ± 0.098ms 190.805ms 193.087ms 193.712ms 193.761ms 1.72% 2.743 6.245 0.46% 0.177ms 1 25
flagevaluation_evp/coalescer/stress/10flags_1000users_250fields throughput 5160.994op/s 5240.748op/s ± 24.067op/s 5249.565op/s ± 2.714op/s 5251.150op/s 5252.805op/s 5258.170op/s 5259.855op/s 0.20% -2.733 6.206 0.45% 4.813op/s 1 25
flagevaluation_evp/coalescer/typical/100flags_50users_10fields execution_time 684.733µs 696.204µs ± 4.890µs 694.208µs ± 2.058µs 701.425µs 703.662µs 704.467µs 704.890µs 1.54% 0.120 -0.944 0.70% 0.489µs 1 100
flagevaluation_evp/coalescer/typical/100flags_50users_10fields throughput 141866.073op/s 143643.123op/s ± 1008.073op/s 144049.033op/s ± 428.310op/s 144261.575op/s 145288.962op/s 145497.157op/s 146042.326op/s 1.38% -0.097 -0.922 0.70% 100.807op/s 1 100
scenario metric 95% CI mean Shapiro-Wilk pvalue Ljung-Box pvalue (lag=1) Dip test pvalue
flagevaluation_evp/coalescer/scale/2500flags_500users_20fields execution_time [31.433ms; 31.507ms] or [-0.119%; +0.119%] None None None
flagevaluation_evp/coalescer/scale/2500flags_500users_20fields throughput [79348.969op/s; 79535.124op/s] or [-0.117%; +0.117%] None None None
flagevaluation_evp/coalescer/stress/10flags_1000users_250fields execution_time [190.469ms; 191.164ms] or [-0.182%; +0.182%] None None None
flagevaluation_evp/coalescer/stress/10flags_1000users_250fields throughput [5231.314op/s; 5250.183op/s] or [-0.180%; +0.180%] None None None
flagevaluation_evp/coalescer/typical/100flags_50users_10fields execution_time [695.245µs; 697.162µs] or [-0.138%; +0.138%] None None None
flagevaluation_evp/coalescer/typical/100flags_50users_10fields throughput [143445.544op/s; 143840.701op/s] or [-0.138%; +0.138%] None None None

Group 3

cpu_model git_commit_sha git_commit_date git_branch
Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz d816927 1794003979 helen/dependent-flags-sdk-ffi
scenario metric min mean ± sd median ± mad p75 p95 p99 max peak_to_median_ratio skewness kurtosis cv sem runs sample_size
dependent_flags/memoized_16_references execution_time 3.056µs 3.073µs ± 0.014µs 3.071µs ± 0.001µs 3.073µs 3.079µs 3.094µs 3.252µs 5.90% 11.501 146.002 0.44% 0.001µs 1 200
scenario metric 95% CI mean Shapiro-Wilk pvalue Ljung-Box pvalue (lag=1) Dip test pvalue
dependent_flags/memoized_16_references execution_time [3.071µs; 3.075µs] or [-0.062%; +0.062%] None None None

Group 4

cpu_model git_commit_sha git_commit_date git_branch
Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz d816927 1794003979 helen/dependent-flags-sdk-ffi
scenario metric min mean ± sd median ± mad p75 p95 p99 max peak_to_median_ratio skewness kurtosis cv sem runs sample_size
dependent_flags/legacy execution_time 113.395ns 113.965ns ± 0.126ns 113.948ns ± 0.048ns 114.004ns 114.151ns 114.483ns 114.527ns 0.51% 0.882 8.145 0.11% 0.009ns 1 200
scenario metric 95% CI mean Shapiro-Wilk pvalue Ljung-Box pvalue (lag=1) Dip test pvalue
dependent_flags/legacy execution_time [113.947ns; 113.982ns] or [-0.015%; +0.015%] None None None

Group 5

cpu_model git_commit_sha git_commit_date git_branch
Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz d816927 1794003979 helen/dependent-flags-sdk-ffi
scenario metric min mean ± sd median ± mad p75 p95 p99 max peak_to_median_ratio skewness kurtosis cv sem runs sample_size
single_flag_killswitch/rules-based execution_time 192.234ns 195.014ns ± 1.963ns 194.597ns ± 1.529ns 196.184ns 198.756ns 199.521ns 203.469ns 4.56% 0.830 0.943 1.00% 0.139ns 1 200
scenario metric 95% CI mean Shapiro-Wilk pvalue Ljung-Box pvalue (lag=1) Dip test pvalue
single_flag_killswitch/rules-based execution_time [194.742ns; 195.287ns] or [-0.140%; +0.140%] None None None

Group 6

cpu_model git_commit_sha git_commit_date git_branch
Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz d816927 1794003979 helen/dependent-flags-sdk-ffi
scenario metric min mean ± sd median ± mad p75 p95 p99 max peak_to_median_ratio skewness kurtosis cv sem runs sample_size
dependent_flags/one_prerequisite execution_time 749.739ns 753.889ns ± 1.182ns 753.789ns ± 0.305ns 754.065ns 755.165ns 758.931ns 764.387ns 1.41% 5.035 39.247 0.16% 0.084ns 1 200
scenario metric 95% CI mean Shapiro-Wilk pvalue Ljung-Box pvalue (lag=1) Dip test pvalue
dependent_flags/one_prerequisite execution_time [753.725ns; 754.053ns] or [-0.022%; +0.022%] None None None

Group 7

cpu_model git_commit_sha git_commit_date git_branch
Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz d816927 1794003979 helen/dependent-flags-sdk-ffi
scenario metric min mean ± sd median ± mad p75 p95 p99 max peak_to_median_ratio skewness kurtosis cv sem runs sample_size
sdk_test_data/rules-based execution_time 302.003µs 307.579µs ± 11.606µs 304.712µs ± 1.234µs 306.490µs 319.329µs 354.286µs 426.423µs 39.94% 6.961 59.677 3.76% 0.821µs 1 200
scenario metric 95% CI mean Shapiro-Wilk pvalue Ljung-Box pvalue (lag=1) Dip test pvalue
sdk_test_data/rules-based execution_time [305.971µs; 309.188µs] or [-0.523%; +0.523%] None None None

Baseline

Baseline benchmark details

Group 1

cpu_model git_commit_sha git_commit_date git_branch
Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz cb3bfba 1794003063 helen/ffe-dependent-flags-evaluator
scenario metric min mean ± sd median ± mad p75 p95 p99 max peak_to_median_ratio skewness kurtosis cv sem runs sample_size
flagevaluation_evp/payloads/scale/2500flags_500users_20fields execution_time 34.637ms 34.977ms ± 0.150ms 34.928ms ± 0.093ms 35.090ms 35.254ms 35.298ms 35.332ms 1.16% 0.404 -0.272 0.42% 0.021ms 1 50
flagevaluation_evp/payloads/scale/2500flags_500users_20fields throughput 70757.019op/s 71477.569op/s ± 305.679op/s 71576.734op/s ± 189.635op/s 71662.960op/s 71877.556op/s 72064.817op/s 72176.716op/s 0.84% -0.384 -0.276 0.42% 43.230op/s 1 50
flagevaluation_evp/payloads/stress/10flags_1000users_250fields execution_time 180.793ms 181.498ms ± 0.274ms 181.466ms ± 0.151ms 181.625ms 181.911ms 181.996ms 182.015ms 0.30% -0.387 0.349 0.15% 0.055ms 1 25
flagevaluation_evp/payloads/stress/10flags_1000users_250fields throughput 5494.045op/s 5509.725op/s ± 8.315op/s 5510.689op/s ± 4.583op/s 5512.987op/s 5520.953op/s 5528.756op/s 5531.181op/s 0.37% 0.397 0.362 0.15% 1.663op/s 1 25
flagevaluation_evp/payloads/typical/100flags_50users_10fields execution_time 846.090µs 847.846µs ± 0.699µs 847.851µs ± 0.438µs 848.308µs 848.925µs 849.474µs 849.940µs 0.25% 0.003 0.236 0.08% 0.070µs 1 100
flagevaluation_evp/payloads/typical/100flags_50users_10fields throughput 117655.329op/s 117945.963op/s ± 97.254op/s 117945.296op/s ± 60.859op/s 118001.838op/s 118107.649op/s 118174.725op/s 118190.701op/s 0.21% 0.003 0.233 0.08% 9.725op/s 1 100
scenario metric 95% CI mean Shapiro-Wilk pvalue Ljung-Box pvalue (lag=1) Dip test pvalue
flagevaluation_evp/payloads/scale/2500flags_500users_20fields execution_time [34.935ms; 35.018ms] or [-0.119%; +0.119%] None None None
flagevaluation_evp/payloads/scale/2500flags_500users_20fields throughput [71392.841op/s; 71562.297op/s] or [-0.119%; +0.119%] None None None
flagevaluation_evp/payloads/stress/10flags_1000users_250fields execution_time [181.390ms; 181.605ms] or [-0.059%; +0.059%] None None None
flagevaluation_evp/payloads/stress/10flags_1000users_250fields throughput [5506.466op/s; 5512.985op/s] or [-0.059%; +0.059%] None None None
flagevaluation_evp/payloads/typical/100flags_50users_10fields execution_time [847.709µs; 847.983µs] or [-0.016%; +0.016%] None None None
flagevaluation_evp/payloads/typical/100flags_50users_10fields throughput [117926.902op/s; 117965.024op/s] or [-0.016%; +0.016%] None None None

Group 2

cpu_model git_commit_sha git_commit_date git_branch
Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz cb3bfba 1794003063 helen/ffe-dependent-flags-evaluator
scenario metric min mean ± sd median ± mad p75 p95 p99 max peak_to_median_ratio skewness kurtosis cv sem runs sample_size
flagevaluation_evp/coalescer/scale/2500flags_500users_20fields execution_time 31.408ms 31.518ms ± 0.061ms 31.508ms ± 0.038ms 31.551ms 31.614ms 31.649ms 31.681ms 0.55% 0.442 -0.396 0.19% 0.009ms 1 50
flagevaluation_evp/coalescer/scale/2500flags_500users_20fields throughput 78911.901op/s 79319.512op/s ± 153.075op/s 79345.203op/s ± 96.443op/s 79436.956op/s 79531.578op/s 79575.105op/s 79596.876op/s 0.32% -0.434 -0.407 0.19% 21.648op/s 1 50
flagevaluation_evp/coalescer/stress/10flags_1000users_250fields execution_time 189.764ms 190.841ms ± 1.135ms 190.434ms ± 0.270ms 190.870ms 193.563ms 193.899ms 194.001ms 1.87% 1.947 2.506 0.58% 0.227ms 1 25
flagevaluation_evp/coalescer/stress/10flags_1000users_250fields throughput 5154.602op/s 5240.137op/s ± 30.814op/s 5251.161op/s ± 7.436op/s 5256.102op/s 5262.591op/s 5268.006op/s 5269.715op/s 0.35% -1.934 2.471 0.58% 6.163op/s 1 25
flagevaluation_evp/coalescer/typical/100flags_50users_10fields execution_time 684.353µs 696.401µs ± 4.502µs 695.445µs ± 2.144µs 700.394µs 702.831µs 703.149µs 703.316µs 1.13% -0.352 0.061 0.64% 0.450µs 1 100
flagevaluation_evp/coalescer/typical/100flags_50users_10fields throughput 142183.608op/s 143601.303op/s ± 930.564op/s 143792.773op/s ± 444.746op/s 144102.696op/s 145499.059op/s 145938.659op/s 146123.510op/s 1.62% 0.390 0.131 0.64% 93.056op/s 1 100
scenario metric 95% CI mean Shapiro-Wilk pvalue Ljung-Box pvalue (lag=1) Dip test pvalue
flagevaluation_evp/coalescer/scale/2500flags_500users_20fields execution_time [31.501ms; 31.535ms] or [-0.054%; +0.054%] None None None
flagevaluation_evp/coalescer/scale/2500flags_500users_20fields throughput [79277.082op/s; 79361.941op/s] or [-0.053%; +0.053%] None None None
flagevaluation_evp/coalescer/stress/10flags_1000users_250fields execution_time [190.396ms; 191.286ms] or [-0.233%; +0.233%] None None None
flagevaluation_evp/coalescer/stress/10flags_1000users_250fields throughput [5228.058op/s; 5252.216op/s] or [-0.231%; +0.231%] None None None
flagevaluation_evp/coalescer/typical/100flags_50users_10fields execution_time [695.519µs; 697.284µs] or [-0.127%; +0.127%] None None None
flagevaluation_evp/coalescer/typical/100flags_50users_10fields throughput [143418.916op/s; 143783.690op/s] or [-0.127%; +0.127%] None None None

Group 3

cpu_model git_commit_sha git_commit_date git_branch
Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz cb3bfba 1794003063 helen/ffe-dependent-flags-evaluator
scenario metric min mean ± sd median ± mad p75 p95 p99 max peak_to_median_ratio skewness kurtosis cv sem runs sample_size
dependent_flags/memoized_16_references execution_time 3.046µs 3.061µs ± 0.003µs 3.061µs ± 0.001µs 3.062µs 3.067µs 3.072µs 3.078µs 0.56% 0.698 8.317 0.10% 0.000µs 1 200
scenario metric 95% CI mean Shapiro-Wilk pvalue Ljung-Box pvalue (lag=1) Dip test pvalue
dependent_flags/memoized_16_references execution_time [3.061µs; 3.062µs] or [-0.014%; +0.014%] None None None

Group 4

cpu_model git_commit_sha git_commit_date git_branch
Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz cb3bfba 1794003063 helen/ffe-dependent-flags-evaluator
scenario metric min mean ± sd median ± mad p75 p95 p99 max peak_to_median_ratio skewness kurtosis cv sem runs sample_size
dependent_flags/legacy execution_time 111.532ns 112.115ns ± 0.122ns 112.129ns ± 0.053ns 112.175ns 112.276ns 112.380ns 112.561ns 0.39% -1.210 5.624 0.11% 0.009ns 1 200
scenario metric 95% CI mean Shapiro-Wilk pvalue Ljung-Box pvalue (lag=1) Dip test pvalue
dependent_flags/legacy execution_time [112.098ns; 112.132ns] or [-0.015%; +0.015%] None None None

Group 5

cpu_model git_commit_sha git_commit_date git_branch
Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz cb3bfba 1794003063 helen/ffe-dependent-flags-evaluator
scenario metric min mean ± sd median ± mad p75 p95 p99 max peak_to_median_ratio skewness kurtosis cv sem runs sample_size
single_flag_killswitch/rules-based execution_time 191.100ns 194.477ns ± 1.996ns 194.106ns ± 1.656ns 195.770ns 197.800ns 199.676ns 202.175ns 4.16% 0.706 0.515 1.02% 0.141ns 1 200
scenario metric 95% CI mean Shapiro-Wilk pvalue Ljung-Box pvalue (lag=1) Dip test pvalue
single_flag_killswitch/rules-based execution_time [194.200ns; 194.753ns] or [-0.142%; +0.142%] None None None

Group 6

cpu_model git_commit_sha git_commit_date git_branch
Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz cb3bfba 1794003063 helen/ffe-dependent-flags-evaluator
scenario metric min mean ± sd median ± mad p75 p95 p99 max peak_to_median_ratio skewness kurtosis cv sem runs sample_size
dependent_flags/one_prerequisite execution_time 735.202ns 738.092ns ± 0.867ns 738.022ns ± 0.243ns 738.236ns 739.206ns 741.593ns 745.880ns 1.06% 4.289 34.212 0.12% 0.061ns 1 200
scenario metric 95% CI mean Shapiro-Wilk pvalue Ljung-Box pvalue (lag=1) Dip test pvalue
dependent_flags/one_prerequisite execution_time [737.972ns; 738.212ns] or [-0.016%; +0.016%] None None None

Group 7

cpu_model git_commit_sha git_commit_date git_branch
Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz cb3bfba 1794003063 helen/ffe-dependent-flags-evaluator
scenario metric min mean ± sd median ± mad p75 p95 p99 max peak_to_median_ratio skewness kurtosis cv sem runs sample_size
sdk_test_data/rules-based execution_time 301.838µs 307.254µs ± 11.559µs 304.270µs ± 1.038µs 306.201µs 317.936µs 353.883µs 426.403µs 40.14% 6.973 60.568 3.75% 0.817µs 1 200
scenario metric 95% CI mean Shapiro-Wilk pvalue Ljung-Box pvalue (lag=1) Dip test pvalue
sdk_test_data/rules-based execution_time [305.652µs; 308.856µs] or [-0.521%; +0.521%] None None None

@dd-octo-sts

dd-octo-sts Bot commented Nov 3, 2026 •

Copy link
Copy Markdown
Contributor

Artifact Size Benchmark Report

aarch64-alpine-linux-musl
Artifact Baseline Commit Change
/aarch64-alpine-linux-musl/lib/libdatadog_profiling.so 9.21 MB 9.21 MB 0% (0 B) 👌
/aarch64-alpine-linux-musl/lib/libdatadog_profiling.a 96.35 MB 96.65 MB +.31% (+307.77 KB) 🔍
aarch64-unknown-linux-gnu
Artifact Baseline Commit Change
/aarch64-unknown-linux-gnu/lib/libdatadog_profiling.so 12.39 MB 12.46 MB +.58% (+74.24 KB) 🔍
/aarch64-unknown-linux-gnu/lib/libdatadog_profiling.a 107.50 MB 107.81 MB +.28% (+309.95 KB) 🔍
libdatadog-x64-windows
Artifact Baseline Commit Change
/libdatadog-x64-windows/debug/dynamic/datadog_profiling_ffi.dll 29.65 MB 29.74 MB +.28% (+87.50 KB) 🔍
/libdatadog-x64-windows/debug/dynamic/datadog_profiling_ffi.lib 99.96 KB 101.26 KB +1.30% (+1.30 KB) ⚠️
/libdatadog-x64-windows/debug/dynamic/datadog_profiling_ffi.pdb 192.58 MB 193.27 MB +.36% (+712.00 KB) 🔍
/libdatadog-x64-windows/debug/static/datadog_profiling_ffi.lib 801.89 MB 803.61 MB +.21% (+1.71 MB) 🔍
/libdatadog-x64-windows/release/dynamic/datadog_profiling_ffi.dll 9.75 MB 9.78 MB +.29% (+29.00 KB) 🔍
/libdatadog-x64-windows/release/dynamic/datadog_profiling_ffi.lib 99.96 KB 101.26 KB +1.30% (+1.30 KB) ⚠️
/libdatadog-x64-windows/release/dynamic/datadog_profiling_ffi.pdb 27.80 MB 27.89 MB +.33% (+96.00 KB) 🔍
/libdatadog-x64-windows/release/static/datadog_profiling_ffi.lib 55.90 MB 56.08 MB +.32% (+185.52 KB) 🔍
libdatadog-x86-windows
Artifact Baseline Commit Change
/libdatadog-x86-windows/debug/dynamic/datadog_profiling_ffi.dll 26.15 MB 26.23 MB +.30% (+81.00 KB) 🔍
/libdatadog-x86-windows/debug/dynamic/datadog_profiling_ffi.lib 101.51 KB 102.83 KB +1.30% (+1.32 KB) ⚠️
/libdatadog-x86-windows/debug/dynamic/datadog_profiling_ffi.pdb 198.44 MB 199.13 MB +.35% (+712.00 KB) 🔍
/libdatadog-x86-windows/debug/static/datadog_profiling_ffi.lib 787.78 MB 789.36 MB +.19% (+1.57 MB) 🔍
/libdatadog-x86-windows/release/dynamic/datadog_profiling_ffi.dll 7.51 MB 7.54 MB +.42% (+32.50 KB) 🔍
/libdatadog-x86-windows/release/dynamic/datadog_profiling_ffi.lib 101.51 KB 102.83 KB +1.30% (+1.32 KB) ⚠️
/libdatadog-x86-windows/release/dynamic/datadog_profiling_ffi.pdb 29.89 MB 29.98 MB +.31% (+96.00 KB) 🔍
/libdatadog-x86-windows/release/static/datadog_profiling_ffi.lib 52.77 MB 52.95 MB +.33% (+182.79 KB) 🔍
x86_64-alpine-linux-musl
Artifact Baseline Commit Change
/x86_64-alpine-linux-musl/lib/libdatadog_profiling.a 86.84 MB 87.13 MB +.34% (+302.82 KB) 🔍
/x86_64-alpine-linux-musl/lib/libdatadog_profiling.so 10.03 MB 10.06 MB +.31% (+32.00 KB) 🔍
x86_64-unknown-linux-gnu
Artifact Baseline Commit Change
/x86_64-unknown-linux-gnu/lib/libdatadog_profiling.a 102.53 MB 102.83 MB +.29% (+304.88 KB) 🔍
/x86_64-unknown-linux-gnu/lib/libdatadog_profiling.so 12.28 MB 12.32 MB +.33% (+41.77 KB) 🔍

@hhan2024
hhan2024 marked this pull request as ready for review November 4, 2026 03:49
@hhan2024
hhan2024 requested review from a team as code owners November 4, 2026 03:49
@chatgpt-codex-connector

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

Copy link
Copy Markdown

Codex Review Summary

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

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-11-04T03:53:36.580213Z a6cb21f Draft marked ready
🔒 Security Review ✅ Completed 2026-11-04T03:53:27.419764Z a6cb21f Draft marked ready
ℹ️ 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: a6cb21f762

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

};

let assignment_result = config.eval_flag_with_options(
let evaluation = config.eval_flag_with_trace(

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 Preserve evaluation trace logging

When any ddog_ffe_get_assignment* entry point is used with trace logging enabled, this direct call to eval_flag_with_trace bypasses Configuration::eval_flag_with_options, whose success and failure branches emit the evaluator's log::trace! records. Consequently, all C FFI evaluations silently lose their existing diagnostic logs, including evaluations without prerequisites; retain equivalent logging while collecting the trace.

Useful? React with 👍 / 👎.

@aarsilv aarsilv added the crucible: reviewing A Crucible review has started; this PR has reviewer attention. label Nov 4, 2026
/// `assignment` must be a live handle.
#[unsafe(no_mangle)]
// allow(ffi-panic-boundary): reads the length of an owned vector.
pub unsafe extern "C" fn ddog_ffe_assignment_dependency_count(

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 PR is based on 1cf7834, not on the current head of #2748 (983b4b0).

  • A merge of this head with 983b4b0 is clean, and 983b4b0 does not change any type that this PR uses.
  • 983b4b0 does change behavior that these accessors expose: prerequisites rejected by the depth guard now appear in ddog_ffe_assignment_dependency_count, an invalid maxDependencyDepth no longer fails ddog_ffe_configuration_new, and empty value lists are accepted.
  • This PR also conflicts with main in this file: main adds features and feature_destinations next to the new dependencies field. Keep all three fields.
  • The description reports 991 Ruby OpenFeature examples against a local build of this stack. Please rerun them after the rebase.

/// # Safety
/// `assignment` must be a live handle.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn ddog_ffe_assignment_dependency_result(

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:

[P3] Small API points to settle before these accessors ship.

  • This function returns an owned handle, but it has no #[must_use]. A caller that ignores the result leaks it. With #[must_use], cbindgen emits DDOG_CHECK_RETURN.
  • The new names (ddog_ffe_assignment_dependency_{count,key,exposure_eligible,result}) do not follow the existing ddog_ffe_assignment_get_* pattern. Consider ddog_ffe_assignment_get_dependency_*, before callers depend on them.
  • The allow(ffi-panic-boundary) comments say these calls only read an owned vector. Handle::as_ref can panic on a null handle, as the existing accessors can; these accessors require a live handle. Please reword the comments to say so.
  • The open Codex thread on line 298 is valid: calling eval_flag_with_trace directly bypasses the evaluator's log::trace! records for every C FFI evaluation. The impact is low (trace level only). The fix belongs in eval_flag_with_trace in feat(ffe): evaluate dependent flags with prerequisite telemetry #2748.

Merge the repaired evaluator and current main. Preserve both prerequisite observations and selected-split feature views in resolution handles. Validate all 12 FFI tests and the independently owned prerequisite C example.

Environment: Datadog workspace

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

This branch has not been deployed

No deployments
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.

2 participants