feat(logger): add size/age/backup rotation for file output (#874)
This commit is contained in:
@@ -136,6 +136,10 @@ func realMain() int {
|
||||
Level: cfg.Logging.Level,
|
||||
Format: cfg.Logging.Format,
|
||||
OutputPath: cfg.Logging.OutputPath,
|
||||
MaxSizeMB: cfg.Logging.MaxSizeMB,
|
||||
MaxBackups: cfg.Logging.MaxBackups,
|
||||
MaxAgeDays: cfg.Logging.MaxAgeDays,
|
||||
Compress: cfg.Logging.Compress,
|
||||
})
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Failed to initialize logger: %v\n", err)
|
||||
|
||||
@@ -109,6 +109,7 @@ require (
|
||||
google.golang.org/grpc v1.80.0 // indirect
|
||||
google.golang.org/protobuf v1.36.11 // indirect
|
||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
|
||||
gotest.tools/v3 v3.5.2 // indirect
|
||||
)
|
||||
|
||||
|
||||
@@ -683,6 +683,8 @@ gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EV
|
||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
|
||||
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
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.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
|
||||
@@ -140,6 +140,13 @@ type LoggingConfig struct {
|
||||
Level string `mapstructure:"level"`
|
||||
Format string `mapstructure:"format"`
|
||||
OutputPath string `mapstructure:"outputPath"`
|
||||
|
||||
// Rotation options — apply only when OutputPath is a file path
|
||||
// (ignored for stdout/stderr). Backed by lumberjack.
|
||||
MaxSizeMB int `mapstructure:"maxSizeMb"`
|
||||
MaxBackups int `mapstructure:"maxBackups"`
|
||||
MaxAgeDays int `mapstructure:"maxAgeDays"`
|
||||
Compress bool `mapstructure:"compress"`
|
||||
}
|
||||
|
||||
// RepositoryDiscoveryConfig holds configuration for local repository scanning.
|
||||
@@ -271,6 +278,10 @@ func setDefaults(v *viper.Viper) {
|
||||
v.SetDefault("logging.level", "info")
|
||||
v.SetDefault("logging.format", detectDefaultLogFormat())
|
||||
v.SetDefault("logging.outputPath", "stdout")
|
||||
v.SetDefault("logging.maxSizeMb", 100)
|
||||
v.SetDefault("logging.maxBackups", 5)
|
||||
v.SetDefault("logging.maxAgeDays", 30)
|
||||
v.SetDefault("logging.compress", true)
|
||||
|
||||
// Repository discovery defaults
|
||||
v.SetDefault("repositoryDiscovery.roots", []string{})
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
|
||||
"go.uber.org/zap"
|
||||
"go.uber.org/zap/zapcore"
|
||||
"gopkg.in/natefinch/lumberjack.v2"
|
||||
|
||||
"github.com/kandev/kandev/internal/common/logger/buffer"
|
||||
)
|
||||
@@ -25,6 +26,13 @@ type LoggingConfig struct {
|
||||
Level string `mapstructure:"level"` // debug, info, warn, error
|
||||
Format string `mapstructure:"format"` // json, console
|
||||
OutputPath string `mapstructure:"output_path"` // stdout, stderr, or file path
|
||||
|
||||
// Rotation options — apply only when OutputPath is a file path
|
||||
// (ignored for stdout/stderr). Backed by lumberjack.
|
||||
MaxSizeMB int `mapstructure:"max_size_mb"` // rotate when file exceeds this size; 0 = lumberjack default (100MB)
|
||||
MaxBackups int `mapstructure:"max_backups"` // max number of rotated files to retain; 0 = unlimited
|
||||
MaxAgeDays int `mapstructure:"max_age_days"` // max age of rotated files; 0 = unlimited
|
||||
Compress bool `mapstructure:"compress"` // gzip rotated files
|
||||
}
|
||||
|
||||
// Logger wraps zap.Logger to provide structured logging with helper methods.
|
||||
@@ -94,11 +102,13 @@ func NewLogger(cfg LoggingConfig) (*Logger, error) {
|
||||
case "stderr":
|
||||
writeSyncer = zapcore.AddSync(os.Stderr)
|
||||
default:
|
||||
file, err := os.OpenFile(cfg.OutputPath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
writeSyncer = zapcore.AddSync(file)
|
||||
writeSyncer = zapcore.AddSync(&lumberjack.Logger{
|
||||
Filename: cfg.OutputPath,
|
||||
MaxSize: cfg.MaxSizeMB,
|
||||
MaxBackups: cfg.MaxBackups,
|
||||
MaxAge: cfg.MaxAgeDays,
|
||||
Compress: cfg.Compress,
|
||||
})
|
||||
}
|
||||
|
||||
outputCore := zapcore.NewCore(encoder, writeSyncer, level)
|
||||
|
||||
Reference in New Issue
Block a user