veza/veza-backend-api/internal/logging/logger_performance_test.go
2025-12-03 20:29:37 +01:00

213 lines
5.6 KiB
Go

package logging
import (
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.uber.org/zap"
)
// BenchmarkLogging_Optimized benchmark le logger optimisé
func BenchmarkLogging_Optimized(b *testing.B) {
logger, err := NewOptimizedLogger("production", "INFO")
require.NoError(b, err)
defer logger.Sync()
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
logger.Info("test message",
zap.String("key", "value"),
zap.Int("count", 42),
)
}
})
}
// BenchmarkLogging_Standard benchmark le logger standard (pour comparaison)
func BenchmarkLogging_Standard(b *testing.B) {
logger, err := NewLogger("production", "INFO")
require.NoError(b, err)
defer logger.Sync()
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
logger.Info("test message",
zap.String("key", "value"),
zap.Int("count", 42),
)
}
})
}
// TestOptimizedLogger_Performance teste que le logger optimisé atteint < 1ms par log
func TestOptimizedLogger_Performance(t *testing.T) {
logger, err := NewOptimizedLogger("production", "INFO")
require.NoError(t, err)
defer logger.Sync()
iterations := 1000
start := time.Now()
for i := 0; i < iterations; i++ {
logger.Info("test message",
zap.String("key", "value"),
zap.Int("iteration", i),
)
}
// Sync pour s'assurer que tous les logs sont écrits
// Note: Sync() peut retourner une erreur sur stdout/stderr sur certains systèmes, c'est OK
_ = logger.Sync()
duration := time.Since(start)
avgDuration := duration / time.Duration(iterations)
// Vérifier que la moyenne est < 1ms par log
assert.Less(t, avgDuration, 1*time.Millisecond,
"Average log time should be < 1ms, got %v", avgDuration)
}
// TestOptimizedLogger_HighLoad teste la performance avec 10K logs/seconde
func TestOptimizedLogger_HighLoad(t *testing.T) {
logger, err := NewOptimizedLogger("production", "INFO")
require.NoError(t, err)
defer logger.Sync()
duration := 1 * time.Second
iteration := 0
done := make(chan struct{})
// Goroutine qui envoie des logs rapidement
go func() {
endTime := time.Now().Add(duration)
for time.Now().Before(endTime) {
logger.Info("high load test",
zap.String("test", "high_load"),
zap.Int("iteration", iteration),
)
iteration++
}
close(done)
}()
// Attendre la fin
<-done
// Sync pour s'assurer que tous les logs sont écrits
// Note: Sync() peut retourner une erreur sur stdout/stderr sur certains systèmes, c'est OK
_ = logger.Sync()
// Le système devrait pouvoir gérer cette charge sans bloquer
// Avec sampling activé, certains logs peuvent être filtrés, c'est normal
// On vérifie juste qu'il n'y a pas eu de panique et que le système répond
}
// TestOptimizedLogger_Sampling teste que le sampling fonctionne correctement
func TestOptimizedLogger_Sampling(t *testing.T) {
logger, err := NewOptimizedLogger("production", "INFO")
require.NoError(t, err)
defer logger.Sync()
// Envoyer beaucoup de logs rapidement
// Avec sampling Initial:100, Thereafter:100, on devrait voir une réduction après 100 logs
for i := 0; i < 500; i++ {
logger.Info("sampling test",
zap.Int("iteration", i),
)
}
// Sync pour s'assurer que tous les logs sont écrits
// Note: Sync() peut retourner une erreur sur stdout/stderr sur certains systèmes, c'est OK
_ = logger.Sync()
// Le sampling devrait être actif sans erreur
// On vérifie juste que ça ne panique pas et que le logger fonctionne
}
// TestOptimizedLogger_Concurrent teste que le logger peut gérer des logs concurrents
func TestOptimizedLogger_Concurrent(t *testing.T) {
logger, err := NewOptimizedLogger("production", "INFO")
require.NoError(t, err)
defer logger.Sync()
goroutines := 10
logsPerGoroutine := 100
done := make(chan struct{}, goroutines)
for i := 0; i < goroutines; i++ {
go func(id int) {
for j := 0; j < logsPerGoroutine; j++ {
logger.Info("concurrent test",
zap.Int("goroutine", id),
zap.Int("iteration", j),
)
}
done <- struct{}{}
}(i)
}
// Attendre que toutes les goroutines terminent
for i := 0; i < goroutines; i++ {
<-done
}
// Sync pour s'assurer que tous les logs sont écrits
// Note: Sync() peut retourner une erreur sur stdout/stderr sur certains systèmes, c'est OK
_ = logger.Sync()
// Le logger devrait gérer les logs concurrents sans problème
// On vérifie juste qu'il n'y a pas eu de panique
}
// TestOptimizedLogger_WithRotation teste le logger optimisé avec rotation
func TestOptimizedLogger_WithRotation(t *testing.T) {
tmpDir := t.TempDir()
logFile := tmpDir + "/optimized.log"
logger, err := NewOptimizedLoggerWithRotation("production", logFile, "INFO")
require.NoError(t, err)
defer logger.Sync()
// Envoyer des logs
for i := 0; i < 100; i++ {
logger.Info("optimized rotation test",
zap.Int("iteration", i),
)
}
// Sync pour s'assurer que tous les logs sont écrits
err = logger.Sync()
require.NoError(t, err)
// Vérifier que le fichier existe et contient des données
// (le buffering async peut prendre un peu de temps)
time.Sleep(200 * time.Millisecond)
// Le logger devrait fonctionner avec rotation
assert.NoError(t, err)
}
// BenchmarkLogging_OptimizedWithRotation benchmark le logger optimisé avec rotation
func BenchmarkLogging_OptimizedWithRotation(b *testing.B) {
tmpDir := b.TempDir()
logFile := tmpDir + "/bench.log"
logger, err := NewOptimizedLoggerWithRotation("production", logFile, "INFO")
require.NoError(b, err)
defer logger.Sync()
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
logger.Info("benchmark message",
zap.String("key", "value"),
zap.Int("count", 42),
)
}
})
}