more logging fixes

This commit is contained in:
Steve White 2024-10-29 11:32:47 -05:00
parent cb202de53f
commit c604251b7a
4 changed files with 64 additions and 22 deletions

View File

@ -17,6 +17,7 @@ type Config struct {
ListeningPort int `yaml:"listening_port"` ListeningPort int `yaml:"listening_port"`
LogFile string `yaml:"log_file"` LogFile string `yaml:"log_file"`
LogLevel string `yaml:"log_level"` LogLevel string `yaml:"log_level"`
LogOutput string `yaml:"log_output"`
StaticFilesDir string `yaml:"static_files_dir"` StaticFilesDir string `yaml:"static_files_dir"`
AllowedOrigins string `yaml:"allowed_origins"` AllowedOrigins string `yaml:"allowed_origins"`
} }

View File

@ -5,5 +5,6 @@ image_storage_dir: "/app/images"
listening_port: 8080 listening_port: 8080
log_file: "/app/data/boxes.log" log_file: "/app/data/boxes.log"
log_level: "INFO" log_level: "INFO"
log_output: "both" # Can be "file", "stdout", or "both"
static_files_dir: "/app/build/" static_files_dir: "/app/build/"
allowed_origins: "*" allowed_origins: "*"

View File

@ -3,6 +3,7 @@ package main
import ( import (
"fmt" "fmt"
"io"
"log" "log"
"os" "os"
"runtime" "runtime"
@ -11,8 +12,8 @@ import (
type Logger struct { type Logger struct {
*log.Logger *log.Logger
file *os.File writers []io.Writer
level LogLevel level LogLevel
} }
type LogLevel int type LogLevel int
@ -35,23 +36,50 @@ var (
} }
) )
// Initialize creates a new logger instance with specified level // Initialize creates a new logger instance with specified configuration
func Initialize(logPath string) (*Logger, error) { func Initialize(logPath string, logOutput string) (*Logger, error) {
if instance != nil { if instance != nil {
return instance, nil return instance, nil
} }
file, err := os.OpenFile(logPath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666) var writers []io.Writer
if err != nil {
return nil, fmt.Errorf("failed to open log file: %v", err) // Handle different output configurations
switch logOutput {
case "stdout":
writers = append(writers, os.Stdout)
case "file":
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)
}
writers = append(writers, file)
case "both":
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)
}
writers = append(writers, file, os.Stdout)
default:
// Default to stdout if invalid option provided
writers = append(writers, os.Stdout)
} }
// Default to INFO if no level specified // Create multi-writer if we have multiple writers
logger := &Logger{ var writer io.Writer
Logger: log.New(file, "", 0), if len(writers) > 1 {
file: file, writer = io.MultiWriter(writers...)
level: INFO, } else {
writer = writers[0]
} }
// Create logger instance
logger := &Logger{
Logger: log.New(writer, "", 0),
writers: writers,
level: INFO, // Default to INFO level
}
instance = logger instance = logger
return logger, nil return logger, nil
} }
@ -81,10 +109,18 @@ func GetLogger() *Logger {
return instance return instance
} }
// Close closes the log file // Close closes all writers that implement io.Closer
func (l *Logger) Close() error { func (l *Logger) Close() error {
if l.file != nil { var errs []error
return l.file.Close() for _, writer := range l.writers {
if closer, ok := writer.(io.Closer); ok {
if err := closer.Close(); err != nil {
errs = append(errs, err)
}
}
}
if len(errs) > 0 {
return fmt.Errorf("errors closing writers: %v", errs)
} }
return nil return nil
} }
@ -94,7 +130,6 @@ func (l *Logger) log(level LogLevel, format string, v ...interface{}) {
return return
} }
// Check if this message should be logged based on current level
if level < l.level { if level < l.level {
return return
} }

17
main.go
View File

@ -22,13 +22,14 @@ var (
) )
func main() { func main() {
log := GetLogger()
// Load configuration // Load configuration
var err error var err error
config, err = loadAndValidateConfig() config, err = loadAndValidateConfig()
if err != nil { if err != nil {
log.Fatalf("Failed to load config: %v", err) log.Fatalf("Failed to load config: %v", err)
} }
fmt.Printf("Config loaded successfully in main(), DB path %s\n", config.DatabasePath) log.Printf("Config loaded successfully in main(), DB path %s\n", config.DatabasePath)
// Set up logging BEFORE logging config details // Set up logging BEFORE logging config details
if err := setupLogging(config.LogFile); err != nil { if err := setupLogging(config.LogFile); err != nil {
@ -86,7 +87,7 @@ func loadAndValidateConfig() (*Config, error) {
func setupLogging(logFile string) error { func setupLogging(logFile string) error {
// Initialize returns a *Logger, but we don't need to store it // Initialize returns a *Logger, but we don't need to store it
_, err := Initialize(logFile) _, err := Initialize(logFile, config.LogOutput)
if err != nil { if err != nil {
return fmt.Errorf("failed to initialize logger: %v", err) return fmt.Errorf("failed to initialize logger: %v", err)
} }
@ -109,7 +110,7 @@ func setupLogging(logFile string) error {
func logConfigDetails(config *Config) { func logConfigDetails(config *Config) {
log := GetLogger() log := GetLogger()
if log == nil { if log == nil {
fmt.Println("Warning: Logger not initialized when attempting to log config details") log.Warn("Warning: Logger not initialized when attempting to log config details")
return return
} }
@ -118,6 +119,7 @@ func logConfigDetails(config *Config) {
log.Info("Image Storage Dir: %s", config.ImageStorageDir) log.Info("Image Storage Dir: %s", config.ImageStorageDir)
log.Info("Log File: %s", config.LogFile) log.Info("Log File: %s", config.LogFile)
log.Info("Log Level: %s", config.LogLevel) log.Info("Log Level: %s", config.LogLevel)
log.Info("Log Output: %s", config.LogOutput)
log.Info("Listening Port: %d", config.ListeningPort) log.Info("Listening Port: %d", config.ListeningPort)
log.Info("Allowed Origins: %s", config.AllowedOrigins) log.Info("Allowed Origins: %s", config.AllowedOrigins)
@ -126,14 +128,17 @@ func logConfigDetails(config *Config) {
} }
func connectToDatabase(config *Config) (*gorm.DB, error) { func connectToDatabase(config *Config) (*gorm.DB, error) {
log := GetLogger()
if config == nil { if config == nil {
return nil, fmt.Errorf("config is nil in connectToDatabase") log.Error("config is nil in connectToDatabase")
return nil, fmt.Errorf("config is nil")
} }
db, err := ConnectDB(config.DatabasePath) db, err := ConnectDB(config.DatabasePath)
if err != nil || db == nil { if err != nil || db == nil {
log.Error("Failed to connect to database in connectToDatabase")
return nil, fmt.Errorf("failed to connect to database: %v", err) return nil, fmt.Errorf("failed to connect to database: %v", err)
} }
log.Println("Connected to database in connectToDatabase") log.Info("Connected to database in connectToDatabase")
return db, nil return db, nil
} }
@ -225,7 +230,7 @@ func startServer(port int, handler http.Handler) {
if log != nil { if log != nil {
log.Info("Server starting on port %d", port) log.Info("Server starting on port %d", port)
} }
fmt.Printf("Server listening on port %d\n", port) log.Info("Server listening on port %d\n", port)
log.Fatal(http.ListenAndServe(fmt.Sprintf(":%d", port), handler)) log.Fatal(http.ListenAndServe(fmt.Sprintf(":%d", port), handler))
} }