fix: log management race condition, partial delete reporting, and UX issues

- Fix data race on gin.DefaultWriter during log rotation by adding LogWriterMu
- Report partial failure when some log files fail to delete instead of always returning success
- Fix misleading "logging disabled" banner shown before API responds
- Fix en.json translation for numeric validation message
This commit is contained in:
RedwindA
2026-03-21 20:40:39 +08:00
parent e904579a5b
commit dcd0911612
5 changed files with 44 additions and 20 deletions

View File

@@ -3,53 +3,60 @@ package common
import (
"fmt"
"os"
"sync"
"time"
"github.com/gin-gonic/gin"
)
// LogWriterMu protects concurrent access to gin.DefaultWriter/gin.DefaultErrorWriter
// during log file rotation. Acquire RLock when reading/writing through the writers,
// acquire Lock when swapping writers and closing old files.
var LogWriterMu sync.RWMutex
func SysLog(s string) {
t := time.Now()
LogWriterMu.RLock()
_, _ = fmt.Fprintf(gin.DefaultWriter, "[SYS] %v | %s \n", t.Format("2006/01/02 - 15:04:05"), s)
LogWriterMu.RUnlock()
}
func SysError(s string) {
t := time.Now()
LogWriterMu.RLock()
_, _ = fmt.Fprintf(gin.DefaultErrorWriter, "[SYS] %v | %s \n", t.Format("2006/01/02 - 15:04:05"), s)
LogWriterMu.RUnlock()
}
func FatalLog(v ...any) {
t := time.Now()
LogWriterMu.RLock()
_, _ = fmt.Fprintf(gin.DefaultErrorWriter, "[FATAL] %v | %v \n", t.Format("2006/01/02 - 15:04:05"), v)
LogWriterMu.RUnlock()
os.Exit(1)
}
func LogStartupSuccess(startTime time.Time, port string) {
duration := time.Since(startTime)
durationMs := duration.Milliseconds()
// Get network IPs
networkIps := GetNetworkIps()
// Print blank line for spacing
fmt.Fprintf(gin.DefaultWriter, "\n")
LogWriterMu.RLock()
defer LogWriterMu.RUnlock()
// Print the main success message
fmt.Fprintf(gin.DefaultWriter, "\n")
fmt.Fprintf(gin.DefaultWriter, " \033[32m%s %s\033[0m ready in %d ms\n", SystemName, Version, durationMs)
fmt.Fprintf(gin.DefaultWriter, "\n")
// Skip fancy startup message in container environments
if !IsRunningInContainer() {
// Print local URL
fmt.Fprintf(gin.DefaultWriter, " ➜ \033[1mLocal:\033[0m http://localhost:%s/\n", port)
}
// Print network URLs
for _, ip := range networkIps {
fmt.Fprintf(gin.DefaultWriter, " ➜ \033[1mNetwork:\033[0m http://%s:%s/\n", ip, port)
}
// Print blank line for spacing
fmt.Fprintf(gin.DefaultWriter, "\n")
}