Goal
The HTTP middleware in crates/common/src/server.rs captures request-level latency for every route, but it doesn't measure the actual work — the embedding API call, the LanceDB search, the workflow dispatch. When those slow down, p99 HTTP latency tells us something is wrong but not which operation.
Add operation-level histograms and error counters so we can answer "what's slow?" and "what's failing?" precisely.
Tasks
Histograms
| Service |
Metric |
Location |
| orchestrator |
workflow_dispatch_duration_seconds |
crates/orchestrator/src/scheduler/runner.rs (around the dispatch call) |
| memory |
memory_search_duration_seconds |
crates/memory/src/api.rs (search handler) |
| memory |
memory_embedding_duration_seconds |
crates/memory/src/ (wherever embeddings are computed) |
| index |
index_query_duration_seconds |
crates/index/src/api.rs (search handler) |
| index |
index_embedding_duration_seconds |
embedding call site |
| notify |
notification_delivery_age_seconds |
histogram of (delivered_at - created_at) — crates/notify/src/api.rs |
Pattern:
let start = std::time::Instant::now();
let result = do_work().await;
metrics::histogram!("memory_search_duration_seconds").record(start.elapsed().as_secs_f64());
Per-operation error counters
The HTTP middleware already counts 5xx via http_requests_total{status="5xx"}, but that's coarse. For each operation that can fail in a recoverable way (embedding API timeout, LanceDB error, workflow dispatch error), emit a labeled counter:
memory_errors_total{operation, kind} — operation = search|embed|store, kind = timeout|api_error|db_error
index_errors_total{operation, kind}
workflow_dispatch_errors_total{reason} (reason = template_render | agent_unavailable | etc.)
embedding_errors_total{service, provider} (cross-service — both memory and index call embeddings)
Files Touched
crates/orchestrator/src/scheduler/runner.rs
crates/memory/src/api.rs + embedding caller
crates/index/src/api.rs + embedding caller
crates/notify/src/api.rs
Verification
cargo build clean
- Exercise each operation; confirm via
/metrics that the histogram has populated buckets
- Force an error (e.g. point embedding service at a bad URL); confirm the error counter increments
- Dashboard query
histogram_quantile(0.99, sum(rate(memory_search_duration_seconds_bucket[5m])) by (le)) returns a real value
Depends On
Phase A — index and ask need their /metrics endpoints functional first (index already has one; verify before starting)
Goal
The HTTP middleware in
crates/common/src/server.rscaptures request-level latency for every route, but it doesn't measure the actual work — the embedding API call, the LanceDB search, the workflow dispatch. When those slow down, p99 HTTP latency tells us something is wrong but not which operation.Add operation-level histograms and error counters so we can answer "what's slow?" and "what's failing?" precisely.
Tasks
Histograms
workflow_dispatch_duration_secondscrates/orchestrator/src/scheduler/runner.rs(around the dispatch call)memory_search_duration_secondscrates/memory/src/api.rs(search handler)memory_embedding_duration_secondscrates/memory/src/(wherever embeddings are computed)index_query_duration_secondscrates/index/src/api.rs(search handler)index_embedding_duration_secondsnotification_delivery_age_secondscrates/notify/src/api.rsPattern:
Per-operation error counters
The HTTP middleware already counts 5xx via
http_requests_total{status="5xx"}, but that's coarse. For each operation that can fail in a recoverable way (embedding API timeout, LanceDB error, workflow dispatch error), emit a labeled counter:memory_errors_total{operation, kind}— operation = search|embed|store, kind = timeout|api_error|db_errorindex_errors_total{operation, kind}workflow_dispatch_errors_total{reason}(reason = template_render | agent_unavailable | etc.)embedding_errors_total{service, provider}(cross-service — both memory and index call embeddings)Files Touched
crates/orchestrator/src/scheduler/runner.rscrates/memory/src/api.rs+ embedding callercrates/index/src/api.rs+ embedding callercrates/notify/src/api.rsVerification
cargo buildclean/metricsthat the histogram has populated bucketshistogram_quantile(0.99, sum(rate(memory_search_duration_seconds_bucket[5m])) by (le))returns a real valueDepends On
Phase A — index and ask need their
/metricsendpoints functional first (index already has one; verify before starting)