bench/end_to_end_bench_test.go

package bench_test

import (
	"io"
	"testing"
	"time"

	"mercemay.top/src/lambdalog/internal/encoder"
	logjson "mercemay.top/src/lambdalog/internal/encoder/json"
	"mercemay.top/src/lambdalog/internal/sampler"
	"mercemay.top/src/lambdalog/internal/sampler/adaptive"
	"mercemay.top/src/lambdalog/internal/sampler/threshold"
)

// pipeline simulates the minimum path a log call goes through: threshold,
// adaptive sampler, JSON encoder, io.Discard. It does not exercise the
// Logger type itself, which is in the root package.
func pipeline(enc logjson.Encoder, thr *threshold.Sampler, adp *adaptive.Sampler, rec encoder.Record, now time.Time) {
	in := sampler.Input{Level: rec.Level, Now: now}
	if thr.Sample(in) == sampler.Drop {
		return
	}
	if adp.Sample(in) == sampler.Drop {
		return
	}
	_ = enc.Encode(io.Discard, rec)
}

func BenchmarkEndToEnd_HappyPath(b *testing.B) {
	enc := logjson.Encoder{}
	thr := threshold.New("info")
	adp := adaptive.New(1000)
	adp.SeedFixed(1)
	rec := makeRecord(5)
	now := time.Unix(0, 0)
	b.ReportAllocs()
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		pipeline(enc, thr, adp, rec, now.Add(time.Duration(i)*time.Microsecond))
	}
}

func BenchmarkEndToEnd_ThresholdDrops(b *testing.B) {
	enc := logjson.Encoder{}
	thr := threshold.New("error") // message is info, so always dropped
	adp := adaptive.New(1000)
	rec := makeRecord(5)
	now := time.Unix(0, 0)
	b.ReportAllocs()
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		pipeline(enc, thr, adp, rec, now)
	}
}

func BenchmarkEndToEnd_HighVolumeThrottled(b *testing.B) {
	enc := logjson.Encoder{}
	thr := threshold.New("info")
	adp := adaptive.New(10) // aggressive
	adp.SeedFixed(2)
	rec := makeRecord(5)
	now := time.Unix(0, 0)
	b.ReportAllocs()
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		pipeline(enc, thr, adp, rec, now.Add(time.Duration(i)*time.Nanosecond))
	}
}

func BenchmarkEndToEnd_Parallel(b *testing.B) {
	enc := logjson.Encoder{}
	thr := threshold.New("info")
	adp := adaptive.New(5000)
	adp.SeedFixed(3)
	rec := makeRecord(5)
	b.ReportAllocs()
	b.ResetTimer()
	b.RunParallel(func(pb *testing.PB) {
		now := time.Unix(0, 0)
		for pb.Next() {
			pipeline(enc, thr, adp, rec, now)
		}
	})
}