fix logger, update http settings
This commit is contained in:
parent
4f02f0e5bf
commit
d8f7b9a1de
|
@ -1,2 +1,6 @@
|
||||||
# Moonshark
|
# Moonshark
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git submodule update --init --recursive
|
||||||
|
git submodule update --remote --recursive
|
||||||
|
```
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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()
|
|
||||||
}
|
|
||||||
|
|
|
@ -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
2
luajit
|
@ -1 +1 @@
|
||||||
Subproject commit 98ca857d73956bf69a07641710b678c11681319f
|
Subproject commit 13686b3e66b388a31d459fe95d1aa3bfa05aeb27
|
|
@ -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")
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user