//! Integration test: Guardian anchor updates observability metrics //! //! Run with: cargo test -p vaultmesh-guardian --features metrics --test metrics_integration #![cfg(feature = "metrics")] use std::net::TcpListener; use std::sync::Arc; use tokio::time::{sleep, Duration}; use vaultmesh_core::Scroll; use vaultmesh_guardian::GuardianEngine; use vaultmesh_observability::ObservabilityEngine; #[tokio::test] async fn test_anchor_updates_observability_metrics() { // Create temp directory for test let tmp = tempfile::TempDir::new().unwrap(); let receipts_dir = tmp.path().join("receipts/guardian"); std::fs::create_dir_all(&receipts_dir).unwrap(); // Dynamic port allocation - bind to port 0 to get an available port let listener = TcpListener::bind("127.0.0.1:0").expect("bind to port 0"); let addr = listener.local_addr().expect("get local addr"); drop(listener); // Release so ObservabilityEngine can bind // Create Observability engine and run its HTTP server on dynamic port let obs = Arc::new(ObservabilityEngine::new()); obs.clone().serve(&addr).await.expect("serve failed"); // Give the server time to start sleep(Duration::from_millis(100)).await; // Build guardian with observability (using the metrics feature) let guardian = GuardianEngine::new(tmp.path(), "did:vm:guardian:test") .with_observability(obs.clone()); // Perform an anchor let scrolls = vec![Scroll::Guardian, Scroll::Treasury]; guardian.anchor(&scrolls).expect("anchor failed"); // Give time for metrics to update sleep(Duration::from_millis(100)).await; // Fetch metrics from Observability server using dynamic address let metrics_url = format!("http://{}/metrics", addr); let resp = reqwest::get(&metrics_url) .await .expect("request failed"); let body = resp.text().await.expect("body read failed"); // Assert metrics contain receipts counter assert!( body.contains("vaultmesh_receipts_total"), "metrics should expose receipts counter" ); // Assert metrics contain anchor age gauge assert!( body.contains("vaultmesh_anchor_age_seconds"), "metrics should expose anchor age gauge" ); // Assert guardian module appears in metrics assert!( body.contains("guardian"), "guardian module should appear in metrics" ); // Anchor age should be 0 (just anchored) assert!( body.contains("vaultmesh_anchor_age_seconds 0"), "anchor age should be 0 after fresh anchor" ); }