fix logger, update http settings

This commit is contained in:
Sky Johnson 2025-03-12 17:38:00 -05:00
parent 4f02f0e5bf
commit d8f7b9a1de
6 changed files with 58 additions and 107 deletions

View File

@ -1,2 +1,6 @@
# Moonshark # Moonshark
```bash
git submodule update --init --recursive
git submodule update --remote --recursive
```

View File

@ -3,6 +3,7 @@ package http
import ( import (
"context" "context"
"encoding/json" "encoding/json"
"net"
"net/http" "net/http"
"time" "time"
@ -20,16 +21,40 @@ type Server struct {
httpServer *http.Server httpServer *http.Server
} }
// New creates a new HTTP server // New creates a new HTTP server with optimized connection settings
func New(luaRouter *routers.LuaRouter, staticRouter *routers.StaticRouter, pool *workers.Pool, log *logger.Logger) *Server { func New(luaRouter *routers.LuaRouter, staticRouter *routers.StaticRouter, pool *workers.Pool, log *logger.Logger) *Server {
server := &Server{ server := &Server{
luaRouter: luaRouter, luaRouter: luaRouter,
staticRouter: staticRouter, staticRouter: staticRouter,
workerPool: pool, workerPool: pool,
logger: log, logger: log,
httpServer: &http.Server{}, httpServer: &http.Server{
// Connection timeouts
ReadTimeout: 30 * time.Second,
WriteTimeout: 30 * time.Second,
IdleTimeout: 120 * time.Second,
ReadHeaderTimeout: 10 * time.Second,
// Improved connection handling
MaxHeaderBytes: 1 << 16, // 64KB
},
} }
server.httpServer.Handler = server server.httpServer.Handler = server
// Set TCP keep-alive settings for the underlying TCP connections
server.httpServer.ConnState = func(conn net.Conn, state http.ConnState) {
if state == http.StateNew {
if tcpConn, ok := conn.(*net.TCPConn); ok {
// Enable TCP keep-alive
tcpConn.SetKeepAlive(true)
tcpConn.SetKeepAlivePeriod(30 * time.Second)
// Set TCP_NODELAY (disable Nagle's algorithm)
tcpConn.SetNoDelay(true)
}
}
}
return server return server
} }

View File

@ -34,56 +34,39 @@ var levelProps = map[int]struct {
tag string tag string
color string color string
}{ }{
LevelDebug: {" DBG", colorCyan}, LevelDebug: {"DBG", colorCyan},
LevelInfo: {"INFO", colorBlue}, LevelInfo: {"INF", colorBlue},
LevelWarning: {"WARN", colorYellow}, LevelWarning: {"WRN", colorYellow},
LevelError: {" ERR", colorRed}, LevelError: {"ERR", colorRed},
LevelFatal: {"FATL", colorPurple}, LevelFatal: {"FTL", colorPurple},
} }
// Time format for log messages // Time format for log messages
const timeFormat = "15:04:05" const timeFormat = "15:04:05"
// logMessage represents a message to be logged
type logMessage struct {
level int
message string
rawMode bool // Indicates if raw formatting should be used
}
// Logger handles logging operations // Logger handles logging operations
type Logger struct { type Logger struct {
writer io.Writer writer io.Writer
messages chan logMessage
wg sync.WaitGroup
level int level int
useColors bool useColors bool
done chan struct{}
timeFormat string timeFormat string
mu sync.Mutex // Mutex for thread-safe writing mu sync.Mutex // Mutex for thread-safe writing
} }
// New creates a new logger // New creates a new logger
func New(minLevel int, useColors bool) *Logger { func New(minLevel int, useColors bool) *Logger {
l := &Logger{ return &Logger{
writer: os.Stdout, writer: os.Stdout,
messages: make(chan logMessage, 100), // Buffer 100 messages
level: minLevel, level: minLevel,
useColors: useColors, useColors: useColors,
done: make(chan struct{}),
timeFormat: timeFormat, timeFormat: timeFormat,
} }
l.wg.Add(1)
go l.processLogs()
return l
} }
// SetOutput changes the output destination // 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() defer l.mu.Unlock()
l.writer = w l.writer = w
} }
@ -112,67 +95,45 @@ func (l *Logger) DisableColors() {
l.useColors = false l.useColors = false
} }
// processLogs processes incoming log messages // writeMessage writes a formatted log message directly to the writer
func (l *Logger) processLogs() { func (l *Logger) writeMessage(level int, message string, rawMode bool) {
defer l.wg.Done()
for {
select {
case msg := <-l.messages:
if msg.level >= l.level {
l.writeMessage(msg)
}
case <-l.done:
// Process remaining messages
for {
select {
case msg := <-l.messages:
if msg.level >= l.level {
l.writeMessage(msg)
}
default:
return
}
}
}
}
}
// writeMessage writes a formatted log message
func (l *Logger) writeMessage(msg logMessage) {
var logLine string var logLine string
if msg.rawMode { if rawMode {
// Raw mode - message is already formatted, just append newline // Raw mode - message is already formatted, just append newline
logLine = msg.message + "\n" logLine = message + "\n"
} else { } else {
// Standard format with timestamp, level tag, and message // Standard format with timestamp, level tag, and message
now := time.Now().Format(l.timeFormat) now := time.Now().Format(l.timeFormat)
props := levelProps[msg.level] props := levelProps[level]
if l.useColors { if l.useColors {
logLine = fmt.Sprintf("%s %s[%s]%s %s\n", logLine = fmt.Sprintf("%s %s[%s]%s %s\n",
now, props.color, props.tag, colorReset, msg.message) now, 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, msg.message) now, props.tag, message)
} }
} }
// Synchronize writing // Asynchronously write the log message
l.mu.Lock() go func(w io.Writer, data string) {
_, _ = fmt.Fprint(l.writer, logLine) l.mu.Lock()
l.mu.Unlock() _, _ = fmt.Fprint(w, data)
l.mu.Unlock()
}(l.writer, logLine)
// Auto-flush for fatal errors // For fatal errors, ensure we sync immediately in the current goroutine
if msg.level == LevelFatal { if level == LevelFatal {
l.mu.Lock()
if f, ok := l.writer.(*os.File); ok { if f, ok := l.writer.(*os.File); ok {
_ = f.Sync() _ = f.Sync()
} }
l.mu.Unlock()
} }
} }
// log sends a message to the logger goroutine // log handles the core logging logic with level filtering
func (l *Logger) log(level int, format string, args ...any) { func (l *Logger) log(level int, format string, args ...any) {
if level < l.level { if level < l.level {
return return
@ -185,18 +146,10 @@ func (l *Logger) log(level int, format string, args ...any) {
message = format message = format
} }
// Don't block if channel is full l.writeMessage(level, message, false)
select {
case l.messages <- logMessage{level: level, message: message, rawMode: false}:
// Message sent
default:
// Channel full, write directly
l.writeMessage(logMessage{level: level, message: message, rawMode: false})
}
// Exit on fatal errors // Exit on fatal errors
if level == LevelFatal { if level == LevelFatal {
l.Close()
os.Exit(1) os.Exit(1)
} }
} }
@ -218,18 +171,10 @@ func (l *Logger) LogRaw(format string, args ...any) {
// Don't apply colors if disabled // Don't apply colors if disabled
if !l.useColors { if !l.useColors {
// Strip ANSI color codes if colors are disabled // Strip ANSI color codes if colors are disabled
// Simple approach to strip common ANSI codes
message = removeAnsiColors(message) message = removeAnsiColors(message)
} }
// Don't block if channel is full l.writeMessage(LevelInfo, message, true)
select {
case l.messages <- logMessage{level: LevelInfo, message: message, rawMode: true}:
// Message sent
default:
// Channel full, write directly
l.writeMessage(logMessage{level: LevelInfo, message: message, rawMode: true})
}
} }
// Simple helper to remove ANSI color codes // Simple helper to remove ANSI color codes
@ -282,13 +227,6 @@ func (l *Logger) Fatal(format string, args ...any) {
// No need for os.Exit here as it's handled in log() // No need for os.Exit here as it's handled in log()
} }
// Close shuts down the logger goroutine
func (l *Logger) Close() {
close(l.done)
l.wg.Wait()
close(l.messages)
}
// Default global logger // Default global logger
var defaultLogger = New(LevelInfo, true) var defaultLogger = New(LevelInfo, true)
@ -331,8 +269,3 @@ func SetLevel(level int) {
func SetOutput(w io.Writer) { func SetOutput(w io.Writer) {
defaultLogger.SetOutput(w) defaultLogger.SetOutput(w)
} }
// Close shuts down the default logger
func Close() {
defaultLogger.Close()
}

View File

@ -64,8 +64,6 @@ func TestLoggerLevels(t *testing.T) {
if !strings.Contains(buf.String(), "[ERR]") { if !strings.Contains(buf.String(), "[ERR]") {
t.Errorf("Error message not logged after level change, got: %q", buf.String()) t.Errorf("Error message not logged after level change, got: %q", buf.String())
} }
logger.Close()
} }
func TestLoggerConcurrency(t *testing.T) { func TestLoggerConcurrency(t *testing.T) {
@ -96,8 +94,6 @@ func TestLoggerConcurrency(t *testing.T) {
break break
} }
} }
logger.Close()
} }
func TestLoggerColors(t *testing.T) { func TestLoggerColors(t *testing.T) {
@ -124,8 +120,6 @@ func TestLoggerColors(t *testing.T) {
if strings.Contains(content, "\033[") { if strings.Contains(content, "\033[") {
t.Errorf("Color codes present when disabled, got: %q", content) t.Errorf("Color codes present when disabled, got: %q", content)
} }
logger.Close()
} }
func TestDefaultLogger(t *testing.T) { func TestDefaultLogger(t *testing.T) {
@ -139,8 +133,6 @@ func TestDefaultLogger(t *testing.T) {
if !strings.Contains(content, "[INF]") { if !strings.Contains(content, "[INF]") {
t.Errorf("Default logger not working, got: %q", content) t.Errorf("Default logger not working, got: %q", content)
} }
Close()
} }
func BenchmarkLogger(b *testing.B) { func BenchmarkLogger(b *testing.B) {
@ -152,7 +144,6 @@ func BenchmarkLogger(b *testing.B) {
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
logger.Info("Benchmark message %d", i) logger.Info("Benchmark message %d", i)
} }
logger.Close()
} }
func BenchmarkLoggerParallel(b *testing.B) { func BenchmarkLoggerParallel(b *testing.B) {
@ -168,5 +159,4 @@ func BenchmarkLoggerParallel(b *testing.B) {
i++ i++
} }
}) })
logger.Close()
} }

2
luajit

@ -1 +1 @@
Subproject commit 98ca857d73956bf69a07641710b678c11681319f Subproject commit 13686b3e66b388a31d459fe95d1aa3bfa05aeb27

View File

@ -47,7 +47,6 @@ func initRouters(routesDir, staticDir string, log *logger.Logger) (*routers.LuaR
func main() { func main() {
// Initialize logger // Initialize logger
log := logger.New(logger.LevelDebug, true) log := logger.New(logger.LevelDebug, true)
defer log.Close()
log.Info("Starting Moonshark server") log.Info("Starting Moonshark server")