351 lines
10 KiB
Go
351 lines
10 KiB
Go
package monitoring
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
"time"
|
|
|
|
"veza-backend-api/internal/models"
|
|
"veza-backend-api/internal/services"
|
|
|
|
"github.com/google/uuid"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
"go.uber.org/zap"
|
|
"gorm.io/driver/sqlite"
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
func setupTestDB(t *testing.T) *gorm.DB {
|
|
db, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{})
|
|
require.NoError(t, err)
|
|
|
|
// Migrer les modèles nécessaires
|
|
err = db.AutoMigrate(
|
|
&models.Track{},
|
|
&models.PlaybackAnalytics{},
|
|
)
|
|
require.NoError(t, err)
|
|
|
|
return db
|
|
}
|
|
|
|
func TestNewPlaybackAnalyticsMonitor(t *testing.T) {
|
|
db := setupTestDB(t)
|
|
logger := zap.NewNop()
|
|
alertsService := services.NewPlaybackAlertsService(db, logger)
|
|
analyticsService := services.NewPlaybackAnalyticsService(db, logger)
|
|
|
|
monitor := NewPlaybackAnalyticsMonitor(db, logger, alertsService, analyticsService)
|
|
|
|
assert.NotNil(t, monitor)
|
|
assert.Equal(t, db, monitor.db)
|
|
assert.Equal(t, logger, monitor.logger)
|
|
assert.Equal(t, alertsService, monitor.alertsService)
|
|
assert.Equal(t, analyticsService, monitor.analyticsService)
|
|
assert.NotNil(t, monitor.metrics)
|
|
assert.Equal(t, 5*time.Minute, monitor.alertCheckInterval)
|
|
}
|
|
|
|
func TestPlaybackAnalyticsMonitor_RecordEvent(t *testing.T) {
|
|
db := setupTestDB(t)
|
|
logger := zap.NewNop()
|
|
monitor := NewPlaybackAnalyticsMonitor(db, logger, nil, nil)
|
|
|
|
trackID := uuid.New()
|
|
userID := uuid.New()
|
|
|
|
analytics := &models.PlaybackAnalytics{
|
|
TrackID: trackID,
|
|
UserID: userID,
|
|
PlayTime: 180,
|
|
PauseCount: 2,
|
|
SeekCount: 1,
|
|
CompletionRate: 75.0,
|
|
StartedAt: time.Now(),
|
|
}
|
|
|
|
// Test avec succès
|
|
monitor.RecordEvent(context.Background(), analytics, 100*time.Millisecond, nil)
|
|
|
|
metrics := monitor.GetPerformanceMetrics()
|
|
assert.Equal(t, int64(1), metrics.TotalEventsRecorded)
|
|
assert.Equal(t, int64(0), metrics.TotalEventsFailed)
|
|
assert.Equal(t, 100*time.Millisecond, metrics.AverageRecordLatency)
|
|
|
|
// Test avec erreur
|
|
monitor.RecordEvent(context.Background(), analytics, 50*time.Millisecond, assert.AnError)
|
|
|
|
metrics = monitor.GetPerformanceMetrics()
|
|
assert.Equal(t, int64(1), metrics.TotalEventsRecorded)
|
|
assert.Equal(t, int64(1), metrics.TotalEventsFailed)
|
|
}
|
|
|
|
func TestPlaybackAnalyticsMonitor_RecordBatchEvent(t *testing.T) {
|
|
db := setupTestDB(t)
|
|
logger := zap.NewNop()
|
|
monitor := NewPlaybackAnalyticsMonitor(db, logger, nil, nil)
|
|
|
|
// Test avec succès
|
|
monitor.RecordBatchEvent(context.Background(), 10, 200*time.Millisecond, nil)
|
|
|
|
metrics := monitor.GetPerformanceMetrics()
|
|
assert.Equal(t, int64(10), metrics.TotalEventsRecorded)
|
|
assert.Equal(t, int64(0), metrics.TotalEventsFailed)
|
|
|
|
// Test avec erreur
|
|
monitor.RecordBatchEvent(context.Background(), 5, 100*time.Millisecond, assert.AnError)
|
|
|
|
metrics = monitor.GetPerformanceMetrics()
|
|
assert.Equal(t, int64(10), metrics.TotalEventsRecorded)
|
|
assert.Equal(t, int64(5), metrics.TotalEventsFailed)
|
|
}
|
|
|
|
func TestPlaybackAnalyticsMonitor_UpdateMetrics(t *testing.T) {
|
|
db := setupTestDB(t)
|
|
logger := zap.NewNop()
|
|
monitor := NewPlaybackAnalyticsMonitor(db, logger, nil, nil)
|
|
|
|
trackID := uuid.New()
|
|
userID1 := uuid.New()
|
|
userID2 := uuid.New()
|
|
|
|
// Créer un track
|
|
track := &models.Track{
|
|
ID: trackID,
|
|
Title: "Test Track",
|
|
Duration: 180,
|
|
}
|
|
require.NoError(t, db.Create(track).Error)
|
|
|
|
// Créer des analytics
|
|
analytics1 := &models.PlaybackAnalytics{
|
|
TrackID: trackID,
|
|
UserID: userID1,
|
|
PlayTime: 180,
|
|
CompletionRate: 100.0,
|
|
StartedAt: time.Now().Add(-10 * time.Minute),
|
|
CreatedAt: time.Now().Add(-10 * time.Minute),
|
|
}
|
|
analytics2 := &models.PlaybackAnalytics{
|
|
TrackID: trackID,
|
|
UserID: userID2,
|
|
PlayTime: 90,
|
|
CompletionRate: 50.0,
|
|
StartedAt: time.Now().Add(-5 * time.Minute),
|
|
CreatedAt: time.Now().Add(-5 * time.Minute),
|
|
}
|
|
require.NoError(t, db.Create(analytics1).Error)
|
|
require.NoError(t, db.Create(analytics2).Error)
|
|
|
|
// Mettre à jour les métriques
|
|
err := monitor.UpdateMetrics(context.Background())
|
|
require.NoError(t, err)
|
|
|
|
metrics := monitor.GetPerformanceMetrics()
|
|
assert.GreaterOrEqual(t, metrics.ActiveSessions, int64(0))
|
|
assert.Greater(t, metrics.AverageCompletionRate, 0.0)
|
|
assert.Greater(t, metrics.AveragePlayTime, 0.0)
|
|
}
|
|
|
|
func TestPlaybackAnalyticsMonitor_CheckAlerts(t *testing.T) {
|
|
db := setupTestDB(t)
|
|
logger := zap.NewNop()
|
|
alertsService := services.NewPlaybackAlertsService(db, logger)
|
|
monitor := NewPlaybackAnalyticsMonitor(db, logger, alertsService, nil)
|
|
|
|
trackID := uuid.New()
|
|
userID := uuid.New()
|
|
|
|
// Créer un track
|
|
track := &models.Track{
|
|
ID: trackID,
|
|
Title: "Test Track",
|
|
Duration: 180,
|
|
}
|
|
require.NoError(t, db.Create(track).Error)
|
|
|
|
// Créer des analytics avec un faible taux de complétion
|
|
analytics := &models.PlaybackAnalytics{
|
|
TrackID: trackID,
|
|
UserID: userID,
|
|
PlayTime: 30,
|
|
CompletionRate: 15.0, // Faible taux de complétion
|
|
StartedAt: time.Now().Add(-1 * time.Hour),
|
|
CreatedAt: time.Now().Add(-1 * time.Hour),
|
|
}
|
|
require.NoError(t, db.Create(analytics).Error)
|
|
|
|
// Vérifier les alertes
|
|
alerts, err := monitor.CheckAlerts(context.Background())
|
|
require.NoError(t, err)
|
|
|
|
// Il devrait y avoir au moins une alerte pour le faible taux de complétion
|
|
assert.GreaterOrEqual(t, len(alerts), 0) // Peut être 0 si les seuils ne sont pas atteints
|
|
|
|
metrics := monitor.GetPerformanceMetrics()
|
|
assert.GreaterOrEqual(t, metrics.TotalAlertsGenerated, int64(0))
|
|
}
|
|
|
|
func TestPlaybackAnalyticsMonitor_GetPerformanceMetrics(t *testing.T) {
|
|
db := setupTestDB(t)
|
|
logger := zap.NewNop()
|
|
monitor := NewPlaybackAnalyticsMonitor(db, logger, nil, nil)
|
|
|
|
trackID := uuid.New()
|
|
userID := uuid.New()
|
|
|
|
// Enregistrer quelques événements
|
|
analytics := &models.PlaybackAnalytics{
|
|
TrackID: trackID,
|
|
UserID: userID,
|
|
PlayTime: 180,
|
|
}
|
|
|
|
monitor.RecordEvent(context.Background(), analytics, 100*time.Millisecond, nil)
|
|
monitor.RecordEvent(context.Background(), analytics, 150*time.Millisecond, nil)
|
|
monitor.RecordEvent(context.Background(), analytics, 200*time.Millisecond, assert.AnError)
|
|
|
|
metrics := monitor.GetPerformanceMetrics()
|
|
|
|
assert.Equal(t, int64(2), metrics.TotalEventsRecorded)
|
|
assert.Equal(t, int64(1), metrics.TotalEventsFailed)
|
|
assert.Greater(t, metrics.AverageRecordLatency, time.Duration(0))
|
|
assert.NotZero(t, metrics.LastUpdated)
|
|
}
|
|
|
|
func TestPlaybackAnalyticsMonitor_GetDashboardMetrics(t *testing.T) {
|
|
db := setupTestDB(t)
|
|
logger := zap.NewNop()
|
|
alertsService := services.NewPlaybackAlertsService(db, logger)
|
|
monitor := NewPlaybackAnalyticsMonitor(db, logger, alertsService, nil)
|
|
|
|
trackID := uuid.New()
|
|
userID := uuid.New()
|
|
|
|
// Créer un track
|
|
track := &models.Track{
|
|
ID: trackID,
|
|
Title: "Test Track",
|
|
Duration: 180,
|
|
}
|
|
require.NoError(t, db.Create(track).Error)
|
|
|
|
// Créer des analytics
|
|
analytics := &models.PlaybackAnalytics{
|
|
TrackID: trackID,
|
|
UserID: userID,
|
|
PlayTime: 180,
|
|
CompletionRate: 100.0,
|
|
StartedAt: time.Now().Add(-1 * time.Hour),
|
|
CreatedAt: time.Now().Add(-1 * time.Hour),
|
|
}
|
|
require.NoError(t, db.Create(analytics).Error)
|
|
|
|
// Enregistrer quelques événements
|
|
monitor.RecordEvent(context.Background(), analytics, 100*time.Millisecond, nil)
|
|
monitor.RecordEvent(context.Background(), analytics, 150*time.Millisecond, nil)
|
|
|
|
// Obtenir les métriques du dashboard
|
|
dashboard, err := monitor.GetDashboardMetrics(context.Background())
|
|
require.NoError(t, err)
|
|
|
|
assert.NotNil(t, dashboard)
|
|
assert.NotNil(t, dashboard.Performance)
|
|
assert.NotNil(t, dashboard.RecentAlerts)
|
|
assert.NotNil(t, dashboard.TopTracks)
|
|
assert.GreaterOrEqual(t, dashboard.ErrorRate, 0.0)
|
|
assert.GreaterOrEqual(t, dashboard.SuccessRate, 0.0)
|
|
assert.GreaterOrEqual(t, dashboard.Throughput, 0.0)
|
|
assert.NotZero(t, dashboard.Timestamp)
|
|
}
|
|
|
|
func TestPlaybackAnalyticsMonitor_GetTopTracks(t *testing.T) {
|
|
db := setupTestDB(t)
|
|
logger := zap.NewNop()
|
|
monitor := NewPlaybackAnalyticsMonitor(db, logger, nil, nil)
|
|
|
|
trackID1 := uuid.New()
|
|
trackID2 := uuid.New()
|
|
|
|
// Créer des tracks
|
|
track1 := &models.Track{
|
|
ID: trackID1,
|
|
Title: "Track 1",
|
|
Duration: 180,
|
|
}
|
|
track2 := &models.Track{
|
|
ID: trackID2,
|
|
Title: "Track 2",
|
|
Duration: 240,
|
|
}
|
|
require.NoError(t, db.Create(track1).Error)
|
|
require.NoError(t, db.Create(track2).Error)
|
|
|
|
// Créer des analytics pour track1 (plus de sessions)
|
|
for i := 0; i < 5; i++ {
|
|
analytics := &models.PlaybackAnalytics{
|
|
TrackID: trackID1,
|
|
UserID: uuid.New(),
|
|
PlayTime: 180,
|
|
CompletionRate: 100.0,
|
|
StartedAt: time.Now().Add(-1 * time.Hour),
|
|
CreatedAt: time.Now().Add(-1 * time.Hour),
|
|
}
|
|
require.NoError(t, db.Create(analytics).Error)
|
|
}
|
|
|
|
// Créer des analytics pour track2 (moins de sessions)
|
|
for i := 0; i < 2; i++ {
|
|
analytics := &models.PlaybackAnalytics{
|
|
TrackID: trackID2,
|
|
UserID: uuid.New(),
|
|
PlayTime: 120,
|
|
CompletionRate: 50.0,
|
|
StartedAt: time.Now().Add(-1 * time.Hour),
|
|
CreatedAt: time.Now().Add(-1 * time.Hour),
|
|
}
|
|
require.NoError(t, db.Create(analytics).Error)
|
|
}
|
|
|
|
// Obtenir les top tracks
|
|
topTracks, err := monitor.getTopTracks(context.Background(), 10)
|
|
require.NoError(t, err)
|
|
|
|
assert.GreaterOrEqual(t, len(topTracks), 2)
|
|
// Track1 devrait être en premier (plus de sessions)
|
|
if len(topTracks) >= 2 {
|
|
assert.Equal(t, trackID1, topTracks[0].TrackID)
|
|
assert.Equal(t, int64(5), topTracks[0].TotalSessions)
|
|
}
|
|
}
|
|
|
|
func TestPlaybackAnalyticsMonitor_StartBackgroundMonitoring(t *testing.T) {
|
|
db := setupTestDB(t)
|
|
logger := zap.NewNop()
|
|
monitor := NewPlaybackAnalyticsMonitor(db, logger, nil, nil)
|
|
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
defer cancel()
|
|
|
|
// Démarrer le monitoring en arrière-plan avec un intervalle court
|
|
done := make(chan bool)
|
|
go func() {
|
|
monitor.StartBackgroundMonitoring(ctx, 100*time.Millisecond)
|
|
done <- true
|
|
}()
|
|
|
|
// Attendre un peu pour que le monitoring se mette à jour
|
|
time.Sleep(200 * time.Millisecond)
|
|
|
|
// Arrêter le monitoring
|
|
cancel()
|
|
|
|
// Attendre que la goroutine se termine
|
|
select {
|
|
case <-done:
|
|
// OK
|
|
case <-time.After(1 * time.Second):
|
|
t.Fatal("Background monitoring did not stop")
|
|
}
|
|
}
|