- add custom LogLevel constructors and richer color configuration - support ANSI, 256-color, RGB, and text attributes on LogLevel - introduce clearer preferred APIs such as NewLogger and SetName - preserve backward compatibility with deprecated wrappers for v2.0.1 APIs - restore legacy ColorStringBuilder signatures as compatibility wrappers - fix newline separator handling in Println-style output - add tests for color precedence, deprecated aliases, and LogLevel attributes - update GoDoc and bilingual README documentation
This commit is contained in:
@@ -7,46 +7,154 @@ import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
type replacer struct {
|
||||
old string
|
||||
new string
|
||||
}
|
||||
|
||||
func (r replacer) replace(s string) string {
|
||||
return strings.ReplaceAll(s, r.old, r.new)
|
||||
}
|
||||
|
||||
// Logger routes log records to one or more configured writers.
|
||||
type Logger struct {
|
||||
prefix string
|
||||
level LogLevel
|
||||
writers []LoggerWriter
|
||||
replacers []replacer
|
||||
|
||||
jsonPretty bool
|
||||
}
|
||||
|
||||
// LogLevel describes a logging severity.
|
||||
type LogLevel struct {
|
||||
n uint8
|
||||
t string
|
||||
fg FgColor
|
||||
bg BgColor
|
||||
n uint8
|
||||
t string
|
||||
|
||||
fg FgColor
|
||||
fg256 FgColor256
|
||||
fgRgb FgColorRGB
|
||||
|
||||
bg BgColor
|
||||
bg256 BgColor256
|
||||
bgRgb BgColorRGB
|
||||
|
||||
attrs []Attribute
|
||||
}
|
||||
|
||||
// NewLogLevel creates a log level without predefined colors.
|
||||
func NewLogLevel(index uint8, name string) LogLevel {
|
||||
return LogLevel{n: index, t: name, attrs: []Attribute{}}
|
||||
}
|
||||
|
||||
// NewLogLevelWithColors creates a log level with ANSI foreground and background colors.
|
||||
func NewLogLevelWithColors(index uint8, name string, fg FgColor, bg BgColor) LogLevel {
|
||||
return LogLevel{n: index, t: name, fg: fg, bg: bg, attrs: []Attribute{}}
|
||||
}
|
||||
|
||||
// GetName returns the lowercase textual representation of the level.
|
||||
func (l *LogLevel) GetName() string { return l.t }
|
||||
func (l *LogLevel) GetFgColor() FgColor { return l.fg }
|
||||
func (l *LogLevel) GetName() string { return l.t }
|
||||
|
||||
// SetFgColor sets the ANSI foreground color and clears other foreground color modes.
|
||||
// Deprecated: use SetForegroundColor. This method will be removed in v3.
|
||||
func (l *LogLevel) SetFgColor(color FgColor) *LogLevel {
|
||||
return l.SetForegroundColor(color)
|
||||
}
|
||||
|
||||
// GetFgColor returns the ANSI foreground color for the level.
|
||||
// Deprecated: use GetForegroundColor. This method will be removed in v3.
|
||||
func (l *LogLevel) GetFgColor() FgColor { return l.GetForegroundColor() }
|
||||
|
||||
// SetForegroundColor sets the ANSI foreground color and clears other foreground color modes.
|
||||
func (l *LogLevel) SetForegroundColor(color FgColor) *LogLevel {
|
||||
l.fg = color
|
||||
l.fg256 = 0
|
||||
l.fgRgb = nil
|
||||
return l
|
||||
}
|
||||
func (l *LogLevel) GetBgColor() BgColor { return l.bg }
|
||||
func (l *LogLevel) SetBgColor(color BgColor) *LogLevel {
|
||||
l.bg = color
|
||||
|
||||
// GetForegroundColor returns the ANSI foreground color for the level.
|
||||
func (l *LogLevel) GetForegroundColor() FgColor { return l.fg }
|
||||
|
||||
// SetForeground256Color sets the 256-color foreground and clears other foreground color modes.
|
||||
func (l *LogLevel) SetForeground256Color(color FgColor256) *LogLevel {
|
||||
l.fg = 0
|
||||
l.fg256 = color
|
||||
l.fgRgb = nil
|
||||
return l
|
||||
}
|
||||
|
||||
// GetForeground256Color returns the configured 256-color foreground value.
|
||||
func (l *LogLevel) GetForeground256Color() FgColor256 { return l.fg256 }
|
||||
|
||||
// SetForegroundRGB sets the RGB foreground color and clears other foreground color modes.
|
||||
func (l *LogLevel) SetForegroundRGB(r, g, b uint8) *LogLevel {
|
||||
l.fg = 0
|
||||
l.fg256 = 0
|
||||
l.fgRgb = FgColorRGB{r, g, b}
|
||||
return l
|
||||
}
|
||||
|
||||
// GetForegroundRGB returns the configured RGB foreground value.
|
||||
func (l *LogLevel) GetForegroundRGB() FgColorRGB { return l.fgRgb }
|
||||
|
||||
// SetBgColor sets the ANSI background color and clears other background color modes.
|
||||
// Deprecated: use SetBackgroundColor. This method will be removed in v3.
|
||||
func (l *LogLevel) SetBgColor(color BgColor) *LogLevel {
|
||||
return l.SetBackgroundColor(color)
|
||||
}
|
||||
|
||||
// GetBgColor returns the ANSI background color for the level.
|
||||
// Deprecated: use GetBackgroundColor. This method will be removed in v3.
|
||||
func (l *LogLevel) GetBgColor() BgColor { return l.GetBackgroundColor() }
|
||||
|
||||
// SetBackgroundColor sets the ANSI background color and clears other background color modes.
|
||||
func (l *LogLevel) SetBackgroundColor(color BgColor) *LogLevel {
|
||||
l.bg = color
|
||||
l.bg256 = 0
|
||||
l.bgRgb = nil
|
||||
return l
|
||||
}
|
||||
|
||||
// GetBackgroundColor returns the ANSI background color for the level.
|
||||
func (l *LogLevel) GetBackgroundColor() BgColor { return l.bg }
|
||||
|
||||
// SetBackground256Color sets the 256-color background and clears other background color modes.
|
||||
func (l *LogLevel) SetBackground256Color(color BgColor256) *LogLevel {
|
||||
l.bg = 0
|
||||
l.bg256 = color
|
||||
l.bgRgb = nil
|
||||
return l
|
||||
}
|
||||
|
||||
// GetBackground256Color returns the configured 256-color background value.
|
||||
func (l *LogLevel) GetBackground256Color() BgColor256 { return l.bg256 }
|
||||
|
||||
// SetBackgroundRGB sets the RGB background color and clears other background color modes.
|
||||
func (l *LogLevel) SetBackgroundRGB(r, g, b uint8) *LogLevel {
|
||||
l.bg = 0
|
||||
l.bg256 = 0
|
||||
l.bgRgb = BgColorRGB{r, g, b}
|
||||
return l
|
||||
}
|
||||
|
||||
// GetBackgroundRGB returns the configured RGB background value.
|
||||
func (l *LogLevel) GetBackgroundRGB() BgColorRGB { return l.bgRgb }
|
||||
|
||||
// AddAttribute appends an ANSI text attribute to the level.
|
||||
func (l *LogLevel) AddAttribute(a Attribute) *LogLevel {
|
||||
l.attrs = append(l.attrs, a)
|
||||
return l
|
||||
}
|
||||
|
||||
// RemoveAttribute removes all matching ANSI text attributes from the level.
|
||||
func (l *LogLevel) RemoveAttribute(a Attribute) *LogLevel {
|
||||
attrs := make([]Attribute, 0)
|
||||
for _, attr := range l.attrs {
|
||||
if attr != a {
|
||||
attrs = append(attrs, attr)
|
||||
}
|
||||
}
|
||||
l.attrs = attrs
|
||||
return l
|
||||
}
|
||||
|
||||
// SetAttributes replaces the level attributes with a copy of the provided slice.
|
||||
func (l *LogLevel) SetAttributes(a []Attribute) *LogLevel {
|
||||
attrs := make([]Attribute, len(a))
|
||||
copy(attrs, a)
|
||||
l.attrs = attrs
|
||||
return l
|
||||
}
|
||||
|
||||
// GetAttributes returns a copy of the configured ANSI text attributes.
|
||||
func (l *LogLevel) GetAttributes() []Attribute {
|
||||
attrs := make([]Attribute, len(l.attrs))
|
||||
copy(attrs, l.attrs)
|
||||
return attrs
|
||||
}
|
||||
|
||||
// MethodTraceback describes a single stack frame attached to a log entry.
|
||||
type MethodTraceback struct {
|
||||
Method string `json:"method"`
|
||||
@@ -58,14 +166,25 @@ type MethodTraceback struct {
|
||||
|
||||
// Predefined log levels.
|
||||
var (
|
||||
INFO = LogLevel{n: 0, t: "info", fg: FgWhite}
|
||||
WARN = LogLevel{n: 1, t: "warn", fg: FgHiYellow}
|
||||
ERROR = LogLevel{n: 2, t: "error", fg: FgHiRed}
|
||||
FATAL = LogLevel{n: 3, t: "fatal", fg: FgRed}
|
||||
DEBUG = LogLevel{n: 4, t: "debug", fg: FgGreen}
|
||||
INFO = NewLogLevelWithColors(0, "info", FgWhite, BgNone)
|
||||
WARN = NewLogLevelWithColors(1, "warn", FgHiYellow, BgNone)
|
||||
ERROR = NewLogLevelWithColors(2, "error", FgHiRed, BgNone)
|
||||
FATAL = NewLogLevelWithColors(3, "fatal", FgRed, BgNone)
|
||||
DEBUG = NewLogLevelWithColors(4, "debug", FgGreen, BgNone)
|
||||
)
|
||||
|
||||
// Logger routes log records to one or more configured writers.
|
||||
type Logger struct {
|
||||
prefix string
|
||||
level LogLevel
|
||||
writers []LoggerWriter
|
||||
replacers []replacer
|
||||
|
||||
jsonPretty bool
|
||||
}
|
||||
|
||||
// CreateLogger creates a logger with default settings.
|
||||
// Deprecated: use NewLogger. This method will be removed in v3.
|
||||
func CreateLogger() *Logger {
|
||||
return &Logger{
|
||||
prefix: "LOG",
|
||||
@@ -73,24 +192,53 @@ func CreateLogger() *Logger {
|
||||
}
|
||||
}
|
||||
|
||||
// NewLogger creates a logger with default settings.
|
||||
func NewLogger() *Logger {
|
||||
return &Logger{
|
||||
prefix: "LOG",
|
||||
level: FATAL,
|
||||
}
|
||||
}
|
||||
|
||||
// Prefix sets the record prefix and returns the logger for chaining.
|
||||
// Deprecated: use SetName. This method will be removed in v3.
|
||||
func (l *Logger) Prefix(prefix string) *Logger {
|
||||
l.prefix = prefix
|
||||
return l
|
||||
}
|
||||
|
||||
// SetName sets the record prefix and returns the logger for chaining.
|
||||
func (l *Logger) SetName(name string) *Logger {
|
||||
l.prefix = name
|
||||
return l
|
||||
}
|
||||
|
||||
// Level sets the maximum enabled level and returns the logger for chaining.
|
||||
// Deprecated: use SetLevel. This method will be removed in v3.
|
||||
func (l *Logger) Level(level LogLevel) *Logger {
|
||||
l.level = level
|
||||
return l
|
||||
}
|
||||
|
||||
// JsonPretty enables indented JSON output for JSON writers.
|
||||
// SetLevel sets the maximum enabled level and returns the logger for chaining.
|
||||
func (l *Logger) SetLevel(level LogLevel) *Logger {
|
||||
l.level = level
|
||||
return l
|
||||
}
|
||||
|
||||
// JsonPretty enables or disables indented JSON output for JSON writers created by the logger.
|
||||
// Deprecated: use SetJSONPretty. This method will be removed in v3.
|
||||
func (l *Logger) JsonPretty(b bool) *Logger {
|
||||
l.jsonPretty = b
|
||||
return l
|
||||
}
|
||||
|
||||
// SetJSONPretty enables or disables indented output for JSON writers created by the logger.
|
||||
func (l *Logger) SetJSONPretty(b bool) *Logger {
|
||||
l.jsonPretty = b
|
||||
return l
|
||||
}
|
||||
|
||||
// AddWriters appends multiple writers to the logger.
|
||||
func (l *Logger) AddWriters(writers ...LoggerWriter) *Logger {
|
||||
l.writers = append(l.writers, writers...)
|
||||
@@ -98,6 +246,7 @@ func (l *Logger) AddWriters(writers ...LoggerWriter) *Logger {
|
||||
}
|
||||
|
||||
// AddWriter appends a single writer to the logger.
|
||||
// Deprecated: use AddWriters. This method will be removed in v3.
|
||||
func (l *Logger) AddWriter(writer LoggerWriter) *Logger {
|
||||
l.writers = append(l.writers, writer)
|
||||
return l
|
||||
@@ -134,14 +283,10 @@ func (l *Logger) Close() error {
|
||||
}
|
||||
|
||||
// CreateTextWriter wraps an external writer with the logger text settings.
|
||||
func (l *Logger) CreateTextWriter(w io.Writer) *LoggerTextWriter {
|
||||
return CreateTextWriter(w)
|
||||
}
|
||||
func (l *Logger) CreateTextWriter(w io.Writer) *LoggerTextWriter { return CreateTextWriter(w) }
|
||||
|
||||
// CreateTextStdoutWriter creates a non-owning text writer for os.Stdout.
|
||||
func (l *Logger) CreateTextStdoutWriter() *LoggerTextWriter {
|
||||
return CreateTextStdoutWriter()
|
||||
}
|
||||
func (l *Logger) CreateTextStdoutWriter() *LoggerTextWriter { return CreateTextStdoutWriter() }
|
||||
|
||||
// CreateTextFileWriter creates an owning text writer for a file.
|
||||
func (l *Logger) CreateTextFileWriter(filename string) (*LoggerTextWriter, error) {
|
||||
@@ -163,6 +308,12 @@ func (l *Logger) CreateJsonFileWriter(filename string) (*LoggerJsonWriter, error
|
||||
return CreateJsonFileWriter(filename, l.jsonPretty)
|
||||
}
|
||||
|
||||
type replacer struct {
|
||||
old string
|
||||
new string
|
||||
}
|
||||
|
||||
func (r replacer) replace(s string) string { return strings.ReplaceAll(s, r.old, r.new) }
|
||||
func (l *Logger) replace(s string) string {
|
||||
out := s
|
||||
for _, repl := range l.replacers {
|
||||
@@ -170,7 +321,6 @@ func (l *Logger) replace(s string) string {
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func (l *Logger) replaceAll(messages ...any) []any {
|
||||
if len(l.replacers) == 0 {
|
||||
return messages
|
||||
|
||||
Reference in New Issue
Block a user