something
This commit is contained in:
@@ -1,31 +1,87 @@
|
||||
package logger
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
|
||||
"gopkg.in/natefinch/lumberjack.v2"
|
||||
)
|
||||
|
||||
// Level represents log severity
|
||||
type Level int
|
||||
|
||||
const (
|
||||
LevelDebug Level = iota
|
||||
LevelInfo
|
||||
LevelWarn
|
||||
LevelError
|
||||
)
|
||||
|
||||
var levelNames = map[Level]string{
|
||||
LevelDebug: "DEBUG",
|
||||
LevelInfo: "INFO",
|
||||
LevelWarn: "WARN",
|
||||
LevelError: "ERROR",
|
||||
}
|
||||
|
||||
// ParseLevel parses a level string into a Level
|
||||
func ParseLevel(s string) Level {
|
||||
switch s {
|
||||
case "debug", "DEBUG":
|
||||
return LevelDebug
|
||||
case "info", "INFO":
|
||||
return LevelInfo
|
||||
case "warn", "WARN", "warning", "WARNING":
|
||||
return LevelWarn
|
||||
case "error", "ERROR":
|
||||
return LevelError
|
||||
default:
|
||||
return LevelInfo
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
defaultLogger *Logger
|
||||
once sync.Once
|
||||
currentLevel Level = LevelInfo
|
||||
)
|
||||
|
||||
// Logger wraps the standard log.Logger with file and stdout output
|
||||
// Logger wraps the standard log.Logger with optional file output and levels
|
||||
type Logger struct {
|
||||
*log.Logger
|
||||
fileWriter io.WriteCloser
|
||||
}
|
||||
|
||||
// Init initializes the default logger with both file and stdout output
|
||||
func Init(logDir, logFileName string, maxSizeMB int, maxBackups int, maxAgeDays int) error {
|
||||
// SetLevel sets the global log level
|
||||
func SetLevel(level Level) {
|
||||
currentLevel = level
|
||||
}
|
||||
|
||||
// GetLevel returns the current log level
|
||||
func GetLevel() Level {
|
||||
return currentLevel
|
||||
}
|
||||
|
||||
// InitStdout initializes the logger to only write to stdout
|
||||
func InitStdout() {
|
||||
once.Do(func() {
|
||||
log.SetOutput(os.Stdout)
|
||||
log.SetFlags(log.LstdFlags | log.Lshortfile)
|
||||
defaultLogger = &Logger{
|
||||
Logger: log.Default(),
|
||||
fileWriter: nil,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// InitWithFile initializes the logger with both file and stdout output
|
||||
// The file is truncated on each start
|
||||
func InitWithFile(logPath string) error {
|
||||
var err error
|
||||
once.Do(func() {
|
||||
defaultLogger, err = New(logDir, logFileName, maxSizeMB, maxBackups, maxAgeDays)
|
||||
defaultLogger, err = NewWithFile(logPath)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@@ -37,22 +93,19 @@ func Init(logDir, logFileName string, maxSizeMB int, maxBackups int, maxAgeDays
|
||||
return err
|
||||
}
|
||||
|
||||
// New creates a new logger that writes to both stdout and a log file
|
||||
func New(logDir, logFileName string, maxSizeMB int, maxBackups int, maxAgeDays int) (*Logger, error) {
|
||||
// NewWithFile creates a new logger that writes to both stdout and a log file
|
||||
// The file is truncated on each start
|
||||
func NewWithFile(logPath string) (*Logger, error) {
|
||||
// Ensure log directory exists
|
||||
logDir := filepath.Dir(logPath)
|
||||
if err := os.MkdirAll(logDir, 0755); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
logPath := filepath.Join(logDir, logFileName)
|
||||
|
||||
// Create file writer with rotation
|
||||
fileWriter := &lumberjack.Logger{
|
||||
Filename: logPath,
|
||||
MaxSize: maxSizeMB, // megabytes
|
||||
MaxBackups: maxBackups, // number of backup files
|
||||
MaxAge: maxAgeDays, // days
|
||||
Compress: true, // compress old log files
|
||||
// Create/truncate the log file
|
||||
fileWriter, err := os.Create(logPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Create multi-writer that writes to both stdout and file
|
||||
@@ -80,48 +133,91 @@ func GetDefault() *Logger {
|
||||
return defaultLogger
|
||||
}
|
||||
|
||||
// Printf logs a formatted message
|
||||
func Printf(format string, v ...interface{}) {
|
||||
if defaultLogger != nil {
|
||||
defaultLogger.Printf(format, v...)
|
||||
} else {
|
||||
log.Printf(format, v...)
|
||||
// logf logs a formatted message at the given level
|
||||
func logf(level Level, format string, v ...interface{}) {
|
||||
if level < currentLevel {
|
||||
return
|
||||
}
|
||||
prefix := fmt.Sprintf("[%s] ", levelNames[level])
|
||||
msg := fmt.Sprintf(format, v...)
|
||||
log.Print(prefix + msg)
|
||||
}
|
||||
|
||||
// Print logs a message
|
||||
func Print(v ...interface{}) {
|
||||
if defaultLogger != nil {
|
||||
defaultLogger.Print(v...)
|
||||
} else {
|
||||
log.Print(v...)
|
||||
// logln logs a message at the given level
|
||||
func logln(level Level, v ...interface{}) {
|
||||
if level < currentLevel {
|
||||
return
|
||||
}
|
||||
prefix := fmt.Sprintf("[%s] ", levelNames[level])
|
||||
msg := fmt.Sprint(v...)
|
||||
log.Print(prefix + msg)
|
||||
}
|
||||
|
||||
// Println logs a message with newline
|
||||
func Println(v ...interface{}) {
|
||||
if defaultLogger != nil {
|
||||
defaultLogger.Println(v...)
|
||||
} else {
|
||||
log.Println(v...)
|
||||
}
|
||||
// Debug logs a debug message
|
||||
func Debug(v ...interface{}) {
|
||||
logln(LevelDebug, v...)
|
||||
}
|
||||
|
||||
// Fatal logs a message and exits
|
||||
// Debugf logs a formatted debug message
|
||||
func Debugf(format string, v ...interface{}) {
|
||||
logf(LevelDebug, format, v...)
|
||||
}
|
||||
|
||||
// Info logs an info message
|
||||
func Info(v ...interface{}) {
|
||||
logln(LevelInfo, v...)
|
||||
}
|
||||
|
||||
// Infof logs a formatted info message
|
||||
func Infof(format string, v ...interface{}) {
|
||||
logf(LevelInfo, format, v...)
|
||||
}
|
||||
|
||||
// Warn logs a warning message
|
||||
func Warn(v ...interface{}) {
|
||||
logln(LevelWarn, v...)
|
||||
}
|
||||
|
||||
// Warnf logs a formatted warning message
|
||||
func Warnf(format string, v ...interface{}) {
|
||||
logf(LevelWarn, format, v...)
|
||||
}
|
||||
|
||||
// Error logs an error message
|
||||
func Error(v ...interface{}) {
|
||||
logln(LevelError, v...)
|
||||
}
|
||||
|
||||
// Errorf logs a formatted error message
|
||||
func Errorf(format string, v ...interface{}) {
|
||||
logf(LevelError, format, v...)
|
||||
}
|
||||
|
||||
// Fatal logs an error message and exits
|
||||
func Fatal(v ...interface{}) {
|
||||
if defaultLogger != nil {
|
||||
defaultLogger.Fatal(v...)
|
||||
} else {
|
||||
log.Fatal(v...)
|
||||
}
|
||||
logln(LevelError, v...)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Fatalf logs a formatted message and exits
|
||||
// Fatalf logs a formatted error message and exits
|
||||
func Fatalf(format string, v ...interface{}) {
|
||||
if defaultLogger != nil {
|
||||
defaultLogger.Fatalf(format, v...)
|
||||
} else {
|
||||
log.Fatalf(format, v...)
|
||||
}
|
||||
logf(LevelError, format, v...)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// --- Backwards compatibility (maps to Info level) ---
|
||||
|
||||
// Printf logs a formatted message at Info level
|
||||
func Printf(format string, v ...interface{}) {
|
||||
logf(LevelInfo, format, v...)
|
||||
}
|
||||
|
||||
// Print logs a message at Info level
|
||||
func Print(v ...interface{}) {
|
||||
logln(LevelInfo, v...)
|
||||
}
|
||||
|
||||
// Println logs a message at Info level
|
||||
func Println(v ...interface{}) {
|
||||
logln(LevelInfo, v...)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user