Files
Genarrative/server-rs/crates/module-runtime/tests/analytics_granularity.rs
历冰郁-hermes版 1d9d8c2e41
Some checks failed
CI / verify (push) Has been cancelled
feat: add analytics metric granularity query
2026-05-04 16:29:48 +08:00

106 lines
3.7 KiB
Rust

use module_runtime::{
AnalyticsGranularity, RuntimeAnalyticsDailyStatSnapshot, RuntimeTrackingScopeKind,
aggregate_runtime_tracking_daily_stats,
};
fn stat(event_key: &str, scope_id: &str, day_key: i64, count: u32) -> RuntimeAnalyticsDailyStatSnapshot {
RuntimeAnalyticsDailyStatSnapshot {
event_key: event_key.to_string(),
scope_kind: RuntimeTrackingScopeKind::User,
scope_id: scope_id.to_string(),
day_key,
count,
}
}
#[test]
fn aggregates_daily_stats_by_iso_week_bucket() {
let buckets = aggregate_runtime_tracking_daily_stats(
vec![
stat("daily_login", "user-1", 20_517, 1), // 2026-03-05
stat("daily_login", "user-1", 20_518, 2), // 2026-03-06
stat("daily_login", "user-1", 20_524, 3), // 2026-03-12
stat("daily_login", "user-2", 20_517, 9),
],
"daily_login",
RuntimeTrackingScopeKind::User,
"user-1",
AnalyticsGranularity::Week,
);
assert_eq!(buckets.len(), 2);
assert_eq!(buckets[0].bucket_key, "202610");
assert_eq!(buckets[0].bucket_start_date_key, 20_514); // 2026-03-02
assert_eq!(buckets[0].bucket_end_date_key, 20_520); // 2026-03-08
assert_eq!(buckets[0].value, 3);
assert_eq!(buckets[1].bucket_key, "202611");
assert_eq!(buckets[1].bucket_start_date_key, 20_521); // 2026-03-09
assert_eq!(buckets[1].bucket_end_date_key, 20_527); // 2026-03-15
assert_eq!(buckets[1].value, 3);
}
#[test]
fn aggregates_daily_stats_by_month_quarter_and_year_bucket() {
let stats = vec![
stat("play", "user-1", 20_545, 2), // 2026-04-02
stat("play", "user-1", 20_573, 3), // 2026-04-30
stat("play", "user-1", 20_574, 5), // 2026-05-01
stat("play", "user-1", 20_818, 7), // 2026-12-31
];
let month = aggregate_runtime_tracking_daily_stats(
stats.clone(),
"play",
RuntimeTrackingScopeKind::User,
"user-1",
AnalyticsGranularity::Month,
);
assert_eq!(month.iter().map(|bucket| (&bucket.bucket_key, bucket.value)).collect::<Vec<_>>(), vec![(&"202604".to_string(), 5), (&"202605".to_string(), 5), (&"202612".to_string(), 7)]);
assert_eq!(month[0].bucket_start_date_key, 20_544);
assert_eq!(month[0].bucket_end_date_key, 20_573);
let quarter = aggregate_runtime_tracking_daily_stats(
stats.clone(),
"play",
RuntimeTrackingScopeKind::User,
"user-1",
AnalyticsGranularity::Quarter,
);
assert_eq!(quarter.iter().map(|bucket| (&bucket.bucket_key, bucket.value)).collect::<Vec<_>>(), vec![(&"20262".to_string(), 10), (&"20264".to_string(), 7)]);
let year = aggregate_runtime_tracking_daily_stats(
stats,
"play",
RuntimeTrackingScopeKind::User,
"user-1",
AnalyticsGranularity::Year,
);
assert_eq!(year.len(), 1);
assert_eq!(year[0].bucket_key, "2026");
assert_eq!(year[0].value, 17);
}
#[test]
fn day_granularity_keeps_each_day_bucket_and_filters_scope() {
let buckets = aggregate_runtime_tracking_daily_stats(
vec![
stat("daily_login", "user-1", 20_517, 1),
stat("daily_login", "user-1", 20_518, 2),
stat("daily_login", "user-2", 20_517, 9),
stat("other", "user-1", 20_517, 9),
],
"daily_login",
RuntimeTrackingScopeKind::User,
"user-1",
AnalyticsGranularity::Day,
);
assert_eq!(buckets.len(), 2);
assert_eq!(buckets[0].bucket_key, "2026-03-05");
assert_eq!(buckets[0].bucket_start_date_key, 20_517);
assert_eq!(buckets[0].bucket_end_date_key, 20_517);
assert_eq!(buckets[0].value, 1);
assert_eq!(buckets[1].bucket_key, "2026-03-06");
assert_eq!(buckets[1].value, 2);
}