179 lines
3.3 KiB
Go
179 lines
3.3 KiB
Go
|
// logger.go
|
||
|
package main
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
"log"
|
||
|
"os"
|
||
|
"runtime"
|
||
|
"time"
|
||
|
)
|
||
|
|
||
|
type Logger struct {
|
||
|
*log.Logger
|
||
|
file *os.File
|
||
|
level LogLevel
|
||
|
}
|
||
|
|
||
|
type LogLevel int
|
||
|
|
||
|
const (
|
||
|
DEBUG LogLevel = iota
|
||
|
INFO
|
||
|
WARN
|
||
|
ERROR
|
||
|
)
|
||
|
|
||
|
var (
|
||
|
instance *Logger
|
||
|
// Map for converting string to LogLevel
|
||
|
logLevelMap = map[string]LogLevel{
|
||
|
"DEBUG": DEBUG,
|
||
|
"INFO": INFO,
|
||
|
"WARN": WARN,
|
||
|
"ERROR": ERROR,
|
||
|
}
|
||
|
)
|
||
|
|
||
|
// Initialize creates a new logger instance with specified level
|
||
|
func Initialize(logPath string) (*Logger, error) {
|
||
|
if instance != nil {
|
||
|
return instance, nil
|
||
|
}
|
||
|
|
||
|
file, err := os.OpenFile(logPath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
|
||
|
if err != nil {
|
||
|
return nil, fmt.Errorf("failed to open log file: %v", err)
|
||
|
}
|
||
|
|
||
|
// Default to INFO if no level specified
|
||
|
logger := &Logger{
|
||
|
Logger: log.New(file, "", 0),
|
||
|
file: file,
|
||
|
level: INFO,
|
||
|
}
|
||
|
instance = logger
|
||
|
return logger, nil
|
||
|
}
|
||
|
|
||
|
// SetLogLevel sets the logging level from a string
|
||
|
func (l *Logger) SetLogLevel(levelStr string) error {
|
||
|
level, ok := logLevelMap[levelStr]
|
||
|
if !ok {
|
||
|
return fmt.Errorf("invalid log level: %s. Must be one of: DEBUG, INFO, WARN, ERROR", levelStr)
|
||
|
}
|
||
|
l.level = level
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
// GetLogLevel returns the current logging level as a string
|
||
|
func (l *Logger) GetLogLevel() string {
|
||
|
for str, level := range logLevelMap {
|
||
|
if level == l.level {
|
||
|
return str
|
||
|
}
|
||
|
}
|
||
|
return "UNKNOWN"
|
||
|
}
|
||
|
|
||
|
// GetLogger returns the singleton logger instance
|
||
|
func GetLogger() *Logger {
|
||
|
return instance
|
||
|
}
|
||
|
|
||
|
// Close closes the log file
|
||
|
func (l *Logger) Close() error {
|
||
|
if l.file != nil {
|
||
|
return l.file.Close()
|
||
|
}
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func (l *Logger) log(level LogLevel, format string, v ...interface{}) {
|
||
|
if l == nil {
|
||
|
return
|
||
|
}
|
||
|
|
||
|
// Check if this message should be logged based on current level
|
||
|
if level < l.level {
|
||
|
return
|
||
|
}
|
||
|
|
||
|
// Get caller information
|
||
|
_, file, line, _ := runtime.Caller(2)
|
||
|
|
||
|
// Create timestamp
|
||
|
timestamp := time.Now().Format("2006-01-02 15:04:05")
|
||
|
|
||
|
// Create level string
|
||
|
levelStr := "INFO"
|
||
|
switch level {
|
||
|
case DEBUG:
|
||
|
levelStr = "DEBUG"
|
||
|
case WARN:
|
||
|
levelStr = "WARN"
|
||
|
case ERROR:
|
||
|
levelStr = "ERROR"
|
||
|
}
|
||
|
|
||
|
// Format message
|
||
|
message := fmt.Sprintf(format, v...)
|
||
|
|
||
|
// Final log format
|
||
|
logLine := fmt.Sprintf("[%s] [%s] [%s:%d] %s\n",
|
||
|
timestamp,
|
||
|
levelStr,
|
||
|
file,
|
||
|
line,
|
||
|
message,
|
||
|
)
|
||
|
|
||
|
l.Logger.Print(logLine)
|
||
|
}
|
||
|
|
||
|
// Debug logs a debug message
|
||
|
func (l *Logger) Debug(format string, v ...interface{}) {
|
||
|
l.log(DEBUG, format, v...)
|
||
|
}
|
||
|
|
||
|
// Info logs an info message
|
||
|
func (l *Logger) Info(format string, v ...interface{}) {
|
||
|
l.log(INFO, format, v...)
|
||
|
}
|
||
|
|
||
|
// Warn logs a warning message
|
||
|
func (l *Logger) Warn(format string, v ...interface{}) {
|
||
|
l.log(WARN, format, v...)
|
||
|
}
|
||
|
|
||
|
// Error logs an error message
|
||
|
func (l *Logger) Error(format string, v ...interface{}) {
|
||
|
l.log(ERROR, format, v...)
|
||
|
}
|
||
|
|
||
|
// HTTPRequest logs an HTTP request
|
||
|
func (l *Logger) HTTPRequest(method, path, username string, statusCode int) {
|
||
|
l.log(INFO, "HTTP %s %s - User: %s - Status: %d",
|
||
|
method,
|
||
|
path,
|
||
|
username,
|
||
|
statusCode,
|
||
|
)
|
||
|
}
|
||
|
|
||
|
// UserAction logs user actions like login, logout, etc.
|
||
|
func (l *Logger) UserAction(username, action string) {
|
||
|
l.log(INFO, "User Action - Username: %s - Action: %s",
|
||
|
username,
|
||
|
action,
|
||
|
)
|
||
|
}
|
||
|
|
||
|
// DatabaseAction logs database operations
|
||
|
func (l *Logger) DatabaseAction(operation, details string) {
|
||
|
l.log(INFO, "Database Action - Operation: %s - Details: %s",
|
||
|
operation,
|
||
|
details,
|
||
|
)
|
||
|
}
|