mirror of
https://github.com/taigrr/log-socket
synced 2026-03-21 14:12:18 -07:00
feat(log): add colored terminal output without external packages (#16)
Adds ANSI color-coded log levels for terminal output: - TRACE: Gray - DEBUG: Cyan - INFO: Green - NOTICE: Blue - WARN: Yellow - ERROR/PANIC/FATAL: Red (bold for PANIC/FATAL) Colors are auto-detected based on terminal capability and can be controlled via SetColorEnabled()/ColorEnabled(). Fixes #9
This commit is contained in:
99
log/color.go
Normal file
99
log/color.go
Normal file
@@ -0,0 +1,99 @@
|
||||
package log
|
||||
|
||||
import (
|
||||
"os"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// ANSI color codes for terminal output
|
||||
const (
|
||||
colorReset = "\033[0m"
|
||||
colorRed = "\033[31m"
|
||||
colorGreen = "\033[32m"
|
||||
colorYellow = "\033[33m"
|
||||
colorBlue = "\033[34m"
|
||||
colorPurple = "\033[35m"
|
||||
colorCyan = "\033[36m"
|
||||
colorWhite = "\033[37m"
|
||||
colorGray = "\033[90m"
|
||||
|
||||
// Bold variants
|
||||
colorBoldRed = "\033[1;31m"
|
||||
colorBoldYellow = "\033[1;33m"
|
||||
colorBoldWhite = "\033[1;37m"
|
||||
)
|
||||
|
||||
var (
|
||||
colorEnabled = true
|
||||
colorEnabledOnce sync.Once
|
||||
colorMux sync.RWMutex
|
||||
)
|
||||
|
||||
// SetColorEnabled enables or disables colored output for stderr logging.
|
||||
// By default, color is enabled when stderr is a terminal.
|
||||
func SetColorEnabled(enabled bool) {
|
||||
colorMux.Lock()
|
||||
colorEnabled = enabled
|
||||
colorMux.Unlock()
|
||||
}
|
||||
|
||||
// ColorEnabled returns whether colored output is currently enabled.
|
||||
func ColorEnabled() bool {
|
||||
colorMux.RLock()
|
||||
defer colorMux.RUnlock()
|
||||
return colorEnabled
|
||||
}
|
||||
|
||||
// isTerminal checks if the given file descriptor is a terminal.
|
||||
// This is a simple heuristic that works on Unix-like systems.
|
||||
func isTerminal(f *os.File) bool {
|
||||
stat, err := f.Stat()
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return (stat.Mode() & os.ModeCharDevice) != 0
|
||||
}
|
||||
|
||||
// initColorEnabled sets the default color state based on whether stderr is a terminal.
|
||||
func initColorEnabled() {
|
||||
colorEnabledOnce.Do(func() {
|
||||
colorEnabled = isTerminal(os.Stderr)
|
||||
})
|
||||
}
|
||||
|
||||
// levelColor returns the ANSI color code for a given log level.
|
||||
func levelColor(level Level) string {
|
||||
switch level {
|
||||
case LTrace:
|
||||
return colorGray
|
||||
case LDebug:
|
||||
return colorCyan
|
||||
case LInfo:
|
||||
return colorGreen
|
||||
case LNotice:
|
||||
return colorBlue
|
||||
case LWarn:
|
||||
return colorYellow
|
||||
case LError:
|
||||
return colorRed
|
||||
case LPanic:
|
||||
return colorBoldRed
|
||||
case LFatal:
|
||||
return colorBoldRed
|
||||
default:
|
||||
return colorReset
|
||||
}
|
||||
}
|
||||
|
||||
// colorize wraps text with ANSI color codes if color is enabled.
|
||||
func colorize(text string, color string) string {
|
||||
if !ColorEnabled() {
|
||||
return text
|
||||
}
|
||||
return color + text + colorReset
|
||||
}
|
||||
|
||||
// colorizeLevelText returns the level string with appropriate color.
|
||||
func colorizeLevelText(level string, lvl Level) string {
|
||||
return colorize(level, levelColor(lvl))
|
||||
}
|
||||
Reference in New Issue
Block a user