use only global logger

This commit is contained in:
Sky Johnson 2025-03-28 14:15:34 -05:00
parent 6154b5303c
commit d6feb408ce
7 changed files with 175 additions and 126 deletions

View File

@ -18,12 +18,12 @@ const (
) )
// LogRequest logs an HTTP request with custom formatting // LogRequest logs an HTTP request with custom formatting
func LogRequest(log *logger.Logger, statusCode int, r *http.Request, duration time.Duration) { func LogRequest(statusCode int, r *http.Request, duration time.Duration) {
statusColor := getStatusColor(statusCode) statusColor := getStatusColor(statusCode)
// Use the logger's raw message writer to bypass the standard format // Use the logger's raw message writer to bypass the standard format
log.LogRaw("%s%s%s %s%d %s%s %s %s(%v)%s", logger.LogRaw("%s%s%s %s%d %s%s %s %s(%v)%s",
colorGray, time.Now().Format(log.TimeFormat()), colorReset, colorGray, time.Now().Format(logger.TimeFormat()), colorReset,
statusColor, statusCode, r.Method, colorReset, r.URL.Path, colorGray, duration, colorReset) statusColor, statusCode, r.Method, colorReset, r.URL.Path, colorGray, duration, colorReset)
} }

View File

@ -19,7 +19,6 @@ type Server struct {
luaRouter *routers.LuaRouter luaRouter *routers.LuaRouter
staticRouter *routers.StaticRouter staticRouter *routers.StaticRouter
luaRunner *runner.LuaRunner luaRunner *runner.LuaRunner
logger *logger.Logger
httpServer *http.Server httpServer *http.Server
loggingEnabled bool loggingEnabled bool
debugMode bool // Controls whether to show error details debugMode bool // Controls whether to show error details
@ -28,15 +27,13 @@ type Server struct {
} }
// New creates a new HTTP server with optimized connection settings // New creates a new HTTP server with optimized connection settings
func New(luaRouter *routers.LuaRouter, staticRouter *routers.StaticRouter, func New(luaRouter *routers.LuaRouter, staticRouter *routers.StaticRouter, runner *runner.LuaRunner,
runner *runner.LuaRunner, log *logger.Logger,
loggingEnabled bool, debugMode bool, overrideDir string, config *config.Config) *Server { loggingEnabled bool, debugMode bool, overrideDir string, config *config.Config) *Server {
server := &Server{ server := &Server{
luaRouter: luaRouter, luaRouter: luaRouter,
staticRouter: staticRouter, staticRouter: staticRouter,
luaRunner: runner, luaRunner: runner,
logger: log,
httpServer: &http.Server{}, httpServer: &http.Server{},
loggingEnabled: loggingEnabled, loggingEnabled: loggingEnabled,
debugMode: debugMode, debugMode: debugMode,
@ -63,13 +60,13 @@ func New(luaRouter *routers.LuaRouter, staticRouter *routers.StaticRouter,
// ListenAndServe starts the server on the given address // ListenAndServe starts the server on the given address
func (s *Server) ListenAndServe(addr string) error { func (s *Server) ListenAndServe(addr string) error {
s.httpServer.Addr = addr s.httpServer.Addr = addr
s.logger.Info("Server listening at http://localhost%s", addr) logger.Info("Server listening at http://localhost%s", addr)
return s.httpServer.ListenAndServe() return s.httpServer.ListenAndServe()
} }
// Shutdown gracefully shuts down the server // Shutdown gracefully shuts down the server
func (s *Server) Shutdown(ctx context.Context) error { func (s *Server) Shutdown(ctx context.Context) error {
s.logger.Info("Server shutting down...") logger.Info("Server shutting down...")
return s.httpServer.Shutdown(ctx) return s.httpServer.Shutdown(ctx)
} }
@ -84,7 +81,7 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
// Calculate and log request duration // Calculate and log request duration
duration := time.Since(start) duration := time.Since(start)
if s.loggingEnabled { if s.loggingEnabled {
LogRequest(s.logger, http.StatusOK, r, duration) LogRequest(http.StatusOK, r, duration)
} }
return return
} }
@ -103,13 +100,13 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
// Log the request with our custom format // Log the request with our custom format
if s.loggingEnabled { if s.loggingEnabled {
LogRequest(s.logger, statusCode, r, duration) LogRequest(statusCode, r, duration)
} }
} }
// handleRequest processes the actual request // handleRequest processes the actual request
func (s *Server) handleRequest(w http.ResponseWriter, r *http.Request) { func (s *Server) handleRequest(w http.ResponseWriter, r *http.Request) {
s.logger.Debug("Processing request %s %s", r.Method, r.URL.Path) logger.Debug("Processing request %s %s", r.Method, r.URL.Path)
// Try Lua routes first // Try Lua routes first
params := &routers.Params{} params := &routers.Params{}
@ -126,7 +123,7 @@ func (s *Server) handleRequest(w http.ResponseWriter, r *http.Request) {
errorMsg = node.Error.Error() errorMsg = node.Error.Error()
} }
s.logger.Error("%s %s - %s", r.Method, r.URL.Path, errorMsg) logger.Error("%s %s - %s", r.Method, r.URL.Path, errorMsg)
// Show error page with the actual error message // Show error page with the actual error message
w.Header().Set("Content-Type", "text/html; charset=utf-8") w.Header().Set("Content-Type", "text/html; charset=utf-8")
@ -135,7 +132,7 @@ func (s *Server) handleRequest(w http.ResponseWriter, r *http.Request) {
w.Write([]byte(errorHTML)) w.Write([]byte(errorHTML))
return return
} else if found { } else if found {
s.logger.Debug("Found Lua route match for %s %s with %d params", r.Method, r.URL.Path, params.Count) logger.Debug("Found Lua route match for %s %s with %d params", r.Method, r.URL.Path, params.Count)
s.handleLuaRoute(w, r, bytecode, scriptPath, params) s.handleLuaRoute(w, r, bytecode, scriptPath, params)
return return
} }
@ -165,7 +162,7 @@ func (s *Server) handleLuaRoute(w http.ResponseWriter, r *http.Request, bytecode
defer ctx.Release() defer ctx.Release()
// Log bytecode size // Log bytecode size
s.logger.Debug("Executing Lua route with %d bytes of bytecode", len(bytecode)) logger.Debug("Executing Lua route with %d bytes of bytecode", len(bytecode))
// Add request info directly to context // Add request info directly to context
ctx.Set("method", r.Method) ctx.Set("method", r.Method)
@ -219,7 +216,7 @@ func (s *Server) handleLuaRoute(w http.ResponseWriter, r *http.Request, bytecode
// Execute Lua script // Execute Lua script
result, err := s.luaRunner.Run(bytecode, ctx, scriptPath) result, err := s.luaRunner.Run(bytecode, ctx, scriptPath)
if err != nil { if err != nil {
s.logger.Error("Error executing Lua route: %v", err) logger.Error("Error executing Lua route: %v", err)
// Set content type to HTML // Set content type to HTML
w.Header().Set("Content-Type", "text/html; charset=utf-8") w.Header().Set("Content-Type", "text/html; charset=utf-8")
@ -232,7 +229,7 @@ func (s *Server) handleLuaRoute(w http.ResponseWriter, r *http.Request, bytecode
return return
} }
writeResponse(w, result, s.logger) writeResponse(w, result)
} }
// Content types for responses // Content types for responses
@ -242,7 +239,7 @@ const (
) )
// writeResponse writes the Lua result to the HTTP response // writeResponse writes the Lua result to the HTTP response
func writeResponse(w http.ResponseWriter, result any, log *logger.Logger) { func writeResponse(w http.ResponseWriter, result any) {
if result == nil { if result == nil {
w.WriteHeader(http.StatusNoContent) w.WriteHeader(http.StatusNoContent)
return return
@ -283,7 +280,7 @@ func writeResponse(w http.ResponseWriter, result any, log *logger.Logger) {
setContentTypeIfMissing(w, contentTypeJSON) setContentTypeIfMissing(w, contentTypeJSON)
data, err := json.Marshal(res) data, err := json.Marshal(res)
if err != nil { if err != nil {
log.Error("Failed to marshal response: %v", err) logger.Error("Failed to marshal response: %v", err)
http.Error(w, "Internal Server Error", http.StatusInternalServerError) http.Error(w, "Internal Server Error", http.StatusInternalServerError)
return return
} }

View File

@ -54,13 +54,20 @@ const (
defaultRateLimitTime = 10 * time.Second // How long to pause during rate limiting defaultRateLimitTime = 10 * time.Second // How long to pause during rate limiting
) )
// Single global logger instance with mutex for safe initialization
var (
globalLogger *Logger
globalLoggerOnce sync.Once
)
// Logger handles logging operations // Logger handles logging operations
type Logger struct { type Logger struct {
writer io.Writer writer io.Writer
level int level int
useColors bool useColors bool
timeFormat string timeFormat string
mu sync.Mutex // Mutex for thread-safe writing mu sync.Mutex // Mutex for thread-safe writing
debugMode atomic.Bool // Force debug logging regardless of level
// Simple rate limiting // Simple rate limiting
logCount atomic.Int64 // Number of logs in current window logCount atomic.Int64 // Number of logs in current window
@ -71,8 +78,23 @@ type Logger struct {
limitDuration time.Duration // How long to pause logging when rate limited limitDuration time.Duration // How long to pause logging when rate limited
} }
// New creates a new logger // GetLogger returns the global logger instance, creating it if needed
func New(minLevel int, useColors bool) *Logger { func GetLogger() *Logger {
globalLoggerOnce.Do(func() {
globalLogger = newLogger(LevelInfo, true)
})
return globalLogger
}
// InitGlobalLogger initializes the global logger with custom settings
func InitGlobalLogger(minLevel int, useColors bool) {
globalLoggerOnce.Do(func() {
globalLogger = newLogger(minLevel, useColors)
})
}
// newLogger creates a new logger instance (internal use)
func newLogger(minLevel int, useColors bool) *Logger {
logger := &Logger{ logger := &Logger{
writer: os.Stdout, writer: os.Stdout,
level: minLevel, level: minLevel,
@ -88,6 +110,11 @@ func New(minLevel int, useColors bool) *Logger {
return logger return logger
} }
// New creates a new logger (deprecated - use GetLogger() instead)
func New(minLevel int, useColors bool) *Logger {
return newLogger(minLevel, useColors)
}
// resetCounters resets the rate limiting counters // resetCounters resets the rate limiting counters
func (l *Logger) resetCounters() { func (l *Logger) resetCounters() {
l.logCount.Store(0) l.logCount.Store(0)
@ -128,6 +155,21 @@ func (l *Logger) DisableColors() {
l.useColors = false l.useColors = false
} }
// EnableDebug forces debug logs to be shown regardless of level
func (l *Logger) EnableDebug() {
l.debugMode.Store(true)
}
// DisableDebug stops forcing debug logs
func (l *Logger) DisableDebug() {
l.debugMode.Store(false)
}
// IsDebugEnabled returns true if debug mode is enabled
func (l *Logger) IsDebugEnabled() bool {
return l.debugMode.Load()
}
// writeMessage writes a formatted log message directly to the writer // writeMessage writes a formatted log message directly to the writer
func (l *Logger) writeMessage(level int, message string, rawMode bool) { func (l *Logger) writeMessage(level int, message string, rawMode bool) {
var logLine string var logLine string
@ -217,8 +259,9 @@ func (l *Logger) checkRateLimit(level int) bool {
// log handles the core logging logic with level filtering // log handles the core logging logic with level filtering
func (l *Logger) log(level int, format string, args ...any) { func (l *Logger) log(level int, format string, args ...any) {
// First check normal level filtering // Check if we should log this message
if level < l.level { // Either level is high enough OR (it's a debug message AND debug mode is enabled)
if level < l.level && !(level == LevelDebug && l.debugMode.Load()) {
return return
} }
@ -326,50 +369,69 @@ func (l *Logger) Server(format string, args ...any) {
l.log(LevelServer, format, args...) l.log(LevelServer, format, args...)
} }
// Default global logger // Global helper functions that use the global logger
var defaultLogger = New(LevelInfo, true)
// Debug logs a debug message to the default logger // Debug logs a debug message to the global logger
func Debug(format string, args ...any) { func Debug(format string, args ...any) {
defaultLogger.Debug(format, args...) GetLogger().Debug(format, args...)
} }
// Info logs an informational message to the default logger // Info logs an informational message to the global logger
func Info(format string, args ...any) { func Info(format string, args ...any) {
defaultLogger.Info(format, args...) GetLogger().Info(format, args...)
} }
// Warning logs a warning message to the default logger // Warning logs a warning message to the global logger
func Warning(format string, args ...any) { func Warning(format string, args ...any) {
defaultLogger.Warning(format, args...) GetLogger().Warning(format, args...)
} }
// Error logs an error message to the default logger // Error logs an error message to the global logger
func Error(format string, args ...any) { func Error(format string, args ...any) {
defaultLogger.Error(format, args...) GetLogger().Error(format, args...)
} }
// Fatal logs a fatal error message to the default logger and exits // Fatal logs a fatal error message to the global logger and exits
func Fatal(format string, args ...any) { func Fatal(format string, args ...any) {
defaultLogger.Fatal(format, args...) GetLogger().Fatal(format, args...)
} }
// Server logs a server message to the default logger // Server logs a server message to the global logger
func Server(format string, args ...any) { func Server(format string, args ...any) {
defaultLogger.Server(format, args...) GetLogger().Server(format, args...)
} }
// LogRaw logs a raw message to the default logger // LogRaw logs a raw message to the global logger
func LogRaw(format string, args ...any) { func LogRaw(format string, args ...any) {
defaultLogger.LogRaw(format, args...) GetLogger().LogRaw(format, args...)
} }
// SetLevel changes the minimum log level of the default logger // SetLevel changes the minimum log level of the global logger
func SetLevel(level int) { func SetLevel(level int) {
defaultLogger.SetLevel(level) GetLogger().SetLevel(level)
} }
// SetOutput changes the output destination of the default logger // SetOutput changes the output destination of the global logger
func SetOutput(w io.Writer) { func SetOutput(w io.Writer) {
defaultLogger.SetOutput(w) GetLogger().SetOutput(w)
}
// TimeFormat returns the current time format of the global logger
func TimeFormat() string {
return GetLogger().TimeFormat()
}
// EnableDebug enables debug messages regardless of log level
func EnableDebug() {
GetLogger().EnableDebug()
}
// DisableDebug disables forced debug messages
func DisableDebug() {
GetLogger().DisableDebug()
}
// IsDebugEnabled returns true if debug mode is enabled
func IsDebugEnabled() bool {
return GetLogger().IsDebugEnabled()
} }

View File

@ -16,9 +16,9 @@ var (
) )
// GetWatcherManager returns the global watcher manager, creating it if needed // GetWatcherManager returns the global watcher manager, creating it if needed
func GetWatcherManager(log *logger.Logger, adaptive bool) *WatcherManager { func GetWatcherManager(adaptive bool) *WatcherManager {
globalManagerOnce.Do(func() { globalManagerOnce.Do(func() {
globalManager = NewWatcherManager(log, adaptive) globalManager = NewWatcherManager(adaptive)
}) })
return globalManager return globalManager
} }
@ -39,7 +39,7 @@ func WatchDirectory(config DirectoryWatcherConfig, manager *WatcherManager) (*Wa
manager: manager, manager: manager,
} }
config.Log.Debug("Started watching directory: %s", config.Dir) logger.Debug("Started watching directory: %s", config.Dir)
return w, nil return w, nil
} }
@ -58,12 +58,11 @@ func (w *Watcher) Close() error {
// WatchLuaRouter sets up a watcher for a LuaRouter's routes directory; also updates // WatchLuaRouter sets up a watcher for a LuaRouter's routes directory; also updates
// the LuaRunner so that the state can be rebuilt // the LuaRunner so that the state can be rebuilt
func WatchLuaRouter(router *routers.LuaRouter, runner *runner.LuaRunner, routesDir string, log *logger.Logger) (*Watcher, error) { func WatchLuaRouter(router *routers.LuaRouter, runner *runner.LuaRunner, routesDir string) (*Watcher, error) {
manager := GetWatcherManager(log, true) // Use adaptive polling manager := GetWatcherManager(true)
// Create LuaRunner refresh callback
runnerRefresh := func() error { runnerRefresh := func() error {
log.Debug("Refreshing LuaRunner state due to file change") logger.Debug("Refreshing LuaRunner state due to file change")
runner.NotifyFileChanged("") runner.NotifyFileChanged("")
return nil return nil
} }
@ -73,7 +72,6 @@ func WatchLuaRouter(router *routers.LuaRouter, runner *runner.LuaRunner, routesD
config := DirectoryWatcherConfig{ config := DirectoryWatcherConfig{
Dir: routesDir, Dir: routesDir,
Callback: combinedCallback, Callback: combinedCallback,
Log: log,
Recursive: true, Recursive: true,
} }
@ -82,18 +80,17 @@ func WatchLuaRouter(router *routers.LuaRouter, runner *runner.LuaRunner, routesD
return nil, err return nil, err
} }
log.Info("Started watching Lua routes directory: %s", routesDir) logger.Info("Started watching Lua routes directory: %s", routesDir)
return watcher, nil return watcher, nil
} }
// WatchStaticRouter sets up a watcher for a StaticRouter's root directory // WatchStaticRouter sets up a watcher for a StaticRouter's root directory
func WatchStaticRouter(router *routers.StaticRouter, staticDir string, log *logger.Logger) (*Watcher, error) { func WatchStaticRouter(router *routers.StaticRouter, staticDir string) (*Watcher, error) {
manager := GetWatcherManager(log, true) // Use adaptive polling manager := GetWatcherManager(true)
config := DirectoryWatcherConfig{ config := DirectoryWatcherConfig{
Dir: staticDir, Dir: staticDir,
Callback: router.Refresh, Callback: router.Refresh,
Log: log,
Recursive: true, Recursive: true,
} }
@ -102,13 +99,13 @@ func WatchStaticRouter(router *routers.StaticRouter, staticDir string, log *logg
return nil, err return nil, err
} }
log.Info("Started watching static files directory: %s", staticDir) logger.Info("Started watching static files directory: %s", staticDir)
return watcher, nil return watcher, nil
} }
// WatchLuaModules sets up watchers for Lua module directories // WatchLuaModules sets up watchers for Lua module directories
func WatchLuaModules(luaRunner *runner.LuaRunner, libDirs []string, log *logger.Logger) ([]*Watcher, error) { func WatchLuaModules(luaRunner *runner.LuaRunner, libDirs []string) ([]*Watcher, error) {
manager := GetWatcherManager(log, true) // Use adaptive polling manager := GetWatcherManager(true)
watchers := make([]*Watcher, 0, len(libDirs)) watchers := make([]*Watcher, 0, len(libDirs))
for _, dir := range libDirs { for _, dir := range libDirs {
@ -116,11 +113,11 @@ func WatchLuaModules(luaRunner *runner.LuaRunner, libDirs []string, log *logger.
dirCopy := dir // Capture for closure dirCopy := dir // Capture for closure
callback := func() error { callback := func() error {
log.Debug("Detected changes in Lua module directory: %s", dirCopy) logger.Debug("Detected changes in Lua module directory: %s", dirCopy)
// Reload modules from this directory // Reload modules from this directory
if err := luaRunner.ReloadAllModules(); err != nil { if err := luaRunner.ReloadAllModules(); err != nil {
log.Warning("Error reloading modules: %v", err) logger.Warning("Error reloading modules: %v", err)
} }
return nil return nil
@ -129,7 +126,6 @@ func WatchLuaModules(luaRunner *runner.LuaRunner, libDirs []string, log *logger.
config := DirectoryWatcherConfig{ config := DirectoryWatcherConfig{
Dir: dir, Dir: dir,
Callback: callback, Callback: callback,
Log: log,
Recursive: true, Recursive: true,
} }
@ -143,7 +139,7 @@ func WatchLuaModules(luaRunner *runner.LuaRunner, libDirs []string, log *logger.
} }
watchers = append(watchers, watcher) watchers = append(watchers, watcher)
log.Info("Started watching Lua modules directory: %s", dir) logger.Info("Started watching Lua modules directory: %s", dir)
} }
return watchers, nil return watchers, nil

View File

@ -31,7 +31,6 @@ type DirectoryWatcher struct {
// Configuration // Configuration
callback func() error callback func() error
log *logger.Logger
debounceTime time.Duration debounceTime time.Duration
recursive bool recursive bool
@ -49,9 +48,6 @@ type DirectoryWatcherConfig struct {
// Callback function to call when changes are detected // Callback function to call when changes are detected
Callback func() error Callback func() error
// Logger instance
Log *logger.Logger
// Debounce time (0 means use default) // Debounce time (0 means use default)
DebounceTime time.Duration DebounceTime time.Duration
@ -70,7 +66,6 @@ func NewDirectoryWatcher(config DirectoryWatcherConfig) (*DirectoryWatcher, erro
dir: config.Dir, dir: config.Dir,
files: make(map[string]FileInfo), files: make(map[string]FileInfo),
callback: config.Callback, callback: config.Callback,
log: config.Log,
debounceTime: debounceTime, debounceTime: debounceTime,
recursive: config.Recursive, recursive: config.Recursive,
} }
@ -217,15 +212,15 @@ func (w *DirectoryWatcher) notifyChange() {
// logDebug logs a debug message with the watcher's directory prefix // logDebug logs a debug message with the watcher's directory prefix
func (w *DirectoryWatcher) logDebug(format string, args ...any) { func (w *DirectoryWatcher) logDebug(format string, args ...any) {
w.log.Debug("[Watcher] [%s] %s", w.dir, fmt.Sprintf(format, args...)) logger.Debug("[Watcher] [%s] %s", w.dir, fmt.Sprintf(format, args...))
} }
// logWarning logs a warning message with the watcher's directory prefix // logWarning logs a warning message with the watcher's directory prefix
func (w *DirectoryWatcher) logWarning(format string, args ...any) { func (w *DirectoryWatcher) logWarning(format string, args ...any) {
w.log.Warning("[Watcher] [%s] %s", w.dir, fmt.Sprintf(format, args...)) logger.Warning("[Watcher] [%s] %s", w.dir, fmt.Sprintf(format, args...))
} }
// logError logs an error message with the watcher's directory prefix // logError logs an error message with the watcher's directory prefix
func (w *DirectoryWatcher) logError(format string, args ...any) { func (w *DirectoryWatcher) logError(format string, args ...any) {
w.log.Error("[Watcher] [%s] %s", w.dir, fmt.Sprintf(format, args...)) logger.Error("[Watcher] [%s] %s", w.dir, fmt.Sprintf(format, args...))
} }

View File

@ -29,22 +29,18 @@ type WatcherManager struct {
done chan struct{} done chan struct{}
ticker *time.Ticker ticker *time.Ticker
// Logger
log *logger.Logger
// Wait group for shutdown coordination // Wait group for shutdown coordination
wg sync.WaitGroup wg sync.WaitGroup
} }
// NewWatcherManager creates a new watcher manager // NewWatcherManager creates a new watcher manager
func NewWatcherManager(log *logger.Logger, adaptive bool) *WatcherManager { func NewWatcherManager(adaptive bool) *WatcherManager {
manager := &WatcherManager{ manager := &WatcherManager{
watchers: make(map[string]*DirectoryWatcher), watchers: make(map[string]*DirectoryWatcher),
pollInterval: defaultPollInterval, pollInterval: defaultPollInterval,
adaptive: adaptive, adaptive: adaptive,
lastActivity: time.Now(), lastActivity: time.Now(),
done: make(chan struct{}), done: make(chan struct{}),
log: log,
} }
// Start the polling loop // Start the polling loop
@ -71,7 +67,7 @@ func (m *WatcherManager) AddWatcher(watcher *DirectoryWatcher) {
defer m.mu.Unlock() defer m.mu.Unlock()
m.watchers[watcher.dir] = watcher m.watchers[watcher.dir] = watcher
m.log.Debug("[WatcherManager] Added watcher for directory: %s", watcher.dir) logger.Debug("[WatcherManager] Added watcher for directory: %s", watcher.dir)
} }
// RemoveWatcher unregisters a directory watcher // RemoveWatcher unregisters a directory watcher
@ -80,7 +76,7 @@ func (m *WatcherManager) RemoveWatcher(dir string) {
defer m.mu.Unlock() defer m.mu.Unlock()
delete(m.watchers, dir) delete(m.watchers, dir)
m.log.Debug("[WatcherManager] Removed watcher for directory: %s", dir) logger.Debug("[WatcherManager] Removed watcher for directory: %s", dir)
} }
// pollLoop is the main polling loop that checks all watched directories // pollLoop is the main polling loop that checks all watched directories
@ -100,7 +96,7 @@ func (m *WatcherManager) pollLoop() {
if m.pollInterval > defaultPollInterval { if m.pollInterval > defaultPollInterval {
m.pollInterval = defaultPollInterval m.pollInterval = defaultPollInterval
m.ticker.Reset(m.pollInterval) m.ticker.Reset(m.pollInterval)
m.log.Debug("[WatcherManager] Reset to base polling interval: %v", m.pollInterval) logger.Debug("[WatcherManager] Reset to base polling interval: %v", m.pollInterval)
} }
} else { } else {
// No activity, consider slowing down polling // No activity, consider slowing down polling
@ -108,7 +104,7 @@ func (m *WatcherManager) pollLoop() {
if m.pollInterval == defaultPollInterval && inactiveDuration > inactivityThreshold { if m.pollInterval == defaultPollInterval && inactiveDuration > inactivityThreshold {
m.pollInterval = extendedPollInterval m.pollInterval = extendedPollInterval
m.ticker.Reset(m.pollInterval) m.ticker.Reset(m.pollInterval)
m.log.Debug("[WatcherManager] Extended polling interval to: %v after %v of inactivity", logger.Debug("[WatcherManager] Extended polling interval to: %v after %v of inactivity",
m.pollInterval, inactiveDuration.Round(time.Minute)) m.pollInterval, inactiveDuration.Round(time.Minute))
} }
} }
@ -129,7 +125,7 @@ func (m *WatcherManager) checkAllDirectories() bool {
for _, watcher := range m.watchers { for _, watcher := range m.watchers {
changed, err := watcher.checkForChanges() changed, err := watcher.checkForChanges()
if err != nil { if err != nil {
m.log.Error("[WatcherManager] Error checking directory %s: %v", watcher.dir, err) logger.Error("[WatcherManager] Error checking directory %s: %v", watcher.dir, err)
continue continue
} }

View File

@ -26,7 +26,7 @@ type WatcherConfig struct {
} }
// initRouters sets up the Lua and static routers // initRouters sets up the Lua and static routers
func initRouters(routesDir, staticDir string, log *logger.Logger) (*routers.LuaRouter, *routers.StaticRouter, error) { func initRouters(routesDir, staticDir string) (*routers.LuaRouter, *routers.StaticRouter, error) {
// Ensure directories exist // Ensure directories exist
if err := utils.EnsureDir(routesDir); err != nil { if err := utils.EnsureDir(routesDir); err != nil {
return nil, nil, fmt.Errorf("routes directory doesn't exist, and could not create it: %v", err) return nil, nil, fmt.Errorf("routes directory doesn't exist, and could not create it: %v", err)
@ -41,12 +41,12 @@ func initRouters(routesDir, staticDir string, log *logger.Logger) (*routers.LuaR
// Check if this is a compilation warning or a more serious error // Check if this is a compilation warning or a more serious error
if errors.Is(err, routers.ErrRoutesCompilationErrors) { if errors.Is(err, routers.ErrRoutesCompilationErrors) {
// Some routes failed to compile, but router is still usable // Some routes failed to compile, but router is still usable
log.Warning("Some Lua routes failed to compile. Check logs for details.") logger.Warning("Some Lua routes failed to compile. Check logs for details.")
// Log details about each failed route // Log details about each failed route
if failedRoutes := luaRouter.ReportFailedRoutes(); len(failedRoutes) > 0 { if failedRoutes := luaRouter.ReportFailedRoutes(); len(failedRoutes) > 0 {
for _, re := range failedRoutes { for _, re := range failedRoutes {
log.Error("Route %s %s failed to compile: %v", re.Method, re.Path, re.Err) logger.Error("Route %s %s failed to compile: %v", re.Method, re.Path, re.Err)
} }
} }
} else { } else {
@ -54,14 +54,14 @@ func initRouters(routesDir, staticDir string, log *logger.Logger) (*routers.LuaR
return nil, nil, fmt.Errorf("failed to initialize Lua router: %v", err) return nil, nil, fmt.Errorf("failed to initialize Lua router: %v", err)
} }
} }
log.Info("Lua router initialized with routes from %s", routesDir) logger.Info("Lua router initialized with routes from %s", routesDir)
// Initialize static file router // Initialize static file router
staticRouter, err := routers.NewStaticRouterWithLogger(staticDir, log) staticRouter, err := routers.NewStaticRouter(staticDir)
if err != nil { if err != nil {
return nil, nil, fmt.Errorf("failed to initialize static router: %v", err) return nil, nil, fmt.Errorf("failed to initialize static router: %v", err)
} }
log.Info("Static router initialized with files from %s", staticDir) logger.Info("Static router initialized with files from %s", staticDir)
staticRouter.EnableDebugLog() staticRouter.EnableDebugLog()
return luaRouter, staticRouter, nil return luaRouter, staticRouter, nil
@ -70,15 +70,15 @@ func initRouters(routesDir, staticDir string, log *logger.Logger) (*routers.LuaR
// setupWatchers initializes and starts all file watchers // setupWatchers initializes and starts all file watchers
func setupWatchers(luaRouter *routers.LuaRouter, staticRouter *routers.StaticRouter, func setupWatchers(luaRouter *routers.LuaRouter, staticRouter *routers.StaticRouter,
luaRunner *runner.LuaRunner, routesDir string, staticDir string, luaRunner *runner.LuaRunner, routesDir string, staticDir string,
libDirs []string, log *logger.Logger, config WatcherConfig) ([]func() error, error) { libDirs []string, config WatcherConfig) ([]func() error, error) {
var cleanupFuncs []func() error var cleanupFuncs []func() error
// Set up watcher for Lua routes // Set up watcher for Lua routes
if config.Routes { if config.Routes {
luaRouterWatcher, err := watchers.WatchLuaRouter(luaRouter, luaRunner, routesDir, log) luaRouterWatcher, err := watchers.WatchLuaRouter(luaRouter, luaRunner, routesDir)
if err != nil { if err != nil {
log.Warning("Failed to watch routes directory: %v", err) logger.Warning("Failed to watch routes directory: %v", err)
} else { } else {
cleanupFuncs = append(cleanupFuncs, luaRouterWatcher.Close) cleanupFuncs = append(cleanupFuncs, luaRouterWatcher.Close)
} }
@ -86,9 +86,9 @@ func setupWatchers(luaRouter *routers.LuaRouter, staticRouter *routers.StaticRou
// Set up watcher for static files // Set up watcher for static files
if config.Static { if config.Static {
staticWatcher, err := watchers.WatchStaticRouter(staticRouter, staticDir, log) staticWatcher, err := watchers.WatchStaticRouter(staticRouter, staticDir)
if err != nil { if err != nil {
log.Warning("Failed to watch static directory: %v", err) logger.Warning("Failed to watch static directory: %v", err)
} else { } else {
cleanupFuncs = append(cleanupFuncs, staticWatcher.Close) cleanupFuncs = append(cleanupFuncs, staticWatcher.Close)
} }
@ -96,15 +96,15 @@ func setupWatchers(luaRouter *routers.LuaRouter, staticRouter *routers.StaticRou
// Set up watchers for Lua modules libraries // Set up watchers for Lua modules libraries
if config.Modules && len(libDirs) > 0 { if config.Modules && len(libDirs) > 0 {
moduleWatchers, err := watchers.WatchLuaModules(luaRunner, libDirs, log) moduleWatchers, err := watchers.WatchLuaModules(luaRunner, libDirs)
if err != nil { if err != nil {
log.Warning("Failed to watch Lua module directories: %v", err) logger.Warning("Failed to watch Lua module directories: %v", err)
} else { } else {
for _, watcher := range moduleWatchers { for _, watcher := range moduleWatchers {
w := watcher // Capture variable for closure w := watcher // Capture variable for closure
cleanupFuncs = append(cleanupFuncs, w.Close) cleanupFuncs = append(cleanupFuncs, w.Close)
} }
log.Info("File watchers active for %d Lua module directories", len(moduleWatchers)) logger.Info("File watchers active for %d Lua module directories", len(moduleWatchers))
} }
} }
@ -112,33 +112,38 @@ func setupWatchers(luaRouter *routers.LuaRouter, staticRouter *routers.StaticRou
} }
func main() { func main() {
// Initialize logger // Initialize global logger with debug level
log := logger.New(logger.LevelDebug, true) logger.InitGlobalLogger(logger.LevelDebug, true)
log.Server("Starting Moonshark server") logger.Server("Starting Moonshark server")
// Load configuration from config.lua // Load configuration from config.lua
cfg, err := config.Load("config.lua") cfg, err := config.Load("config.lua")
if err != nil { if err != nil {
log.Warning("Failed to load config.lua: %v", err) logger.Warning("Failed to load config.lua: %v", err)
log.Info("Using default configuration") logger.Info("Using default configuration")
cfg = config.New() cfg = config.New()
} }
// Set log level from config // Set log level from config
switch cfg.GetString("log_level", "info") { switch cfg.GetString("log_level", "info") {
case "debug":
log.SetLevel(logger.LevelDebug)
case "warn": case "warn":
log.SetLevel(logger.LevelWarning) logger.SetLevel(logger.LevelWarning)
case "error": case "error":
log.SetLevel(logger.LevelError) logger.SetLevel(logger.LevelError)
case "server": case "server":
log.SetLevel(logger.LevelServer) logger.SetLevel(logger.LevelServer)
case "fatal": case "fatal":
log.SetLevel(logger.LevelFatal) logger.SetLevel(logger.LevelFatal)
default: default:
log.SetLevel(logger.LevelInfo) logger.SetLevel(logger.LevelInfo)
}
// Get debug mode setting
debugMode := cfg.GetBool("debug", false)
if debugMode {
logger.EnableDebug() // Force debug logs regardless of level
logger.Debug("Debug mode enabled")
} }
// Get configuration values // Get configuration values
@ -149,7 +154,7 @@ func main() {
bufferSize := cfg.GetInt("buffer_size", 20) bufferSize := cfg.GetInt("buffer_size", 20)
if err := utils.EnsureDir(overrideDir); err != nil { if err := utils.EnsureDir(overrideDir); err != nil {
log.Warning("Override directory doesn't exist, and could not create it: %v", err) logger.Warning("Override directory doesn't exist, and could not create it: %v", err)
overrideDir = "" // Disable overrides if directory can't be created overrideDir = "" // Disable overrides if directory can't be created
} }
@ -166,14 +171,14 @@ func main() {
// Ensure lib directories exist // Ensure lib directories exist
for _, dir := range libDirs { for _, dir := range libDirs {
if err := utils.EnsureDir(dir); err != nil { if err := utils.EnsureDir(dir); err != nil {
log.Warning("Lib directory doesn't exist, and could not create it: %v", err) logger.Warning("Lib directory doesn't exist, and could not create it: %v", err)
} }
} }
// Initialize routers // Initialize routers
luaRouter, staticRouter, err := initRouters(routesDir, staticDir, log) luaRouter, staticRouter, err := initRouters(routesDir, staticDir)
if err != nil { if err != nil {
log.Fatal("Router initialization failed: %v", err) logger.Fatal("Router initialization failed: %v", err)
} }
// Initialize Lua runner // Initialize Lua runner
@ -183,9 +188,9 @@ func main() {
runner.WithDebugEnabled(), runner.WithDebugEnabled(),
) )
if err != nil { if err != nil {
log.Fatal("Failed to initialize Lua runner: %v", err) logger.Fatal("Failed to initialize Lua runner: %v", err)
} }
log.Server("Lua runner initialized with buffer size %d", bufferSize) logger.Server("Lua runner initialized with buffer size %d", bufferSize)
defer luaRunner.Close() defer luaRunner.Close()
// Set up file watchers if enabled // Set up file watchers if enabled
@ -214,31 +219,29 @@ func main() {
// Setup enabled watchers // Setup enabled watchers
cleanupFuncs, err = setupWatchers(luaRouter, staticRouter, luaRunner, cleanupFuncs, err = setupWatchers(luaRouter, staticRouter, luaRunner,
routesDir, staticDir, libDirs, log, watcherConfig) routesDir, staticDir, libDirs, watcherConfig)
if err != nil { if err != nil {
log.Warning("Error setting up watchers: %v", err) logger.Warning("Error setting up watchers: %v", err)
} }
// Register cleanup functions // Register cleanup functions
defer func() { defer func() {
for _, cleanup := range cleanupFuncs { for _, cleanup := range cleanupFuncs {
if err := cleanup(); err != nil { if err := cleanup(); err != nil {
log.Warning("Cleanup error: %v", err) logger.Warning("Cleanup error: %v", err)
} }
} }
}() }()
httpLoggingEnabled := cfg.GetBool("http_logging_enabled", true) httpLoggingEnabled := cfg.GetBool("http_logging_enabled", true)
if httpLoggingEnabled { if httpLoggingEnabled {
log.Info("HTTP logging is enabled") logger.Info("HTTP logging is enabled")
} else { } else {
log.Info("HTTP logging is disabled") logger.Info("HTTP logging is disabled")
} }
debugMode := cfg.GetBool("debug", false)
// Create HTTP server // Create HTTP server
server := http.New(luaRouter, staticRouter, luaRunner, log, httpLoggingEnabled, debugMode, overrideDir, cfg) server := http.New(luaRouter, staticRouter, luaRunner, httpLoggingEnabled, debugMode, overrideDir, cfg)
// Handle graceful shutdown // Handle graceful shutdown
stop := make(chan os.Signal, 1) stop := make(chan os.Signal, 1)
@ -248,24 +251,24 @@ func main() {
go func() { go func() {
if err := server.ListenAndServe(fmt.Sprintf(":%d", port)); err != nil { if err := server.ListenAndServe(fmt.Sprintf(":%d", port)); err != nil {
if err.Error() != "http: Server closed" { if err.Error() != "http: Server closed" {
log.Error("Server error: %v", err) logger.Error("Server error: %v", err)
} }
} }
}() }()
log.Server("Server started on port %d", port) logger.Server("Server started on port %d", port)
// Wait for interrupt signal // Wait for interrupt signal
<-stop <-stop
log.Server("Shutdown signal received") logger.Server("Shutdown signal received")
// Gracefully shut down the server // Gracefully shut down the server
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel() defer cancel()
if err := server.Shutdown(ctx); err != nil { if err := server.Shutdown(ctx); err != nil {
log.Error("Server shutdown error: %v", err) logger.Error("Server shutdown error: %v", err)
} }
log.Server("Server stopped") logger.Server("Server stopped")
} }