veza/veza-backend-api/internal/metrics/aggregation_test.go
2026-03-05 23:03:43 +01:00

213 lines
6.6 KiB
Go

package metrics
import (
"testing"
"time"
"veza-backend-api/internal/errors"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestNewAggregatedMetrics(t *testing.T) {
agg := NewAggregatedMetrics()
require.NotNil(t, agg)
assert.NotNil(t, agg.windows)
assert.NotNil(t, agg.windowSizes)
assert.Equal(t, 3, len(agg.windowSizes)) // 1m, 5m, 1h
}
func TestAggregatedMetrics_AddError(t *testing.T) {
agg := NewAggregatedMetrics()
// Ajouter une erreur
agg.AddError("1m", errors.ErrCodeValidation, 400)
agg.AddError("5m", errors.ErrCodeValidation, 400)
agg.AddError("1h", errors.ErrCodeValidation, 400)
// Vérifier que les fenêtres ont été créées
windows1m := agg.GetAggregated("1m")
assert.Greater(t, len(windows1m), 0)
windows5m := agg.GetAggregated("5m")
assert.Greater(t, len(windows5m), 0)
windows1h := agg.GetAggregated("1h")
assert.Greater(t, len(windows1h), 0)
// Vérifier que l'erreur a été comptabilisée
assert.Equal(t, int64(1), windows1m[len(windows1m)-1].Errors)
assert.Equal(t, int64(1), windows5m[len(windows5m)-1].Errors)
assert.Equal(t, int64(1), windows1h[len(windows1h)-1].Errors)
}
func TestAggregatedMetrics_AddMultipleErrors(t *testing.T) {
agg := NewAggregatedMetrics()
// Ajouter plusieurs erreurs dans la même fenêtre
for i := 0; i < 5; i++ {
agg.AddError("1m", errors.ErrCodeInternal, 500)
}
windows := agg.GetAggregated("1m")
require.Greater(t, len(windows), 0)
// Vérifier que toutes les erreurs sont dans la dernière fenêtre
lastWindow := windows[len(windows)-1]
assert.Equal(t, int64(5), lastWindow.Errors)
assert.Equal(t, int64(5), lastWindow.ErrorsByCode[errors.ErrCodeInternal])
assert.Equal(t, int64(5), lastWindow.ErrorsByHTTPStatus[500])
}
func TestAggregatedMetrics_AddRequest(t *testing.T) {
agg := NewAggregatedMetrics()
// Ajouter des requêtes
agg.AddRequest("1m")
agg.AddRequest("1m")
agg.AddRequest("5m")
windows1m := agg.GetAggregated("1m")
require.Greater(t, len(windows1m), 0)
assert.Equal(t, int64(2), windows1m[len(windows1m)-1].Requests)
windows5m := agg.GetAggregated("5m")
require.Greater(t, len(windows5m), 0)
assert.Equal(t, int64(1), windows5m[len(windows5m)-1].Requests)
}
func TestAggregatedMetrics_GetAggregated(t *testing.T) {
agg := NewAggregatedMetrics()
// Ajouter des erreurs pour différentes fenêtres
agg.AddError("1m", errors.ErrCodeValidation, 400)
agg.AddError("5m", errors.ErrCodeNotFound, 404)
windows1m := agg.GetAggregated("1m")
require.Greater(t, len(windows1m), 0)
// Vérifier la structure de la fenêtre
window := windows1m[len(windows1m)-1]
assert.NotZero(t, window.Start)
assert.NotZero(t, window.End)
assert.Greater(t, window.End.Unix(), window.Start.Unix())
}
func TestAggregatedMetrics_GetAllAggregated(t *testing.T) {
agg := NewAggregatedMetrics()
// Ajouter des métriques pour toutes les fenêtres
agg.AddError("1m", errors.ErrCodeValidation, 400)
agg.AddError("5m", errors.ErrCodeNotFound, 404)
agg.AddError("1h", errors.ErrCodeInternal, 500)
allWindows := agg.GetAllAggregated()
assert.Contains(t, allWindows, "1m")
assert.Contains(t, allWindows, "5m")
assert.Contains(t, allWindows, "1h")
assert.Greater(t, len(allWindows["1m"]), 0)
assert.Greater(t, len(allWindows["5m"]), 0)
assert.Greater(t, len(allWindows["1h"]), 0)
}
func TestAggregatedMetrics_SlidingWindow(t *testing.T) {
agg := NewAggregatedMetrics()
// Simuler plusieurs fenêtres en ajoutant des erreurs avec des délais
now := time.Now()
// Ajouter une erreur maintenant
agg.AddError("1m", errors.ErrCodeValidation, 400)
// Attendre un peu (pas besoin d'attendre 1 minute, on teste juste la logique)
windows1 := agg.GetAggregated("1m")
assert.Equal(t, 1, len(windows1))
// Ajouter une autre erreur - devrait être dans la même fenêtre si on est dans la même minute
agg.AddError("1m", errors.ErrCodeValidation, 400)
windows2 := agg.GetAggregated("1m")
// Soit la même fenêtre (si même minute), soit une nouvelle
assert.GreaterOrEqual(t, len(windows2), 1)
// Le total devrait être au moins 2 erreurs
totalErrors := int64(0)
for _, w := range windows2 {
totalErrors += w.Errors
}
assert.GreaterOrEqual(t, totalErrors, int64(2))
// S'assurer que le temps n'est pas dans le futur
for _, w := range windows2 {
assert.LessOrEqual(t, w.Start.Unix(), now.Unix()+60) // Max 1 minute dans le futur
assert.LessOrEqual(t, w.End.Unix(), now.Unix()+120) // Max 2 minutes dans le futur
}
}
func TestAggregatedMetrics_InvalidWindowType(t *testing.T) {
agg := NewAggregatedMetrics()
// Ajouter une erreur avec un type de fenêtre invalide
agg.AddError("invalid", errors.ErrCodeValidation, 400)
// Ne devrait pas créer de fenêtre
windows := agg.GetAggregated("invalid")
assert.Equal(t, 0, len(windows))
}
func TestAggregatedMetrics_ErrorsByCode(t *testing.T) {
agg := NewAggregatedMetrics()
// Ajouter différentes erreurs avec différents codes
agg.AddError("1m", errors.ErrCodeValidation, 400)
agg.AddError("1m", errors.ErrCodeNotFound, 404)
agg.AddError("1m", errors.ErrCodeValidation, 400)
windows := agg.GetAggregated("1m")
require.Greater(t, len(windows), 0)
lastWindow := windows[len(windows)-1]
// Vérifier que les erreurs sont comptabilisées par code
assert.Equal(t, int64(2), lastWindow.ErrorsByCode[errors.ErrCodeValidation])
assert.Equal(t, int64(1), lastWindow.ErrorsByCode[errors.ErrCodeNotFound])
}
func TestAggregatedMetrics_ErrorsByHTTPStatus(t *testing.T) {
agg := NewAggregatedMetrics()
// Ajouter différentes erreurs avec différents status HTTP
agg.AddError("1m", errors.ErrCodeValidation, 400)
agg.AddError("1m", errors.ErrCodeNotFound, 404)
agg.AddError("1m", errors.ErrCodeInternal, 500)
agg.AddError("1m", errors.ErrCodeValidation, 400)
windows := agg.GetAggregated("1m")
require.Greater(t, len(windows), 0)
lastWindow := windows[len(windows)-1]
// Vérifier que les erreurs sont comptabilisées par status HTTP
assert.Equal(t, int64(2), lastWindow.ErrorsByHTTPStatus[400])
assert.Equal(t, int64(1), lastWindow.ErrorsByHTTPStatus[404])
assert.Equal(t, int64(1), lastWindow.ErrorsByHTTPStatus[500])
}
func TestErrorMetrics_IntegrationWithAggregation(t *testing.T) {
errorMetrics := NewErrorMetrics()
require.NotNil(t, errorMetrics.aggregated)
// Enregistrer des erreurs
errorMetrics.RecordError(errors.ErrCodeValidation, 400)
errorMetrics.RecordError(errors.ErrCodeNotFound, 404)
// Vérifier que l'agrégation a été mise à jour
windows1m := errorMetrics.GetAggregatedMetrics().GetAggregated("1m")
require.Greater(t, len(windows1m), 0)
lastWindow := windows1m[len(windows1m)-1]
assert.GreaterOrEqual(t, lastWindow.Errors, int64(2))
}