Files
radiantwave-legacy/internal/logger/logger.go
T

106 lines
2.2 KiB
Go

package logger
import (
"fmt"
"log"
"os"
"time"
"gorm.io/gorm"
"rhemawavetech.com/rhemawave/internal/db"
)
type Level int
const (
LevelDebug Level = iota
LevelInfo
LevelWarning
LevelError
LevelFatal
)
func (l Level) String() string {
return [...]string{"DEBUG", "INFO", "WARNING", "ERROR", "FATAL"}[l]
}
var (
DB *gorm.DB
file *os.File
console = log.New(os.Stderr, "", 0)
SetLevel Level = LevelInfo
)
// AddFile attaches or replaces the file backend
func AddFile(path string) error {
if file != nil {
file.Close()
}
_, err := os.OpenFile(path, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0o644)
if err != nil {
return err
}
return nil
}
// AddDatabase attaches or replaces the database backend
func AddDatabase(d *gorm.DB) {
console.Println("Adding database to logger")
DB = d
}
// Close shuts down the file backend.
func Close() error {
if file != nil {
err := file.Close()
file = nil
return err
}
return nil
}
func logMsg(level Level, format string, args ...any) {
if level == LevelDebug && SetLevel != LevelDebug {
return
}
message := fmt.Sprintf(format, args...)
now := time.Now()
timestamp := now.Format("2006-01-02 15:04:05.000")
line := fmt.Sprintf("%s [%s] %s", timestamp, level, message)
// 1. The standard log package is internally thread-safe
console.Println(line)
// 2. Write to file
if file != nil {
fmt.Fprintln(file, line)
}
// 3. Write to DB using GORM. It handles its own connection pooling and locking.
if DB != nil {
var entry db.Log
entry.Timestamp = now.UnixMilli()
entry.Level = level.String()
entry.Message = message
// Use Save() to insert the new record.
result := DB.Save(&entry)
if result.Error != nil {
console.Printf("Failed to write log to database: %v\n", result.Error)
}
}
}
func Debug(format string, args ...any) { logMsg(LevelDebug, format, args...) }
func Info(format string, args ...any) { logMsg(LevelInfo, format, args...) }
func Warning(format string, args ...any) { logMsg(LevelWarning, format, args...) }
func Error(format string, args ...any) { logMsg(LevelError, format, args...) }
func Fatal(format string, args ...any) {
logMsg(LevelFatal, format, args...)
time.Sleep(100 * time.Millisecond)
os.Exit(1)
}