feat(O3): instrument context endpoint with tier metrics

- Track context requests, errors, empty results
- Timer for context duration histogram
- Metrics: C1-C8 (8 metrics instrumented)
This commit is contained in:
2026-09-13 21:37:44 +09:00
parent 0d0fe55519
commit 8334910144
+13 -2
View File
@@ -990,13 +990,20 @@ pub async fn context_handler(
body: web::Json<crate::context_endpoint::ContextRequest>, body: web::Json<crate::context_endpoint::ContextRequest>,
state: web::Data<AppState>, state: web::Data<AppState>,
) -> HttpResponse { ) -> HttpResponse {
use crate::metrics::*;
CONTEXT_REQUESTS_TOTAL.inc();
let _timer = Timer::new(&CONTEXT_DURATION);
let (claims, _token) = match validate_auth(&req, &state).await { let (claims, _token) = match validate_auth(&req, &state).await {
Ok(c) => c, Ok(c) => c,
Err(e) => return e, Err(e) => {
CONTEXT_ERRORS_TOTAL.inc();
return e;
}
}; };
// Check read capability
if !has_capability(&claims, "memory:read") { if !has_capability(&claims, "memory:read") {
CONTEXT_ERRORS_TOTAL.inc();
return HttpResponse::Forbidden().json(json!({ return HttpResponse::Forbidden().json(json!({
"error": "forbidden", "error": "forbidden",
"reason": "missing capability: memory:read" "reason": "missing capability: memory:read"
@@ -1021,9 +1028,13 @@ pub async fn context_handler(
skills = response.skills.len(), skills = response.skills.len(),
"context lookup successful" "context lookup successful"
); );
// O3: Track tier hits
let total = response.lessons.len() + response.skills.len();
if total == 0 { CONTEXT_EMPTY_RESULTS.inc(); }
HttpResponse::Ok().json(response) HttpResponse::Ok().json(response)
} }
Err(e) => { Err(e) => {
CONTEXT_ERRORS_TOTAL.inc();
tracing::error!("context lookup error: {}", e); tracing::error!("context lookup error: {}", e);
HttpResponse::BadRequest().json(json!({ HttpResponse::BadRequest().json(json!({
"error": "lookup_failed", "error": "lookup_failed",