feat: add --log-level support for manager and scheduler (#4146)

Signed-off-by: Aaron Wang <aaron.wang@maiscrm.com>
Co-authored-by: Aaron Wang <aaron.wang@maiscrm.com>
This commit is contained in:
Aaron Wang 2025-06-24 11:53:31 +08:00 committed by GitHub
parent 917348d419
commit 1ba7014527
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 75 additions and 33 deletions

View File

@ -26,6 +26,7 @@ scheduler:
# when enabled, pprof will be enabled, # when enabled, pprof will be enabled,
verbose: true verbose: true
log-level: debug
console: false console: false
# current host info used for scheduler # current host info used for scheduler

View File

@ -19,6 +19,7 @@ package base
type Options struct { type Options struct {
Console bool `yaml:"console" mapstructure:"console"` Console bool `yaml:"console" mapstructure:"console"`
Verbose bool `yaml:"verbose" mapstructure:"verbose"` Verbose bool `yaml:"verbose" mapstructure:"verbose"`
LogLevel string `yaml:"log-level" mapstructure:"log-level"`
PProfPort int `yaml:"pprof-port" mapstructure:"pprof-port"` PProfPort int `yaml:"pprof-port" mapstructure:"pprof-port"`
Tracing TracingConfig `yaml:"tracing" mapstructure:"tracing"` Tracing TracingConfig `yaml:"tracing" mapstructure:"tracing"`
} }

View File

@ -72,6 +72,7 @@ func InitCommandAndConfig(cmd *cobra.Command, useConfigFile bool, config any) {
flags := cmd.PersistentFlags() flags := cmd.PersistentFlags()
flags.Bool("console", false, "whether logger output records to the stdout") flags.Bool("console", false, "whether logger output records to the stdout")
flags.Bool("verbose", false, "whether logger use debug level") flags.Bool("verbose", false, "whether logger use debug level")
flags.String("log-level", "", "use specific log level(debug, info, warn, error), take precedence over verbose flag")
flags.Int("pprof-port", -1, "listen port for pprof, 0 represents random port") flags.Int("pprof-port", -1, "listen port for pprof, 0 represents random port")
flags.String("config", "", fmt.Sprintf("the path of configuration file with yaml extension name, default is %s, it can also be set by env var: %s", filepath.Join(dfpath.DefaultConfigDir, rootName+".yaml"), strings.ToUpper(rootName+"_config"))) flags.String("config", "", fmt.Sprintf("the path of configuration file with yaml extension name, default is %s, it can also be set by env var: %s", filepath.Join(dfpath.DefaultConfigDir, rootName+".yaml"), strings.ToUpper(rootName+"_config")))

View File

@ -142,7 +142,7 @@ func runDfcacheSubcmd(ctx context.Context, cmdName string, args []string) error
MaxBackups: dfcacheConfig.LogMaxBackups} MaxBackups: dfcacheConfig.LogMaxBackups}
// Initialize logger // Initialize logger
if err := logger.InitDfcache(dfcacheConfig.Console, d.LogDir(), rotateConfig); err != nil { if err := logger.InitDfcache(dfcacheConfig.Verbose, dfcacheConfig.LogLevel, d.LogDir(), rotateConfig); err != nil {
return fmt.Errorf("init client dfcache logger: %w", err) return fmt.Errorf("init client dfcache logger: %w", err)
} }
logger.Infof("version:\n%s", version.Version()) logger.Infof("version:\n%s", version.Version())

View File

@ -80,7 +80,7 @@ it supports container engine, wget and other downloading tools through proxy fun
MaxBackups: cfg.LogMaxBackups} MaxBackups: cfg.LogMaxBackups}
// Initialize logger // Initialize logger
if err := logger.InitDaemon(cfg.Verbose, cfg.Console, d.LogDir(), rotateConfig); err != nil { if err := logger.InitDaemon(cfg.Verbose, cfg.LogLevel, cfg.Console, d.LogDir(), rotateConfig); err != nil {
return fmt.Errorf("init client daemon logger: %w", err) return fmt.Errorf("init client daemon logger: %w", err)
} }
logger.RedirectStdoutAndStderr(cfg.Console, path.Join(d.LogDir(), types.DaemonName)) logger.RedirectStdoutAndStderr(cfg.Console, path.Join(d.LogDir(), types.DaemonName))

View File

@ -94,7 +94,7 @@ var rootCmd = &cobra.Command{
MaxBackups: dfgetConfig.LogMaxBackups} MaxBackups: dfgetConfig.LogMaxBackups}
// Initialize logger // Initialize logger
if err := logger.InitDfget(dfgetConfig.Verbose, dfgetConfig.Console, d.LogDir(), rotateConfig); err != nil { if err := logger.InitDfget(dfgetConfig.Verbose, dfgetConfig.LogLevel, dfgetConfig.Console, d.LogDir(), rotateConfig); err != nil {
return fmt.Errorf("init client dfget logger: %w", err) return fmt.Errorf("init client dfget logger: %w", err)
} }

View File

@ -72,7 +72,7 @@ for managing schedulers and seed peers, offering http apis and portal, etc.`,
MaxBackups: cfg.Server.LogMaxBackups} MaxBackups: cfg.Server.LogMaxBackups}
// Initialize logger. // Initialize logger.
if err := logger.InitManager(cfg.Verbose, cfg.Console, d.LogDir(), rotateConfig); err != nil { if err := logger.InitManager(cfg.Verbose, cfg.LogLevel, cfg.Console, d.LogDir(), rotateConfig); err != nil {
return fmt.Errorf("init manager logger: %w", err) return fmt.Errorf("init manager logger: %w", err)
} }
logger.RedirectStdoutAndStderr(cfg.Console, path.Join(d.LogDir(), types.ManagerName)) logger.RedirectStdoutAndStderr(cfg.Console, path.Join(d.LogDir(), types.ManagerName))

View File

@ -72,7 +72,7 @@ generate and maintain a P2P network during the download process, and push suitab
MaxBackups: cfg.Server.LogMaxBackups} MaxBackups: cfg.Server.LogMaxBackups}
// Initialize logger. // Initialize logger.
if err := logger.InitScheduler(cfg.Verbose, cfg.Console, d.LogDir(), rotateConfig); err != nil { if err := logger.InitScheduler(cfg.Verbose, cfg.LogLevel, cfg.Console, d.LogDir(), rotateConfig); err != nil {
return fmt.Errorf("init scheduler logger: %w", err) return fmt.Errorf("init scheduler logger: %w", err)
} }
logger.RedirectStdoutAndStderr(cfg.Console, path.Join(d.LogDir(), types.SchedulerName)) logger.RedirectStdoutAndStderr(cfg.Console, path.Join(d.LogDir(), types.SchedulerName))

View File

@ -165,6 +165,9 @@ console: false
# Whether to enable debug level logger and enable pprof. # Whether to enable debug level logger and enable pprof.
verbose: true verbose: true
# Use specific log level(debug, info, warn, error), take precedence over verbose flag.
# log-level: debug
# Listen port for pprof, only valid when the verbose option is true, default is -1. # Listen port for pprof, only valid when the verbose option is true, default is -1.
pprof-port: -1 pprof-port: -1

View File

@ -181,6 +181,9 @@ console: false
# Whether to enable debug level logger and enable pprof. # Whether to enable debug level logger and enable pprof.
verbose: true verbose: true
# Use specific log level(debug, info, warn, error), take precedence over verbose flag.
# log-level: debug
# Listen port for pprof, only valid when the verbose option is true, default is -1. # Listen port for pprof, only valid when the verbose option is true, default is -1.
pprof-port: -1 pprof-port: -1

View File

@ -17,6 +17,7 @@
package logger package logger
import ( import (
"fmt"
"strings" "strings"
"go.uber.org/atomic" "go.uber.org/atomic"
@ -52,7 +53,7 @@ var customCoreLevel atomic.Bool
var grpcLevel = zap.NewAtomicLevelAt(zapcore.WarnLevel) var grpcLevel = zap.NewAtomicLevelAt(zapcore.WarnLevel)
var customGrpcLevel atomic.Bool var customGrpcLevel atomic.Bool
func CreateLogger(filePath string, compress bool, stats bool, verbose bool, config LogRotateConfig) (*zap.Logger, zap.AtomicLevel, error) { func CreateLogger(filePath string, compress bool, stats bool, verbose bool, logLevel string, config LogRotateConfig) (*zap.Logger, zap.AtomicLevel, error) {
rotateConfig := &lumberjack.Logger{ rotateConfig := &lumberjack.Logger{
Filename: filePath, Filename: filePath,
@ -66,10 +67,25 @@ func CreateLogger(filePath string, compress bool, stats bool, verbose bool, conf
encoderConfig := zap.NewProductionEncoderConfig() encoderConfig := zap.NewProductionEncoderConfig()
encoderConfig.EncodeTime = zapcore.TimeEncoderOfLayout(encodeTimeFormat) encoderConfig.EncodeTime = zapcore.TimeEncoderOfLayout(encodeTimeFormat)
var level = zap.NewAtomicLevel() var level = zap.NewAtomicLevelAt(zap.InfoLevel)
if verbose { // Use logLevel first, then fallback to verbose flag.
if logLevel != "" {
switch strings.ToLower(logLevel) {
case "debug":
level = zap.NewAtomicLevelAt(zapcore.DebugLevel)
case "info":
level = zap.NewAtomicLevelAt(zapcore.InfoLevel)
case "warn":
level = zap.NewAtomicLevelAt(zapcore.WarnLevel)
case "error":
level = zap.NewAtomicLevelAt(zapcore.ErrorLevel)
default:
fmt.Printf("Warning: invalid log level '%s', using 'info' instead\n", logLevel)
}
} else if verbose {
level = zap.NewAtomicLevelAt(zapcore.DebugLevel) level = zap.NewAtomicLevelAt(zapcore.DebugLevel)
} }
if strings.HasSuffix(filePath, GrpcLogFileName) && customGrpcLevel.Load() { if strings.HasSuffix(filePath, GrpcLogFileName) && customGrpcLevel.Load() {
level = grpcLevel level = grpcLevel
} else if strings.HasSuffix(filePath, CoreLogFileName) && customCoreLevel.Load() { } else if strings.HasSuffix(filePath, CoreLogFileName) && customCoreLevel.Load() {

View File

@ -17,10 +17,12 @@
package logger package logger
import ( import (
"fmt"
"io/fs" "io/fs"
"os" "os"
"path" "path"
"path/filepath" "path/filepath"
"strings"
"go.uber.org/zap" "go.uber.org/zap"
@ -33,9 +35,9 @@ type logInitMeta struct {
setLoggerFunc func(log *zap.Logger) setLoggerFunc func(log *zap.Logger)
} }
func InitManager(verbose, console bool, dir string, rotateConfig LogRotateConfig) error { func InitManager(verbose bool, logLevel string, console bool, dir string, rotateConfig LogRotateConfig) error {
if console { if console {
return createConsoleLogger(verbose) return createConsoleLogger(verbose, logLevel)
} }
logDir := filepath.Join(dir, types.ManagerName) logDir := filepath.Join(dir, types.ManagerName)
@ -62,12 +64,12 @@ func InitManager(verbose, console bool, dir string, rotateConfig LogRotateConfig
}, },
} }
return createFileLogger(verbose, meta, logDir, rotateConfig) return createFileLogger(verbose, logLevel, meta, logDir, rotateConfig)
} }
func InitScheduler(verbose, console bool, dir string, rotateConfig LogRotateConfig) error { func InitScheduler(verbose bool, logLevel string, console bool, dir string, rotateConfig LogRotateConfig) error {
if console { if console {
return createConsoleLogger(verbose) return createConsoleLogger(verbose, logLevel)
} }
logDir := filepath.Join(dir, types.SchedulerName) logDir := filepath.Join(dir, types.SchedulerName)
@ -90,12 +92,12 @@ func InitScheduler(verbose, console bool, dir string, rotateConfig LogRotateConf
}, },
} }
return createFileLogger(verbose, meta, logDir, rotateConfig) return createFileLogger(verbose, logLevel, meta, logDir, rotateConfig)
} }
func InitDaemon(verbose, console bool, dir string, rotateConfig LogRotateConfig) error { func InitDaemon(verbose bool, logLevel string, console bool, dir string, rotateConfig LogRotateConfig) error {
if console { if console {
return createConsoleLogger(verbose) return createConsoleLogger(verbose, logLevel)
} }
logDir := filepath.Join(dir, types.DaemonName) logDir := filepath.Join(dir, types.DaemonName)
@ -118,12 +120,12 @@ func InitDaemon(verbose, console bool, dir string, rotateConfig LogRotateConfig)
}, },
} }
return createFileLogger(verbose, meta, logDir, rotateConfig) return createFileLogger(verbose, logLevel, meta, logDir, rotateConfig)
} }
func InitDfget(verbose, console bool, dir string, rotateConfig LogRotateConfig) error { func InitDfget(verbose bool, logLevel string, console bool, dir string, rotateConfig LogRotateConfig) error {
if console { if console {
return createConsoleLogger(verbose) return createConsoleLogger(verbose, logLevel)
} }
logDir := filepath.Join(dir, types.DfgetName) logDir := filepath.Join(dir, types.DfgetName)
@ -138,10 +140,10 @@ func InitDfget(verbose, console bool, dir string, rotateConfig LogRotateConfig)
}, },
} }
return createFileLogger(verbose, meta, logDir, rotateConfig) return createFileLogger(verbose, logLevel, meta, logDir, rotateConfig)
} }
func InitDfcache(console bool, dir string, rotateConfig LogRotateConfig) error { func InitDfcache(verbose bool, logLevel string, dir string, rotateConfig LogRotateConfig) error {
logDir := filepath.Join(dir, types.DfcacheName) logDir := filepath.Join(dir, types.DfcacheName)
var meta = []logInitMeta{ var meta = []logInitMeta{
{ {
@ -154,16 +156,31 @@ func InitDfcache(console bool, dir string, rotateConfig LogRotateConfig) error {
}, },
} }
return createFileLogger(console, meta, logDir, rotateConfig) return createFileLogger(verbose, logLevel, meta, logDir, rotateConfig)
} }
func createConsoleLogger(verbose bool) error { func createConsoleLogger(verbose bool, logLevel string) error {
levels = nil levels = nil
config := zap.NewDevelopmentConfig() config := zap.NewDevelopmentConfig()
config.Level = zap.NewAtomicLevelAt(zap.InfoLevel) config.Level = zap.NewAtomicLevelAt(zap.InfoLevel)
if verbose { // Use logLevel first, then fallback to verbose flag.
if logLevel != "" {
switch strings.ToLower(logLevel) {
case "debug":
config.Level = zap.NewAtomicLevelAt(zap.DebugLevel)
case "info":
config.Level = zap.NewAtomicLevelAt(zap.InfoLevel)
case "warn":
config.Level = zap.NewAtomicLevelAt(zap.WarnLevel)
case "error":
config.Level = zap.NewAtomicLevelAt(zap.ErrorLevel)
default:
fmt.Printf("Warning: invalid log level '%s', using 'info' instead\n", logLevel)
}
} else if verbose {
config.Level = zap.NewAtomicLevelAt(zap.DebugLevel) config.Level = zap.NewAtomicLevelAt(zap.DebugLevel)
} }
log, err := config.Build(zap.AddCaller(), zap.AddStacktrace(zap.WarnLevel), zap.AddCallerSkip(1)) log, err := config.Build(zap.AddCaller(), zap.AddStacktrace(zap.WarnLevel), zap.AddCallerSkip(1))
if err == nil { if err == nil {
sugar := log.Sugar() sugar := log.Sugar()
@ -182,13 +199,13 @@ func createConsoleLogger(verbose bool) error {
return nil return nil
} }
func createFileLogger(verbose bool, meta []logInitMeta, logDir string, rotateConfig LogRotateConfig) error { func createFileLogger(verbose bool, logLevel string, meta []logInitMeta, logDir string, rotateConfig LogRotateConfig) error {
levels = nil levels = nil
// create parent dir first // create parent dir first
_ = os.MkdirAll(logDir, fs.FileMode(0700)) _ = os.MkdirAll(logDir, fs.FileMode(0700))
for _, m := range meta { for _, m := range meta {
log, level, err := CreateLogger(path.Join(logDir, m.fileName), false, false, verbose, rotateConfig) log, level, err := CreateLogger(path.Join(logDir, m.fileName), false, false, verbose, logLevel, rotateConfig)
if err != nil { if err != nil {
return err return err
} }

View File

@ -34,7 +34,7 @@ func SetGrpcLevel(level zapcore.Level) {
} }
// SetupDaemon sets daemon log config: path, console // SetupDaemon sets daemon log config: path, console
func SetupDaemon(logDir string, verbose bool, console bool, rotateConfig logger.LogRotateConfig) error { func SetupDaemon(logDir string, verbose bool, logLevel string, console bool, rotateConfig logger.LogRotateConfig) error {
var options []dfpath.Option var options []dfpath.Option
if logDir != "" { if logDir != "" {
options = append(options, dfpath.WithLogDir(logDir)) options = append(options, dfpath.WithLogDir(logDir))
@ -45,5 +45,5 @@ func SetupDaemon(logDir string, verbose bool, console bool, rotateConfig logger.
return err return err
} }
return logger.InitDaemon(verbose, console, d.LogDir(), rotateConfig) return logger.InitDaemon(verbose, logLevel, console, d.LogDir(), rotateConfig)
} }

View File

@ -212,7 +212,7 @@ func (p *peerManager) RunGC(ctx context.Context) error {
if elapsed > p.hostTTL { if elapsed > p.hostTTL {
peer.Log.Info("peer elapsed exceeds the host ttl, causing the peer to leave") peer.Log.Info("peer elapsed exceeds the host ttl, causing the peer to leave")
if err := peer.FSM.Event(ctx, PeerEventLeave); err != nil { if err := peer.FSM.Event(ctx, PeerEventLeave); err != nil {
peer.Log.Errorf("peer fsm event failed: %s", err.Error()) peer.Log.Infof("peer fsm event failed: %s", err.Error())
return true return true
} }