big logger update 1
This commit is contained in:
parent
b0dcdec6a5
commit
5bba4ffcf8
23
Moonshark.go
23
Moonshark.go
|
@ -77,8 +77,8 @@ func (s *Moonshark) loadConfig(configPath string) error {
|
||||||
// Load configuration from file
|
// Load configuration from file
|
||||||
s.Config, err = config.Load(configPath)
|
s.Config, err = config.Load(configPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Warning("Failed to load config file: %v", err)
|
logger.Warning("Wipeout! Couldn't load config file: %v", err)
|
||||||
logger.Info("Using default configuration")
|
logger.WarningCont("Rolling with the default setup")
|
||||||
s.Config = config.New()
|
s.Config = config.New()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -104,7 +104,7 @@ func (s *Moonshark) setupLogging() {
|
||||||
// Set debug mode if configured
|
// Set debug mode if configured
|
||||||
if s.Config.Debug {
|
if s.Config.Debug {
|
||||||
logger.EnableDebug() // Force debug logs regardless of level
|
logger.EnableDebug() // Force debug logs regardless of level
|
||||||
logger.Debug("Debug mode enabled")
|
logger.Debug("Debug mode is ready to party, bro")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -139,14 +139,14 @@ func (s *Moonshark) initRouters() error {
|
||||||
return fmt.Errorf("failed to initialize Lua router: %v", err)
|
return fmt.Errorf("failed to initialize Lua router: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
logger.Info("Lua router initialized with routes from %s", s.Config.RoutesDir)
|
logger.Info("Lua router is stoked and riding routes from %s", s.Config.RoutesDir)
|
||||||
|
|
||||||
// Initialize static file router
|
// Initialize static file router
|
||||||
s.StaticRouter, err = routers.NewStaticRouter(s.Config.StaticDir)
|
s.StaticRouter, err = routers.NewStaticRouter(s.Config.StaticDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to initialize static router: %v", err)
|
return fmt.Errorf("failed to initialize static router: %v", err)
|
||||||
}
|
}
|
||||||
logger.Info("Static router initialized with files from %s", s.Config.StaticDir)
|
logger.Info("Static router catching waves with files from %s", s.Config.StaticDir)
|
||||||
s.StaticRouter.EnableDebugLog()
|
s.StaticRouter.EnableDebugLog()
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -201,7 +201,7 @@ func (s *Moonshark) initRunner() error {
|
||||||
return fmt.Errorf("failed to initialize Lua runner: %v", err)
|
return fmt.Errorf("failed to initialize Lua runner: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Server("Lua runner initialized with pool size %d", s.Config.PoolSize)
|
logger.Server("Lua runner waxing up with a pool size of %d", s.Config.PoolSize)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -246,13 +246,13 @@ func (s *Moonshark) setupWatchers() error {
|
||||||
|
|
||||||
// Start starts the HTTP server
|
// Start starts the HTTP server
|
||||||
func (s *Moonshark) Start() error {
|
func (s *Moonshark) Start() error {
|
||||||
logger.Server("Starting server on port %d", s.Config.Port)
|
logger.Server("Surf's up on port %d!", s.Config.Port)
|
||||||
|
|
||||||
// Log HTTP logging status
|
// Log HTTP logging status
|
||||||
if s.Config.HTTPLoggingEnabled {
|
if s.Config.HTTPLoggingEnabled {
|
||||||
logger.Info("HTTP logging is enabled")
|
logger.ServerCont("HTTP logging is turned on - watch those waves")
|
||||||
} else {
|
} else {
|
||||||
logger.Info("HTTP logging is disabled")
|
logger.ServerCont("HTTP logging is turned off - waves are flat bro")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start the server in a non-blocking way
|
// Start the server in a non-blocking way
|
||||||
|
@ -271,7 +271,6 @@ func (s *Moonshark) Start() error {
|
||||||
func (s *Moonshark) Shutdown() error {
|
func (s *Moonshark) Shutdown() error {
|
||||||
logger.Server("Shutting down server...")
|
logger.Server("Shutting down server...")
|
||||||
|
|
||||||
// Shutdown HTTP server with timeout
|
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
|
@ -280,16 +279,14 @@ func (s *Moonshark) Shutdown() error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run cleanup functions
|
|
||||||
for _, cleanup := range s.cleanupFuncs {
|
for _, cleanup := range s.cleanupFuncs {
|
||||||
if err := cleanup(); err != nil {
|
if err := cleanup(); err != nil {
|
||||||
logger.Warning("Cleanup error: %v", err)
|
logger.Warning("Cleanup error: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close Lua runner
|
|
||||||
s.LuaRunner.Close()
|
s.LuaRunner.Close()
|
||||||
|
|
||||||
logger.Server("Server stopped")
|
logger.ServerCont("Server stopped")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,7 +76,7 @@ func Load(filePath string) (*Config, error) {
|
||||||
|
|
||||||
// Execute the config file
|
// Execute the config file
|
||||||
if err := state.DoFile(filePath); err != nil {
|
if err := state.DoFile(filePath); err != nil {
|
||||||
return nil, fmt.Errorf("failed to load config file: %w", err)
|
return nil, fmt.Errorf("%w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Extract configuration values
|
// Extract configuration values
|
||||||
|
|
|
@ -61,13 +61,12 @@ func New(luaRouter *routers.LuaRouter, staticRouter *routers.StaticRouter, runne
|
||||||
// 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
|
||||||
logger.Info("Server listening at http://localhost%s", addr)
|
logger.ServerCont("Catch the swell 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 {
|
||||||
logger.Info("Server shutting down...")
|
|
||||||
return s.httpServer.Shutdown(ctx)
|
return s.httpServer.Shutdown(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
@ -66,8 +67,12 @@ type Logger struct {
|
||||||
level int
|
level int
|
||||||
useColors bool
|
useColors bool
|
||||||
timeFormat string
|
timeFormat string
|
||||||
|
showTimestamp bool // Whether to show timestamp
|
||||||
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
|
debugMode atomic.Bool // Force debug logging regardless of level
|
||||||
|
indentCache string // Cached indent string for continuations
|
||||||
|
indentSize int // Size of the indent for continuations
|
||||||
|
lastLevel int // Last log level used, for continuations
|
||||||
|
|
||||||
// Simple rate limiting
|
// Simple rate limiting
|
||||||
logCount atomic.Int64 // Number of logs in current window
|
logCount atomic.Int64 // Number of logs in current window
|
||||||
|
@ -81,38 +86,42 @@ type Logger struct {
|
||||||
// GetLogger returns the global logger instance, creating it if needed
|
// GetLogger returns the global logger instance, creating it if needed
|
||||||
func GetLogger() *Logger {
|
func GetLogger() *Logger {
|
||||||
globalLoggerOnce.Do(func() {
|
globalLoggerOnce.Do(func() {
|
||||||
globalLogger = newLogger(LevelInfo, true)
|
globalLogger = newLogger(LevelInfo, true, true)
|
||||||
})
|
})
|
||||||
return globalLogger
|
return globalLogger
|
||||||
}
|
}
|
||||||
|
|
||||||
// InitGlobalLogger initializes the global logger with custom settings
|
// InitGlobalLogger initializes the global logger with custom settings
|
||||||
func InitGlobalLogger(minLevel int, useColors bool) {
|
func InitGlobalLogger(minLevel int, useColors bool, showTimestamp bool) {
|
||||||
globalLoggerOnce.Do(func() {
|
// Reset the global logger instance
|
||||||
globalLogger = newLogger(minLevel, useColors)
|
globalLogger = newLogger(minLevel, useColors, showTimestamp)
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// newLogger creates a new logger instance (internal use)
|
// newLogger creates a new logger instance (internal use)
|
||||||
func newLogger(minLevel int, useColors bool) *Logger {
|
func newLogger(minLevel int, useColors bool, showTimestamp bool) *Logger {
|
||||||
logger := &Logger{
|
logger := &Logger{
|
||||||
writer: os.Stdout,
|
writer: os.Stdout,
|
||||||
level: minLevel,
|
level: minLevel,
|
||||||
useColors: useColors,
|
useColors: useColors,
|
||||||
timeFormat: timeFormat,
|
timeFormat: timeFormat,
|
||||||
|
showTimestamp: showTimestamp,
|
||||||
maxLogsPerSec: defaultMaxLogs,
|
maxLogsPerSec: defaultMaxLogs,
|
||||||
limitDuration: defaultRateLimitTime,
|
limitDuration: defaultRateLimitTime,
|
||||||
|
lastLevel: -1, // Initialize to invalid level
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize counters
|
// Initialize counters
|
||||||
logger.resetCounters()
|
logger.resetCounters()
|
||||||
|
|
||||||
|
// Calculate the base indent size
|
||||||
|
logger.updateIndentCache()
|
||||||
|
|
||||||
return logger
|
return logger
|
||||||
}
|
}
|
||||||
|
|
||||||
// New creates a new logger (deprecated - use GetLogger() instead)
|
// New creates a new logger (deprecated - use GetLogger() instead)
|
||||||
func New(minLevel int, useColors bool) *Logger {
|
func New(minLevel int, useColors bool, showTimestamp bool) *Logger {
|
||||||
return newLogger(minLevel, useColors)
|
return newLogger(minLevel, useColors, showTimestamp)
|
||||||
}
|
}
|
||||||
|
|
||||||
// resetCounters resets the rate limiting counters
|
// resetCounters resets the rate limiting counters
|
||||||
|
@ -135,9 +144,47 @@ func (l *Logger) TimeFormat() string {
|
||||||
return l.timeFormat
|
return l.timeFormat
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetTimeFormat changes the time format string
|
// updateIndentCache recalculates and updates the indent cache
|
||||||
|
func (l *Logger) updateIndentCache() {
|
||||||
|
tagWidth := 7
|
||||||
|
|
||||||
|
if l.showTimestamp {
|
||||||
|
// Format: "15:04:05 DEBUG "
|
||||||
|
timeWidth := len(time.Now().Format(l.timeFormat))
|
||||||
|
l.indentSize = timeWidth + 1 + tagWidth + 1
|
||||||
|
} else {
|
||||||
|
// Format: "DEBUG "
|
||||||
|
l.indentSize = tagWidth + 1
|
||||||
|
}
|
||||||
|
|
||||||
|
l.indentCache = strings.Repeat(" ", l.indentSize)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetTimeFormat changes the time format string and updates the indent cache
|
||||||
func (l *Logger) SetTimeFormat(format string) {
|
func (l *Logger) SetTimeFormat(format string) {
|
||||||
|
l.mu.Lock()
|
||||||
|
defer l.mu.Unlock()
|
||||||
|
|
||||||
l.timeFormat = format
|
l.timeFormat = format
|
||||||
|
l.updateIndentCache()
|
||||||
|
}
|
||||||
|
|
||||||
|
// EnableTimestamp enables timestamp display
|
||||||
|
func (l *Logger) EnableTimestamp() {
|
||||||
|
l.mu.Lock()
|
||||||
|
defer l.mu.Unlock()
|
||||||
|
|
||||||
|
l.showTimestamp = true
|
||||||
|
l.updateIndentCache()
|
||||||
|
}
|
||||||
|
|
||||||
|
// DisableTimestamp disables timestamp display
|
||||||
|
func (l *Logger) DisableTimestamp() {
|
||||||
|
l.mu.Lock()
|
||||||
|
defer l.mu.Unlock()
|
||||||
|
|
||||||
|
l.showTimestamp = false
|
||||||
|
l.updateIndentCache()
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetLevel changes the minimum log level
|
// SetLevel changes the minimum log level
|
||||||
|
@ -171,24 +218,49 @@ func (l *Logger) IsDebugEnabled() bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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, continuation bool) {
|
||||||
var logLine string
|
var logLine string
|
||||||
|
|
||||||
if rawMode {
|
if rawMode {
|
||||||
// Raw mode - message is already formatted, just append newline
|
// Raw mode - message is already formatted, just append newline
|
||||||
logLine = message + "\n"
|
logLine = message + "\n"
|
||||||
|
} else if continuation {
|
||||||
|
// Continuation format - just indent and message
|
||||||
|
if l.useColors {
|
||||||
|
// For colored output, use the color of the last level
|
||||||
|
props := levelProps[l.lastLevel]
|
||||||
|
logLine = fmt.Sprintf("%s%s%s\n",
|
||||||
|
l.indentCache, props.color, message+colorReset)
|
||||||
} else {
|
} else {
|
||||||
// Standard format with timestamp, level tag, and message
|
logLine = fmt.Sprintf("%s%s\n", l.indentCache, message)
|
||||||
now := time.Now().Format(l.timeFormat)
|
}
|
||||||
|
} else {
|
||||||
|
// Standard format with level tag and optional timestamp
|
||||||
props := levelProps[level]
|
props := levelProps[level]
|
||||||
|
|
||||||
|
if l.showTimestamp {
|
||||||
|
now := time.Now().Format(l.timeFormat)
|
||||||
|
|
||||||
if l.useColors {
|
if l.useColors {
|
||||||
logLine = fmt.Sprintf("%s%s%s %s%s%s %s\n",
|
logLine = fmt.Sprintf("%s%s%s %s[%s]%s %s\n",
|
||||||
colorGray, now, colorReset, props.color, props.tag, colorReset, message)
|
colorGray, now, colorReset, props.color, props.tag, colorReset, message)
|
||||||
} else {
|
} else {
|
||||||
logLine = fmt.Sprintf("%s %s %s\n",
|
logLine = fmt.Sprintf("%s [%s] %s\n",
|
||||||
now, props.tag, message)
|
now, props.tag, message)
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
// No timestamp, just level tag and message
|
||||||
|
if l.useColors {
|
||||||
|
logLine = fmt.Sprintf("%s[%s]%s %s\n",
|
||||||
|
props.color, props.tag, colorReset, message)
|
||||||
|
} else {
|
||||||
|
logLine = fmt.Sprintf("[%s] %s\n",
|
||||||
|
props.tag, message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store the level for continuations
|
||||||
|
l.lastLevel = level
|
||||||
}
|
}
|
||||||
|
|
||||||
// Synchronously write the log message
|
// Synchronously write the log message
|
||||||
|
@ -249,7 +321,7 @@ func (l *Logger) checkRateLimit(level int) bool {
|
||||||
// Log a warning about rate limiting
|
// Log a warning about rate limiting
|
||||||
l.writeMessage(LevelServer,
|
l.writeMessage(LevelServer,
|
||||||
fmt.Sprintf("Rate limiting logger temporarily due to high demand (%d logs/sec exceeded)", count),
|
fmt.Sprintf("Rate limiting logger temporarily due to high demand (%d logs/sec exceeded)", count),
|
||||||
false)
|
false, false)
|
||||||
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
@ -278,7 +350,7 @@ func (l *Logger) log(level int, format string, args ...any) {
|
||||||
message = format
|
message = format
|
||||||
}
|
}
|
||||||
|
|
||||||
l.writeMessage(level, message, false)
|
l.writeMessage(level, message, false, false)
|
||||||
|
|
||||||
// Exit on fatal errors
|
// Exit on fatal errors
|
||||||
if level == LevelFatal {
|
if level == LevelFatal {
|
||||||
|
@ -286,6 +358,31 @@ func (l *Logger) log(level int, format string, args ...any) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// continuation handles continuation log messages (messages that continue from a previous log)
|
||||||
|
func (l *Logger) continuation(level int, format string, args ...any) {
|
||||||
|
// Check if we should log this message
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check rate limiting
|
||||||
|
if !l.checkRateLimit(level) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Format message
|
||||||
|
var message string
|
||||||
|
if len(args) > 0 {
|
||||||
|
message = fmt.Sprintf(format, args...)
|
||||||
|
} else {
|
||||||
|
message = format
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use the continuation format
|
||||||
|
l.writeMessage(level, message, false, true)
|
||||||
|
}
|
||||||
|
|
||||||
// LogRaw logs a message with raw formatting, bypassing the standard format
|
// LogRaw logs a message with raw formatting, bypassing the standard format
|
||||||
func (l *Logger) LogRaw(format string, args ...any) {
|
func (l *Logger) LogRaw(format string, args ...any) {
|
||||||
// Use info level for filtering
|
// Use info level for filtering
|
||||||
|
@ -311,7 +408,7 @@ func (l *Logger) LogRaw(format string, args ...any) {
|
||||||
message = removeAnsiColors(message)
|
message = removeAnsiColors(message)
|
||||||
}
|
}
|
||||||
|
|
||||||
l.writeMessage(LevelInfo, message, true)
|
l.writeMessage(LevelInfo, message, true, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Simple helper to remove ANSI color codes
|
// Simple helper to remove ANSI color codes
|
||||||
|
@ -343,32 +440,63 @@ func (l *Logger) Debug(format string, args ...any) {
|
||||||
l.log(LevelDebug, format, args...)
|
l.log(LevelDebug, format, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DebugCont logs a debug message as a continuation of the previous log
|
||||||
|
func (l *Logger) DebugCont(format string, args ...any) {
|
||||||
|
l.continuation(LevelDebug, format, args...)
|
||||||
|
}
|
||||||
|
|
||||||
// Info logs an informational message
|
// Info logs an informational message
|
||||||
func (l *Logger) Info(format string, args ...any) {
|
func (l *Logger) Info(format string, args ...any) {
|
||||||
l.log(LevelInfo, format, args...)
|
l.log(LevelInfo, format, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// InfoCont logs an informational message as a continuation of the previous log
|
||||||
|
func (l *Logger) InfoCont(format string, args ...any) {
|
||||||
|
l.continuation(LevelInfo, format, args...)
|
||||||
|
}
|
||||||
|
|
||||||
// Warning logs a warning message
|
// Warning logs a warning message
|
||||||
func (l *Logger) Warning(format string, args ...any) {
|
func (l *Logger) Warning(format string, args ...any) {
|
||||||
l.log(LevelWarning, format, args...)
|
l.log(LevelWarning, format, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WarningCont logs a warning message as a continuation of the previous log
|
||||||
|
func (l *Logger) WarningCont(format string, args ...any) {
|
||||||
|
l.continuation(LevelWarning, format, args...)
|
||||||
|
}
|
||||||
|
|
||||||
// Error logs an error message
|
// Error logs an error message
|
||||||
func (l *Logger) Error(format string, args ...any) {
|
func (l *Logger) Error(format string, args ...any) {
|
||||||
l.log(LevelError, format, args...)
|
l.log(LevelError, format, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ErrorCont logs an error message as a continuation of the previous log
|
||||||
|
func (l *Logger) ErrorCont(format string, args ...any) {
|
||||||
|
l.continuation(LevelError, format, args...)
|
||||||
|
}
|
||||||
|
|
||||||
// Fatal logs a fatal error message and exits
|
// Fatal logs a fatal error message and exits
|
||||||
func (l *Logger) Fatal(format string, args ...any) {
|
func (l *Logger) Fatal(format string, args ...any) {
|
||||||
l.log(LevelFatal, format, args...)
|
l.log(LevelFatal, format, args...)
|
||||||
// No need for os.Exit here as it's handled in log()
|
// No need for os.Exit here as it's handled in log()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FatalCont logs a fatal error message as a continuation of the previous log and exits
|
||||||
|
func (l *Logger) FatalCont(format string, args ...any) {
|
||||||
|
l.continuation(LevelFatal, format, args...)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
// Server logs a server message
|
// Server logs a server message
|
||||||
func (l *Logger) Server(format string, args ...any) {
|
func (l *Logger) Server(format string, args ...any) {
|
||||||
l.log(LevelServer, format, args...)
|
l.log(LevelServer, format, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ServerCont logs a server message as a continuation of the previous log
|
||||||
|
func (l *Logger) ServerCont(format string, args ...any) {
|
||||||
|
l.continuation(LevelServer, format, args...)
|
||||||
|
}
|
||||||
|
|
||||||
// Global helper functions that use the global logger
|
// Global helper functions that use the global logger
|
||||||
|
|
||||||
// Debug logs a debug message to the global logger
|
// Debug logs a debug message to the global logger
|
||||||
|
@ -376,31 +504,61 @@ func Debug(format string, args ...any) {
|
||||||
GetLogger().Debug(format, args...)
|
GetLogger().Debug(format, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DebugCont logs a debug message as a continuation of the previous log to the global logger
|
||||||
|
func DebugCont(format string, args ...any) {
|
||||||
|
GetLogger().DebugCont(format, args...)
|
||||||
|
}
|
||||||
|
|
||||||
// Info logs an informational message to the global logger
|
// Info logs an informational message to the global logger
|
||||||
func Info(format string, args ...any) {
|
func Info(format string, args ...any) {
|
||||||
GetLogger().Info(format, args...)
|
GetLogger().Info(format, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// InfoCont logs an informational message as a continuation of the previous log to the global logger
|
||||||
|
func InfoCont(format string, args ...any) {
|
||||||
|
GetLogger().InfoCont(format, args...)
|
||||||
|
}
|
||||||
|
|
||||||
// Warning logs a warning message to the global logger
|
// Warning logs a warning message to the global logger
|
||||||
func Warning(format string, args ...any) {
|
func Warning(format string, args ...any) {
|
||||||
GetLogger().Warning(format, args...)
|
GetLogger().Warning(format, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WarningCont logs a warning message as a continuation of the previous log to the global logger
|
||||||
|
func WarningCont(format string, args ...any) {
|
||||||
|
GetLogger().WarningCont(format, args...)
|
||||||
|
}
|
||||||
|
|
||||||
// Error logs an error message to the global logger
|
// Error logs an error message to the global logger
|
||||||
func Error(format string, args ...any) {
|
func Error(format string, args ...any) {
|
||||||
GetLogger().Error(format, args...)
|
GetLogger().Error(format, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ErrorCont logs an error message as a continuation of the previous log to the global logger
|
||||||
|
func ErrorCont(format string, args ...any) {
|
||||||
|
GetLogger().ErrorCont(format, args...)
|
||||||
|
}
|
||||||
|
|
||||||
// Fatal logs a fatal error message to the global 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) {
|
||||||
GetLogger().Fatal(format, args...)
|
GetLogger().Fatal(format, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FatalCont logs a fatal error message as a continuation of the previous log to the global logger and exits
|
||||||
|
func FatalCont(format string, args ...any) {
|
||||||
|
GetLogger().FatalCont(format, args...)
|
||||||
|
}
|
||||||
|
|
||||||
// Server logs a server message to the global logger
|
// Server logs a server message to the global logger
|
||||||
func Server(format string, args ...any) {
|
func Server(format string, args ...any) {
|
||||||
GetLogger().Server(format, args...)
|
GetLogger().Server(format, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ServerCont logs a server message as a continuation of the previous log to the global logger
|
||||||
|
func ServerCont(format string, args ...any) {
|
||||||
|
GetLogger().ServerCont(format, args...)
|
||||||
|
}
|
||||||
|
|
||||||
// LogRaw logs a raw message to the global logger
|
// LogRaw logs a raw message to the global logger
|
||||||
func LogRaw(format string, args ...any) {
|
func LogRaw(format string, args ...any) {
|
||||||
GetLogger().LogRaw(format, args...)
|
GetLogger().LogRaw(format, args...)
|
||||||
|
@ -435,3 +593,57 @@ func DisableDebug() {
|
||||||
func IsDebugEnabled() bool {
|
func IsDebugEnabled() bool {
|
||||||
return GetLogger().IsDebugEnabled()
|
return GetLogger().IsDebugEnabled()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// EnableTimestamp enables timestamp display
|
||||||
|
func EnableTimestamp() {
|
||||||
|
GetLogger().EnableTimestamp()
|
||||||
|
}
|
||||||
|
|
||||||
|
// DisableTimestamp disables timestamp display
|
||||||
|
func DisableTimestamp() {
|
||||||
|
GetLogger().DisableTimestamp()
|
||||||
|
}
|
||||||
|
|
||||||
|
// LogSpacer adds a horizontal line separator to the log output
|
||||||
|
func (l *Logger) LogSpacer() {
|
||||||
|
l.mu.Lock()
|
||||||
|
defer l.mu.Unlock()
|
||||||
|
|
||||||
|
// Calculate spacer width
|
||||||
|
tagWidth := 7 // Standard width of tag area "[DEBUG]"
|
||||||
|
|
||||||
|
var spacer string
|
||||||
|
if l.showTimestamp {
|
||||||
|
// Format: "15:04:05 [DEBUG] ----"
|
||||||
|
timeWidth := len(time.Now().Format(l.timeFormat))
|
||||||
|
tagSpacer := strings.Repeat("-", tagWidth)
|
||||||
|
restSpacer := strings.Repeat("-", 20) // Fixed width for the rest
|
||||||
|
|
||||||
|
if l.useColors {
|
||||||
|
spacer = fmt.Sprintf("%s%s%s %s%s%s %s\n",
|
||||||
|
colorGray, strings.Repeat("-", timeWidth), colorReset,
|
||||||
|
colorCyan, tagSpacer, colorReset, restSpacer)
|
||||||
|
} else {
|
||||||
|
spacer = fmt.Sprintf("%s %s %s\n",
|
||||||
|
strings.Repeat("-", timeWidth), tagSpacer, restSpacer)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// No timestamp: "[DEBUG] ----"
|
||||||
|
tagSpacer := strings.Repeat("-", tagWidth)
|
||||||
|
restSpacer := strings.Repeat("-", 20) // Fixed width for the rest
|
||||||
|
|
||||||
|
if l.useColors {
|
||||||
|
spacer = fmt.Sprintf("%s%s%s %s\n",
|
||||||
|
colorCyan, tagSpacer, colorReset, restSpacer)
|
||||||
|
} else {
|
||||||
|
spacer = fmt.Sprintf("%s %s\n", tagSpacer, restSpacer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_, _ = fmt.Fprint(l.writer, spacer)
|
||||||
|
}
|
||||||
|
|
||||||
|
// LogSpacer adds a horizontal line separator to the global logger
|
||||||
|
func LogSpacer() {
|
||||||
|
GetLogger().LogSpacer()
|
||||||
|
}
|
||||||
|
|
|
@ -244,7 +244,7 @@ func (r *LuaRouter) matchPath(current *node, segments []string, params *Params,
|
||||||
}
|
}
|
||||||
|
|
||||||
// compileHandler compiles a Lua file to bytecode
|
// compileHandler compiles a Lua file to bytecode
|
||||||
func (r *LuaRouter) compileHandler(n *node, urlPath string) error {
|
func (r *LuaRouter) compileHandler(n *node, _ string) error {
|
||||||
if n.handler == "" {
|
if n.handler == "" {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,16 +44,10 @@ type StaticRouter struct {
|
||||||
bufferPool sync.Pool // Buffer pool for compression
|
bufferPool sync.Pool // Buffer pool for compression
|
||||||
urlPrefix string // URL prefix for static assets
|
urlPrefix string // URL prefix for static assets
|
||||||
log bool // Whether to log debug info
|
log bool // Whether to log debug info
|
||||||
logger *logger.Logger // Logger instance
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewStaticRouter creates a new StaticRouter instance
|
// NewStaticRouterWithLogger creates a new StaticRouter instance
|
||||||
func NewStaticRouter(rootDir string) (*StaticRouter, error) {
|
func NewStaticRouter(rootDir string) (*StaticRouter, error) {
|
||||||
return NewStaticRouterWithLogger(rootDir, logger.New(logger.LevelInfo, true))
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewStaticRouterWithLogger creates a new StaticRouter instance with a custom logger
|
|
||||||
func NewStaticRouterWithLogger(rootDir string, log *logger.Logger) (*StaticRouter, error) {
|
|
||||||
// Verify root directory exists
|
// Verify root directory exists
|
||||||
info, err := os.Stat(rootDir)
|
info, err := os.Stat(rootDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -74,7 +68,6 @@ func NewStaticRouterWithLogger(rootDir string, log *logger.Logger) (*StaticRoute
|
||||||
fileServer: http.FileServer(http.Dir(rootDir)),
|
fileServer: http.FileServer(http.Dir(rootDir)),
|
||||||
urlPrefix: "/static", // Default prefix for static assets
|
urlPrefix: "/static", // Default prefix for static assets
|
||||||
log: false, // Debug logging off by default
|
log: false, // Debug logging off by default
|
||||||
logger: log,
|
|
||||||
bufferPool: sync.Pool{
|
bufferPool: sync.Pool{
|
||||||
New: func() any {
|
New: func() any {
|
||||||
return new(bytes.Buffer)
|
return new(bytes.Buffer)
|
||||||
|
@ -177,13 +170,13 @@ func (r *StaticRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||||
// Try to serve from cache if client accepts gzip
|
// Try to serve from cache if client accepts gzip
|
||||||
if acceptsGzip && r.serveFromCache(w, &newReq, fileURLPath) {
|
if acceptsGzip && r.serveFromCache(w, &newReq, fileURLPath) {
|
||||||
if r.log {
|
if r.log {
|
||||||
r.logger.Debug("[StaticRouter] CACHE HIT: %s", origPath)
|
logger.Debug("[StaticRouter] CACHE HIT: %s", origPath)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if r.log {
|
if r.log {
|
||||||
r.logger.Debug("[StaticRouter] CACHE MISS: %s", origPath)
|
logger.Debug("[StaticRouter] CACHE MISS: %s", origPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fall back to standard file serving
|
// Fall back to standard file serving
|
||||||
|
@ -238,7 +231,7 @@ func (r *StaticRouter) Match(urlPath string) (string, bool) {
|
||||||
_, err := os.Stat(filePath)
|
_, err := os.Stat(filePath)
|
||||||
|
|
||||||
if r.log && err == nil {
|
if r.log && err == nil {
|
||||||
r.logger.Debug("[StaticRouter] MATCH: %s -> %s", urlPath, filePath)
|
logger.Debug("[StaticRouter] MATCH: %s -> %s", urlPath, filePath)
|
||||||
}
|
}
|
||||||
|
|
||||||
return filePath, err == nil
|
return filePath, err == nil
|
||||||
|
@ -443,7 +436,7 @@ func (r *StaticRouter) PreloadCommonFiles() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if r.log {
|
if r.log {
|
||||||
r.logger.Debug("[StaticRouter] Preloading common files from %s", r.rootDir)
|
logger.Debug("[StaticRouter] Preloading common files from %s", r.rootDir)
|
||||||
}
|
}
|
||||||
|
|
||||||
count := 0
|
count := 0
|
||||||
|
@ -477,7 +470,7 @@ func (r *StaticRouter) PreloadCommonFiles() {
|
||||||
})
|
})
|
||||||
|
|
||||||
if r.log {
|
if r.log {
|
||||||
r.logger.Debug("[StaticRouter] Preloaded %d files", count)
|
logger.Debug("[StaticRouter] Preloaded %d files", count)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -41,7 +41,14 @@ func (r *CoreModuleRegistry) EnableDebug() {
|
||||||
// debugLog prints debug messages if enabled
|
// debugLog prints debug messages if enabled
|
||||||
func (r *CoreModuleRegistry) debugLog(format string, args ...interface{}) {
|
func (r *CoreModuleRegistry) debugLog(format string, args ...interface{}) {
|
||||||
if r.debug {
|
if r.debug {
|
||||||
logger.Debug("[CoreModuleRegistry] "+format, args...)
|
logger.Debug("CoreRegistry "+format, args...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// debugLogCont prints continuation debug messages if enabled
|
||||||
|
func (r *CoreModuleRegistry) debugLogCont(format string, args ...interface{}) {
|
||||||
|
if r.debug {
|
||||||
|
logger.DebugCont(format, args...)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,13 +62,12 @@ func (r *CoreModuleRegistry) Register(name string, initFunc StateInitFunc) {
|
||||||
// Add to initialization order if not already there
|
// Add to initialization order if not already there
|
||||||
for _, n := range r.initOrder {
|
for _, n := range r.initOrder {
|
||||||
if n == name {
|
if n == name {
|
||||||
r.debugLog("Module already in init order: %s", name)
|
return // Already registered, silently continue
|
||||||
return
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
r.initOrder = append(r.initOrder, name)
|
r.initOrder = append(r.initOrder, name)
|
||||||
r.debugLog("Registered module: %s", name)
|
r.debugLog("registered module %s", name)
|
||||||
}
|
}
|
||||||
|
|
||||||
// RegisterWithDependencies registers a module with explicit dependencies
|
// RegisterWithDependencies registers a module with explicit dependencies
|
||||||
|
@ -75,13 +81,15 @@ func (r *CoreModuleRegistry) RegisterWithDependencies(name string, initFunc Stat
|
||||||
// Add to initialization order if not already there
|
// Add to initialization order if not already there
|
||||||
for _, n := range r.initOrder {
|
for _, n := range r.initOrder {
|
||||||
if n == name {
|
if n == name {
|
||||||
r.debugLog("Module already in init order: %s", name)
|
return // Already registered, silently continue
|
||||||
return
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
r.initOrder = append(r.initOrder, name)
|
r.initOrder = append(r.initOrder, name)
|
||||||
r.debugLog("Registered module %s with dependencies: %v", name, dependencies)
|
r.debugLog("registered module %s", name)
|
||||||
|
if len(dependencies) > 0 {
|
||||||
|
r.debugLogCont("Dependencies: %v", dependencies)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetInitOrder sets explicit initialization order
|
// SetInitOrder sets explicit initialization order
|
||||||
|
@ -131,28 +139,34 @@ func (r *CoreModuleRegistry) SetInitOrder(order []string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize initializes all registered modules
|
// Initialize initializes all registered modules
|
||||||
func (r *CoreModuleRegistry) Initialize(state *luajit.State) error {
|
func (r *CoreModuleRegistry) Initialize(state *luajit.State, stateIndex int) error {
|
||||||
r.mu.RLock()
|
r.mu.RLock()
|
||||||
defer r.mu.RUnlock()
|
defer r.mu.RUnlock()
|
||||||
|
|
||||||
r.debugLog("Initializing all modules...")
|
verbose := stateIndex == 0
|
||||||
|
if verbose {
|
||||||
|
r.debugLog("initializing %d modules...", len(r.initOrder))
|
||||||
|
}
|
||||||
|
|
||||||
// Clear initialization flags
|
// Clear initialization flags
|
||||||
r.initializedFlag = make(map[string]bool)
|
r.initializedFlag = make(map[string]bool)
|
||||||
|
|
||||||
// Initialize modules in order, respecting dependencies
|
// Initialize modules in order, respecting dependencies
|
||||||
for _, name := range r.initOrder {
|
for _, name := range r.initOrder {
|
||||||
if err := r.initializeModule(state, name, []string{}); err != nil {
|
if err := r.initializeModule(state, name, []string{}, verbose); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
r.debugLog("All modules initialized successfully")
|
if verbose {
|
||||||
|
r.debugLogCont("All modules initialized successfully")
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// initializeModule initializes a module and its dependencies
|
// initializeModule initializes a module and its dependencies
|
||||||
func (r *CoreModuleRegistry) initializeModule(state *luajit.State, name string, initStack []string) error {
|
func (r *CoreModuleRegistry) initializeModule(state *luajit.State, name string,
|
||||||
|
initStack []string, verbose bool) error {
|
||||||
// Check if already initialized
|
// Check if already initialized
|
||||||
if r.initializedFlag[name] {
|
if r.initializedFlag[name] {
|
||||||
return nil
|
return nil
|
||||||
|
@ -177,22 +191,24 @@ func (r *CoreModuleRegistry) initializeModule(state *luajit.State, name string,
|
||||||
if len(deps) > 0 {
|
if len(deps) > 0 {
|
||||||
newStack := append(initStack, name)
|
newStack := append(initStack, name)
|
||||||
for _, dep := range deps {
|
for _, dep := range deps {
|
||||||
if err := r.initializeModule(state, dep, newStack); err != nil {
|
if err := r.initializeModule(state, dep, newStack, verbose); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize this module
|
err := initFunc(state)
|
||||||
r.debugLog("Initializing module: %s", name)
|
if err != nil {
|
||||||
if err := initFunc(state); err != nil {
|
// Always log failures regardless of verbose setting
|
||||||
r.debugLog("Failed to initialize module %s: %v", name, err)
|
r.debugLogCont("Initializing module %s... failure: %v", name, err)
|
||||||
return fmt.Errorf("failed to initialize module %s: %w", name, err)
|
return fmt.Errorf("failed to initialize module %s: %w", name, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mark as initialized
|
|
||||||
r.initializedFlag[name] = true
|
r.initializedFlag[name] = true
|
||||||
r.debugLog("Module %s initialized successfully", name)
|
|
||||||
|
if verbose {
|
||||||
|
r.debugLogCont("Initializing module %s... success", name)
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -205,7 +221,8 @@ func (r *CoreModuleRegistry) InitializeModule(state *luajit.State, name string)
|
||||||
// Clear initialization flag for this module
|
// Clear initialization flag for this module
|
||||||
r.initializedFlag[name] = false
|
r.initializedFlag[name] = false
|
||||||
|
|
||||||
return r.initializeModule(state, name, []string{})
|
// Always use verbose logging for explicit module initialization
|
||||||
|
return r.initializeModule(state, name, []string{}, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ModuleNames returns a list of all registered module names
|
// ModuleNames returns a list of all registered module names
|
||||||
|
@ -246,16 +263,11 @@ var GlobalRegistry = NewCoreModuleRegistry()
|
||||||
// Initialize global registry with core modules
|
// Initialize global registry with core modules
|
||||||
func init() {
|
func init() {
|
||||||
GlobalRegistry.EnableDebug() // Enable debugging by default
|
GlobalRegistry.EnableDebug() // Enable debugging by default
|
||||||
|
logger.Debug("[ModuleRegistry] Registering core modules...")
|
||||||
|
|
||||||
GlobalRegistry.Register("go", GoModuleInitFunc())
|
GlobalRegistry.Register("go", GoModuleInitFunc())
|
||||||
|
|
||||||
// Register HTTP module (no dependencies)
|
|
||||||
GlobalRegistry.Register("http", HTTPModuleInitFunc())
|
GlobalRegistry.Register("http", HTTPModuleInitFunc())
|
||||||
|
|
||||||
// Register cookie module (depends on http)
|
|
||||||
GlobalRegistry.RegisterWithDependencies("cookie", CookieModuleInitFunc(), []string{"http"})
|
GlobalRegistry.RegisterWithDependencies("cookie", CookieModuleInitFunc(), []string{"http"})
|
||||||
|
|
||||||
// Register CSRF module (depends on go)
|
|
||||||
GlobalRegistry.RegisterWithDependencies("csrf", CSRFModuleInitFunc(), []string{"go"})
|
GlobalRegistry.RegisterWithDependencies("csrf", CSRFModuleInitFunc(), []string{"go"})
|
||||||
|
|
||||||
// Set explicit initialization order
|
// Set explicit initialization order
|
||||||
|
@ -266,7 +278,7 @@ func init() {
|
||||||
"csrf", // Fourth: CSRF protection (uses go and possibly session)
|
"csrf", // Fourth: CSRF protection (uses go and possibly session)
|
||||||
})
|
})
|
||||||
|
|
||||||
logger.Debug("[CoreModuleRegistry] Core modules registered in init()")
|
logger.DebugCont("Core modules registered successfully")
|
||||||
}
|
}
|
||||||
|
|
||||||
// RegisterCoreModule is a helper to register a core module with the global registry
|
// RegisterCoreModule is a helper to register a core module with the global registry
|
||||||
|
|
|
@ -371,7 +371,8 @@ func HTTPModuleInitFunc() StateInitFunc {
|
||||||
// CRITICAL: Register the native Go function first
|
// CRITICAL: Register the native Go function first
|
||||||
// This must be done BEFORE any Lua code that references it
|
// This must be done BEFORE any Lua code that references it
|
||||||
if err := state.RegisterGoFunction(httpRequestFuncName, httpRequest); err != nil {
|
if err := state.RegisterGoFunction(httpRequestFuncName, httpRequest); err != nil {
|
||||||
logger.Error("[HTTP Module] Failed to register __http_request function: %v\n", err)
|
logger.Error("[HTTP Module] Failed to register __http_request function")
|
||||||
|
logger.ErrorCont("%v", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -380,7 +381,8 @@ func HTTPModuleInitFunc() StateInitFunc {
|
||||||
|
|
||||||
// Initialize Lua HTTP module
|
// Initialize Lua HTTP module
|
||||||
if err := state.DoString(LuaHTTPModule); err != nil {
|
if err := state.DoString(LuaHTTPModule); err != nil {
|
||||||
logger.Error("[HTTP Module] Failed to initialize HTTP module Lua code: %v\n", err)
|
logger.Error("[HTTP Module] Failed to initialize HTTP module Lua code")
|
||||||
|
logger.ErrorCont("%v", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -510,14 +512,14 @@ func verifyHTTPClient(state *luajit.State) {
|
||||||
// Get the client table
|
// Get the client table
|
||||||
state.GetGlobal("http")
|
state.GetGlobal("http")
|
||||||
if !state.IsTable(-1) {
|
if !state.IsTable(-1) {
|
||||||
logger.Warning("[HTTP Module] 'http' is not a table\n")
|
logger.Warning("[HTTP Module] 'http' is not a table")
|
||||||
state.Pop(1)
|
state.Pop(1)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
state.GetField(-1, "client")
|
state.GetField(-1, "client")
|
||||||
if !state.IsTable(-1) {
|
if !state.IsTable(-1) {
|
||||||
logger.Warning("[HTTP Module] 'http.client' is not a table\n")
|
logger.Warning("[HTTP Module] 'http.client' is not a table")
|
||||||
state.Pop(2)
|
state.Pop(2)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -525,18 +527,14 @@ func verifyHTTPClient(state *luajit.State) {
|
||||||
// Check for get function
|
// Check for get function
|
||||||
state.GetField(-1, "get")
|
state.GetField(-1, "get")
|
||||||
if !state.IsFunction(-1) {
|
if !state.IsFunction(-1) {
|
||||||
logger.Warning("[HTTP Module] 'http.client.get' is not a function\n")
|
logger.Warning("[HTTP Module] 'http.client.get' is not a function")
|
||||||
} else {
|
|
||||||
logger.Debug("[HTTP Module] 'http.client.get' is properly registered\n")
|
|
||||||
}
|
}
|
||||||
state.Pop(1)
|
state.Pop(1)
|
||||||
|
|
||||||
// Check for the request function
|
// Check for the request function
|
||||||
state.GetField(-1, "request")
|
state.GetField(-1, "request")
|
||||||
if !state.IsFunction(-1) {
|
if !state.IsFunction(-1) {
|
||||||
logger.Warning("[HTTP Module] 'http.client.request' is not a function\n")
|
logger.Warning("[HTTP Module] 'http.client.request' is not a function")
|
||||||
} else {
|
|
||||||
logger.Debug("[HTTP Module] 'http.client.request' is properly registered\n")
|
|
||||||
}
|
}
|
||||||
state.Pop(3) // Pop request, client, http
|
state.Pop(3) // Pop request, client, http
|
||||||
}
|
}
|
||||||
|
|
|
@ -137,15 +137,21 @@ func NewRunner(options ...RunnerOption) (*Runner, error) {
|
||||||
// debugLog logs a message if debug mode is enabled
|
// debugLog logs a message if debug mode is enabled
|
||||||
func (r *Runner) debugLog(format string, args ...interface{}) {
|
func (r *Runner) debugLog(format string, args ...interface{}) {
|
||||||
if r.debug {
|
if r.debug {
|
||||||
logger.Debug("[Runner] "+format, args...)
|
logger.Debug("Runner "+format, args...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Runner) debugLogCont(format string, args ...interface{}) {
|
||||||
|
if r.debug {
|
||||||
|
logger.DebugCont(format, args...)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// initializeStates creates and initializes all states in the pool
|
// initializeStates creates and initializes all states in the pool
|
||||||
func (r *Runner) initializeStates() error {
|
func (r *Runner) initializeStates() error {
|
||||||
r.debugLog("Initializing %d Lua states", r.poolSize)
|
r.debugLog("is initializing %d states", r.poolSize)
|
||||||
|
|
||||||
// Create main template state first
|
// Create main template state first with full logging
|
||||||
templateState, err := r.createState(0)
|
templateState, err := r.createState(0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -154,7 +160,8 @@ func (r *Runner) initializeStates() error {
|
||||||
r.states[0] = templateState
|
r.states[0] = templateState
|
||||||
r.statePool <- 0 // Add index to the pool
|
r.statePool <- 0 // Add index to the pool
|
||||||
|
|
||||||
// Create remaining states
|
// Create remaining states with minimal logging
|
||||||
|
successCount := 1
|
||||||
for i := 1; i < r.poolSize; i++ {
|
for i := 1; i < r.poolSize; i++ {
|
||||||
state, err := r.createState(i)
|
state, err := r.createState(i)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -163,15 +170,19 @@ func (r *Runner) initializeStates() error {
|
||||||
|
|
||||||
r.states[i] = state
|
r.states[i] = state
|
||||||
r.statePool <- i // Add index to the pool
|
r.statePool <- i // Add index to the pool
|
||||||
|
successCount++
|
||||||
}
|
}
|
||||||
|
|
||||||
r.debugLog("All %d Lua states initialized successfully", r.poolSize)
|
r.debugLog("has built %d/%d states successfully", successCount, r.poolSize)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// createState initializes a new Lua state
|
// createState initializes a new Lua state
|
||||||
func (r *Runner) createState(index int) (*State, error) {
|
func (r *Runner) createState(index int) (*State, error) {
|
||||||
|
verbose := index == 0
|
||||||
|
if verbose {
|
||||||
r.debugLog("Creating Lua state %d", index)
|
r.debugLog("Creating Lua state %d", index)
|
||||||
|
}
|
||||||
|
|
||||||
// Create a new state
|
// Create a new state
|
||||||
L := luajit.New()
|
L := luajit.New()
|
||||||
|
@ -181,29 +192,35 @@ func (r *Runner) createState(index int) (*State, error) {
|
||||||
|
|
||||||
// Create sandbox
|
// Create sandbox
|
||||||
sandbox := NewSandbox()
|
sandbox := NewSandbox()
|
||||||
if r.debug {
|
if r.debug && verbose {
|
||||||
sandbox.EnableDebug()
|
sandbox.EnableDebug()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set up require system
|
// Set up require system
|
||||||
if err := r.moduleLoader.SetupRequire(L); err != nil {
|
if err := r.moduleLoader.SetupRequire(L); err != nil {
|
||||||
r.debugLog("Failed to set up require for state %d: %v", index, err)
|
if verbose {
|
||||||
|
r.debugLogCont("Failed to set up require for state %d: %v", index, err)
|
||||||
|
}
|
||||||
L.Cleanup()
|
L.Cleanup()
|
||||||
L.Close()
|
L.Close()
|
||||||
return nil, ErrInitFailed
|
return nil, ErrInitFailed
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize all core modules from the registry
|
// Initialize all core modules from the registry
|
||||||
if err := GlobalRegistry.Initialize(L); err != nil {
|
if err := GlobalRegistry.Initialize(L, index); err != nil {
|
||||||
r.debugLog("Failed to initialize core modules for state %d: %v", index, err)
|
if verbose {
|
||||||
|
r.debugLogCont("Failed to initialize core modules for state %d: %v", index, err)
|
||||||
|
}
|
||||||
L.Cleanup()
|
L.Cleanup()
|
||||||
L.Close()
|
L.Close()
|
||||||
return nil, ErrInitFailed
|
return nil, ErrInitFailed
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set up sandbox after core modules are initialized
|
// Set up sandbox after core modules are initialized
|
||||||
if err := sandbox.Setup(L); err != nil {
|
if err := sandbox.Setup(L, index); err != nil {
|
||||||
r.debugLog("Failed to set up sandbox for state %d: %v", index, err)
|
if verbose {
|
||||||
|
r.debugLogCont("Failed to set up sandbox for state %d: %v", index, err)
|
||||||
|
}
|
||||||
L.Cleanup()
|
L.Cleanup()
|
||||||
L.Close()
|
L.Close()
|
||||||
return nil, ErrInitFailed
|
return nil, ErrInitFailed
|
||||||
|
@ -211,7 +228,9 @@ func (r *Runner) createState(index int) (*State, error) {
|
||||||
|
|
||||||
// Preload all modules
|
// Preload all modules
|
||||||
if err := r.moduleLoader.PreloadModules(L); err != nil {
|
if err := r.moduleLoader.PreloadModules(L); err != nil {
|
||||||
r.debugLog("Failed to preload modules for state %d: %v", index, err)
|
if verbose {
|
||||||
|
r.debugLogCont("Failed to preload modules for state %d: %v", index, err)
|
||||||
|
}
|
||||||
L.Cleanup()
|
L.Cleanup()
|
||||||
L.Close()
|
L.Close()
|
||||||
return nil, errors.New("failed to preload modules")
|
return nil, errors.New("failed to preload modules")
|
||||||
|
@ -225,7 +244,9 @@ func (r *Runner) createState(index int) (*State, error) {
|
||||||
initTime: time.Now(),
|
initTime: time.Now(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if verbose {
|
||||||
r.debugLog("State %d created successfully", index)
|
r.debugLog("State %d created successfully", index)
|
||||||
|
}
|
||||||
return state, nil
|
return state, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,14 @@ func (s *Sandbox) EnableDebug() {
|
||||||
// debugLog logs a message if debug mode is enabled
|
// debugLog logs a message if debug mode is enabled
|
||||||
func (s *Sandbox) debugLog(format string, args ...interface{}) {
|
func (s *Sandbox) debugLog(format string, args ...interface{}) {
|
||||||
if s.debug {
|
if s.debug {
|
||||||
logger.Debug("[Sandbox] "+format, args...)
|
logger.Debug("Sandbox "+format, args...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// debugLog logs a message if debug mode is enabled
|
||||||
|
func (s *Sandbox) debugLogCont(format string, args ...interface{}) {
|
||||||
|
if s.debug {
|
||||||
|
logger.DebugCont(format, args...)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,16 +52,24 @@ func (s *Sandbox) AddModule(name string, module any) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setup initializes the sandbox in a Lua state
|
// Setup initializes the sandbox in a Lua state
|
||||||
func (s *Sandbox) Setup(state *luajit.State) error {
|
func (s *Sandbox) Setup(state *luajit.State, stateIndex int) error {
|
||||||
s.debugLog("Setting up sandbox environment")
|
verbose := stateIndex == 0
|
||||||
|
|
||||||
|
if verbose {
|
||||||
|
s.debugLog("is setting up...")
|
||||||
|
}
|
||||||
|
|
||||||
// Register modules in the global environment
|
// Register modules in the global environment
|
||||||
s.mu.RLock()
|
s.mu.RLock()
|
||||||
for name, module := range s.modules {
|
for name, module := range s.modules {
|
||||||
s.debugLog("Registering module: %s", name)
|
if verbose {
|
||||||
|
s.debugLog("is registering module: %s", name)
|
||||||
|
}
|
||||||
if err := state.PushValue(module); err != nil {
|
if err := state.PushValue(module); err != nil {
|
||||||
s.mu.RUnlock()
|
s.mu.RUnlock()
|
||||||
s.debugLog("Failed to register module %s: %v", name, err)
|
if verbose {
|
||||||
|
s.debugLog("failed to register module %s: %v", name, err)
|
||||||
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
state.SetGlobal(name)
|
state.SetGlobal(name)
|
||||||
|
@ -106,11 +121,16 @@ func (s *Sandbox) Setup(state *luajit.State) error {
|
||||||
`)
|
`)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.debugLog("Failed to set up sandbox: %v", err)
|
if verbose {
|
||||||
|
s.debugLog("failed to set up...")
|
||||||
|
s.debugLogCont("%v", err)
|
||||||
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
s.debugLog("Sandbox setup complete")
|
if verbose {
|
||||||
|
s.debugLogCont("Complete")
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -39,7 +39,6 @@ func WatchDirectory(config DirectoryWatcherConfig, manager *WatcherManager) (*Wa
|
||||||
manager: manager,
|
manager: manager,
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Debug("Started watching directory: %s", config.Dir)
|
|
||||||
return w, nil
|
return w, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -67,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
|
||||||
logger.Debug("[WatcherManager] Added watcher for directory: %s", watcher.dir)
|
logger.Debug("WatcherManager added watcher for %s", watcher.dir)
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemoveWatcher unregisters a directory watcher
|
// RemoveWatcher unregisters a directory watcher
|
||||||
|
@ -76,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)
|
||||||
logger.Debug("[WatcherManager] Removed watcher for directory: %s", dir)
|
logger.Debug("WatcherManager removed watcher for %s", dir)
|
||||||
}
|
}
|
||||||
|
|
||||||
// pollLoop is the main polling loop that checks all watched directories
|
// pollLoop is the main polling loop that checks all watched directories
|
||||||
|
|
11
main.go
11
main.go
|
@ -1,6 +1,7 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
@ -9,29 +10,25 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
// Initialize global logger
|
logger.InitGlobalLogger(logger.LevelDebug, true, false)
|
||||||
logger.InitGlobalLogger(logger.LevelDebug, true)
|
logger.Server("Moonshark is starting to prowl 🦈")
|
||||||
logger.Server("Starting Moonshark server")
|
|
||||||
|
|
||||||
// Create and initialize server
|
|
||||||
server, err := NewMoonshark("config.lua")
|
server, err := NewMoonshark("config.lua")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Fatal("Failed to initialize server: %v", err)
|
logger.Fatal("Failed to initialize server: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start server
|
|
||||||
if err := server.Start(); err != nil {
|
if err := server.Start(); err != nil {
|
||||||
logger.Fatal("Failed to start server: %v", err)
|
logger.Fatal("Failed to start server: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wait for interrupt signal
|
|
||||||
stop := make(chan os.Signal, 1)
|
stop := make(chan os.Signal, 1)
|
||||||
signal.Notify(stop, os.Interrupt, syscall.SIGTERM)
|
signal.Notify(stop, os.Interrupt, syscall.SIGTERM)
|
||||||
<-stop
|
<-stop
|
||||||
|
|
||||||
|
fmt.Print("\n")
|
||||||
logger.Server("Shutdown signal received")
|
logger.Server("Shutdown signal received")
|
||||||
|
|
||||||
// Shutdown server
|
|
||||||
if err := server.Shutdown(); err != nil {
|
if err := server.Shutdown(); err != nil {
|
||||||
logger.Error("Error during shutdown: %v", err)
|
logger.Error("Error during shutdown: %v", err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user