improve color feature for package glog

This commit is contained in:
John Guo
2021-07-15 13:31:32 +08:00
parent 860b22aba4
commit fae4dea37a
9 changed files with 130 additions and 124 deletions

View File

@ -0,0 +1,15 @@
package main
import (
"github.com/gogf/gf/frame/g"
)
func main() {
g.Log().Print("Print")
g.Log().Debug("Debug")
g.Log().Info("Info")
g.Log().Notice("Notice")
g.Log().Warning("Warning")
g.Log().Error("Error")
g.Log().Critical("Critical")
}

View File

@ -16,7 +16,7 @@ import (
)
var (
// Buffer size for reading file content.
// DefaultReadBuffer is the buffer size for reading file content.
DefaultReadBuffer = 1024
)

View File

@ -78,7 +78,7 @@ func StackWithFilter(filter string) *Logger {
return logger.StackWithFilter(filter)
}
// StdPrint is a chaining function,
// Stdout is a chaining function,
// which enables/disables stdout for the current logging content output.
// It's enabled in default.
func Stdout(enabled ...bool) *Logger {

View File

@ -7,7 +7,6 @@
package glog
import (
"bytes"
"context"
"fmt"
"github.com/gogf/gf/container/gtype"
@ -119,6 +118,7 @@ func (l *Logger) print(ctx context.Context, level int, values ...interface{}) {
index: -1,
Ctx: ctx,
Time: now,
Color: defaultLevelColor[level],
Level: level,
}
)
@ -219,30 +219,48 @@ 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) {
// doPrint outputs the logging content according configuration.
func (l *Logger) doPrint(ctx context.Context, input *HandlerInput) {
if l.config.Writer == nil {
// Output content to disk file.
if l.config.Path != "" {
l.printToFile(ctx, input.Time, input.Buffer())
l.printToFile(ctx, input.Time, input)
}
// Allow output to stdout?
if l.config.StdoutPrint {
if err := input.Stdout(); err != nil {
intlog.Error(ctx, err)
}
l.printToStdout(ctx, input)
}
} else {
if _, err := l.config.Writer.Write(input.Buffer().Bytes()); err != nil {
// panic(err)
// Output to custom writer.
l.printToWriter(ctx, input)
}
}
// printToWriter writes buffer to writer.
func (l *Logger) printToWriter(ctx context.Context, input *HandlerInput) {
if l.config.Writer != nil {
var (
buffer = input.getBuffer(l.config.WriterColorEnable)
)
if _, err := l.config.Writer.Write(buffer.Bytes()); err != nil {
intlog.Error(ctx, err)
}
}
}
// printToStdout outputs logging content to stdout.
func (l *Logger) printToStdout(ctx context.Context, input *HandlerInput) {
if l.config.StdoutPrint {
if _, err := os.Stdout.Write(input.getBuffer(true).Bytes()); err != nil {
intlog.Error(ctx, err)
}
}
}
// printToFile outputs logging content to disk file.
func (l *Logger) printToFile(ctx context.Context, t time.Time, buffer *bytes.Buffer) {
func (l *Logger) printToFile(ctx context.Context, t time.Time, input *HandlerInput) {
var (
buffer = input.getBuffer(l.config.WriterColorEnable)
logFilePath = l.getFilePath(t)
memoryLockKey = memoryLockPrefixForPrintingToFile + logFilePath
)

View File

@ -8,7 +8,6 @@ package glog
import (
"context"
"github.com/fatih/color"
"github.com/gogf/gf/internal/intlog"
"io"
@ -246,16 +245,3 @@ 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

@ -0,0 +1,41 @@
// Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
//
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file,
// You can obtain one at https://github.com/gogf/gf.
package glog
import "github.com/fatih/color"
const (
COLOR_BLACK = 30 + iota
COLOR_RED
COLOR_GREEN
COLOR_YELLOW
COLOR_BLUE
COLOR_MAGENTA
COLOR_CYAN
COLOR_WHITE
)
// defaultLevelColor defines the default level and its mapping prefix string.
var defaultLevelColor = map[int]int{
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,
}
// getColoredStr returns a string that is colored by given color.
func (l *Logger) getColoredStr(c int, s string) string {
return color.New(color.Attribute(c)).Sprint(s)
}
func (l *Logger) getColorByLevel(level int) int {
return defaultLevelColor[level]
}

View File

@ -7,7 +7,6 @@
package glog
import (
"github.com/fatih/color"
"io"
"strings"
"time"
@ -21,28 +20,27 @@ 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"` // 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:"-"`
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"` // Asynchronously checks the backups and expiration at intervals. It's 1 hour in default.
WriterColorEnable bool `json:"writerColorEnable"` // Logging level prefix with color to writer or not (false in default).
}
// DefaultConfig returns the default configuration for logger.

View File

@ -9,9 +9,6 @@ package glog
import (
"bytes"
"context"
"github.com/fatih/color"
"github.com/gogf/gf/internal/intlog"
"os"
"time"
)
@ -23,6 +20,7 @@ type HandlerInput struct {
Ctx context.Context
Time time.Time
TimeFormat string
Color int
Level int
LevelFormat string
CallerFunc string
@ -35,52 +33,34 @@ type HandlerInput struct {
// defaultHandler is the default handler for logger.
func defaultHandler(ctx context.Context, input *HandlerInput) {
input.logger.printToWriter(ctx, input)
input.logger.doPrint(ctx, input)
}
func (i *HandlerInput) addStringToBuffer(buffer *bytes.Buffer, s string) {
if buffer.Len() > 0 {
buffer.WriteByte(' ')
func (i *HandlerInput) addStringToBuffer(buffer *bytes.Buffer, strings ...string) {
for _, s := range strings {
if buffer.Len() > 0 {
buffer.WriteByte(' ')
}
buffer.WriteString(s)
}
buffer.WriteString(s)
}
func (i *HandlerInput) Buffer() *bytes.Buffer {
return i.getBuffer(false)
}
func (i *HandlerInput) getBuffer(withColor bool) *bytes.Buffer {
buffer := bytes.NewBuffer(nil)
buffer.WriteString(i.TimeFormat)
levelString := i.LevelFormat
if i.logger.config.FileColorEnable {
fg := i.getLevelFormatColor()
levelString = color.New(fg).Sprintf(i.LevelFormat)
if i.LevelFormat != "" {
if withColor {
i.addStringToBuffer(buffer, i.logger.getColoredStr(
i.logger.getColorByLevel(i.Level), i.LevelFormat,
))
} else {
i.addStringToBuffer(buffer, 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)
}
@ -100,15 +80,6 @@ func (i *HandlerInput) GetContent() *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,7 +7,6 @@
package glog
import (
"github.com/fatih/color"
"github.com/gogf/gf/errors/gerror"
"strings"
)
@ -29,17 +28,6 @@ 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",
@ -52,18 +40,6 @@ 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,
@ -125,8 +101,9 @@ func (l *Logger) GetLevelPrefix(level int) string {
// getLevelPrefixWithBrackets returns the prefix string with brackets for specified level.
func (l *Logger) getLevelPrefixWithBrackets(level int) string {
levelStr := ""
if s, ok := l.config.LevelPrefixes[level]; ok {
return "[" + s + "]"
levelStr = "[" + s + "]"
}
return ""
return levelStr
}