81 lines
1.9 KiB
Go
81 lines
1.9 KiB
Go
// Package log provides optional colored console logging, independent of decryption.
|
|
package log
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"path"
|
|
"runtime"
|
|
"sync"
|
|
"time"
|
|
)
|
|
|
|
// Logger writes timestamped, colorized log lines to stderr.
|
|
type Logger struct{}
|
|
|
|
// New returns a logger instance.
|
|
func New() *Logger { return &Logger{} }
|
|
|
|
func (l *Logger) Debug(a ...any) { output(1, "cyan", a...) }
|
|
func (l *Logger) Info(a ...any) { output(1, "green", a...) }
|
|
func (l *Logger) Warn(a ...any) { output(1, "yellow", a...) }
|
|
func (l *Logger) Error(a ...any) { output(1, "red", a...) }
|
|
|
|
// With returns the same logger (scope is ignored; kept for call-site compatibility).
|
|
func (l *Logger) With(_ any) *Logger { return l }
|
|
|
|
// PrintSuccess prints a green/cyan success line for CLI use.
|
|
func PrintSuccess(src, dst string) {
|
|
mu.Lock()
|
|
defer mu.Unlock()
|
|
fmt.Fprintf(os.Stderr, "%s %s: ", time.Now().Format("15:04:05.000"), trace(3))
|
|
fmt.Fprintf(os.Stderr, "操作成功: %s -> %s\n", green(src), cyan(dst))
|
|
}
|
|
|
|
var mu sync.Mutex
|
|
|
|
func output(skip int, color string, v ...any) {
|
|
mu.Lock()
|
|
defer mu.Unlock()
|
|
fmt.Fprint(os.Stderr, time.Now().Format("15:04:05.000"), " ", trace(skip+2), " ")
|
|
fmt.Fprintln(os.Stderr, colorize(color, fmt.Sprint(v...)))
|
|
}
|
|
|
|
func trace(skip int) string {
|
|
_, file, line, ok := runtime.Caller(skip)
|
|
if !ok {
|
|
return "unknown:0"
|
|
}
|
|
return fmt.Sprintf("%s:%d", path.Base(file), line)
|
|
}
|
|
|
|
func colorize(color, s string) string {
|
|
if !supportsColor() {
|
|
return s
|
|
}
|
|
const reset = "\033[0m"
|
|
switch color {
|
|
case "red":
|
|
return "\033[31m" + s + reset
|
|
case "green":
|
|
return "\033[32m" + s + reset
|
|
case "yellow":
|
|
return "\033[33m" + s + reset
|
|
case "cyan":
|
|
return "\033[36m" + s + reset
|
|
default:
|
|
return s
|
|
}
|
|
}
|
|
|
|
func green(s string) string { return colorize("green", s) }
|
|
func cyan(s string) string { return colorize("cyan", s) }
|
|
|
|
func supportsColor() bool {
|
|
if os.Getenv("NO_COLOR") != "" {
|
|
return false
|
|
}
|
|
// Windows 10+ and most Unix terminals support ANSI.
|
|
return true
|
|
}
|