diff --git a/buffer_pool.go b/buffer_pool.go new file mode 100644 index 000000000..4545dec07 --- /dev/null +++ b/buffer_pool.go @@ -0,0 +1,52 @@ +package logrus + +import ( + "bytes" + "sync" +) + +var ( + bufferPool BufferPool +) + +type BufferPool interface { + Put(*bytes.Buffer) + Get() *bytes.Buffer +} + +type defaultPool struct { + pool *sync.Pool +} + +func (p *defaultPool) Put(buf *bytes.Buffer) { + p.pool.Put(buf) +} + +func (p *defaultPool) Get() *bytes.Buffer { + return p.pool.Get().(*bytes.Buffer) +} + +func getBuffer() *bytes.Buffer { + return bufferPool.Get() +} + +func putBuffer(buf *bytes.Buffer) { + buf.Reset() + bufferPool.Put(buf) +} + +// SetBufferPool allows to replace the default logrus buffer pool +// to better meets the specific needs of an application. +func SetBufferPool(bp BufferPool) { + bufferPool = bp +} + +func init() { + SetBufferPool(&defaultPool{ + pool: &sync.Pool{ + New: func() interface{} { + return new(bytes.Buffer) + }, + }, + }) +} diff --git a/entry.go b/entry.go index f6e062a34..9b32ccb44 100644 --- a/entry.go +++ b/entry.go @@ -13,7 +13,6 @@ import ( ) var ( - bufferPool *sync.Pool // qualified package name, cached at first use logrusPackage string @@ -31,12 +30,6 @@ const ( ) func init() { - bufferPool = &sync.Pool{ - New: func() interface{} { - return new(bytes.Buffer) - }, - } - // start at the bottom of the stack before the package-name cache is primed minimumCallerDepth = 1 } @@ -80,6 +73,7 @@ type Entry struct { func NewEntry(logger *Logger) *Entry { return &Entry{ Logger: logger, + Level: logger.Level, // Default is three fields, plus one optional. Give a little extra room. Data: make(Fields, 6), } @@ -148,7 +142,14 @@ func (entry *Entry) WithFields(fields Fields) *Entry { data[k] = v } } - return &Entry{Logger: entry.Logger, Data: data, Time: entry.Time, err: fieldErr, Context: entry.Context} + return &Entry{ + Logger: entry.Logger, + Data: data, + Time: entry.Time, + Level: entry.Level, + err: fieldErr, + Context: entry.Context, + } } // Overrides the time of the Entry. @@ -243,9 +244,12 @@ func (entry Entry) log(level Level, msg string) { entry.fireHooks() - buffer = bufferPool.Get().(*bytes.Buffer) + buffer = getBuffer() + defer func() { + entry.Buffer = nil + putBuffer(buffer) + }() buffer.Reset() - defer bufferPool.Put(buffer) entry.Buffer = buffer entry.write() diff --git a/logger.go b/logger.go index dbf627c97..337704457 100644 --- a/logger.go +++ b/logger.go @@ -12,7 +12,7 @@ import ( // LogFunction For big messages, it can be more efficient to pass a function // and only call it if the log level is actually enables rather than // generating the log message and then checking if the level is enabled -type LogFunction func()[]interface{} +type LogFunction func() []interface{} type Logger struct { // The logs are `io.Copy`'d to this in a mutex. It's common to set this to a diff --git a/logrus_test.go b/logrus_test.go index 9c3c920de..944adbc59 100644 --- a/logrus_test.go +++ b/logrus_test.go @@ -763,3 +763,15 @@ func TestSetReportCallerRace(t *testing.T) { } wg.Wait() } + +func TestLevel(t *testing.T) { + l := New() + l.SetLevel(InfoLevel) + + e := l.WithField("foo", "bar") + + assert.Equal(t, l.Level, e.Level) + e.Debug("I shouldn't be printed") + e.Info("I should be printed") + assert.Equal(t, l.Level, e.Level) +} diff --git a/text_formatter_test.go b/text_formatter_test.go index 5b1cc0ab5..8921aef1d 100644 --- a/text_formatter_test.go +++ b/text_formatter_test.go @@ -22,7 +22,7 @@ func TestFormatting(t *testing.T) { value string expected string }{ - {`foo`, "time=\"0001-01-01T00:00:00Z\" level=panic test=foo\n"}, + {`foo`, "time=\"0001-01-01T00:00:00Z\" level=info test=foo\n"}, } for _, tc := range testCases {