132 lines
2.4 KiB
Go
132 lines
2.4 KiB
Go
package logger
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"io"
|
|
"os"
|
|
"sync"
|
|
"sync/atomic"
|
|
"time"
|
|
)
|
|
|
|
// Level represents log level.
|
|
type Level int
|
|
|
|
const (
|
|
LevelDebug Level = iota
|
|
LevelInfo
|
|
LevelWarn
|
|
LevelError
|
|
)
|
|
|
|
func (l Level) String() string {
|
|
switch l {
|
|
case LevelDebug:
|
|
return "DEBUG"
|
|
case LevelInfo:
|
|
return "INFO"
|
|
case LevelWarn:
|
|
return "WARN"
|
|
case LevelError:
|
|
return "ERROR"
|
|
default:
|
|
return "INFO"
|
|
}
|
|
}
|
|
|
|
// Logger is a simple JSON logger compatible with Go 1.20.
|
|
type Logger struct {
|
|
level Level
|
|
writer io.Writer
|
|
mu sync.Mutex
|
|
}
|
|
|
|
// Default is the global default logger.
|
|
var Default atomic.Value
|
|
|
|
func init() {
|
|
Default.Store(&Logger{level: LevelInfo, writer: os.Stderr})
|
|
}
|
|
|
|
func getDefault() *Logger {
|
|
if l, ok := Default.Load().(*Logger); ok && l != nil {
|
|
return l
|
|
}
|
|
return &Logger{level: LevelInfo, writer: os.Stderr}
|
|
}
|
|
|
|
// Init initializes the logger with the specified log level.
|
|
func Init(level string) {
|
|
InitWithWriter(level, os.Stdout)
|
|
}
|
|
|
|
// InitWithWriter initializes the logger with the specified log level and writer.
|
|
func InitWithWriter(level string, writer io.Writer) {
|
|
var lvl Level
|
|
switch level {
|
|
case "debug":
|
|
lvl = LevelDebug
|
|
case "info":
|
|
lvl = LevelInfo
|
|
case "warn":
|
|
lvl = LevelWarn
|
|
case "error":
|
|
lvl = LevelError
|
|
default:
|
|
lvl = LevelInfo
|
|
}
|
|
if writer == nil {
|
|
writer = os.Stdout
|
|
}
|
|
Default.Store(&Logger{level: lvl, writer: writer})
|
|
}
|
|
|
|
func (l *Logger) log(level Level, msg string, args ...any) {
|
|
if level < l.level {
|
|
return
|
|
}
|
|
record := map[string]any{
|
|
"time": time.Now().Format(time.RFC3339Nano),
|
|
"level": level.String(),
|
|
"msg": msg,
|
|
}
|
|
for i := 0; i < len(args)-1; i += 2 {
|
|
key, ok := args[i].(string)
|
|
if !ok {
|
|
continue
|
|
}
|
|
record[key] = args[i+1]
|
|
}
|
|
l.mu.Lock()
|
|
defer l.mu.Unlock()
|
|
data, _ := json.Marshal(record)
|
|
fmt.Fprintln(l.writer, string(data))
|
|
}
|
|
|
|
// Debug logs a message at Debug level.
|
|
func Debug(msg string, args ...any) {
|
|
getDefault().log(LevelDebug, msg, args...)
|
|
}
|
|
|
|
// Info logs a message at Info level.
|
|
func Info(msg string, args ...any) {
|
|
getDefault().log(LevelInfo, msg, args...)
|
|
}
|
|
|
|
// Warn logs a message at Warn level.
|
|
func Warn(msg string, args ...any) {
|
|
getDefault().log(LevelWarn, msg, args...)
|
|
}
|
|
|
|
// Error logs a message at Error level.
|
|
func Error(msg string, args ...any) {
|
|
getDefault().log(LevelError, msg, args...)
|
|
}
|
|
|
|
// Fatal logs a message at Error level and exits.
|
|
func Fatal(msg string, args ...any) {
|
|
getDefault().log(LevelError, msg, args...)
|
|
os.Exit(1)
|
|
}
|