add log rotate to 3xui.log file to avoid disk space consumption (#4277)

* add log rotate to 3xui.log file to avoid disk space consumption
This commit is contained in:
Amirmohammad Sadat Shokouhi
2026-05-13 18:33:56 +03:30
committed by GitHub
parent 6c6b40e063
commit 4399fe2a85
3 changed files with 27 additions and 19 deletions
+1
View File
@@ -26,6 +26,7 @@ require (
golang.org/x/sys v0.44.0 golang.org/x/sys v0.44.0
golang.org/x/text v0.37.0 golang.org/x/text v0.37.0
google.golang.org/grpc v1.81.0 google.golang.org/grpc v1.81.0
gopkg.in/natefinch/lumberjack.v2 v2.2.1
gorm.io/driver/sqlite v1.6.0 gorm.io/driver/sqlite v1.6.0
gorm.io/gorm v1.31.1 gorm.io/gorm v1.31.1
) )
+2
View File
@@ -265,6 +265,8 @@ google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc=
gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+24 -19
View File
@@ -11,17 +11,25 @@ import (
"github.com/mhsanaei/3x-ui/v3/config" "github.com/mhsanaei/3x-ui/v3/config"
"github.com/op/go-logging" "github.com/op/go-logging"
"gopkg.in/natefinch/lumberjack.v2"
) )
const ( const (
maxLogBufferSize = 10240 // Maximum log entries kept in memory maxLogBufferSize = 10240 // Maximum log entries kept in memory
logFileName = "3xui.log" // Log file name logFileName = "3xui.log" // Log file name
timeFormat = "2006/01/02 15:04:05" // Log timestamp format timeFormat = "2006/01/02 15:04:05" // Log timestamp format
// On-disk rotation limits — single file capped, old segments pruned automatically.
maxLogFileMB = 10 // rotate active log when larger than this
maxLogBackups = 5 // rotated files retained (beyond current segment)
maxLogAgeDays = 7 // remove rotated backups older than this (0 disables time-based pruning)
compressRotated = true
) )
var ( var (
logger *logging.Logger logger *logging.Logger
logFile *os.File fileRotate *lumberjack.Logger // nil when file backend disabled
// logBuffer maintains recent log entries in memory for web UI retrieval // logBuffer maintains recent log entries in memory for web UI retrieval
logBuffer []struct { logBuffer []struct {
@@ -81,8 +89,8 @@ func initDefaultBackend() logging.Backend {
return logging.NewBackendFormatter(backend, newFormatter(includeTime)) return logging.NewBackendFormatter(backend, newFormatter(includeTime))
} }
// initFileBackend creates the file logging backend. // initFileBackend creates the file logging backend with size/agebounded rotation
// Creates log directory and truncates log file on startup for fresh logs. // so log volume cannot grow without limit on disk.
func initFileBackend() logging.Backend { func initFileBackend() logging.Backend {
logDir := config.GetLogFolder() logDir := config.GetLogFolder()
if err := os.MkdirAll(logDir, 0o750); err != nil { if err := os.MkdirAll(logDir, 0o750); err != nil {
@@ -91,19 +99,16 @@ func initFileBackend() logging.Backend {
} }
logPath := filepath.Join(logDir, logFileName) logPath := filepath.Join(logDir, logFileName)
file, err := os.OpenFile(logPath, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0o660) fileRotate = &lumberjack.Logger{
if err != nil { Filename: logPath,
fmt.Fprintf(os.Stderr, "failed to open log file %s: %v\n", logPath, err) MaxSize: maxLogFileMB,
return nil MaxBackups: maxLogBackups,
MaxAge: maxLogAgeDays,
LocalTime: true,
Compress: compressRotated,
} }
// Close previous log file if exists backend := logging.NewLogBackend(fileRotate, "", 0)
if logFile != nil {
_ = logFile.Close()
}
logFile = file
backend := logging.NewLogBackend(file, "", 0)
return logging.NewBackendFormatter(backend, newFormatter(true)) return logging.NewBackendFormatter(backend, newFormatter(true))
} }
@@ -116,12 +121,12 @@ func newFormatter(withTime bool) logging.Formatter {
return logging.MustStringFormatter(format) return logging.MustStringFormatter(format)
} }
// CloseLogger closes the log file and cleans up resources. // CloseLogger closes the rotating log writer and cleans up resources.
// Should be called during application shutdown. // Should be called during application shutdown.
func CloseLogger() { func CloseLogger() {
if logFile != nil { if fileRotate != nil {
_ = logFile.Close() _ = fileRotate.Close()
logFile = nil fileRotate = nil
} }
} }