mirror of
https://github.com/router-for-me/CLIProxyAPI.git
synced 2026-02-03 04:50:52 +08:00
This commit introduces a new configuration option `logs-max-total-size-mb` that allows users to set a maximum total size (in MB) for log files in the logs directory. When this limit is exceeded, the oldest log files will be automatically deleted to stay within the specified size. Setting this value to 0 (the default) disables this feature. This change enhances log management by preventing excessive disk space usage.
167 lines
3.2 KiB
Go
167 lines
3.2 KiB
Go
package logging
|
|
|
|
import (
|
|
"context"
|
|
"os"
|
|
"path/filepath"
|
|
"sort"
|
|
"strings"
|
|
"time"
|
|
|
|
log "github.com/sirupsen/logrus"
|
|
)
|
|
|
|
const logDirCleanerInterval = time.Minute
|
|
|
|
var logDirCleanerCancel context.CancelFunc
|
|
|
|
func configureLogDirCleanerLocked(logDir string, maxTotalSizeMB int, protectedPath string) {
|
|
stopLogDirCleanerLocked()
|
|
|
|
if maxTotalSizeMB <= 0 {
|
|
return
|
|
}
|
|
|
|
maxBytes := int64(maxTotalSizeMB) * 1024 * 1024
|
|
if maxBytes <= 0 {
|
|
return
|
|
}
|
|
|
|
dir := strings.TrimSpace(logDir)
|
|
if dir == "" {
|
|
return
|
|
}
|
|
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
logDirCleanerCancel = cancel
|
|
go runLogDirCleaner(ctx, filepath.Clean(dir), maxBytes, strings.TrimSpace(protectedPath))
|
|
}
|
|
|
|
func stopLogDirCleanerLocked() {
|
|
if logDirCleanerCancel == nil {
|
|
return
|
|
}
|
|
logDirCleanerCancel()
|
|
logDirCleanerCancel = nil
|
|
}
|
|
|
|
func runLogDirCleaner(ctx context.Context, logDir string, maxBytes int64, protectedPath string) {
|
|
ticker := time.NewTicker(logDirCleanerInterval)
|
|
defer ticker.Stop()
|
|
|
|
cleanOnce := func() {
|
|
deleted, errClean := enforceLogDirSizeLimit(logDir, maxBytes, protectedPath)
|
|
if errClean != nil {
|
|
log.WithError(errClean).Warn("logging: failed to enforce log directory size limit")
|
|
return
|
|
}
|
|
if deleted > 0 {
|
|
log.Debugf("logging: removed %d old log file(s) to enforce log directory size limit", deleted)
|
|
}
|
|
}
|
|
|
|
cleanOnce()
|
|
for {
|
|
select {
|
|
case <-ctx.Done():
|
|
return
|
|
case <-ticker.C:
|
|
cleanOnce()
|
|
}
|
|
}
|
|
}
|
|
|
|
func enforceLogDirSizeLimit(logDir string, maxBytes int64, protectedPath string) (int, error) {
|
|
if maxBytes <= 0 {
|
|
return 0, nil
|
|
}
|
|
|
|
dir := strings.TrimSpace(logDir)
|
|
if dir == "" {
|
|
return 0, nil
|
|
}
|
|
dir = filepath.Clean(dir)
|
|
|
|
entries, errRead := os.ReadDir(dir)
|
|
if errRead != nil {
|
|
if os.IsNotExist(errRead) {
|
|
return 0, nil
|
|
}
|
|
return 0, errRead
|
|
}
|
|
|
|
protected := strings.TrimSpace(protectedPath)
|
|
if protected != "" {
|
|
protected = filepath.Clean(protected)
|
|
}
|
|
|
|
type logFile struct {
|
|
path string
|
|
size int64
|
|
modTime time.Time
|
|
}
|
|
|
|
var (
|
|
files []logFile
|
|
total int64
|
|
)
|
|
for _, entry := range entries {
|
|
if entry.IsDir() {
|
|
continue
|
|
}
|
|
name := entry.Name()
|
|
if !isLogFileName(name) {
|
|
continue
|
|
}
|
|
info, errInfo := entry.Info()
|
|
if errInfo != nil {
|
|
continue
|
|
}
|
|
if !info.Mode().IsRegular() {
|
|
continue
|
|
}
|
|
path := filepath.Join(dir, name)
|
|
files = append(files, logFile{
|
|
path: path,
|
|
size: info.Size(),
|
|
modTime: info.ModTime(),
|
|
})
|
|
total += info.Size()
|
|
}
|
|
|
|
if total <= maxBytes {
|
|
return 0, nil
|
|
}
|
|
|
|
sort.Slice(files, func(i, j int) bool {
|
|
return files[i].modTime.Before(files[j].modTime)
|
|
})
|
|
|
|
deleted := 0
|
|
for _, file := range files {
|
|
if total <= maxBytes {
|
|
break
|
|
}
|
|
if protected != "" && filepath.Clean(file.path) == protected {
|
|
continue
|
|
}
|
|
if errRemove := os.Remove(file.path); errRemove != nil {
|
|
log.WithError(errRemove).Warnf("logging: failed to remove old log file: %s", filepath.Base(file.path))
|
|
continue
|
|
}
|
|
total -= file.size
|
|
deleted++
|
|
}
|
|
|
|
return deleted, nil
|
|
}
|
|
|
|
func isLogFileName(name string) bool {
|
|
trimmed := strings.TrimSpace(name)
|
|
if trimmed == "" {
|
|
return false
|
|
}
|
|
lower := strings.ToLower(trimmed)
|
|
return strings.HasSuffix(lower, ".log") || strings.HasSuffix(lower, ".log.gz")
|
|
}
|