/* * SPDX-FileCopyrightText: 2020 Stalwart Labs LLC * * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL */ use crate::utils::server::TestServer; use common::telemetry::metrics::store::MetricsStore; use registry::{schema::prelude::ObjectType, types::datetime::UTCDateTime}; use std::time::Duration; use store::write::now; use types::id::Id; pub async fn test(test: &TestServer) { println!("Running Metrics tests..."); // Make sure there are no span entries in the db let admin = test.account("admin@example.org"); assert_eq!( admin .registry_query( ObjectType::Metric, Vec::<(&str, &str)>::new(), Vec::<&str>::new(), ) .await .object_ids() .collect::>(), Vec::::new() ); // Insert test metrics test.server.insert_test_metrics().await; // Fetch all metrics let metric_ids = admin .registry_query( ObjectType::Metric, Vec::<(&str, &str)>::new(), Vec::<&str>::new(), ) .await .object_ids() .collect::>(); let response = admin .registry_get_many(ObjectType::Metric, Vec::<&str>::new()) .await; let metrics = response.list(); assert!( metrics.len() > 2000, "Found {} metrics, expected more than 2000", metrics.len() ); assert_eq!(metrics.len(), metric_ids.len()); // Fetch the last 48 hours of metrics let metric_ids = admin .registry_query( ObjectType::Metric, [( "timestampIsGreaterThan", UTCDateTime::from_timestamp((now() - (2 * 86400)) as i64).to_string(), )], Vec::<&str>::new(), ) .await .object_ids() .collect::>(); assert!( metric_ids.len() > 20 && metric_ids.len() < 2000, "Found {} metrics, expected more than 20 and less than 2000", metric_ids.len() ); // Test pagination (forward and reverse) let asc_order: Vec = admin .registry_query_paginated( ObjectType::Metric, "timestamp", true, None, None, None, None, false, ) .await .object_ids() .collect(); assert!(asc_order.len() > 100, "expected >100 metrics, got {}", asc_order.len()); let desc_order: Vec = asc_order.iter().rev().copied().collect(); let total = asc_order.len(); let limit = 25usize; for chunk_start in [0usize, limit, total - limit] { let asc = admin .registry_query_paginated( ObjectType::Metric, "timestamp", true, Some(chunk_start as i32), Some(limit), None, None, false, ) .await .object_ids() .collect::>(); assert_eq!( asc, asc_order[chunk_start..chunk_start + limit], "ascending position={chunk_start} limit={limit}", ); let desc = admin .registry_query_paginated( ObjectType::Metric, "timestamp", false, Some(chunk_start as i32), Some(limit), None, None, false, ) .await .object_ids() .collect::>(); assert_eq!( desc, desc_order[chunk_start..chunk_start + limit], "descending position={chunk_start} limit={limit}", ); } for anchor_idx in [limit - 1, total - limit - 1] { let asc = admin .registry_query_paginated( ObjectType::Metric, "timestamp", true, None, Some(limit), Some(asc_order[anchor_idx]), Some(1), false, ) .await .object_ids() .collect::>(); let asc_size = std::cmp::min(limit, total - anchor_idx - 1); assert_eq!( asc, asc_order[anchor_idx + 1..anchor_idx + 1 + asc_size], "ascending anchor={} offset=1 limit={limit}", asc_order[anchor_idx], ); let desc = admin .registry_query_paginated( ObjectType::Metric, "timestamp", false, None, Some(limit), Some(desc_order[anchor_idx]), Some(1), false, ) .await .object_ids() .collect::>(); let desc_size = std::cmp::min(limit, total - anchor_idx - 1); assert_eq!( desc, desc_order[anchor_idx + 1..anchor_idx + 1 + desc_size], "descending anchor={} offset=1 limit={limit}", desc_order[anchor_idx], ); } // Purge metrics and make sure they are gone test.server .metrics_store() .purge_metrics(Duration::from_secs(0)) .await .unwrap(); assert_eq!( admin .registry_query( ObjectType::Metric, Vec::<(&str, &str)>::new(), Vec::<&str>::new(), ) .await .object_ids() .collect::>(), Vec::::new() ); }