Summary
Add per-plugin / per-PDP wall-clock instrumentation to the execution pipeline, gated behind a Cargo feature so it has zero impact on CPEX when not compiled in: no extra fields, no branches, no allocations on the production hot path.
Motivation
We need reliable timing to profile the executor phases and compare PDP backends (Cedar vs CEL vs OPA). The feat/benchmark branch proved out the instrumentation points but gated them at runtime (a capture_timings: bool on ExecutorConfig / PluginSettings plus Option<PipelineTimings> fields on every result). That leaves the timing fields, the Instant::now() calls, and
per-phase branches present in production builds even when disabled. This time we want it gated at compile time and designed carefully rather than bolted on.
Scope
- A Cargo feature (e.g.
bench / instrument) that, when off, compiles the instrumentation to nothing — the PipelineTimings types and result fields do not exist in the default build.
- Wrap capture points in a small internal helper/macro so call sites stay readable and collapse to a no-op when the feature is off (avoid scattering raw
#[cfg(...)] around the hot path).
- Instrumentation points (from the
feat/benchmark prototype — re-derive, do not copy the hacky shape):
- executor phases: SEQUENTIAL / TRANSFORM / AUDIT / CONCURRENT plugin invoke (
cpex-core/src/executor.rs)
- PDP evaluation with dialect tag (
apl-cpex/src/pdp_router.rs)
- CMF invoker (
apl-cpex/src/cmf_invoker.rs)
- delegation invoker (
apl-cpex/src/delegation_invoker.rs)
- A way to surface the collected timings (result field or reporting hook) that
only exists in instrumented builds.
Acceptance Criteria
Scenario: zero cost when not compiled in
Given CPEX built without the instrumentation feature
Then no timing types, fields, or timing calls appear in the pipeline path
Scenario: timings captured when compiled in
Given CPEX built with the instrumentation feature
When a request runs through the pipeline
Then per-plugin and per-PDP durations are recorded and retrievable
Notes
- Reference (do not merge):
feat/benchmark — see the executor, pdp_router, cmf_invoker, and delegation_invoker diffs for where the probes belong.
- Decide up front how timings leave the pipeline (typed result field vs a callback/collector), since the return-type shape drives the
#[cfg] boundaries.
Summary
Add per-plugin / per-PDP wall-clock instrumentation to the execution pipeline, gated behind a Cargo feature so it has zero impact on CPEX when not compiled in: no extra fields, no branches, no allocations on the production hot path.
Motivation
We need reliable timing to profile the executor phases and compare PDP backends (Cedar vs CEL vs OPA). The
feat/benchmarkbranch proved out the instrumentation points but gated them at runtime (acapture_timings: boolonExecutorConfig/PluginSettingsplusOption<PipelineTimings>fields on every result). That leaves the timing fields, theInstant::now()calls, andper-phase branches present in production builds even when disabled. This time we want it gated at compile time and designed carefully rather than bolted on.
Scope
bench/instrument) that, when off, compiles the instrumentation to nothing — thePipelineTimingstypes and result fields do not exist in the default build.#[cfg(...)]around the hot path).feat/benchmarkprototype — re-derive, do not copy the hacky shape):cpex-core/src/executor.rs)apl-cpex/src/pdp_router.rs)apl-cpex/src/cmf_invoker.rs)apl-cpex/src/delegation_invoker.rs)only exists in instrumented builds.
Acceptance Criteria
Notes
feat/benchmark— see the executor,pdp_router,cmf_invoker, anddelegation_invokerdiffs for where the probes belong.#[cfg]boundaries.