Add log level output support.

This commit is contained in:
Qingshan Luo 2021-05-17 16:52:53 +08:00
parent b50299cfaa
commit 8d97681ef7
3 changed files with 35 additions and 1 deletions

View File

@ -4,6 +4,7 @@ import (
"bytes" "bytes"
"context" "context"
"fmt" "fmt"
"io"
"os" "os"
"reflect" "reflect"
"runtime" "runtime"
@ -291,7 +292,15 @@ func (entry *Entry) write() {
} }
entry.Logger.mu.Lock() entry.Logger.mu.Lock()
defer entry.Logger.mu.Unlock() defer entry.Logger.mu.Unlock()
if _, err := entry.Logger.Out.Write(serialized); err != nil {
var out io.Writer
if entry.Logger.LevelOut != nil && entry.Logger.LevelOut[entry.Level] != nil {
out = entry.Logger.LevelOut[entry.Level]
} else {
out = entry.Logger.Out
}
if _, err := out.Write(serialized); err != nil {
fmt.Fprintf(os.Stderr, "Failed to write to log, %v\n", err) fmt.Fprintf(os.Stderr, "Failed to write to log, %v\n", err)
} }
} }

View File

@ -19,6 +19,9 @@ type Logger struct {
// file, or leave it default which is `os.Stderr`. You can also set this to // file, or leave it default which is `os.Stderr`. You can also set this to
// something more adventurous, such as logging to Kafka. // something more adventurous, such as logging to Kafka.
Out io.Writer Out io.Writer
// LevelOut specifies writers of different log levels to help applications
// distribute logs of different levels to different locations.
LevelOut map[Level]io.Writer
// Hooks for the logger instance. These allow firing events based on logging // Hooks for the logger instance. These allow firing events based on logging
// levels and log entries. For example, to send errors to an error tracking // levels and log entries. For example, to send errors to an error tracking
// service, log to StatsD or dump the core on fatal errors. // service, log to StatsD or dump the core on fatal errors.
@ -391,6 +394,16 @@ func (logger *Logger) SetOutput(output io.Writer) {
logger.Out = output logger.Out = output
} }
// SetLevelOutput sets the logger level output.
func (logger *Logger) SetLevelOutput(level Level, output io.Writer) {
logger.mu.Lock()
defer logger.mu.Unlock()
if logger.LevelOut == nil {
logger.LevelOut = make(map[Level]io.Writer)
}
logger.LevelOut[level] = output
}
func (logger *Logger) SetReportCaller(reportCaller bool) { func (logger *Logger) SetReportCaller(reportCaller bool) {
logger.mu.Lock() logger.mu.Lock()
defer logger.mu.Unlock() defer logger.mu.Unlock()

View File

@ -95,3 +95,15 @@ func TestLogger_SetBufferPool(t *testing.T) {
assert.Equal(t, pool.get, 1, "Logger.SetBufferPool(): The BufferPool.Get() must be called") assert.Equal(t, pool.get, 1, "Logger.SetBufferPool(): The BufferPool.Get() must be called")
assert.Len(t, pool.buffers, 1, "Logger.SetBufferPool(): The BufferPool.Put() must be called") assert.Len(t, pool.buffers, 1, "Logger.SetBufferPool(): The BufferPool.Put() must be called")
} }
func TestLogger_SetLevelOutput(t *testing.T) {
out := &bytes.Buffer{}
l := New()
l.SetOutput(out)
errOut := &bytes.Buffer{}
l.SetLevelOutput(ErrorLevel, errOut)
l.Error("test for err out")
assert.Contains(t, errOut.String(), "test for err out", "Logger.SetLevelOutput(): Logger.LevelOut no log content")
assert.Equal(t, out.Len(), 0, "Logger.SetLevelOutput(): Logger.Out got log content")
}