package telemetry import ( "context" "fmt" "testing" "time" "github.com/alicebob/miniredis/v2" "github.com/glebarez/sqlite" "github.com/redis/go-redis/v9" "gorm.io/datatypes" "gorm.io/gorm" "dudu/server/internal/store" ) func TestAggregateDay(t *testing.T) { mr := miniredis.RunT(t) rdb := redis.NewClient(&redis.Options{Addr: mr.Addr()}) db, _ := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{}) _ = db.AutoMigrate(store.AllModels()...) h := New(db, rdb) cst := time.FixedZone("CST", 8*3600) day := time.Now().In(cst).Format("2006-01-02") noon, _ := time.ParseInLocation("2006-01-02 15", day+" 12", cst) // 100 条延迟事件:ms = 1..100 → P50≈50, P95≈95 for i := 1; i <= 100; i++ { db.Create(&store.MetricEvent{ DeviceID: "d1", Platform: "mac", Event: "asr.first_partial_ms", Props: datatypes.JSON(fmt.Sprintf(`{"ms":%d}`, i)), ReceivedAt: noon, }) } // 计数型事件不参与分位 db.Create(&store.MetricEvent{ DeviceID: "d1", Platform: "mac", Event: "login.success", Props: datatypes.JSON(`{}`), ReceivedAt: noon, }) if err := h.AggregateDay(context.Background(), day); err != nil { t.Fatal(err) } var md store.MetricDaily if err := db.First(&md, "date = ? AND event = ? AND platform = ?", day, "asr.first_partial_ms", "mac").Error; err != nil { t.Fatal(err) } if md.Count != 100 || md.P50Ms < 45 || md.P50Ms > 55 || md.P95Ms < 90 || md.P95Ms > 100 { t.Fatalf("bad aggregate: %+v", md) } var login store.MetricDaily if err := db.First(&login, "date = ? AND event = ?", day, "login.success").Error; err != nil || login.Count != 1 { t.Fatalf("login aggregate missing: %+v err=%v", login, err) } }