Metrics Implementation Status¶
This document tracks the implementation status of metrics referenced in Grafana dashboards. Generated by NEM-4153 audit.
Fully Implemented Metrics¶
Backend HSI Metrics (backend/core/metrics.py)¶
These metrics are exported via the /api/metrics endpoint:
| Metric | Type | Labels | Description |
|---|---|---|---|
hsi_detection_queue_depth | Gauge | - | Detection queue depth |
hsi_analysis_queue_depth | Gauge | - | Analysis queue depth |
hsi_dlq_depth | Gauge | queue_name | Dead letter queue depth |
hsi_stage_duration_seconds | Histogram | stage | Pipeline stage duration |
hsi_events_created_total | Counter | - | Total events created |
hsi_detections_processed_total | Counter | - | Total detections processed |
hsi_detections_by_class_total | Counter | object_class | Detections by COCO class |
hsi_ai_request_duration_seconds | Histogram | service | AI service request duration |
hsi_pipeline_errors_total | Counter | error_type | Pipeline errors |
hsi_events_by_risk_level_total | Counter | level | Events by risk level |
hsi_cache_hits_total | Counter | cache_type | Cache hits |
hsi_cache_misses_total | Counter | cache_type | Cache misses |
hsi_redis_pool_size | Gauge | - | Redis connection pool size |
hsi_redis_pool_available | Gauge | - | Available Redis connections |
hsi_redis_pool_in_use | Gauge | - | Redis connections in use |
hsi_daily_cost_usd | Gauge | - | Daily inference cost |
hsi_monthly_cost_usd | Gauge | - | Monthly inference cost |
hsi_budget_utilization_ratio | Gauge | period | Budget utilization ratio |
hsi_face_embeddings_generated_total | Counter | match_status | Face embeddings generated |
hsi_face_matches_total | Counter | person_id | Face matches to known persons |
hsi_loitering_alerts_total | Counter | - | Loitering detection alerts |
hsi_loitering_dwell_time_seconds | Histogram | - | Loitering dwell time |
JSON Exporter Metrics (monitoring/json-exporter-config.yml)¶
These metrics are scraped from backend API endpoints:
| Metric | Source Endpoint | Description |
|---|---|---|
hsi_system_healthy | /api/health | System health status |
hsi_database_healthy | /api/health | Database health status |
hsi_redis_healthy | /api/health | Redis health status |
hsi_ai_healthy | /api/health | AI services health status |
hsi_total_cameras | /api/stats | Total number of cameras |
hsi_total_events | /api/stats | Total number of events |
hsi_total_detections | /api/stats | Total number of detections |
hsi_uptime_seconds | /api/stats | Application uptime |
hsi_detect_latency_p95_ms | /api/telemetry | Detect stage P95 latency |
hsi_analyze_latency_p95_ms | /api/telemetry | Analyze stage P95 latency |
hsi_gpu_utilization | /api/gpu | GPU utilization percentage |
hsi_gpu_memory_used_mb | /api/gpu | GPU memory used |
hsi_gpu_temperature | /api/gpu | GPU temperature |
Recording Rules (monitoring/prometheus-rules.yml)¶
These pre-compute SLI/SLO metrics:
hsi:api_availability:ratio_rate30d- 30-day API availabilityhsi:detection_latency:p95_5m- 5-minute P95 detection latencyhsi:analysis_latency:p95_5m- 5-minute P95 analysis latencyhsi:error_budget:api_availability_remaining- API error budget remaininghsi:burn_rate:api_availability_1h- 1-hour burn ratejob:service_cpu_regression_ratio:5m_vs_24h- CPU regression detectionjob:service_memory_regression_ratio:current_vs_6h- Memory regression detection
Retired AI Service Metrics (gateway topology — standalone exporters retired)¶
The standalone AI containers (ai-yolo26, ai-florence, ai-clip, ai-enrichment, ai-enrichment-light) were retired by the gateway consolidation: no compose stack runs them, so the prometheus_client exporters defined in ai/yolo26/metrics.py, ai/florence/model.py, ai/clip/model.py and ai/enrichment/metrics.py never start — none of the yolo26_* / florence_* / clip_* / enrichment_* series below is exported anymore (the module residue is dead code in the live topology — the gateway export scripts (ai/gateway/export/) and adapter routers never import these modules; the only remaining importers are the native-CLIP reference in backend/tests/contracts/ai_providers/test_client_conformance.py and a lazy ai.enrichment.metrics import in the deprecated-PaddleOCR branch of ai/enrichment/models/plate_ocr.py, plus the ai/*/tests suites themselves (flat-import stubs in ai/conftest.py). The same series were removed from monitoring/alerting-rules.yml / monitoring/ai-pipeline-alerts.yml in the same sweep (see the retirement comments there, e.g. "nothing to retarget" at monitoring/alerting-rules.yml:953-961), and the dashboards were retargeted — see monitoring/grafana/dashboards/AGENTS.md. Live coverage for the signals these lists used to provide:
| Signal | Live series | Source |
|---|---|---|
| Per-model inference rate / mean latency | nv_inference_request_success / nv_inference_request_failure / nv_inference_request_duration_us (by model) | Triton inside ai-gateway — scrape job triton-metrics (ai-gateway:8002) |
| Client-side latency percentiles | hsi_ai_request_duration_seconds (by service: yolo26, clip, florence, enrichment_pose, ...) | backend AI clients (detector/clip/florence/enrichment _client.py) |
| Gateway request duration / errors | hsi_ai_inference_duration_seconds / hsi_ai_inference_errors_total (by service, endpoint) | GatewayMetricsMiddleware in ai/gateway/main.py — job ai-gateway-metrics |
| Model loaded / serving health | probe_success{job="blackbox-http-2xx", model=~"yolo26\|clip\|florence2\|enrichment\|enrichment-light\|llm\|gateway"} | blackbox probes of the gateway adapter routers |
| GPU utilization / VRAM | nv_gpu_utilization, nv_gpu_memory_used_bytes, DCGM_* | triton-metrics / dcgm-exporter jobs |
| Detection throughput | hsi_detections_processed_total, hsi_detections_by_class_total | backend/core/metrics.py |
| Enrichment model calls / latency | hsi_enrichment_model_calls_total, hsi_enrichment_model_duration_seconds (by model) | backend enrichment pipeline / vision_extractor |
The per-service exporter lists below are kept for grepping historical dashboards/queries only. None of these series is live.
YOLO26 (ai/yolo26/metrics.py — exporter dead):
yolo26_inference_duration_seconds- Inference duration histogramyolo26_requests_total- Request counter with status labelyolo26_detections_total- Detection counter by classyolo26_vram_bytes- VRAM usage gaugeyolo26_model_loaded- Model loaded statusyolo26_model_inference_healthy- Model health status
Florence (ai/florence/model.py — exporter dead):
florence_inference_latency_seconds- Inference latency histogramflorence_inference_requests_total- Request counterflorence_model_loaded- Model loaded status
CLIP (ai/clip/model.py — exporter dead):
clip_inference_latency_seconds- Inference latency histogramclip_inference_requests_total- Request counterclip_model_loaded- Model loaded status
Enrichment (ai/enrichment/metrics.py — exporter dead; pose/threat/reid now run as Triton models behind the gateway's /enrich-lt adapter by default — enrichment_{pose,threat,reid}_service settings pick light vs heavy — with client-side volume/latency covered live by hsi_enrichment_model_calls_total / hsi_enrichment_model_duration_seconds and errors by hsi_pipeline_errors_total{error_type="enrichment_*"}):
enrichment_pose_estimation_inferences_total- Pose estimation inferencesenrichment_reid_embeddings_generated_total- Re-ID embeddings generatedenrichment_threat_detection_inferences_total- Threat detection inferences
Retired with the xclip cleanup (NEM-5563): the
enrichment_action_recognition_*families (_inferences_total,_inference_latency_seconds,_confidence,_frames_processed_total) no longer exist inai/enrichment/metrics.py— their last observer went when the X-CLIPActionRecognizerretired. Action recognition now runs skeleton-based as Tritonstgcn_actionvia the ai-gateway/action-classifyadapter. The FED familyhsi_action_detections_total/hsi_action_confidence/hsi_action_corrections_totalwas defined insidebackend/services/action_recognition_service.py— notbackend/core/metrics.py— so when that service was archived 2026-09-23 (full X-CLIP removal, with thePOST /api/action-events/analyzeendpoint) the definitions left the runtime entirely: the series no longer exist, and a ST-GCN++-era feeder would define them fresh if wired. Action-inference latency rideshsi_enrichment_model_duration_seconds{model="stgcn"}in the meantime. Thehsi_action_recognition_*trio inbackend/core/metrics.pyis still defined but never observed outside tests — so the two labelled members (_total{action_type,camera_id},_confidence{action_type}) export nothing, while the unlabelled_duration_secondshistogram does scrape as zero-valued buckets (prometheus_clientemits unlabelled histograms unconditionally). The dashboards say the same (seemonitoring/grafana/dashboards/AGENTS.md).
Pending Implementation¶
The following metrics are referenced in dashboards but not yet implemented:
Real User Monitoring (RUM)¶
Dashboard: analytics.json (section marked as PENDING)
| Metric | Description | Priority |
|---|---|---|
hsi_rum_page_load_time_seconds | Browser page load time | Low |
hsi_rum_fcp_seconds | First Contentful Paint | Low |
hsi_rum_lcp_seconds | Largest Contentful Paint | Low |
hsi_rum_cls | Cumulative Layout Shift | Low |
hsi_rum_inp_seconds | Interaction to Next Paint | Low |
hsi_rum_js_errors_total | JavaScript error counter | Low |
hsi_rum_active_sessions | Active user sessions | Low |
Implementation: Requires frontend RUM library (e.g., @opentelemetry/sdk-trace-web)
Database Pool Metrics¶
Dashboard: analytics.json (section marked as PENDING)
| Metric | Description | Priority |
|---|---|---|
hsi_db_query_duration_seconds | Query duration histogram | Medium |
hsi_db_pool_connections_active | Active DB connections | Medium |
hsi_db_pool_connections_idle | Idle DB connections | Medium |
hsi_slow_queries_total | Slow query counter | Medium |
Implementation: Requires SQLAlchemy instrumentation or postgres_exporter
A/B Testing Metrics¶
Dashboard: analytics.json (section marked as PENDING)
| Metric | Description | Priority |
|---|---|---|
hsi_ab_variant_traffic_total | Traffic per A/B variant | Low |
hsi_ab_conversions_total | Conversions per variant | Low |
hsi_prompt_accuracy | Prompt accuracy by type | Low |
hsi_prompt_latency_seconds | Prompt latency histogram | Low |
hsi_prompt_agreement_total | Shadow/production agreement | Low |
Implementation: Requires prompt A/B testing framework
External Dependencies¶
These metrics require external exporters:
| Metric Prefix | Exporter | Status |
|---|---|---|
node_* | node_exporter | Required for host metrics |
redis_* | redis_exporter | Required for Redis metrics |
probe_* | blackbox_exporter | Required for synthetic monitoring |
container_* | cAdvisor | Required for container metrics |
DCGM_* | dcgm-exporter | Optional for NVIDIA GPU metrics |
llamacpp:* | llama.cpp server | Required for LLM server metrics |
Changes Made (NEM-4153)¶
Fixed PromQL Queries¶
-
video-analytics.json
-
Fixed histogram_quantile queries missing rate() aggregation for Re-ID latency
-
Fixed avg(hsi_track_duration_seconds) to use rate sum/count pattern
-
ai-services.json
-
Fixed action confidence distribution to use enrichment metrics
- Fixed action false positive rate to use enrichment metrics
- Fixed cold start latency to use enrichment_model_load_time_seconds
-
Fixed model restarts to use hsi_pipeline_worker_restarts_total
-
analytics.json
-
Added [PENDING] markers to sections with unimplemented metrics (RUM, Database, A/B Testing)
- Fixed LLM cost metrics to use existing hsi_daily_cost_usd, hsi_estimated_cost_usd_total
- Fixed budget utilization to use hsi_budget_utilization_ratio
-
Fixed Redis pool metrics to use hsi_redis_pool_in_use, hsi_redis_pool_size
-
tracing.json
-
Fixed hsi_http_requests_total to use http_request_duration_seconds_count
-
Fixed hsi_http_request_duration_seconds_bucket to http_request_duration_seconds_bucket
-
prometheus-rules.yml
- Added note referencing profiling-recording-rules.yml for regression detection rules
Dashboard Health Summary¶
After NEM-4153 fixes:
| Dashboard | Total Queries | Working | Health |
|---|---|---|---|
| consolidated.json | 263 | ~255 | ~97% |
| analytics.json | 52 | 37 | 71% (pending RUM/DB/AB sections) |
| video-analytics.json | 33 | 33 | 100% |
| ai-services.json | 64 | 64 | 100% |
| hsi-gpu-metrics.json | 17 | 17 | 100% |
| hsi-profiling.json | 8 | 8 | 100% |
| hsi-request-profiling.json | 8 | 8 | 100% |
| api-health.json | 20 | 20 | 100% |
| tracing.json | 21 | 21 | 100% |
| logs.json | 13 | 13 | 100% |
Total Queries: 499 Overall Health: >90% (excluding explicitly marked PENDING sections)
Note: analytics.json sections marked [PENDING] intentionally show "No data" until metrics are implemented (RUM, database pool, A/B testing frameworks).