From c72a799508cb0efa30fa3ad8d61e633e56573aa3 Mon Sep 17 00:00:00 2001 From: hectorj Date: Sun, 30 Apr 2017 14:50:05 +0200 Subject: [PATCH 1/3] Pack everything in an instantiable struct instead of using global vars. The global interface is maintained though, by forwarding calls to a default global log writer. --- nanolog.go | 103 ++++++++++++++++++++++++++++++++---------------- nanolog_test.go | 46 ++++++++++----------- 2 files changed, 92 insertions(+), 57 deletions(-) diff --git a/nanolog.go b/nanolog.go index 8d1003c..1d77214 100644 --- a/nanolog.go +++ b/nanolog.go @@ -161,34 +161,59 @@ type Logger struct { Segs []string } -var ( - loggers = make([]Logger, MaxLoggers) - curLoggersIdx = new(uint32) -) +var defaultLogWriter = New() -var ( - initBuf = &bytes.Buffer{} - w = bufio.NewWriter(initBuf) - firstSet = true -) +type logWriter struct { + initBuf *bytes.Buffer + w *bufio.Writer + firstSet bool + + bufpool *sync.Pool + writeLock sync.Locker + + loggers []Logger + curLoggersIdx *uint32 +} + +func New() *logWriter { + initBuf := &bytes.Buffer{} + return &logWriter{ + initBuf: initBuf, + w: bufio.NewWriter(initBuf), + firstSet: true, + bufpool: &sync.Pool{ + New: func() interface{} { + temp := make([]byte, 1024) // 1k default size + return &temp + }, + }, + writeLock: new(sync.Mutex), + loggers: make([]Logger, MaxLoggers), + curLoggersIdx: new(uint32), + } +} + +func SetWriter(new io.Writer) error { + return defaultLogWriter.SetWriter(new) +} // SetWriter will set up efficient writing for the log to the output stream given. // A raw IO stream is best. The first time SetWriter is called any logs that were // created or posted before the call will be sent to the writer all in one go. -func SetWriter(new io.Writer) error { +func (lw *logWriter) SetWriter(new io.Writer) error { // grab write lock to ensure no prblems - writeLock.Lock() - defer writeLock.Unlock() + lw.writeLock.Lock() + defer lw.writeLock.Unlock() - if err := w.Flush(); err != nil { + if err := lw.w.Flush(); err != nil { return err } - w = bufio.NewWriter(new) + lw.w = bufio.NewWriter(new) - if firstSet { - firstSet = false - if _, err := initBuf.WriteTo(w); err != nil { + if lw.firstSet { + lw.firstSet = false + if _, err := lw.initBuf.WriteTo(lw.w); err != nil { return err } } @@ -196,28 +221,36 @@ func SetWriter(new io.Writer) error { return nil } -// Flush ensures all log entries written up to this point are written to the underlying io.Writer func Flush() error { + return defaultLogWriter.Flush() +} + +// Flush ensures all log entries written up to this point are written to the underlying io.Writer +func (lw *logWriter) Flush() error { // grab write lock to ensure no prblems - writeLock.Lock() - defer writeLock.Unlock() + lw.writeLock.Lock() + defer lw.writeLock.Unlock() - return w.Flush() + return lw.w.Flush() } -// AddLogger initializes a logger and returns a handle for future logging func AddLogger(fmt string) Handle { + return defaultLogWriter.AddLogger(fmt) +} + +// AddLogger initializes a logger and returns a handle for future logging +func (lw *logWriter) AddLogger(fmt string) Handle { // save some kind of string format to the file - idx := atomic.AddUint32(curLoggersIdx, 1) - 1 + idx := atomic.AddUint32(lw.curLoggersIdx, 1) - 1 if idx >= MaxLoggers { panic("Too many loggers") } l, segs := parseLogLine(fmt) - loggers[idx] = l + lw.loggers[idx] = l - writeLogDataToFile(idx, l.Kinds, segs) + lw.writeLogDataToFile(idx, l.Kinds, segs) return Handle(idx) } @@ -424,7 +457,7 @@ func next(s *string) rune { return r } -func writeLogDataToFile(idx uint32, kinds []reflect.Kind, segs []string) { +func (lw *logWriter) writeLogDataToFile(idx uint32, kinds []reflect.Kind, segs []string) { buf := &bytes.Buffer{} b := make([]byte, 4) @@ -459,7 +492,7 @@ func writeLogDataToFile(idx uint32, kinds []reflect.Kind, segs []string) { } // finally write all of it together to the output - w.Write(buf.Bytes()) + lw.w.Write(buf.Bytes()) } // helper function to have consistently formatted panics and shorter code above @@ -474,13 +507,15 @@ var ( return &temp }, } - - writeLock = new(sync.Mutex) ) -// Log logs to the output stream for the logging package func Log(handle Handle, args ...interface{}) error { - l := loggers[handle] + return defaultLogWriter.Log(handle, args...) +} + +// Log logs to the output stream for the logging package +func (lw *logWriter) Log(handle Handle, args ...interface{}) error { + l := lw.loggers[handle] if len(l.Kinds) != len(args) { panic("Number of args does not match log line") @@ -612,9 +647,9 @@ func Log(handle Handle, args ...interface{}) error { } } - writeLock.Lock() - _, err := w.Write(*buf) - writeLock.Unlock() + lw.writeLock.Lock() + _, err := lw.w.Write(*buf) + lw.writeLock.Unlock() bufpool.Put(buf) return err diff --git a/nanolog_test.go b/nanolog_test.go index bdbd11a..a99c22f 100644 --- a/nanolog_test.go +++ b/nanolog_test.go @@ -48,7 +48,7 @@ func TestSetWriter(t *testing.T) { SetWriter(buf) // simulate some logging - w.WriteByte(35) + defaultLogWriter.w.WriteByte(35) SetWriter(&bytes.Buffer{}) @@ -65,7 +65,7 @@ func TestFlush(t *testing.T) { SetWriter(buf) // simulate some logging - w.WriteByte(35) + defaultLogWriter.w.WriteByte(35) Flush() @@ -87,14 +87,14 @@ func TestAddLogger(t *testing.T) { t.Logf("Expected segs: %v", expectedSegs) // Reset to avoid running over the loggers limit - *curLoggersIdx = 0 + *defaultLogWriter.curLoggersIdx = 0 buf := &bytes.Buffer{} - w = bufio.NewWriter(buf) + defaultLogWriter.w = bufio.NewWriter(buf) h := AddLogger(logLine) //t.Log("Handle:", h) - w.Flush() + defaultLogWriter.w.Flush() out := buf.Bytes() //t.Log(string(out)) @@ -241,7 +241,7 @@ func TestAddLoggerLimit(t *testing.T) { } // reset so other tests can actually continue testing - *curLoggersIdx = 0 + *defaultLogWriter.curLoggersIdx = 0 }() t.Logf("Filling up loggers") @@ -253,7 +253,7 @@ func TestAddLoggerLimit(t *testing.T) { func TestParseLogLine(t *testing.T) { t.Run("Correct", func(t *testing.T) { buf := &bytes.Buffer{} - w = bufio.NewWriter(buf) + defaultLogWriter.w = bufio.NewWriter(buf) f := "foo thing bar thing %i64. Fubar %s foo. sadf %% asdf %u32 sdfasfasdfasdffds %u32." l, segs := parseLogLine(f) @@ -317,17 +317,17 @@ func TestParseLogLine(t *testing.T) { func TestLog(t *testing.T) { check := func(t *testing.T, fmtstring string, toWrite interface{}, dataLen int, checkRest func(*testing.T, []byte) bool) bool { // Reset to avoid running over the loggers limit - *curLoggersIdx = 0 + *defaultLogWriter.curLoggersIdx = 0 buf := &bytes.Buffer{} - w = bufio.NewWriter(buf) + defaultLogWriter.w = bufio.NewWriter(buf) h := AddLogger(fmtstring) //t.Log("Handle:", h) - w.Flush() + defaultLogWriter.w.Flush() buf.Reset() Log(h, toWrite) - w.Flush() + defaultLogWriter.w.Flush() out := buf.Bytes() expectedLen := 1 + 4 + dataLen @@ -765,12 +765,12 @@ func TestLog(t *testing.T) { }() // Reset to avoid running over the loggers limit - *curLoggersIdx = 0 + *defaultLogWriter.curLoggersIdx = 0 buf := &bytes.Buffer{} - w = bufio.NewWriter(buf) + defaultLogWriter.w = bufio.NewWriter(buf) h := AddLogger("%b") //t.Log("Handle:", h) - w.Flush() + defaultLogWriter.w.Flush() buf.Reset() Log(h, 42) @@ -785,12 +785,12 @@ func TestLog(t *testing.T) { }() // Reset to avoid running over the loggers limit - *curLoggersIdx = 0 + *defaultLogWriter.curLoggersIdx = 0 buf := &bytes.Buffer{} - w = bufio.NewWriter(buf) + defaultLogWriter.w = bufio.NewWriter(buf) h := AddLogger("%b") //t.Log("Handle:", h) - w.Flush() + defaultLogWriter.w.Flush() buf.Reset() Log(h, true, 42) @@ -805,7 +805,7 @@ func BenchmarkAddLogger(b *testing.B) { testLogHandleSink = AddLogger("foo thing bar thing %i64. Fubar %s foo. sadfasdf %u32 sdfasfasdfasdffds %u32.") // to prevent it from overflowing the logger array - *curLoggersIdx = 0 + *defaultLogWriter.curLoggersIdx = 0 } } @@ -815,7 +815,7 @@ var ( ) func BenchmarkParseLogLine(b *testing.B) { - w = bufio.NewWriter(ioutil.Discard) + defaultLogWriter.w = bufio.NewWriter(ioutil.Discard) f := "The operation %s could not be completed. Wanted %u64 bar %c128 %b %{s} %{i32}" for i := 0; i < b.N; i++ { testLoggerSink, testSegmentsSink = parseLogLine(f) @@ -823,7 +823,7 @@ func BenchmarkParseLogLine(b *testing.B) { } func BenchmarkLogParallel(b *testing.B) { - w = bufio.NewWriter(ioutil.Discard) + defaultLogWriter.w = bufio.NewWriter(ioutil.Discard) h := AddLogger("foo thing bar thing %i64. Fubar %s foo. sadfasdf %u32 sdfasfasdfasdffds %u32.") args := []interface{}{int64(1), "string", uint32(2), uint32(3)} @@ -836,7 +836,7 @@ func BenchmarkLogParallel(b *testing.B) { } func BenchmarkLogSequential(b *testing.B) { - w = bufio.NewWriter(ioutil.Discard) + defaultLogWriter.w = bufio.NewWriter(ioutil.Discard) h := AddLogger("foo thing bar thing %i64. Fubar %s foo. sadfasdf %u32 sdfasfasdfasdffds %u32.") args := []interface{}{int64(1), "string", uint32(2), uint32(3)} @@ -848,7 +848,7 @@ func BenchmarkLogSequential(b *testing.B) { func BenchmarkCompareToStdlib(b *testing.B) { b.Run("Nanolog", func(b *testing.B) { - w = bufio.NewWriter(ioutil.Discard) + defaultLogWriter.w = bufio.NewWriter(ioutil.Discard) h := AddLogger("foo thing bar thing %i64. Fubar %s foo. sadfasdf %u32 sdfasfasdfasdffds %u32.") args := []interface{}{int64(1), "string", uint32(2), uint32(3)} @@ -872,7 +872,7 @@ func BenchmarkInterpolations(b *testing.B) { return func(b *testing.B) { for i := 1; i <= limit; i++ { b.Run(strconv.Itoa(i), func(b *testing.B) { - w = bufio.NewWriter(ioutil.Discard) + defaultLogWriter.w = bufio.NewWriter(ioutil.Discard) h := AddLogger(strings.Repeat(interp, i)) args := make([]interface{}, i) From b031ea86da2b780bf79a4d9ef4aebabf1d535191 Mon Sep 17 00:00:00 2001 From: hectorj Date: Mon, 1 May 2017 15:43:16 +0200 Subject: [PATCH 2/3] Minor corrections. Wrap *logWriter in an exported interface. Add comments everywhere golint complained --- nanolog.go | 41 +++++++++++++++++++++++------------------ nanolog_test.go | 46 +++++++++++++++++++++++----------------------- 2 files changed, 46 insertions(+), 41 deletions(-) diff --git a/nanolog.go b/nanolog.go index 1d77214..bd4010d 100644 --- a/nanolog.go +++ b/nanolog.go @@ -163,45 +163,50 @@ type Logger struct { var defaultLogWriter = New() +type LogWriter interface { + // SetWriter will set up efficient writing for the log to the output stream given. + // A raw IO stream is best. The first time SetWriter is called any logs that were + // created or posted before the call will be sent to the writer all in one go. + SetWriter(new io.Writer) error + // Flush ensures all log entries written up to this point are written to the underlying io.Writer + Flush() error + // AddLogger initializes a logger and returns a handle for future logging + AddLogger(fmt string) Handle + // Log logs to the output stream + Log(handle Handle, args ...interface{}) error +} + type logWriter struct { initBuf *bytes.Buffer w *bufio.Writer firstSet bool - bufpool *sync.Pool writeLock sync.Locker loggers []Logger curLoggersIdx *uint32 } -func New() *logWriter { +// New creates a new LogWriter +func New() LogWriter { initBuf := &bytes.Buffer{} return &logWriter{ - initBuf: initBuf, - w: bufio.NewWriter(initBuf), - firstSet: true, - bufpool: &sync.Pool{ - New: func() interface{} { - temp := make([]byte, 1024) // 1k default size - return &temp - }, - }, + initBuf: initBuf, + w: bufio.NewWriter(initBuf), + firstSet: true, writeLock: new(sync.Mutex), loggers: make([]Logger, MaxLoggers), curLoggersIdx: new(uint32), } } +// SetWriter calls LogWriter.SetWriter on the default log writer. func SetWriter(new io.Writer) error { return defaultLogWriter.SetWriter(new) } -// SetWriter will set up efficient writing for the log to the output stream given. -// A raw IO stream is best. The first time SetWriter is called any logs that were -// created or posted before the call will be sent to the writer all in one go. func (lw *logWriter) SetWriter(new io.Writer) error { - // grab write lock to ensure no prblems + // grab write lock to ensure no problems lw.writeLock.Lock() defer lw.writeLock.Unlock() @@ -221,11 +226,11 @@ func (lw *logWriter) SetWriter(new io.Writer) error { return nil } +// Flush calls LogWriter.Flush on the default log writer. func Flush() error { return defaultLogWriter.Flush() } -// Flush ensures all log entries written up to this point are written to the underlying io.Writer func (lw *logWriter) Flush() error { // grab write lock to ensure no prblems lw.writeLock.Lock() @@ -234,11 +239,11 @@ func (lw *logWriter) Flush() error { return lw.w.Flush() } +// AddLogger calls LogWriter.AddLogger on the default log writer. func AddLogger(fmt string) Handle { return defaultLogWriter.AddLogger(fmt) } -// AddLogger initializes a logger and returns a handle for future logging func (lw *logWriter) AddLogger(fmt string) Handle { // save some kind of string format to the file idx := atomic.AddUint32(lw.curLoggersIdx, 1) - 1 @@ -509,11 +514,11 @@ var ( } ) +// Log calls LogWriter.Log on the default log writer. func Log(handle Handle, args ...interface{}) error { return defaultLogWriter.Log(handle, args...) } -// Log logs to the output stream for the logging package func (lw *logWriter) Log(handle Handle, args ...interface{}) error { l := lw.loggers[handle] diff --git a/nanolog_test.go b/nanolog_test.go index a99c22f..1725955 100644 --- a/nanolog_test.go +++ b/nanolog_test.go @@ -48,7 +48,7 @@ func TestSetWriter(t *testing.T) { SetWriter(buf) // simulate some logging - defaultLogWriter.w.WriteByte(35) + defaultLogWriter.(*logWriter).w.WriteByte(35) SetWriter(&bytes.Buffer{}) @@ -65,7 +65,7 @@ func TestFlush(t *testing.T) { SetWriter(buf) // simulate some logging - defaultLogWriter.w.WriteByte(35) + defaultLogWriter.(*logWriter).w.WriteByte(35) Flush() @@ -87,14 +87,14 @@ func TestAddLogger(t *testing.T) { t.Logf("Expected segs: %v", expectedSegs) // Reset to avoid running over the loggers limit - *defaultLogWriter.curLoggersIdx = 0 + *defaultLogWriter.(*logWriter).curLoggersIdx = 0 buf := &bytes.Buffer{} - defaultLogWriter.w = bufio.NewWriter(buf) + defaultLogWriter.(*logWriter).w = bufio.NewWriter(buf) h := AddLogger(logLine) //t.Log("Handle:", h) - defaultLogWriter.w.Flush() + defaultLogWriter.(*logWriter).w.Flush() out := buf.Bytes() //t.Log(string(out)) @@ -241,7 +241,7 @@ func TestAddLoggerLimit(t *testing.T) { } // reset so other tests can actually continue testing - *defaultLogWriter.curLoggersIdx = 0 + *defaultLogWriter.(*logWriter).curLoggersIdx = 0 }() t.Logf("Filling up loggers") @@ -253,7 +253,7 @@ func TestAddLoggerLimit(t *testing.T) { func TestParseLogLine(t *testing.T) { t.Run("Correct", func(t *testing.T) { buf := &bytes.Buffer{} - defaultLogWriter.w = bufio.NewWriter(buf) + defaultLogWriter.(*logWriter).w = bufio.NewWriter(buf) f := "foo thing bar thing %i64. Fubar %s foo. sadf %% asdf %u32 sdfasfasdfasdffds %u32." l, segs := parseLogLine(f) @@ -317,17 +317,17 @@ func TestParseLogLine(t *testing.T) { func TestLog(t *testing.T) { check := func(t *testing.T, fmtstring string, toWrite interface{}, dataLen int, checkRest func(*testing.T, []byte) bool) bool { // Reset to avoid running over the loggers limit - *defaultLogWriter.curLoggersIdx = 0 + *defaultLogWriter.(*logWriter).curLoggersIdx = 0 buf := &bytes.Buffer{} - defaultLogWriter.w = bufio.NewWriter(buf) + defaultLogWriter.(*logWriter).w = bufio.NewWriter(buf) h := AddLogger(fmtstring) //t.Log("Handle:", h) - defaultLogWriter.w.Flush() + defaultLogWriter.(*logWriter).w.Flush() buf.Reset() Log(h, toWrite) - defaultLogWriter.w.Flush() + defaultLogWriter.(*logWriter).w.Flush() out := buf.Bytes() expectedLen := 1 + 4 + dataLen @@ -765,12 +765,12 @@ func TestLog(t *testing.T) { }() // Reset to avoid running over the loggers limit - *defaultLogWriter.curLoggersIdx = 0 + *defaultLogWriter.(*logWriter).curLoggersIdx = 0 buf := &bytes.Buffer{} - defaultLogWriter.w = bufio.NewWriter(buf) + defaultLogWriter.(*logWriter).w = bufio.NewWriter(buf) h := AddLogger("%b") //t.Log("Handle:", h) - defaultLogWriter.w.Flush() + defaultLogWriter.(*logWriter).w.Flush() buf.Reset() Log(h, 42) @@ -785,12 +785,12 @@ func TestLog(t *testing.T) { }() // Reset to avoid running over the loggers limit - *defaultLogWriter.curLoggersIdx = 0 + *defaultLogWriter.(*logWriter).curLoggersIdx = 0 buf := &bytes.Buffer{} - defaultLogWriter.w = bufio.NewWriter(buf) + defaultLogWriter.(*logWriter).w = bufio.NewWriter(buf) h := AddLogger("%b") //t.Log("Handle:", h) - defaultLogWriter.w.Flush() + defaultLogWriter.(*logWriter).w.Flush() buf.Reset() Log(h, true, 42) @@ -805,7 +805,7 @@ func BenchmarkAddLogger(b *testing.B) { testLogHandleSink = AddLogger("foo thing bar thing %i64. Fubar %s foo. sadfasdf %u32 sdfasfasdfasdffds %u32.") // to prevent it from overflowing the logger array - *defaultLogWriter.curLoggersIdx = 0 + *defaultLogWriter.(*logWriter).curLoggersIdx = 0 } } @@ -815,7 +815,7 @@ var ( ) func BenchmarkParseLogLine(b *testing.B) { - defaultLogWriter.w = bufio.NewWriter(ioutil.Discard) + defaultLogWriter.(*logWriter).w = bufio.NewWriter(ioutil.Discard) f := "The operation %s could not be completed. Wanted %u64 bar %c128 %b %{s} %{i32}" for i := 0; i < b.N; i++ { testLoggerSink, testSegmentsSink = parseLogLine(f) @@ -823,7 +823,7 @@ func BenchmarkParseLogLine(b *testing.B) { } func BenchmarkLogParallel(b *testing.B) { - defaultLogWriter.w = bufio.NewWriter(ioutil.Discard) + defaultLogWriter.(*logWriter).w = bufio.NewWriter(ioutil.Discard) h := AddLogger("foo thing bar thing %i64. Fubar %s foo. sadfasdf %u32 sdfasfasdfasdffds %u32.") args := []interface{}{int64(1), "string", uint32(2), uint32(3)} @@ -836,7 +836,7 @@ func BenchmarkLogParallel(b *testing.B) { } func BenchmarkLogSequential(b *testing.B) { - defaultLogWriter.w = bufio.NewWriter(ioutil.Discard) + defaultLogWriter.(*logWriter).w = bufio.NewWriter(ioutil.Discard) h := AddLogger("foo thing bar thing %i64. Fubar %s foo. sadfasdf %u32 sdfasfasdfasdffds %u32.") args := []interface{}{int64(1), "string", uint32(2), uint32(3)} @@ -848,7 +848,7 @@ func BenchmarkLogSequential(b *testing.B) { func BenchmarkCompareToStdlib(b *testing.B) { b.Run("Nanolog", func(b *testing.B) { - defaultLogWriter.w = bufio.NewWriter(ioutil.Discard) + defaultLogWriter.(*logWriter).w = bufio.NewWriter(ioutil.Discard) h := AddLogger("foo thing bar thing %i64. Fubar %s foo. sadfasdf %u32 sdfasfasdfasdffds %u32.") args := []interface{}{int64(1), "string", uint32(2), uint32(3)} @@ -872,7 +872,7 @@ func BenchmarkInterpolations(b *testing.B) { return func(b *testing.B) { for i := 1; i <= limit; i++ { b.Run(strconv.Itoa(i), func(b *testing.B) { - defaultLogWriter.w = bufio.NewWriter(ioutil.Discard) + defaultLogWriter.(*logWriter).w = bufio.NewWriter(ioutil.Discard) h := AddLogger(strings.Repeat(interp, i)) args := make([]interface{}, i) From ac5d0da7d2338fc391c38c146dd5fd099905954b Mon Sep 17 00:00:00 2001 From: hectorj Date: Mon, 1 May 2017 20:44:02 +0200 Subject: [PATCH 3/3] Use new log writer for each test --- nanolog_test.go | 102 ++++++++++++++++++++++-------------------------- 1 file changed, 46 insertions(+), 56 deletions(-) diff --git a/nanolog_test.go b/nanolog_test.go index 1725955..94163f5 100644 --- a/nanolog_test.go +++ b/nanolog_test.go @@ -15,7 +15,6 @@ package nanolog import ( - "bufio" "bytes" "encoding/binary" "io/ioutil" @@ -45,12 +44,13 @@ func randString() string { func TestSetWriter(t *testing.T) { buf := &bytes.Buffer{} - SetWriter(buf) + lw := New() + lw.SetWriter(buf) // simulate some logging - defaultLogWriter.(*logWriter).w.WriteByte(35) + lw.(*logWriter).w.WriteByte(35) - SetWriter(&bytes.Buffer{}) + lw.SetWriter(&bytes.Buffer{}) if buf.Bytes()[0] != 35 { t.Fatalf("Expected data to be written to the underlying") @@ -62,12 +62,13 @@ func TestFlush(t *testing.T) { // test new one can be written to // probably set twice and check the middle contents buf := &bytes.Buffer{} - SetWriter(buf) + lw := New() + lw.SetWriter(buf) // simulate some logging - defaultLogWriter.(*logWriter).w.WriteByte(35) + lw.(*logWriter).w.WriteByte(35) - Flush() + lw.Flush() if buf.Bytes()[0] != 35 { t.Fatalf("Expected data to be written to the underlying") @@ -86,15 +87,14 @@ func TestAddLogger(t *testing.T) { t.Logf("Expected kinds: %v", expectedKinds) t.Logf("Expected segs: %v", expectedSegs) - // Reset to avoid running over the loggers limit - *defaultLogWriter.(*logWriter).curLoggersIdx = 0 buf := &bytes.Buffer{} - defaultLogWriter.(*logWriter).w = bufio.NewWriter(buf) - h := AddLogger(logLine) + lw := New() + lw.SetWriter(buf) + h := lw.AddLogger(logLine) //t.Log("Handle:", h) - defaultLogWriter.(*logWriter).w.Flush() + lw.Flush() out := buf.Bytes() //t.Log(string(out)) @@ -237,23 +237,19 @@ func TestAddLoggerLimit(t *testing.T) { if r := recover(); r != nil { t.Logf("Correctly got a panic: %v", r) } else { - t.Fatalf("Expected a panic but did not get one") + t.Fatal("Expected a panic but did not get one") } - - // reset so other tests can actually continue testing - *defaultLogWriter.(*logWriter).curLoggersIdx = 0 }() - t.Logf("Filling up loggers") + lw := New() + t.Log("Filling up loggers") for i := 0; i < MaxLoggers+1; i++ { - AddLogger("") + lw.AddLogger("") } } func TestParseLogLine(t *testing.T) { t.Run("Correct", func(t *testing.T) { - buf := &bytes.Buffer{} - defaultLogWriter.(*logWriter).w = bufio.NewWriter(buf) f := "foo thing bar thing %i64. Fubar %s foo. sadf %% asdf %u32 sdfasfasdfasdffds %u32." l, segs := parseLogLine(f) @@ -317,17 +313,17 @@ func TestParseLogLine(t *testing.T) { func TestLog(t *testing.T) { check := func(t *testing.T, fmtstring string, toWrite interface{}, dataLen int, checkRest func(*testing.T, []byte) bool) bool { // Reset to avoid running over the loggers limit - *defaultLogWriter.(*logWriter).curLoggersIdx = 0 buf := &bytes.Buffer{} - defaultLogWriter.(*logWriter).w = bufio.NewWriter(buf) - h := AddLogger(fmtstring) + lw := New() + lw.SetWriter(buf) + h := lw.AddLogger(fmtstring) //t.Log("Handle:", h) - defaultLogWriter.(*logWriter).w.Flush() + lw.Flush() buf.Reset() - Log(h, toWrite) + lw.Log(h, toWrite) - defaultLogWriter.(*logWriter).w.Flush() + lw.Flush() out := buf.Bytes() expectedLen := 1 + 4 + dataLen @@ -764,16 +760,12 @@ func TestLog(t *testing.T) { } }() - // Reset to avoid running over the loggers limit - *defaultLogWriter.(*logWriter).curLoggersIdx = 0 - buf := &bytes.Buffer{} - defaultLogWriter.(*logWriter).w = bufio.NewWriter(buf) - h := AddLogger("%b") + lw := New() + h := lw.AddLogger("%b") //t.Log("Handle:", h) - defaultLogWriter.(*logWriter).w.Flush() - buf.Reset() + lw.Flush() - Log(h, 42) + lw.Log(h, 42) }) t.Run("WrongNumberOfArgs", func(t *testing.T) { defer func() { @@ -784,16 +776,12 @@ func TestLog(t *testing.T) { } }() - // Reset to avoid running over the loggers limit - *defaultLogWriter.(*logWriter).curLoggersIdx = 0 - buf := &bytes.Buffer{} - defaultLogWriter.(*logWriter).w = bufio.NewWriter(buf) - h := AddLogger("%b") + lw := New() + h := lw.AddLogger("%b") //t.Log("Handle:", h) - defaultLogWriter.(*logWriter).w.Flush() - buf.Reset() + lw.Flush() - Log(h, true, 42) + lw.Log(h, true, 42) }) }) } @@ -801,11 +789,14 @@ func TestLog(t *testing.T) { var testLogHandleSink Handle func BenchmarkAddLogger(b *testing.B) { + lw := New() + + b.ResetTimer() for i := 0; i < b.N; i++ { - testLogHandleSink = AddLogger("foo thing bar thing %i64. Fubar %s foo. sadfasdf %u32 sdfasfasdfasdffds %u32.") + testLogHandleSink = lw.AddLogger("foo thing bar thing %i64. Fubar %s foo. sadfasdf %u32 sdfasfasdfasdffds %u32.") // to prevent it from overflowing the logger array - *defaultLogWriter.(*logWriter).curLoggersIdx = 0 + *lw.(*logWriter).curLoggersIdx = 0 } } @@ -815,7 +806,6 @@ var ( ) func BenchmarkParseLogLine(b *testing.B) { - defaultLogWriter.(*logWriter).w = bufio.NewWriter(ioutil.Discard) f := "The operation %s could not be completed. Wanted %u64 bar %c128 %b %{s} %{i32}" for i := 0; i < b.N; i++ { testLoggerSink, testSegmentsSink = parseLogLine(f) @@ -823,38 +813,38 @@ func BenchmarkParseLogLine(b *testing.B) { } func BenchmarkLogParallel(b *testing.B) { - defaultLogWriter.(*logWriter).w = bufio.NewWriter(ioutil.Discard) - h := AddLogger("foo thing bar thing %i64. Fubar %s foo. sadfasdf %u32 sdfasfasdfasdffds %u32.") + lw := New() + h := lw.AddLogger("foo thing bar thing %i64. Fubar %s foo. sadfasdf %u32 sdfasfasdfasdffds %u32.") args := []interface{}{int64(1), "string", uint32(2), uint32(3)} b.ResetTimer() b.RunParallel(func(pb *testing.PB) { for pb.Next() { - Log(h, args...) + lw.Log(h, args...) } }) } func BenchmarkLogSequential(b *testing.B) { - defaultLogWriter.(*logWriter).w = bufio.NewWriter(ioutil.Discard) - h := AddLogger("foo thing bar thing %i64. Fubar %s foo. sadfasdf %u32 sdfasfasdfasdffds %u32.") + lw := New() + h := lw.AddLogger("foo thing bar thing %i64. Fubar %s foo. sadfasdf %u32 sdfasfasdfasdffds %u32.") args := []interface{}{int64(1), "string", uint32(2), uint32(3)} b.ResetTimer() for i := 0; i < b.N; i++ { - Log(h, args...) + lw.Log(h, args...) } } func BenchmarkCompareToStdlib(b *testing.B) { b.Run("Nanolog", func(b *testing.B) { - defaultLogWriter.(*logWriter).w = bufio.NewWriter(ioutil.Discard) - h := AddLogger("foo thing bar thing %i64. Fubar %s foo. sadfasdf %u32 sdfasfasdfasdffds %u32.") + lw := New() + h := lw.AddLogger("foo thing bar thing %i64. Fubar %s foo. sadfasdf %u32 sdfasfasdfasdffds %u32.") args := []interface{}{int64(1), "string", uint32(2), uint32(3)} b.ResetTimer() for i := 0; i < b.N; i++ { - Log(h, args...) + lw.Log(h, args...) } }) b.Run("Stdlib", func(b *testing.B) { @@ -872,8 +862,8 @@ func BenchmarkInterpolations(b *testing.B) { return func(b *testing.B) { for i := 1; i <= limit; i++ { b.Run(strconv.Itoa(i), func(b *testing.B) { - defaultLogWriter.(*logWriter).w = bufio.NewWriter(ioutil.Discard) - h := AddLogger(strings.Repeat(interp, i)) + lw := New() + h := lw.AddLogger(strings.Repeat(interp, i)) args := make([]interface{}, i) for j := range args {