Test / test (push) Canceled after 0s
Test / fuzz (./compat, FuzzParseFormat) (push) Canceled after 0s
Test / fuzz (./formatter, FuzzFormatJSON) (push) Canceled after 0s
Test / fuzz (./formatter, FuzzFormatTextPolicy) (push) Canceled after 0s
Test / fuzz (./sanitizer, FuzzSanitize) (push) Canceled after 0s
Test / fuzz (./sanitizer, FuzzSerializerJSON) (push) Canceled after 0s
133 lines
3.5 KiB
Go
133 lines
3.5 KiB
Go
package log
|
|
|
|
import (
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
// The benchmarks up to BenchmarkProcessLogRecord measure the producer path:
|
|
// format selection, channel send, and drop accounting. File writes complete
|
|
// asynchronously in the processor and are not attributed to their iterations.
|
|
|
|
// BenchmarkLoggerInfo measures the default raw-format path.
|
|
func BenchmarkLoggerInfo(b *testing.B) {
|
|
logger, _ := newTestLogger(b)
|
|
|
|
b.ReportAllocs()
|
|
for i := 0; b.Loop(); i++ {
|
|
logger.Info("benchmark message", i)
|
|
}
|
|
}
|
|
|
|
// BenchmarkLoggerTxt measures enqueueing with txt output selected.
|
|
func BenchmarkLoggerTxt(b *testing.B) {
|
|
logger, _ := newTestLogger(b)
|
|
|
|
cfg := logger.GetConfig()
|
|
cfg.Format = "txt"
|
|
mustNoErr(b, logger.ApplyConfig(cfg), "ApplyConfig")
|
|
|
|
b.ReportAllocs()
|
|
for i := 0; b.Loop(); i++ {
|
|
logger.Info("benchmark message", i)
|
|
}
|
|
}
|
|
|
|
// BenchmarkLoggerJSON measures the json path with key/value arguments.
|
|
func BenchmarkLoggerJSON(b *testing.B) {
|
|
logger, _ := newTestLogger(b)
|
|
|
|
cfg := logger.GetConfig()
|
|
cfg.Format = "json"
|
|
mustNoErr(b, logger.ApplyConfig(cfg), "ApplyConfig")
|
|
|
|
b.ReportAllocs()
|
|
for i := 0; b.Loop(); i++ {
|
|
logger.Info("benchmark message", i, "key", "value")
|
|
}
|
|
}
|
|
|
|
// BenchmarkLoggerStructured measures enqueueing and snapshotting structured maps.
|
|
func BenchmarkLoggerStructured(b *testing.B) {
|
|
logger, _ := newTestLogger(b)
|
|
|
|
cfg := logger.GetConfig()
|
|
cfg.Format = "json"
|
|
mustNoErr(b, logger.ApplyConfig(cfg), "ApplyConfig")
|
|
|
|
fields := map[string]any{
|
|
"user_id": 123,
|
|
"action": "benchmark",
|
|
"value": 42.5,
|
|
}
|
|
|
|
b.ReportAllocs()
|
|
for b.Loop() {
|
|
logger.LogStructured(LevelInfo, "benchmark", fields)
|
|
}
|
|
}
|
|
|
|
// BenchmarkLoggerSanitized measures enqueueing with PolicyTxt selected;
|
|
// sanitizer CPU work runs asynchronously and is benchmarked in its own package.
|
|
func BenchmarkLoggerSanitized(b *testing.B) {
|
|
logger, _ := newTestLogger(b)
|
|
|
|
cfg := logger.GetConfig()
|
|
cfg.Format = "txt"
|
|
cfg.Sanitization = PolicyTxt
|
|
mustNoErr(b, logger.ApplyConfig(cfg), "ApplyConfig")
|
|
|
|
b.ReportAllocs()
|
|
for i := 0; b.Loop(); i++ {
|
|
logger.Info("benchmark message", i)
|
|
}
|
|
}
|
|
|
|
// BenchmarkConcurrentLogging measures contention on the shared channel.
|
|
func BenchmarkConcurrentLogging(b *testing.B) {
|
|
logger, _ := newTestLogger(b)
|
|
|
|
b.ReportAllocs()
|
|
b.RunParallel(func(pb *testing.PB) {
|
|
i := 0
|
|
for pb.Next() {
|
|
logger.Info("concurrent", i)
|
|
i++
|
|
}
|
|
})
|
|
}
|
|
|
|
// BenchmarkProcessLogRecord measures the processor's write path, which the
|
|
// producer benchmarks above do not see. Record stamps advance by step to stand
|
|
// for a logging rate: at 100/s every record is due a log path check.
|
|
func BenchmarkProcessLogRecord(b *testing.B) {
|
|
for _, bc := range []struct {
|
|
name string
|
|
step time.Duration // 0: time.Now per record, as emit stamps it
|
|
}{{"ts=now", 0}, {"rate=1k/s", time.Millisecond}, {"rate=100/s", 10 * time.Millisecond}} {
|
|
b.Run(bc.name, func(b *testing.B) {
|
|
l := NewLogger()
|
|
c := DefaultConfig()
|
|
c.EnableConsole = false
|
|
c.EnableFile = true
|
|
c.Directory = b.TempDir()
|
|
c.Format = "txt"
|
|
c.MaxSizeKB = 0
|
|
mustNoErr(b, l.ApplyConfig(c), "ApplyConfig") // not started: the benchmark is the processor
|
|
b.Cleanup(func() { _ = l.Shutdown() })
|
|
rec := logRecord{Flags: l.getFlags(), Level: LevelInfo, Args: []any{"benchmark message", 42}}
|
|
ts := time.Now()
|
|
b.ReportAllocs()
|
|
for b.Loop() {
|
|
if ts = ts.Add(bc.step); bc.step == 0 {
|
|
ts = time.Now()
|
|
}
|
|
rec.TimeStamp = ts
|
|
if l.processLogRecord(rec) == 0 {
|
|
b.Fatal("record not written")
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|