Browse Source

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
Amirmohammad Sadat Shokouhi 1 day ago
parent
commit
4399fe2a85
3 changed files with 27 additions and 19 deletions
  1. 1 0
      go.mod
  2. 2 0
      go.sum
  3. 24 19
      logger/logger.go

+ 1 - 0
go.mod

@@ -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 - 0
go.sum

@@ -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
logger/logger.go

@@ -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
-	logFile *os.File
+	logger     *logging.Logger
+	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.
-// Creates log directory and truncates log file on startup for fresh logs.
+// initFileBackend creates the file logging backend with size/age‑bounded rotation
+// 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)
-	if err != nil {
-		fmt.Fprintf(os.Stderr, "failed to open log file %s: %v\n", logPath, err)
-		return nil
-	}
-
-	// Close previous log file if exists
-	if logFile != nil {
-		_ = logFile.Close()
+	fileRotate = &lumberjack.Logger{
+		Filename:   logPath,
+		MaxSize:    maxLogFileMB,
+		MaxBackups: maxLogBackups,
+		MaxAge:     maxLogAgeDays,
+		LocalTime:  true,
+		Compress:   compressRotated,
 	}
 	}
-	logFile = file
 
 
-	backend := logging.NewLogBackend(file, "", 0)
+	backend := logging.NewLogBackend(fileRotate, "", 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 {
-		_ = logFile.Close()
-		logFile = nil
+	if fileRotate != nil {
+		_ = fileRotate.Close()
+		fileRotate = nil
 	}
 	}
 }
 }