# Task 07: `metrics` Feature Flag + Zero-Overhead Verification

## Delivers

Verification that all metrics instrumentation (atomic counters, histogram, HTTP endpoint, Prometheus rendering) is gated behind `#[cfg(feature = "metrics")]` and compiles to zero overhead when the feature is disabled. Adds a CI-enforceable check that `--no-default-features` produces no metrics code.

## Complexity: S

## Dependencies

- task-01 complete (QueryStats is NOT gated -- it has value without Prometheus)
- task-02, task-03, task-04 complete (all atomic counters must exist before we verify gating)
- `tidal/Cargo.toml` -- `metrics` feature definition

## Technical Design

### 1. Audit all `#[cfg(feature = "metrics")]` gates

Every `AtomicU64` counter, the `LatencyHistogram`, and the HTTP server module must be gated. The audit covers:

| Location | Gated item |
|---|---|
| `db/metrics.rs` | `wal_lag_bytes`, `wal_compacted_segments_total`, `last_checkpoint_ns`, `signal_hot_entries`, `signal_writes_total`, `signal_write_latency`, `tantivy_segment_count`, `tantivy_indexed_docs`, `usearch_index_size_bytes`, `usearch_vector_count`, `bitmap_index_cardinality`, `active_sessions`, `closed_sessions_total`, `session_auto_closed_total`, `rate_limited_total`, `degradation_level` |
| `db/http.rs` | Entire module already gated: `#[cfg(feature = "metrics")] pub mod http;` |
| `db/signals.rs` | `Instant::now()` + `observe()` call in `signal()` |
| `db/sessions.rs` | `fetch_add`/`fetch_sub` calls on session counters |
| `db/mod.rs` | `metrics_handle` field, `refresh_index_metrics()` call |
| `lib.rs` | `pub use db::http::MetricsHandle` re-export |

### 2. Verify `QueryStats` is NOT gated

`QueryStats` is always available. It carries per-query telemetry that embedders use for their own logging and debugging, independent of Prometheus. The `stats` field on `Results` and `SearchResults` is always populated.

### 3. Verify `MetricsState` base fields are NOT gated

`MetricsState.opened_at` and `MetricsState.health_ok` exist regardless of the `metrics` feature. The `render_prometheus()` and `render_healthz()` methods exist regardless (they render the base metrics). Only the additional m7p4 counters are gated.

### 4. Zero-overhead verification

Add a compile-time check to CI:

```bash
# Verify the crate compiles without the metrics feature
cargo check --manifest-path tidal/Cargo.toml --no-default-features

# Verify no metrics-related symbols appear in the binary
cargo build --manifest-path tidal/Cargo.toml --release --no-default-features
# Inspect with nm or objdump for tidaldb_wal_lag_bytes etc.
# (This is a manual verification step documented in the task, not automated)
```

### 5. Conditional compilation pattern

Every instrumentation site follows this pattern:

```rust
// GOOD: zero overhead when feature is off
#[cfg(feature = "metrics")]
{
    let elapsed_us = start.elapsed().as_micros() as u64;
    self.metrics.signal_writes_total.fetch_add(1, Ordering::Relaxed);
    self.metrics.signal_write_latency.observe(elapsed_us);
}

// BAD: timing overhead even when feature is off
let start = Instant::now(); // <-- this runs unconditionally
// ... work ...
#[cfg(feature = "metrics")]
{
    self.metrics.signal_writes_total.fetch_add(1, Ordering::Relaxed);
}
```

The `Instant::now()` call must also be inside the `#[cfg]` block. On hot paths (signal writes, query execution), even `Instant::now()` is measurable overhead (~20ns on macOS).

Exception: `QueryStats` timing uses `Instant::now()` unconditionally because `QueryStats` is always populated. This is acceptable because query execution is not the write-path hot loop.

### 6. Feature flag definition

Verify `tidal/Cargo.toml` has:

```toml
[features]
default = ["metrics"]
metrics = []
```

The `metrics` feature is enabled by default so that out-of-the-box usage includes observability. Embedders who need zero overhead opt out with `default-features = false`.

## Acceptance Criteria

- [ ] All m7p4 atomic counters gated behind `#[cfg(feature = "metrics")]`
- [ ] `LatencyHistogram` struct and all its call sites gated
- [ ] HTTP metrics server module gated (already done, verify)
- [ ] `Instant::now()` for metric timing is inside `#[cfg]` blocks on write-path code
- [ ] `QueryStats` is NOT gated (always available)
- [ ] `MetricsState.opened_at` and `MetricsState.health_ok` are NOT gated
- [ ] `cargo check --manifest-path tidal/Cargo.toml --no-default-features` succeeds
- [ ] `cargo test --manifest-path tidal/Cargo.toml --no-default-features --lib` passes
- [ ] No dead code warnings when `metrics` feature is disabled
- [ ] `cargo clippy -D warnings` passes with and without `metrics` feature

## Test Strategy

```rust
// This test runs in both feature configurations via CI matrix
#[test]
fn query_stats_always_available() {
    // QueryStats is not feature-gated
    let stats = QueryStats::new("test".to_owned());
    assert_eq!(stats.profile_name, "test");
}

#[test]
fn metrics_state_base_always_available() {
    let state = MetricsState::new();
    assert!(state.uptime_seconds() >= 0.0);
    assert!((state.health_ok_value() - 1.0).abs() < f64::EPSILON);
}

#[cfg(feature = "metrics")]
#[test]
fn metrics_feature_counters_exist() {
    let state = MetricsState::new();
    state.signal_writes_total.fetch_add(1, Ordering::Relaxed);
    assert_eq!(state.signal_writes_total.load(Ordering::Relaxed), 1);
}
```

CI verification (add to pre-commit or CI script):

```bash
# Verify no-default-features compilation
cargo check --manifest-path tidal/Cargo.toml --no-default-features 2>&1 | grep -c "error" && exit 1 || true
cargo test --manifest-path tidal/Cargo.toml --no-default-features --lib 2>&1
```
