big ol logger refactor
This commit is contained in:
parent
d1ec8ade9c
commit
bf5a841716
@ -9,6 +9,7 @@ import (
|
|||||||
"Moonshark/runner"
|
"Moonshark/runner"
|
||||||
"Moonshark/sessions"
|
"Moonshark/sessions"
|
||||||
"Moonshark/utils"
|
"Moonshark/utils"
|
||||||
|
"Moonshark/utils/color"
|
||||||
"Moonshark/utils/config"
|
"Moonshark/utils/config"
|
||||||
"Moonshark/utils/logger"
|
"Moonshark/utils/logger"
|
||||||
"Moonshark/utils/metadata"
|
"Moonshark/utils/metadata"
|
||||||
@ -73,7 +74,7 @@ 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 {
|
||||||
logger.Server("Catch the swell at http://localhost%s", addr)
|
logger.Info("Catch the swell at %s", color.Apply("http://localhost"+addr, color.Cyan))
|
||||||
return s.fasthttpServer.ListenAndServe(addr)
|
return s.fasthttpServer.ListenAndServe(addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -95,7 +96,7 @@ func (s *Server) handleRequest(ctx *fasthttp.RequestCtx) {
|
|||||||
if s.debugMode && path == "/debug/stats" {
|
if s.debugMode && path == "/debug/stats" {
|
||||||
s.handleDebugStats(ctx)
|
s.handleDebugStats(ctx)
|
||||||
if s.loggingEnabled {
|
if s.loggingEnabled {
|
||||||
LogRequest(ctx.Response.StatusCode(), method, path, time.Since(start))
|
logger.LogRequest(ctx.Response.StatusCode(), method, path, time.Since(start))
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -103,7 +104,7 @@ func (s *Server) handleRequest(ctx *fasthttp.RequestCtx) {
|
|||||||
s.processRequest(ctx, method, path)
|
s.processRequest(ctx, method, path)
|
||||||
|
|
||||||
if s.loggingEnabled {
|
if s.loggingEnabled {
|
||||||
LogRequest(ctx.Response.StatusCode(), method, path, time.Since(start))
|
logger.LogRequest(ctx.Response.StatusCode(), method, path, time.Since(start))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,13 +3,9 @@ package http
|
|||||||
import (
|
import (
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"fmt"
|
|
||||||
"mime/multipart"
|
"mime/multipart"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
|
||||||
|
|
||||||
"Moonshark/utils/logger"
|
|
||||||
|
|
||||||
"github.com/valyala/fasthttp"
|
"github.com/valyala/fasthttp"
|
||||||
)
|
)
|
||||||
@ -29,52 +25,6 @@ var (
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
// LogRequest logs an HTTP request with its status code and duration
|
|
||||||
func LogRequest(statusCode int, method, path string, duration time.Duration) {
|
|
||||||
var statusColor, methodColor string
|
|
||||||
|
|
||||||
// Simplified color assignment
|
|
||||||
switch {
|
|
||||||
case statusCode < 300:
|
|
||||||
statusColor = "\u001b[32m" // Green for 2xx
|
|
||||||
case statusCode < 400:
|
|
||||||
statusColor = "\u001b[36m" // Cyan for 3xx
|
|
||||||
case statusCode < 500:
|
|
||||||
statusColor = "\u001b[33m" // Yellow for 4xx
|
|
||||||
default:
|
|
||||||
statusColor = "\u001b[31m" // Red for 5xx+
|
|
||||||
}
|
|
||||||
|
|
||||||
switch method {
|
|
||||||
case "GET":
|
|
||||||
methodColor = "\u001b[32m"
|
|
||||||
case "POST":
|
|
||||||
methodColor = "\u001b[34m"
|
|
||||||
case "PUT":
|
|
||||||
methodColor = "\u001b[33m"
|
|
||||||
case "DELETE":
|
|
||||||
methodColor = "\u001b[31m"
|
|
||||||
default:
|
|
||||||
methodColor = "\u001b[35m"
|
|
||||||
}
|
|
||||||
|
|
||||||
// Optimized duration formatting
|
|
||||||
var durationStr string
|
|
||||||
micros := duration.Microseconds()
|
|
||||||
if micros < 1000 {
|
|
||||||
durationStr = fmt.Sprintf("%.0fµs", float64(micros))
|
|
||||||
} else if micros < 1000000 {
|
|
||||||
durationStr = fmt.Sprintf("%.1fms", float64(micros)/1000)
|
|
||||||
} else {
|
|
||||||
durationStr = fmt.Sprintf("%.2fs", duration.Seconds())
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.Server("%s%d\u001b[0m %s%s\u001b[0m %s %s",
|
|
||||||
statusColor, statusCode,
|
|
||||||
methodColor, method,
|
|
||||||
path, durationStr)
|
|
||||||
}
|
|
||||||
|
|
||||||
// QueryToLua converts HTTP query args to a Lua-friendly map
|
// QueryToLua converts HTTP query args to a Lua-friendly map
|
||||||
func QueryToLua(ctx *fasthttp.RequestCtx) map[string]any {
|
func QueryToLua(ctx *fasthttp.RequestCtx) map[string]any {
|
||||||
args := ctx.QueryArgs()
|
args := ctx.QueryArgs()
|
||||||
|
137
main.go
137
main.go
@ -8,6 +8,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"strconv"
|
||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -15,8 +16,10 @@ import (
|
|||||||
"Moonshark/routers"
|
"Moonshark/routers"
|
||||||
"Moonshark/runner"
|
"Moonshark/runner"
|
||||||
"Moonshark/sessions"
|
"Moonshark/sessions"
|
||||||
|
"Moonshark/utils/color"
|
||||||
"Moonshark/utils/config"
|
"Moonshark/utils/config"
|
||||||
"Moonshark/utils/logger"
|
"Moonshark/utils/logger"
|
||||||
|
"Moonshark/utils/metadata"
|
||||||
"Moonshark/watchers"
|
"Moonshark/watchers"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -33,23 +36,42 @@ type Moonshark struct {
|
|||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
configPath := flag.String("config", "config.lua", "Path to configuration file")
|
configPath := flag.String("config", "config.lua", "Path to configuration file")
|
||||||
scriptPath := flag.String("script", "", "Path to Lua script to execute once")
|
|
||||||
debugFlag := flag.Bool("debug", false, "Enable debug mode")
|
debugFlag := flag.Bool("debug", false, "Enable debug mode")
|
||||||
|
scriptPath := flag.String("script", "", "Path to Lua script to execute once")
|
||||||
|
scriptMode := *scriptPath != ""
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
// Initialize logger with basic settings first
|
banner()
|
||||||
logger.InitGlobalLogger(logger.LevelInfo, true, false)
|
mode := ""
|
||||||
|
if scriptMode {
|
||||||
|
mode = "[Script Mode]"
|
||||||
|
} else {
|
||||||
|
mode = "[Server Mode]"
|
||||||
|
}
|
||||||
|
fmt.Printf("%s %s\n\n", color.Apply(mode, color.Gray), color.Apply("v"+metadata.Version, color.Blue))
|
||||||
|
|
||||||
|
// Initialize logger
|
||||||
|
logger.InitGlobalLogger(true, false)
|
||||||
|
|
||||||
|
// Load config
|
||||||
|
cfg, err := config.Load(*configPath)
|
||||||
|
if err != nil {
|
||||||
|
logger.Warning("Config load failed: %v, using defaults", color.Apply(err.Error(), color.Red))
|
||||||
|
cfg = config.New()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setup logging with debug mode
|
||||||
|
if *debugFlag || cfg.Server.Debug {
|
||||||
|
logger.EnableDebug()
|
||||||
|
logger.Debug("Debug logging enabled")
|
||||||
|
}
|
||||||
|
|
||||||
scriptMode := *scriptPath != ""
|
|
||||||
var moonshark *Moonshark
|
var moonshark *Moonshark
|
||||||
var err error
|
|
||||||
|
|
||||||
if scriptMode {
|
if scriptMode {
|
||||||
logger.Server("Moonshark script execution mode 🦈")
|
moonshark, err = initScriptMode(cfg)
|
||||||
moonshark, err = initScriptMode(*configPath, *debugFlag)
|
|
||||||
} else {
|
} else {
|
||||||
logger.Server("Moonshark server mode 🦈")
|
moonshark, err = initServerMode(cfg, *debugFlag)
|
||||||
moonshark, err = initServerMode(*configPath, *debugFlag)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -82,23 +104,15 @@ func main() {
|
|||||||
<-stop
|
<-stop
|
||||||
|
|
||||||
fmt.Print("\n")
|
fmt.Print("\n")
|
||||||
logger.Server("Shutdown signal received")
|
logger.Info("Shutdown signal received")
|
||||||
}
|
}
|
||||||
|
|
||||||
// initScriptMode initializes minimal components needed for script execution
|
// initScriptMode initializes minimal components needed for script execution
|
||||||
func initScriptMode(configPath string, debug bool) (*Moonshark, error) {
|
func initScriptMode(cfg *config.Config) (*Moonshark, error) {
|
||||||
moonshark := &Moonshark{scriptMode: true}
|
moonshark := &Moonshark{
|
||||||
|
Config: cfg,
|
||||||
// Load config (minimal validation for script mode)
|
scriptMode: true,
|
||||||
cfg, err := config.Load(configPath)
|
|
||||||
if err != nil {
|
|
||||||
logger.Warning("Config load failed: %v, using defaults", err)
|
|
||||||
cfg = config.New()
|
|
||||||
}
|
}
|
||||||
moonshark.Config = cfg
|
|
||||||
|
|
||||||
// Setup logging
|
|
||||||
setupLogging(cfg, debug)
|
|
||||||
|
|
||||||
// Only initialize the Lua runner with required paths
|
// Only initialize the Lua runner with required paths
|
||||||
runnerOpts := []runner.RunnerOption{
|
runnerOpts := []runner.RunnerOption{
|
||||||
@ -108,6 +122,7 @@ func initScriptMode(configPath string, debug bool) (*Moonshark, error) {
|
|||||||
runner.WithDataDir(cfg.Dirs.Data),
|
runner.WithDataDir(cfg.Dirs.Data),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var err error
|
||||||
moonshark.LuaRunner, err = runner.NewRunner(runnerOpts...)
|
moonshark.LuaRunner, err = runner.NewRunner(runnerOpts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to initialize Lua runner: %v", err)
|
return nil, fmt.Errorf("failed to initialize Lua runner: %v", err)
|
||||||
@ -118,22 +133,16 @@ func initScriptMode(configPath string, debug bool) (*Moonshark, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// initServerMode initializes all components needed for server operation
|
// initServerMode initializes all components needed for server operation
|
||||||
func initServerMode(configPath string, debug bool) (*Moonshark, error) {
|
func initServerMode(cfg *config.Config, debug bool) (*Moonshark, error) {
|
||||||
moonshark := &Moonshark{scriptMode: false}
|
moonshark := &Moonshark{
|
||||||
|
Config: cfg,
|
||||||
cfg, err := config.Load(configPath)
|
scriptMode: false,
|
||||||
if err != nil {
|
|
||||||
logger.Warning("Config load failed: %v, using defaults", err)
|
|
||||||
cfg = config.New()
|
|
||||||
}
|
}
|
||||||
moonshark.Config = cfg
|
|
||||||
|
|
||||||
if debug {
|
if debug {
|
||||||
cfg.Server.Debug = true
|
cfg.Server.Debug = true
|
||||||
}
|
}
|
||||||
|
|
||||||
setupLogging(cfg, debug)
|
|
||||||
|
|
||||||
if err := initRouters(moonshark); err != nil {
|
if err := initRouters(moonshark); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -170,7 +179,7 @@ func (s *Moonshark) RunScript(scriptPath string) error {
|
|||||||
return fmt.Errorf("script file not found: %s", scriptPath)
|
return fmt.Errorf("script file not found: %s", scriptPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Server("Executing: %s", scriptPath)
|
logger.Info("Executing: %s", scriptPath)
|
||||||
|
|
||||||
resp, err := s.LuaRunner.RunScriptFile(scriptPath)
|
resp, err := s.LuaRunner.RunScriptFile(scriptPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -178,9 +187,9 @@ func (s *Moonshark) RunScript(scriptPath string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if resp != nil && resp.Body != nil {
|
if resp != nil && resp.Body != nil {
|
||||||
logger.Server("Script result: %v", resp.Body)
|
logger.Info("Script result: %v", resp.Body)
|
||||||
} else {
|
} else {
|
||||||
logger.Server("Script executed successfully (no return value)")
|
logger.Info("Script executed successfully (no return value)")
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@ -192,7 +201,7 @@ func (s *Moonshark) Start() error {
|
|||||||
return errors.New("cannot start server in script mode")
|
return errors.New("cannot start server in script mode")
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Server("Surf's up on port %d!", s.Config.Server.Port)
|
logger.Info("Surf's up on port %s!", color.Apply(strconv.Itoa(s.Config.Server.Port), color.Cyan))
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
if err := s.HTTPServer.ListenAndServe(fmt.Sprintf(":%d", s.Config.Server.Port)); err != nil {
|
if err := s.HTTPServer.ListenAndServe(fmt.Sprintf(":%d", s.Config.Server.Port)); err != nil {
|
||||||
@ -207,7 +216,7 @@ func (s *Moonshark) Start() error {
|
|||||||
|
|
||||||
// Shutdown gracefully shuts down Moonshark
|
// Shutdown gracefully shuts down Moonshark
|
||||||
func (s *Moonshark) Shutdown() error {
|
func (s *Moonshark) Shutdown() error {
|
||||||
logger.Server("Shutting down...")
|
logger.Info("Shutting down...")
|
||||||
|
|
||||||
if !s.scriptMode && s.HTTPServer != nil {
|
if !s.scriptMode && s.HTTPServer != nil {
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||||
@ -228,30 +237,10 @@ func (s *Moonshark) Shutdown() error {
|
|||||||
s.LuaRunner.Close()
|
s.LuaRunner.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Server("Shutdown complete")
|
logger.Info("Shutdown complete")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func setupLogging(cfg *config.Config, debug bool) {
|
|
||||||
switch cfg.Server.LogLevel {
|
|
||||||
case "warn":
|
|
||||||
logger.SetLevel(logger.LevelWarning)
|
|
||||||
case "error":
|
|
||||||
logger.SetLevel(logger.LevelError)
|
|
||||||
case "server":
|
|
||||||
logger.SetLevel(logger.LevelServer)
|
|
||||||
case "fatal":
|
|
||||||
logger.SetLevel(logger.LevelFatal)
|
|
||||||
default:
|
|
||||||
logger.SetLevel(logger.LevelInfo)
|
|
||||||
}
|
|
||||||
|
|
||||||
if debug || cfg.Server.Debug {
|
|
||||||
logger.EnableDebug()
|
|
||||||
logger.Debug("Debug logging enabled")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func dirExists(path string) bool {
|
func dirExists(path string) bool {
|
||||||
info, err := os.Stat(path)
|
info, err := os.Stat(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -281,16 +270,16 @@ func initRouters(s *Moonshark) error {
|
|||||||
return fmt.Errorf("lua router init failed: %v", err)
|
return fmt.Errorf("lua router init failed: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
logger.Info("Lua router initialized: %s", s.Config.Dirs.Routes)
|
logger.Info("LuaRouter is g2g! %s", color.Set(s.Config.Dirs.Routes, color.Yellow))
|
||||||
|
|
||||||
if dirExists(s.Config.Dirs.Static) {
|
if dirExists(s.Config.Dirs.Static) {
|
||||||
s.StaticRouter, err = routers.NewStaticRouter(s.Config.Dirs.Static)
|
s.StaticRouter, err = routers.NewStaticRouter(s.Config.Dirs.Static)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("static router init failed: %v", err)
|
return fmt.Errorf("static router init failed: %v", err)
|
||||||
}
|
}
|
||||||
logger.Info("Static router initialized: %s", s.Config.Dirs.Static)
|
logger.Info("StaticRouter is g2g! %s", color.Apply(s.Config.Dirs.Static, color.Yellow))
|
||||||
} else {
|
} else {
|
||||||
logger.Warning("Static directory not found: %s", s.Config.Dirs.Static)
|
logger.Warning("Static directory not found... %s", color.Apply(s.Config.Dirs.Static, color.Yellow))
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@ -298,13 +287,13 @@ func initRouters(s *Moonshark) error {
|
|||||||
|
|
||||||
func initRunner(s *Moonshark) error {
|
func initRunner(s *Moonshark) error {
|
||||||
if !dirExists(s.Config.Dirs.Override) {
|
if !dirExists(s.Config.Dirs.Override) {
|
||||||
logger.Warning("Override directory not found: %s", s.Config.Dirs.Override)
|
logger.Warning("Override directory not found... %s", color.Apply(s.Config.Dirs.Override, color.Yellow))
|
||||||
s.Config.Dirs.Override = ""
|
s.Config.Dirs.Override = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, dir := range s.Config.Dirs.Libs {
|
for _, dir := range s.Config.Dirs.Libs {
|
||||||
if !dirExists(dir) {
|
if !dirExists(dir) {
|
||||||
logger.Warning("Lib directory not found: %s", dir)
|
logger.Warning("Lib directory not found... %s", color.Apply(dir, color.Yellow))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -336,7 +325,7 @@ func initRunner(s *Moonshark) error {
|
|||||||
return fmt.Errorf("lua runner init failed: %v", err)
|
return fmt.Errorf("lua runner init failed: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Server("Lua runner initialized with pool size: %d", poolSize)
|
logger.Info("LuaRunner is g2g with %s states!", color.Apply(strconv.Itoa(poolSize), color.Yellow))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -365,8 +354,26 @@ func setupWatchers(s *Moonshark) error {
|
|||||||
return manager.UnwatchDirectory(dirPath)
|
return manager.UnwatchDirectory(dirPath)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
logger.Info("Watching %d module directories", len(moduleWatchers))
|
plural := ""
|
||||||
|
if len(moduleWatchers) == 1 {
|
||||||
|
plural = "directory"
|
||||||
|
} else {
|
||||||
|
plural = "directories"
|
||||||
|
}
|
||||||
|
logger.Info("Watching %s module %s.", color.Apply(strconv.Itoa(len(moduleWatchers)), color.Yellow), plural)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func banner() {
|
||||||
|
banner := `
|
||||||
|
_____ _________.__ __
|
||||||
|
/ \ ____ ____ ____ / _____/| |__ _____ _______| | __
|
||||||
|
/ \ / \ / _ \ / _ \ / \ \_____ \ | | \\__ \\_ __ \ |/ /
|
||||||
|
/ Y ( <_> | <_> ) | \/ \| Y \/ __ \| | \/ <
|
||||||
|
\____|__ /\____/ \____/|___| /_______ /|___| (____ /__| |__|_ \
|
||||||
|
\/ \/ \/ \/ \/ \/
|
||||||
|
`
|
||||||
|
fmt.Println(color.Apply(banner, color.Blue))
|
||||||
|
}
|
||||||
|
@ -8,6 +8,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"Moonshark/utils/color"
|
||||||
"Moonshark/utils/logger"
|
"Moonshark/utils/logger"
|
||||||
|
|
||||||
lru "git.sharkk.net/Go/LRU"
|
lru "git.sharkk.net/Go/LRU"
|
||||||
@ -51,7 +52,7 @@ func InitFS(basePath string) error {
|
|||||||
// Initialize file cache with 2000 entries (reasonable for most use cases)
|
// Initialize file cache with 2000 entries (reasonable for most use cases)
|
||||||
fileCache = lru.NewLRUCache(2000)
|
fileCache = lru.NewLRUCache(2000)
|
||||||
|
|
||||||
logger.Server("Virtual filesystem initialized at: %s", fsBasePath)
|
logger.Info("Filesystem is g2g! %s", color.Apply(fsBasePath, color.Yellow))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,7 +60,11 @@ func InitFS(basePath string) error {
|
|||||||
func CleanupFS() {
|
func CleanupFS() {
|
||||||
if fileCache != nil {
|
if fileCache != nil {
|
||||||
fileCache.Clear()
|
fileCache.Clear()
|
||||||
logger.Server("File cache cleared - Stats: hits=%d, misses=%d", stats.hits, stats.misses)
|
logger.Info(
|
||||||
|
"File cache cleared - %s hits, %s misses",
|
||||||
|
color.Apply(fmt.Sprintf("%d", stats.hits), color.Yellow),
|
||||||
|
color.Apply(fmt.Sprintf("%d", stats.misses), color.Red),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package runner
|
package runner
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"Moonshark/utils/color"
|
||||||
"Moonshark/utils/logger"
|
"Moonshark/utils/logger"
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
@ -8,6 +9,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
"strconv"
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
@ -130,7 +132,7 @@ func NewRunner(options ...RunnerOption) (*Runner, error) {
|
|||||||
|
|
||||||
// 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 {
|
||||||
logger.Server("Initializing %d states...", r.poolSize)
|
logger.Info("[LuaRunner] Creating %s states...", color.Apply(strconv.Itoa(r.poolSize), color.Yellow))
|
||||||
|
|
||||||
for i := range r.poolSize {
|
for i := range r.poolSize {
|
||||||
state, err := r.createState(i)
|
state, err := r.createState(i)
|
||||||
@ -302,7 +304,7 @@ func (r *Runner) RefreshStates() error {
|
|||||||
return ErrRunnerClosed
|
return ErrRunnerClosed
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Server("Runner is refreshing all states...")
|
logger.Info("Runner is refreshing all states...")
|
||||||
|
|
||||||
// Drain all states from the pool
|
// Drain all states from the pool
|
||||||
for {
|
for {
|
||||||
|
@ -13,6 +13,7 @@ import (
|
|||||||
sqlite "zombiezen.com/go/sqlite"
|
sqlite "zombiezen.com/go/sqlite"
|
||||||
"zombiezen.com/go/sqlite/sqlitex"
|
"zombiezen.com/go/sqlite/sqlitex"
|
||||||
|
|
||||||
|
"Moonshark/utils/color"
|
||||||
"Moonshark/utils/logger"
|
"Moonshark/utils/logger"
|
||||||
|
|
||||||
luajit "git.sharkk.net/Sky/LuaJIT-to-Go"
|
luajit "git.sharkk.net/Sky/LuaJIT-to-Go"
|
||||||
@ -48,7 +49,7 @@ func generateConnToken() string {
|
|||||||
// InitSQLite initializes the SQLite subsystem
|
// InitSQLite initializes the SQLite subsystem
|
||||||
func InitSQLite(dir string) {
|
func InitSQLite(dir string) {
|
||||||
dataDir = dir
|
dataDir = dir
|
||||||
logger.Server("SQLite initialized with data directory: %s", dir)
|
logger.Info("SQLite is g2g! %s", color.Apply(dir, color.Yellow))
|
||||||
|
|
||||||
// Start connection cleanup goroutine
|
// Start connection cleanup goroutine
|
||||||
go cleanupIdleConnections()
|
go cleanupIdleConnections()
|
||||||
|
@ -16,7 +16,7 @@ import (
|
|||||||
// setupTestEnv initializes test components and returns cleanup function
|
// setupTestEnv initializes test components and returns cleanup function
|
||||||
func setupTestEnv(b *testing.B) (*routers.LuaRouter, *runner.Runner, func()) {
|
func setupTestEnv(b *testing.B) (*routers.LuaRouter, *runner.Runner, func()) {
|
||||||
// Completely silence logging during benchmarks
|
// Completely silence logging during benchmarks
|
||||||
logger.InitGlobalLogger(logger.LevelFatal, false, false)
|
logger.InitGlobalLogger(false, false)
|
||||||
|
|
||||||
// Redirect standard logger output to discard
|
// Redirect standard logger output to discard
|
||||||
log.SetOutput(io.Discard)
|
log.SetOutput(io.Discard)
|
||||||
|
@ -13,14 +13,39 @@ const (
|
|||||||
Gray = "\033[90m"
|
Gray = "\033[90m"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Apply adds color to text if useColors is true
|
var useColors = true
|
||||||
func Apply(text, color string, useColors bool) string {
|
|
||||||
|
// SetColors enables or disables colors globally
|
||||||
|
func SetColors(enabled bool) {
|
||||||
|
useColors = enabled
|
||||||
|
}
|
||||||
|
|
||||||
|
// ColorsEnabled returns current global color setting
|
||||||
|
func ColorsEnabled() bool {
|
||||||
|
return useColors
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply adds color to text using global color setting
|
||||||
|
func Apply(text, color string) string {
|
||||||
if useColors {
|
if useColors {
|
||||||
return color + text + Reset
|
return color + text + Reset
|
||||||
}
|
}
|
||||||
return text
|
return text
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ApplyIf adds color to text if useColors is true (for backward compatibility)
|
||||||
|
func ApplyIf(text, color string, enabled bool) string {
|
||||||
|
if enabled {
|
||||||
|
return color + text + Reset
|
||||||
|
}
|
||||||
|
return text
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set adds color to text (always applies color, ignores global setting)
|
||||||
|
func Set(text, color string) string {
|
||||||
|
return color + text + Reset
|
||||||
|
}
|
||||||
|
|
||||||
// Strip removes ANSI color codes from a string
|
// Strip removes ANSI color codes from a string
|
||||||
func Strip(s string) string {
|
func Strip(s string) string {
|
||||||
result := ""
|
result := ""
|
||||||
@ -33,14 +58,11 @@ func Strip(s string) string {
|
|||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if c == '\033' {
|
if c == '\033' {
|
||||||
inEscape = true
|
inEscape = true
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
result += string(c)
|
result += string(c)
|
||||||
}
|
}
|
||||||
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,6 @@ type Config struct {
|
|||||||
Server struct {
|
Server struct {
|
||||||
Port int
|
Port int
|
||||||
Debug bool
|
Debug bool
|
||||||
LogLevel string
|
|
||||||
HTTPLogging bool
|
HTTPLogging bool
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,7 +48,6 @@ func New() *Config {
|
|||||||
// Server defaults
|
// Server defaults
|
||||||
config.Server.Port = 3117
|
config.Server.Port = 3117
|
||||||
config.Server.Debug = false
|
config.Server.Debug = false
|
||||||
config.Server.LogLevel = "info"
|
|
||||||
config.Server.HTTPLogging = false
|
config.Server.HTTPLogging = false
|
||||||
|
|
||||||
// Runner defaults
|
// Runner defaults
|
||||||
@ -116,9 +114,6 @@ func applyConfig(config *Config, values map[string]any) {
|
|||||||
if v, ok := serverTable["debug"].(bool); ok {
|
if v, ok := serverTable["debug"].(bool); ok {
|
||||||
config.Server.Debug = v
|
config.Server.Debug = v
|
||||||
}
|
}
|
||||||
if v, ok := serverTable["log_level"].(string); ok {
|
|
||||||
config.Server.LogLevel = v
|
|
||||||
}
|
|
||||||
if v, ok := serverTable["http_logging"].(bool); ok {
|
if v, ok := serverTable["http_logging"].(bool); ok {
|
||||||
config.Server.HTTPLogging = v
|
config.Server.HTTPLogging = v
|
||||||
}
|
}
|
||||||
|
@ -19,145 +19,117 @@ const (
|
|||||||
colorBlue = "\033[34m"
|
colorBlue = "\033[34m"
|
||||||
colorPurple = "\033[35m"
|
colorPurple = "\033[35m"
|
||||||
colorCyan = "\033[36m"
|
colorCyan = "\033[36m"
|
||||||
colorWhite = "\033[37m"
|
|
||||||
colorGray = "\033[90m"
|
colorGray = "\033[90m"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Log levels
|
// Log types
|
||||||
const (
|
const (
|
||||||
LevelDebug = iota
|
TypeNone = iota
|
||||||
LevelInfo
|
TypeDebug
|
||||||
LevelWarning
|
TypeInfo
|
||||||
LevelError
|
TypeWarning
|
||||||
LevelServer
|
TypeError
|
||||||
LevelFatal
|
TypeServer
|
||||||
|
TypeFatal
|
||||||
)
|
)
|
||||||
|
|
||||||
// Level names and colors
|
// Type properties
|
||||||
var levelProps = map[int]struct {
|
var typeProps = map[int]struct {
|
||||||
tag string
|
tag string
|
||||||
color string
|
color string
|
||||||
}{
|
}{
|
||||||
LevelDebug: {"D", colorCyan},
|
TypeDebug: {"D", colorCyan},
|
||||||
LevelInfo: {"I", colorBlue},
|
TypeInfo: {"I", colorBlue},
|
||||||
LevelWarning: {"W", colorYellow},
|
TypeWarning: {"W", colorYellow},
|
||||||
LevelError: {"E", colorRed},
|
TypeError: {"E", colorRed},
|
||||||
LevelServer: {"S", colorGreen},
|
TypeServer: {"S", colorGreen},
|
||||||
LevelFatal: {"F", colorPurple},
|
TypeFatal: {"F", colorPurple},
|
||||||
}
|
}
|
||||||
|
|
||||||
// Time format for log messages
|
|
||||||
const timeFormat = "15:04:05"
|
const timeFormat = "15:04:05"
|
||||||
|
|
||||||
// Single global logger instance with mutex for safe initialization
|
|
||||||
var (
|
var (
|
||||||
globalLogger *Logger
|
globalLogger *Logger
|
||||||
globalLoggerOnce sync.Once
|
globalLoggerOnce sync.Once
|
||||||
)
|
)
|
||||||
|
|
||||||
// Logger handles logging operations
|
|
||||||
type Logger struct {
|
type Logger struct {
|
||||||
writer io.Writer
|
writer io.Writer
|
||||||
level int
|
|
||||||
useColors bool
|
useColors bool
|
||||||
timeFormat string
|
timeFormat string
|
||||||
showTimestamp bool // Whether to show timestamp
|
showTimestamp bool
|
||||||
mu sync.Mutex // Mutex for thread-safe writing
|
mu sync.Mutex
|
||||||
debugMode atomic.Bool // Force debug logging regardless of level
|
debugMode atomic.Bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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, true)
|
globalLogger = newLogger(true, true)
|
||||||
})
|
})
|
||||||
return globalLogger
|
return globalLogger
|
||||||
}
|
}
|
||||||
|
|
||||||
// InitGlobalLogger initializes the global logger with custom settings
|
func InitGlobalLogger(useColors bool, showTimestamp bool) {
|
||||||
func InitGlobalLogger(minLevel int, useColors bool, showTimestamp bool) {
|
globalLogger = newLogger(useColors, showTimestamp)
|
||||||
// Reset the global logger instance
|
|
||||||
globalLogger = newLogger(minLevel, useColors, showTimestamp)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// newLogger creates a new logger instance (internal use)
|
func newLogger(useColors bool, showTimestamp bool) *Logger {
|
||||||
func newLogger(minLevel int, useColors bool, showTimestamp bool) *Logger {
|
return &Logger{
|
||||||
logger := &Logger{
|
|
||||||
writer: os.Stdout,
|
writer: os.Stdout,
|
||||||
level: minLevel,
|
|
||||||
useColors: useColors,
|
useColors: useColors,
|
||||||
timeFormat: timeFormat,
|
timeFormat: timeFormat,
|
||||||
showTimestamp: showTimestamp,
|
showTimestamp: showTimestamp,
|
||||||
}
|
}
|
||||||
|
|
||||||
return logger
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// New creates a new logger (deprecated - use GetLogger() instead)
|
func New(useColors bool, showTimestamp bool) *Logger {
|
||||||
func New(minLevel int, useColors bool, showTimestamp bool) *Logger {
|
return newLogger(useColors, showTimestamp)
|
||||||
return newLogger(minLevel, useColors, showTimestamp)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetOutput changes the output destination
|
|
||||||
func (l *Logger) SetOutput(w io.Writer) {
|
func (l *Logger) SetOutput(w io.Writer) {
|
||||||
l.mu.Lock()
|
l.mu.Lock()
|
||||||
defer l.mu.Unlock()
|
|
||||||
l.writer = w
|
l.writer = w
|
||||||
|
l.mu.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
// TimeFormat returns the current time format
|
|
||||||
func (l *Logger) TimeFormat() string {
|
func (l *Logger) TimeFormat() string {
|
||||||
return l.timeFormat
|
return l.timeFormat
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetTimeFormat changes the time format string
|
|
||||||
func (l *Logger) SetTimeFormat(format string) {
|
func (l *Logger) SetTimeFormat(format string) {
|
||||||
l.mu.Lock()
|
l.mu.Lock()
|
||||||
defer l.mu.Unlock()
|
|
||||||
l.timeFormat = format
|
l.timeFormat = format
|
||||||
|
l.mu.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
// EnableTimestamp enables timestamp display
|
|
||||||
func (l *Logger) EnableTimestamp() {
|
func (l *Logger) EnableTimestamp() {
|
||||||
l.showTimestamp = true
|
l.showTimestamp = true
|
||||||
}
|
}
|
||||||
|
|
||||||
// DisableTimestamp disables timestamp display
|
|
||||||
func (l *Logger) DisableTimestamp() {
|
func (l *Logger) DisableTimestamp() {
|
||||||
l.showTimestamp = false
|
l.showTimestamp = false
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetLevel changes the minimum log level
|
|
||||||
func (l *Logger) SetLevel(level int) {
|
|
||||||
l.level = level
|
|
||||||
}
|
|
||||||
|
|
||||||
// EnableColors enables ANSI color codes in the output
|
|
||||||
func (l *Logger) EnableColors() {
|
func (l *Logger) EnableColors() {
|
||||||
l.useColors = true
|
l.useColors = true
|
||||||
}
|
}
|
||||||
|
|
||||||
// DisableColors disables ANSI color codes in the output
|
|
||||||
func (l *Logger) DisableColors() {
|
func (l *Logger) DisableColors() {
|
||||||
l.useColors = false
|
l.useColors = false
|
||||||
}
|
}
|
||||||
|
|
||||||
// EnableDebug forces debug logs to be shown regardless of level
|
|
||||||
func (l *Logger) EnableDebug() {
|
func (l *Logger) EnableDebug() {
|
||||||
l.debugMode.Store(true)
|
l.debugMode.Store(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DisableDebug stops forcing debug logs
|
|
||||||
func (l *Logger) DisableDebug() {
|
func (l *Logger) DisableDebug() {
|
||||||
l.debugMode.Store(false)
|
l.debugMode.Store(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsDebugEnabled returns true if debug mode is enabled
|
|
||||||
func (l *Logger) IsDebugEnabled() bool {
|
func (l *Logger) IsDebugEnabled() bool {
|
||||||
return l.debugMode.Load()
|
return l.debugMode.Load()
|
||||||
}
|
}
|
||||||
|
|
||||||
// applyColor applies color to text if colors are enabled
|
|
||||||
func (l *Logger) applyColor(text, color string) string {
|
func (l *Logger) applyColor(text, color string) string {
|
||||||
if l.useColors {
|
if l.useColors {
|
||||||
return color + text + colorReset
|
return color + text + colorReset
|
||||||
@ -165,7 +137,6 @@ func (l *Logger) applyColor(text, color string) string {
|
|||||||
return text
|
return text
|
||||||
}
|
}
|
||||||
|
|
||||||
// stripAnsiColors removes ANSI color codes from a string
|
|
||||||
func stripAnsiColors(s string) string {
|
func stripAnsiColors(s string) string {
|
||||||
result := ""
|
result := ""
|
||||||
inEscape := false
|
inEscape := false
|
||||||
@ -177,56 +148,48 @@ func stripAnsiColors(s string) string {
|
|||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if c == '\033' {
|
if c == '\033' {
|
||||||
inEscape = true
|
inEscape = true
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
result += string(c)
|
result += string(c)
|
||||||
}
|
}
|
||||||
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
// writeMessage writes a formatted log message directly to the writer
|
func (l *Logger) writeMessage(logType int, message string, rawMode bool) {
|
||||||
func (l *Logger) writeMessage(level int, message string, rawMode bool) {
|
|
||||||
var logLine string
|
|
||||||
|
|
||||||
if rawMode {
|
if rawMode {
|
||||||
// Raw mode - message is already formatted, just append newline
|
l.mu.Lock()
|
||||||
logLine = message + "\n"
|
_, _ = fmt.Fprint(l.writer, message+"\n")
|
||||||
} else {
|
l.mu.Unlock()
|
||||||
// Standard format with level tag and optional timestamp
|
return
|
||||||
props := levelProps[level]
|
|
||||||
|
|
||||||
if l.showTimestamp {
|
|
||||||
now := time.Now().Format(l.timeFormat)
|
|
||||||
|
|
||||||
if l.useColors {
|
|
||||||
timestamp := l.applyColor(now, colorGray)
|
|
||||||
tag := l.applyColor("["+props.tag+"]", props.color)
|
|
||||||
logLine = fmt.Sprintf("%s %s %s\n", timestamp, tag, message)
|
|
||||||
} else {
|
|
||||||
logLine = fmt.Sprintf("%s [%s] %s\n", now, props.tag, message)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// No timestamp, just level tag and message
|
|
||||||
if l.useColors {
|
|
||||||
tag := l.applyColor("["+props.tag+"]", props.color)
|
|
||||||
logLine = fmt.Sprintf("%s %s\n", tag, message)
|
|
||||||
} else {
|
|
||||||
logLine = fmt.Sprintf("[%s] %s\n", props.tag, message)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Synchronously write the log message
|
parts := []string{}
|
||||||
|
|
||||||
|
if l.showTimestamp {
|
||||||
|
timestamp := time.Now().Format(l.timeFormat)
|
||||||
|
if l.useColors {
|
||||||
|
timestamp = l.applyColor(timestamp, colorGray)
|
||||||
|
}
|
||||||
|
parts = append(parts, timestamp)
|
||||||
|
}
|
||||||
|
|
||||||
|
if logType != TypeNone {
|
||||||
|
props := typeProps[logType]
|
||||||
|
tag := "[" + props.tag + "]"
|
||||||
|
if l.useColors {
|
||||||
|
tag = l.applyColor(tag, props.color)
|
||||||
|
}
|
||||||
|
parts = append(parts, tag)
|
||||||
|
}
|
||||||
|
|
||||||
|
parts = append(parts, message)
|
||||||
|
logLine := strings.Join(parts, " ") + "\n"
|
||||||
|
|
||||||
l.mu.Lock()
|
l.mu.Lock()
|
||||||
_, _ = fmt.Fprint(l.writer, logLine)
|
_, _ = fmt.Fprint(l.writer, logLine)
|
||||||
|
if logType == TypeFatal {
|
||||||
// For fatal errors, ensure we sync immediately
|
|
||||||
if level == LevelFatal {
|
|
||||||
if f, ok := l.writer.(*os.File); ok {
|
if f, ok := l.writer.(*os.File); ok {
|
||||||
_ = f.Sync()
|
_ = f.Sync()
|
||||||
}
|
}
|
||||||
@ -234,15 +197,12 @@ func (l *Logger) writeMessage(level int, message string, rawMode bool) {
|
|||||||
l.mu.Unlock()
|
l.mu.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
// log handles the core logging logic with level filtering
|
func (l *Logger) log(logType int, format string, args ...any) {
|
||||||
func (l *Logger) log(level int, format string, args ...any) {
|
// Only filter debug messages
|
||||||
// Check if we should log this message
|
if logType == TypeDebug && !l.debugMode.Load() {
|
||||||
// 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
|
||||||
}
|
}
|
||||||
|
|
||||||
// Format message
|
|
||||||
var message string
|
var message string
|
||||||
if len(args) > 0 {
|
if len(args) > 0 {
|
||||||
message = fmt.Sprintf(format, args...)
|
message = fmt.Sprintf(format, args...)
|
||||||
@ -250,21 +210,14 @@ func (l *Logger) log(level int, format string, args ...any) {
|
|||||||
message = format
|
message = format
|
||||||
}
|
}
|
||||||
|
|
||||||
l.writeMessage(level, message, false)
|
l.writeMessage(logType, message, false)
|
||||||
|
|
||||||
// Exit on fatal errors
|
if logType == TypeFatal {
|
||||||
if level == LevelFatal {
|
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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
|
|
||||||
if LevelInfo < l.level {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var message string
|
var message string
|
||||||
if len(args) > 0 {
|
if len(args) > 0 {
|
||||||
message = fmt.Sprintf(format, args...)
|
message = fmt.Sprintf(format, args...)
|
||||||
@ -272,163 +225,128 @@ func (l *Logger) LogRaw(format string, args ...any) {
|
|||||||
message = format
|
message = format
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't apply colors if disabled
|
|
||||||
if !l.useColors {
|
if !l.useColors {
|
||||||
// Strip ANSI color codes if colors are disabled
|
|
||||||
message = stripAnsiColors(message)
|
message = stripAnsiColors(message)
|
||||||
}
|
}
|
||||||
|
|
||||||
l.writeMessage(LevelInfo, message, true)
|
l.writeMessage(TypeInfo, message, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Debug logs a debug message
|
|
||||||
func (l *Logger) Debug(format string, args ...any) {
|
func (l *Logger) Debug(format string, args ...any) {
|
||||||
l.log(LevelDebug, format, args...)
|
l.log(TypeDebug, format, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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(TypeInfo, format, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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(TypeWarning, format, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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(TypeError, format, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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(TypeFatal, format, args...)
|
||||||
// No need for os.Exit here as it's handled in log()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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(TypeServer, format, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Global helper functions that use the global logger
|
func (l *Logger) LogRequest(statusCode int, method, path string, duration time.Duration) {
|
||||||
|
var statusColor string
|
||||||
|
|
||||||
// Debug logs a debug message to the global logger
|
switch {
|
||||||
|
case statusCode < 300:
|
||||||
|
statusColor = colorGreen
|
||||||
|
case statusCode < 400:
|
||||||
|
statusColor = colorCyan
|
||||||
|
case statusCode < 500:
|
||||||
|
statusColor = colorYellow
|
||||||
|
default:
|
||||||
|
statusColor = colorRed
|
||||||
|
}
|
||||||
|
|
||||||
|
var durationStr string
|
||||||
|
micros := duration.Microseconds()
|
||||||
|
if micros < 1000 {
|
||||||
|
durationStr = fmt.Sprintf("%.0fµs", float64(micros))
|
||||||
|
} else if micros < 1000000 {
|
||||||
|
durationStr = fmt.Sprintf("%.1fms", float64(micros)/1000)
|
||||||
|
} else {
|
||||||
|
durationStr = fmt.Sprintf("%.2fs", duration.Seconds())
|
||||||
|
}
|
||||||
|
|
||||||
|
message := fmt.Sprintf("%s %s %s %s",
|
||||||
|
l.applyColor("["+method+"]", colorGray),
|
||||||
|
l.applyColor(fmt.Sprintf("%d", statusCode), statusColor),
|
||||||
|
l.applyColor(path, colorGray),
|
||||||
|
l.applyColor(durationStr, colorGray),
|
||||||
|
)
|
||||||
|
|
||||||
|
l.writeMessage(TypeNone, message, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Global functions
|
||||||
func Debug(format string, args ...any) {
|
func Debug(format string, args ...any) {
|
||||||
GetLogger().Debug(format, args...)
|
GetLogger().Debug(format, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetLevel changes the minimum log level of the global logger
|
|
||||||
func SetLevel(level int) {
|
|
||||||
GetLogger().SetLevel(level)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetOutput changes the output destination of the global logger
|
|
||||||
func SetOutput(w io.Writer) {
|
func SetOutput(w io.Writer) {
|
||||||
GetLogger().SetOutput(w)
|
GetLogger().SetOutput(w)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TimeFormat returns the current time format of the global logger
|
|
||||||
func TimeFormat() string {
|
func TimeFormat() string {
|
||||||
return GetLogger().TimeFormat()
|
return GetLogger().TimeFormat()
|
||||||
}
|
}
|
||||||
|
|
||||||
// EnableDebug enables debug messages regardless of log level
|
|
||||||
func EnableDebug() {
|
func EnableDebug() {
|
||||||
GetLogger().EnableDebug()
|
GetLogger().EnableDebug()
|
||||||
}
|
}
|
||||||
|
|
||||||
// DisableDebug disables forced debug messages
|
|
||||||
func DisableDebug() {
|
func DisableDebug() {
|
||||||
GetLogger().DisableDebug()
|
GetLogger().DisableDebug()
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsDebugEnabled returns true if debug mode is enabled
|
|
||||||
func IsDebugEnabled() bool {
|
func IsDebugEnabled() bool {
|
||||||
return GetLogger().IsDebugEnabled()
|
return GetLogger().IsDebugEnabled()
|
||||||
}
|
}
|
||||||
|
|
||||||
// EnableTimestamp enables timestamp display
|
|
||||||
func EnableTimestamp() {
|
func EnableTimestamp() {
|
||||||
GetLogger().EnableTimestamp()
|
GetLogger().EnableTimestamp()
|
||||||
}
|
}
|
||||||
|
|
||||||
// DisableTimestamp disables timestamp display
|
|
||||||
func DisableTimestamp() {
|
func DisableTimestamp() {
|
||||||
GetLogger().DisableTimestamp()
|
GetLogger().DisableTimestamp()
|
||||||
}
|
}
|
||||||
|
|
||||||
// LogSpacer adds a horizontal line separator to the log output
|
func LogRequest(statusCode int, method, path string, duration time.Duration) {
|
||||||
func (l *Logger) LogSpacer() {
|
GetLogger().LogRequest(statusCode, method, path, duration)
|
||||||
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 {
|
|
||||||
timeStr := l.applyColor(strings.Repeat("-", timeWidth), colorGray)
|
|
||||||
tagStr := l.applyColor(tagSpacer, colorCyan)
|
|
||||||
spacer = fmt.Sprintf("%s %s %s\n", timeStr, tagStr, 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 {
|
|
||||||
tagStr := l.applyColor(tagSpacer, colorCyan)
|
|
||||||
spacer = fmt.Sprintf("%s %s\n", tagStr, 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()
|
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ import (
|
|||||||
|
|
||||||
"Moonshark/routers"
|
"Moonshark/routers"
|
||||||
"Moonshark/runner"
|
"Moonshark/runner"
|
||||||
|
"Moonshark/utils/color"
|
||||||
"Moonshark/utils/logger"
|
"Moonshark/utils/logger"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -47,7 +48,7 @@ func WatchLuaRouter(router *routers.LuaRouter, runner *runner.Runner, routesDir
|
|||||||
return nil, fmt.Errorf("failed to watch directory: %w", err)
|
return nil, fmt.Errorf("failed to watch directory: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Info("Started watching Lua routes directory: %s", routesDir)
|
logger.Info("Started watching Lua routes! %s", color.Apply(routesDir, color.Yellow))
|
||||||
return watcher, nil
|
return watcher, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -76,7 +77,7 @@ func WatchLuaModules(luaRunner *runner.Runner, libDirs []string) ([]*DirectoryWa
|
|||||||
}
|
}
|
||||||
|
|
||||||
watchers = append(watchers, watcher)
|
watchers = append(watchers, watcher)
|
||||||
logger.Info("Started watching Lua modules directory: %s", dir)
|
logger.Info("Started watching Lua modules! %s", color.Apply(dir, color.Yellow))
|
||||||
}
|
}
|
||||||
|
|
||||||
return watchers, nil
|
return watchers, nil
|
||||||
|
Loading…
x
Reference in New Issue
Block a user