Merge pull request #1312 from wangle201210/develop

add log level prefix color
This commit is contained in:
John Guo
2021-07-15 09:16:27 +08:00
committed by GitHub
7 changed files with 119 additions and 26 deletions

1
go.mod
View File

@ -5,6 +5,7 @@ go 1.14
require (
github.com/BurntSushi/toml v0.3.1
github.com/clbanning/mxj v1.8.5-0.20200714211355-ff02cfb8ea28
github.com/fatih/color v1.12.0
github.com/fsnotify/fsnotify v1.4.9
github.com/gogf/mysql v1.6.1-0.20210603073548-16164ae25579
github.com/gomodule/redigo v2.0.0+incompatible

8
go.sum
View File

@ -4,6 +4,8 @@ github.com/clbanning/mxj v1.8.5-0.20200714211355-ff02cfb8ea28 h1:LdXxtjzvZYhhUao
github.com/clbanning/mxj v1.8.5-0.20200714211355-ff02cfb8ea28/go.mod h1:BVjHeAH+rl9rs6f+QIpeRl0tfu10SXn1pUSa5PVGJng=
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/fatih/color v1.12.0 h1:mRhaKNwANqRgUBGKmnI5ZxEk7QXmjQeCcuYFMX2bfcc=
github.com/fatih/color v1.12.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM=
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/gogf/mysql v1.6.1-0.20210603073548-16164ae25579 h1:pP/uEy52biKDytlgK/ug8kiYPAiYu6KajKVUHfGrtyw=
@ -16,6 +18,10 @@ github.com/gorilla/websocket v1.4.1 h1:q7AeDBpnBk8AogcD4DSag/Ukw/KV+YhzLj2bP5HvK
github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/grokify/html-strip-tags-go v0.0.0-20190921062105-daaa06bf1aaf h1:wIOAyJMMen0ELGiFzlmqxdcV1yGbkyHBAB6PolcNbLA=
github.com/grokify/html-strip-tags-go v0.0.0-20190921062105-daaa06bf1aaf/go.mod h1:2Su6romC5/1VXOQMaWL2yb618ARB8iVo6/DR99A6d78=
github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8=
github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/mattn/go-runewidth v0.0.10 h1:CoZ3S2P7pvtP45xOtBw+/mDL2z0RKI576gSkzRRpdGg=
github.com/mattn/go-runewidth v0.0.10/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk=
@ -44,6 +50,8 @@ golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwY
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f h1:+Nyd8tzPX9R7BWHguqsrbFdRx3WQ/1ib8I44HXV5yTA=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=

View File

@ -44,6 +44,7 @@ const (
defaultFileExpire = time.Minute
pathFilterKey = "/os/glog/glog"
memoryLockPrefixForPrintingToFile = "glog.printToFile:"
mustWithColor = true
)
const (
@ -220,20 +221,20 @@ func (l *Logger) print(ctx context.Context, level int, values ...interface{}) {
// printToWriter writes buffer to writer.
func (l *Logger) printToWriter(ctx context.Context, input *HandlerInput) {
buffer := input.Buffer()
if l.config.Writer == nil {
// Output content to disk file.
if l.config.Path != "" {
l.printToFile(ctx, input.Time, buffer)
l.printToFile(ctx, input.Time, input.Buffer())
}
// Allow output to stdout?
if l.config.StdoutPrint {
if _, err := os.Stdout.Write(buffer.Bytes()); err != nil {
if err := input.Stdout(); err != nil {
intlog.Error(ctx, err)
}
}
} else {
if _, err := l.config.Writer.Write(buffer.Bytes()); err != nil {
if _, err := l.config.Writer.Write(input.Buffer().Bytes()); err != nil {
// panic(err)
intlog.Error(ctx, err)
}
}

View File

@ -8,6 +8,7 @@ package glog
import (
"context"
"github.com/fatih/color"
"github.com/gogf/gf/internal/intlog"
"io"
@ -245,3 +246,16 @@ func (l *Logger) Async(enabled ...bool) *Logger {
}
return logger
}
// Color is a chaining function,
// which set level prefix color logging output feature.
func (l *Logger) Color(color color.Attribute) *Logger {
logger := (*Logger)(nil)
if l.parent == nil {
logger = l.Clone()
} else {
logger = l
}
logger.config.currentColor = color
return logger
}

View File

@ -7,6 +7,7 @@
package glog
import (
"github.com/fatih/color"
"io"
"strings"
"time"
@ -20,26 +21,28 @@ import (
// Config is the configuration object for logger.
type Config struct {
Handlers []Handler `json:"-"` // Logger handlers which implement feature similar as middleware.
Writer io.Writer `json:"-"` // Customized io.Writer.
Flags int `json:"flags"` // Extra flags for logging output features.
Path string `json:"path"` // Logging directory path.
File string `json:"file"` // Format for logging file.
Level int `json:"level"` // Output level.
Prefix string `json:"prefix"` // Prefix string for every logging content.
StSkip int `json:"stSkip"` // Skip count for stack.
StStatus int `json:"stStatus"` // Stack status(1: enabled - default; 0: disabled)
StFilter string `json:"stFilter"` // Stack string filter.
CtxKeys []interface{} `json:"ctxKeys"` // Context keys for logging, which is used for value retrieving from context.
HeaderPrint bool `json:"header"` // Print header or not(true in default).
StdoutPrint bool `json:"stdout"` // Output to stdout or not(true in default).
LevelPrefixes map[int]string `json:"levelPrefixes"` // Logging level to its prefix string mapping.
RotateSize int64 `json:"rotateSize"` // Rotate the logging file if its size > 0 in bytes.
RotateExpire time.Duration `json:"rotateExpire"` // Rotate the logging file if its mtime exceeds this duration.
RotateBackupLimit int `json:"rotateBackupLimit"` // Max backup for rotated files, default is 0, means no backups.
RotateBackupExpire time.Duration `json:"rotateBackupExpire"` // Max expire for rotated files, which is 0 in default, means no expiration.
RotateBackupCompress int `json:"rotateBackupCompress"` // Compress level for rotated files using gzip algorithm. It's 0 in default, means no compression.
RotateCheckInterval time.Duration `json:"rotateCheckInterval"` // Asynchronous checks the backups and expiration at intervals. It's 1 hour in default.
Handlers []Handler `json:"-"` // Logger handlers which implement feature similar as middleware.
Writer io.Writer `json:"-"` // Customized io.Writer.
Flags int `json:"flags"` // Extra flags for logging output features.
Path string `json:"path"` // Logging directory path.
File string `json:"file"` // Format for logging file.
Level int `json:"level"` // Output level.
Prefix string `json:"prefix"` // Prefix string for every logging content.
StSkip int `json:"stSkip"` // Skip count for stack.
StStatus int `json:"stStatus"` // Stack status(1: enabled - default; 0: disabled)
StFilter string `json:"stFilter"` // Stack string filter.
CtxKeys []interface{} `json:"ctxKeys"` // Context keys for logging, which is used for value retrieving from context.
HeaderPrint bool `json:"header"` // Print header or not(true in default).
StdoutPrint bool `json:"stdout"` // Output to stdout or not(true in default).
LevelPrefixes map[int]string `json:"levelPrefixes"` // Logging level to its prefix string mapping.
RotateSize int64 `json:"rotateSize"` // Rotate the logging file if its size > 0 in bytes.
RotateExpire time.Duration `json:"rotateExpire"` // Rotate the logging file if its mtime exceeds this duration.
RotateBackupLimit int `json:"rotateBackupLimit"` // Max backup for rotated files, default is 0, means no backups.
RotateBackupExpire time.Duration `json:"rotateBackupExpire"` // Max expire for rotated files, which is 0 in default, means no expiration.
RotateBackupCompress int `json:"rotateBackupCompress"` // Compress level for rotated files using gzip algorithm. It's 0 in default, means no compression.
RotateCheckInterval time.Duration `json:"rotateCheckInterval"` // Asynchronizely checks the backups and expiration at intervals. It's 1 hour in default.
FileColorEnable bool `json:"fileColorEnable"` // Logging level prefix with color or not (false in default).
currentColor color.Attribute `json:"-"`
}
// DefaultConfig returns the default configuration for logger.

View File

@ -9,6 +9,9 @@ package glog
import (
"bytes"
"context"
"github.com/fatih/color"
"github.com/gogf/gf/internal/intlog"
"os"
"time"
)
@ -45,9 +48,39 @@ func (i *HandlerInput) addStringToBuffer(buffer *bytes.Buffer, s string) {
func (i *HandlerInput) Buffer() *bytes.Buffer {
buffer := bytes.NewBuffer(nil)
buffer.WriteString(i.TimeFormat)
if i.LevelFormat != "" {
i.addStringToBuffer(buffer, i.LevelFormat)
levelString := i.LevelFormat
if i.logger.config.FileColorEnable {
fg := i.getLevelFormatColor()
levelString = color.New(fg).Sprintf(i.LevelFormat)
}
i.addStringToBuffer(buffer, levelString)
msg := i.GetContent()
i.addStringToBuffer(buffer, msg.String())
return buffer
}
// Stdout print log to console
func (i *HandlerInput) Stdout() error {
if _, err := os.Stdout.Write([]byte(i.TimeFormat)); err != nil {
intlog.Error(i.Ctx, err)
return err
}
fg := i.getLevelFormatColor()
if _, err := color.New(fg).Print(" " + i.LevelFormat + " "); err != nil {
intlog.Error(i.Ctx, err)
return err
}
msg := i.GetContent()
if _, err := os.Stdout.Write(msg.Bytes()); err != nil {
intlog.Error(i.Ctx, err)
return err
}
return nil
}
// GetContent returns the primary content.
func (i *HandlerInput) GetContent() *bytes.Buffer {
buffer := bytes.NewBuffer(nil)
if i.CallerFunc != "" {
i.addStringToBuffer(buffer, i.CallerFunc)
}
@ -67,6 +100,15 @@ func (i *HandlerInput) Buffer() *bytes.Buffer {
return buffer
}
// getLevelFormatColor returns the prefix string color.
func (i *HandlerInput) getLevelFormatColor() color.Attribute {
fg := defaultLevelColor[i.Level]
if i.logger.config.currentColor != 0 {
fg = i.logger.config.currentColor
}
return fg
}
func (i *HandlerInput) String() string {
return i.Buffer().String()
}

View File

@ -7,6 +7,7 @@
package glog
import (
"github.com/fatih/color"
"github.com/gogf/gf/errors/gerror"
"strings"
)
@ -28,6 +29,17 @@ const (
LEVEL_FATA // 1024
)
const (
COLOR_BLACK = 30 + iota
COLOR_RED
COLOR_GREEN
COLOR_YELLOW
COLOR_BLUE
COLOR_MAGENTA
COLOR_CYAN
COLOR_WHITE
)
// defaultLevelPrefixes defines the default level and its mapping prefix string.
var defaultLevelPrefixes = map[int]string{
LEVEL_DEBU: "DEBU",
@ -40,6 +52,18 @@ var defaultLevelPrefixes = map[int]string{
LEVEL_FATA: "FATA",
}
// defaultLevelColor defines the default level and its mapping prefix string.
var defaultLevelColor = map[int]color.Attribute{
LEVEL_DEBU: COLOR_YELLOW,
LEVEL_INFO: COLOR_GREEN,
LEVEL_NOTI: COLOR_CYAN,
LEVEL_WARN: COLOR_YELLOW,
LEVEL_ERRO: COLOR_RED,
LEVEL_CRIT: COLOR_RED,
LEVEL_PANI: COLOR_RED,
LEVEL_FATA: COLOR_RED,
}
// levelStringMap defines level string name to its level mapping.
var levelStringMap = map[string]int{
"ALL": LEVEL_DEBU | LEVEL_INFO | LEVEL_NOTI | LEVEL_WARN | LEVEL_ERRO | LEVEL_CRIT,