Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add custom level color functionality to TextFormatter #1405

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
34 changes: 34 additions & 0 deletions README.md
Expand Up @@ -319,6 +319,40 @@ environment if your application has that.

Note: If you want different log levels for global (`log.SetLevel(...)`) and syslog logging, please check the [syslog hook README](hooks/syslog/README.md#different-log-levels-for-local-and-remote-logging).

#### Level colors

The `TextFormatter` level colors itself can be customized as follows:

Individual overrides:

```go
log.SetFormatter(&log.TextFormatter{
LevelColors: log.DefaultLevelColors(&log.LevelColors{
Debug: 31, // Red
Default: 36, // Blue
}),
ForceColors: true, // Optional
})
```

Or you can provide a complete `log.LevelColors` struct:

```go
log.SetFormatter(&log.TextFormatter{
LevelColors: &log.LevelColors{
Trace: 37, // Gray
Debug: 37, // Gray
Warn: 33, // Yellow
Error: 31, // Red
Fatal: 31, // Red
Panic: 31, // Red
Info: 36, // Blue
Default: 36, // Blue
},
ForceColors: true, // Optional
})
```

#### Entries

Besides the fields added with `WithField` or `WithFields` some fields are
Expand Down
60 changes: 53 additions & 7 deletions text_formatter.go
Expand Up @@ -4,6 +4,7 @@ import (
"bytes"
"fmt"
"os"
"reflect"
"runtime"
"sort"
"strconv"
Expand All @@ -26,8 +27,43 @@ func init() {
baseTimestamp = time.Now()
}

type LevelColors struct {
Trace, Debug, Warn, Error, Fatal, Panic, Info, Default int
}

func DefaultLevelColors(custom *LevelColors) *LevelColors {
levelColors := &LevelColors{
Trace: gray,
Debug: gray,
Warn: yellow,
Error: red,
Fatal: red,
Panic: red,
Info: blue,
Default: blue,
}

if custom != nil {
dstVal := reflect.ValueOf(levelColors).Elem()
srcVal := reflect.ValueOf(custom).Elem()
for i := 0; i < dstVal.NumField(); i++ {
dstField := dstVal.Field(i)
srcField := srcVal.Field(i)

if dstField.Kind() == reflect.Int && srcField.Int() != 0 {
dstField.SetInt(srcField.Int())
}
}
}

return levelColors
}

// TextFormatter formats logs into text
type TextFormatter struct {
// Set level colors
LevelColors *LevelColors

// Set to true to bypass checking for a TTY before outputting colors.
ForceColors bool

Expand Down Expand Up @@ -230,18 +266,28 @@ func (f *TextFormatter) Format(entry *Entry) ([]byte, error) {
}

func (f *TextFormatter) printColored(b *bytes.Buffer, entry *Entry, keys []string, data Fields, timestampFormat string) {
if f.LevelColors == nil {
f.LevelColors = DefaultLevelColors(nil)
}

var levelColor int
switch entry.Level {
case DebugLevel, TraceLevel:
levelColor = gray
case DebugLevel:
levelColor = f.LevelColors.Debug
case TraceLevel:
levelColor = f.LevelColors.Trace
case WarnLevel:
levelColor = yellow
case ErrorLevel, FatalLevel, PanicLevel:
levelColor = red
levelColor = f.LevelColors.Warn
case ErrorLevel:
levelColor = f.LevelColors.Error
case FatalLevel:
levelColor = f.LevelColors.Fatal
case PanicLevel:
levelColor = f.LevelColors.Panic
case InfoLevel:
levelColor = blue
levelColor = f.LevelColors.Info
default:
levelColor = blue
levelColor = f.LevelColors.Default
}

levelText := strings.ToUpper(entry.Level.String())
Expand Down