Add logger package with performance benchmarks
This commit is contained in:
326
logger/logger_test.go
Normal file
326
logger/logger_test.go
Normal file
@@ -0,0 +1,326 @@
|
||||
package logger
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestTextFormat(t *testing.T) {
|
||||
buf := &bytes.Buffer{}
|
||||
l := New(
|
||||
WithOutputFile(""),
|
||||
WithFormat(TEXT),
|
||||
WithTimeFormat("2006-01-02"),
|
||||
)
|
||||
|
||||
l.mu.Lock()
|
||||
l.writer = buf
|
||||
l.mu.Unlock()
|
||||
|
||||
l.Info("hello %s", "world")
|
||||
|
||||
output := buf.String()
|
||||
if !strings.Contains(output, "hello world") {
|
||||
t.Errorf("expected 'hello world' in output, got: %s", output)
|
||||
}
|
||||
}
|
||||
|
||||
func TestJSONFormat(t *testing.T) {
|
||||
buf := &bytes.Buffer{}
|
||||
l := New(
|
||||
WithOutputFile(""),
|
||||
WithFormat(JSON),
|
||||
)
|
||||
|
||||
l.mu.Lock()
|
||||
l.writer = buf
|
||||
l.mu.Unlock()
|
||||
|
||||
l.Info("test message")
|
||||
|
||||
output := buf.String()
|
||||
if !strings.Contains(output, `"message":"test message"`) {
|
||||
t.Errorf("expected JSON message in output, got: %s", output)
|
||||
}
|
||||
if !strings.Contains(output, `"level":"INFO"`) {
|
||||
t.Errorf("expected level INFO in output, got: %s", output)
|
||||
}
|
||||
}
|
||||
|
||||
func TestWithFields(t *testing.T) {
|
||||
buf := &bytes.Buffer{}
|
||||
l := New(
|
||||
WithOutputFile(""),
|
||||
WithFormat(TEXT),
|
||||
)
|
||||
|
||||
l.mu.Lock()
|
||||
l.writer = buf
|
||||
l.mu.Unlock()
|
||||
|
||||
l.InfoField("user logged in",
|
||||
"user_id", 123,
|
||||
"action", "login",
|
||||
)
|
||||
|
||||
output := buf.String()
|
||||
if !strings.Contains(output, "user_id=123") {
|
||||
t.Errorf("expected user_id=123 in output, got: %s", output)
|
||||
}
|
||||
if !strings.Contains(output, "action=login") {
|
||||
t.Errorf("expected action=login in output, got: %s", output)
|
||||
}
|
||||
}
|
||||
|
||||
func TestContextTraceID(t *testing.T) {
|
||||
buf := &bytes.Buffer{}
|
||||
l := New(
|
||||
WithOutputFile(""),
|
||||
WithFormat(JSON),
|
||||
)
|
||||
|
||||
l.mu.Lock()
|
||||
l.writer = buf
|
||||
l.mu.Unlock()
|
||||
|
||||
ctx := context.WithValue(context.Background(), "trace_id", "req-123")
|
||||
l.InfoCtx(ctx, "request processed")
|
||||
|
||||
output := buf.String()
|
||||
if !strings.Contains(output, `"trace_id":"req-123"`) {
|
||||
t.Errorf("expected trace_id in output, got: %s", output)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCustomFieldKey(t *testing.T) {
|
||||
buf := &bytes.Buffer{}
|
||||
l := New(
|
||||
WithOutputFile(""),
|
||||
WithFormat(JSON),
|
||||
WithFieldKey("request_id"),
|
||||
)
|
||||
|
||||
l.mu.Lock()
|
||||
l.writer = buf
|
||||
l.mu.Unlock()
|
||||
|
||||
ctx := context.WithValue(context.Background(), "request_id", "req-456")
|
||||
l.InfoCtx(ctx, "request processed")
|
||||
|
||||
output := buf.String()
|
||||
if !strings.Contains(output, `"request_id":"req-456"`) {
|
||||
t.Errorf("expected request_id in output, got: %s", output)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCaller(t *testing.T) {
|
||||
buf := &bytes.Buffer{}
|
||||
l := New(
|
||||
WithOutputFile(""),
|
||||
WithFormat(TEXT),
|
||||
WithCaller(true),
|
||||
)
|
||||
|
||||
l.mu.Lock()
|
||||
l.writer = buf
|
||||
l.mu.Unlock()
|
||||
|
||||
l.Info("test caller")
|
||||
|
||||
output := buf.String()
|
||||
if !strings.Contains(output, "logger_test.go:") {
|
||||
t.Errorf("expected caller info in output, got: %s", output)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLevelFiltering(t *testing.T) {
|
||||
buf := &bytes.Buffer{}
|
||||
l := New(
|
||||
WithOutputFile(""),
|
||||
WithLevel(ERROR),
|
||||
)
|
||||
|
||||
l.mu.Lock()
|
||||
l.writer = buf
|
||||
l.mu.Unlock()
|
||||
|
||||
l.Debug("debug message")
|
||||
l.Info("info message")
|
||||
l.Error("error message")
|
||||
|
||||
output := buf.String()
|
||||
if strings.Contains(output, "debug message") {
|
||||
t.Errorf("debug message should be filtered out, got: %s", output)
|
||||
}
|
||||
if strings.Contains(output, "info message") {
|
||||
t.Errorf("info message should be filtered out, got: %s", output)
|
||||
}
|
||||
if !strings.Contains(output, "error message") {
|
||||
t.Errorf("error message should be present, got: %s", output)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGlobalLogger(t *testing.T) {
|
||||
buf := &bytes.Buffer{}
|
||||
original := defaultLogger
|
||||
defer func() { defaultLogger = original }()
|
||||
|
||||
defaultLogger = New(
|
||||
WithOutputFile(""),
|
||||
WithFormat(TEXT),
|
||||
)
|
||||
|
||||
defaultLogger.mu.Lock()
|
||||
defaultLogger.writer = buf
|
||||
defaultLogger.mu.Unlock()
|
||||
|
||||
Info("global logger test")
|
||||
|
||||
output := buf.String()
|
||||
if !strings.Contains(output, "global logger test") {
|
||||
t.Errorf("expected global logger output, got: %s", output)
|
||||
}
|
||||
}
|
||||
|
||||
// Benchmarks
|
||||
|
||||
func benchmarkLogger(format Format, caller bool) *Logger {
|
||||
buf := &bytes.Buffer{}
|
||||
l := New(
|
||||
WithOutputFile(""),
|
||||
WithFormat(format),
|
||||
WithCaller(caller),
|
||||
)
|
||||
l.mu.Lock()
|
||||
l.writer = buf
|
||||
l.mu.Unlock()
|
||||
return l
|
||||
}
|
||||
|
||||
func BenchmarkInfoText(b *testing.B) {
|
||||
l := benchmarkLogger(TEXT, false)
|
||||
msg := "hello world"
|
||||
b.ResetTimer()
|
||||
b.ReportAllocs()
|
||||
for i := 0; i < b.N; i++ {
|
||||
l.Info("hello world")
|
||||
_ = msg
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkInfoTextWithArgs(b *testing.B) {
|
||||
l := benchmarkLogger(TEXT, false)
|
||||
b.ResetTimer()
|
||||
b.ReportAllocs()
|
||||
for i := 0; i < b.N; i++ {
|
||||
l.Info("user %s logged in from %s", "john", "192.168.1.1")
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkInfoJSON(b *testing.B) {
|
||||
l := benchmarkLogger(JSON, false)
|
||||
b.ResetTimer()
|
||||
b.ReportAllocs()
|
||||
for i := 0; i < b.N; i++ {
|
||||
l.Info("hello world")
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkInfoField(b *testing.B) {
|
||||
l := benchmarkLogger(TEXT, false)
|
||||
b.ResetTimer()
|
||||
b.ReportAllocs()
|
||||
for i := 0; i < b.N; i++ {
|
||||
l.InfoField("user logged in",
|
||||
"user_id", 123,
|
||||
"action", "login",
|
||||
"ip", "192.168.1.1",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkInfoFieldJSON(b *testing.B) {
|
||||
l := benchmarkLogger(JSON, false)
|
||||
b.ResetTimer()
|
||||
b.ReportAllocs()
|
||||
for i := 0; i < b.N; i++ {
|
||||
l.InfoField("user logged in",
|
||||
"user_id", 123,
|
||||
"action", "login",
|
||||
"ip", "192.168.1.1",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkInfoWithCaller(b *testing.B) {
|
||||
l := benchmarkLogger(TEXT, true)
|
||||
b.ResetTimer()
|
||||
b.ReportAllocs()
|
||||
for i := 0; i < b.N; i++ {
|
||||
l.Info("hello world")
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkInfoCtx(b *testing.B) {
|
||||
l := benchmarkLogger(JSON, false)
|
||||
ctx := context.WithValue(context.Background(), "trace_id", "req-123456789")
|
||||
b.ResetTimer()
|
||||
b.ReportAllocs()
|
||||
for i := 0; i < b.N; i++ {
|
||||
l.InfoCtx(ctx, "request processed")
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkInfoFiltered(b *testing.B) {
|
||||
l := New(
|
||||
WithOutputFile(""),
|
||||
WithLevel(ERROR),
|
||||
)
|
||||
l.mu.Lock()
|
||||
l.writer = &bytes.Buffer{}
|
||||
l.mu.Unlock()
|
||||
b.ResetTimer()
|
||||
b.ReportAllocs()
|
||||
for i := 0; i < b.N; i++ {
|
||||
l.Info("this should be filtered")
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkManyFields(b *testing.B) {
|
||||
l := benchmarkLogger(JSON, false)
|
||||
b.ResetTimer()
|
||||
b.ReportAllocs()
|
||||
for i := 0; i < b.N; i++ {
|
||||
l.InfoField("event",
|
||||
"field1", "value1",
|
||||
"field2", "value2",
|
||||
"field3", "value3",
|
||||
"field4", "value4",
|
||||
"field5", "value5",
|
||||
"field6", "value6",
|
||||
"field7", "value7",
|
||||
"field8", "value8",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkGlobalInfo(b *testing.B) {
|
||||
b.ResetTimer()
|
||||
b.ReportAllocs()
|
||||
for i := 0; i < b.N; i++ {
|
||||
Info("hello world")
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkGlobalInfoField(b *testing.B) {
|
||||
b.ResetTimer()
|
||||
b.ReportAllocs()
|
||||
for i := 0; i < b.N; i++ {
|
||||
InfoField("event",
|
||||
"key1", "value1",
|
||||
"key2", "value2",
|
||||
)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user