diff --git a/bench/main.go b/bench/main.go index 34bd859..50e488b 100644 --- a/bench/main.go +++ b/bench/main.go @@ -33,7 +33,7 @@ func main() { } logger.Infof("starting bench server") config.MustLoadConfig("") - logger.InitLog(conf.LogLevel) + logger.InitLog(conf.Log.Level) if busi.BusiConf.Driver != "" { dtmcli.SetCurrentDBType(busi.BusiConf.Driver) svr.PrepareBenchDB() diff --git a/conf.sample.yml b/conf.sample.yml index cd66cb6..5c046ed 100644 --- a/conf.sample.yml +++ b/conf.sample.yml @@ -48,7 +48,15 @@ # RetryInterval: 10 # the subtrans branch will be retried after this interval # RequestTimeout: 3 # the timeout of HTTP/gRPC request in dtm -# LogLevel: 'info' # default: info. can be debug|info|warn|error +# Log: +# Level: 'info' # default: info. can be debug|info|warn|error +# Output: 'console' # default: console. can be console|file +# FileName: '/tmp/dtm.log' # default: /tmp/dtm.log. +# FileMaxSize: 10 # default: 10, unit: MB. +# FileMaxBackups: 5 # default: 5. +# FileMaxAge: 30 # default: 30, unit: days. +# FileCompress: 0 # default: 0. can by 0|1, means false|true + # HttpPort: 36789 # GrpcPort: 36790 diff --git a/dtmcli/logger/log.go b/dtmcli/logger/log.go index 59b3d43..54237df 100644 --- a/dtmcli/logger/log.go +++ b/dtmcli/logger/log.go @@ -1,9 +1,12 @@ package logger import ( + "fmt" "log" + "net/url" "os" + "github.com/natefinch/lumberjack" "go.uber.org/zap" "go.uber.org/zap/zapcore" ) @@ -24,6 +27,14 @@ type Logger interface { Errorf(format string, args ...interface{}) } +type lumberjackSink struct { + *lumberjack.Logger +} + +func (lumberjackSink) Sync() error { + return nil +} + // WithLogger replaces default logger func WithLogger(log Logger) { logger = log @@ -45,6 +56,28 @@ func InitLog(level string) { logger = p.Sugar() } +// InitRotateLog is an initialization for a rotated logger by lumberjack +func InitRotateLog(logLevel string, output, logFile string, ll *lumberjack.Logger) { + config := zap.NewProductionConfig() + err := config.Level.UnmarshalText([]byte(logLevel)) + FatalIfError(err) + config.EncoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder + config.Encoding = "console" + config.EncoderConfig.EncodeLevel = zapcore.CapitalColorLevelEncoder + config.OutputPaths = []string{fmt.Sprintf("lumberjack:%s", logFile), "stdout"} + if output == "file" { + err := zap.RegisterSink("lumberjack", func(*url.URL) (zap.Sink, error) { + return lumberjackSink{ + Logger: ll, + }, nil + }) + FatalIfError(err) + } + p, err := config.Build(zap.AddCallerSkip(1)) + FatalIfError(err) + logger = p.Sugar() +} + // Debugf log to level debug func Debugf(fmt string, args ...interface{}) { logger.Debugf(fmt, args...) diff --git a/dtmsvr/config/config.go b/dtmsvr/config/config.go index 2e84887..cc74975 100644 --- a/dtmsvr/config/config.go +++ b/dtmsvr/config/config.go @@ -29,6 +29,17 @@ type MicroService struct { EndPoint string `yaml:"EndPoint"` } +// Log config customize log +type Log struct { + Level string `yaml:"Level" default:"info"` + Output string `yaml:"Output" default:"console"` + FileName string `yaml:"FileName" default:"/tmp/dtm.log"` + FileMaxSize int64 `yaml:"FileMaxSize" default:"10"` + FileMaxBackups int64 `yaml:"FileMaxBackups" default:"5"` + FileMaxAge int64 `yaml:"FileMaxAge" default:"30"` + FileCompress int64 `yaml:"FileCompress" default:"0"` +} + // Store defines storage relevant info type Store struct { Driver string `yaml:"Driver" default:"boltdb"` @@ -72,7 +83,7 @@ type configType struct { MicroService MicroService `yaml:"MicroService"` UpdateBranchSync int64 `yaml:"UpdateBranchSync"` UpdateBranchAsyncGoroutineNum int64 `yaml:"UpdateBranchAsyncGoroutineNum" default:"1"` - LogLevel string `yaml:"LogLevel" default:"info"` + Log Log `yaml:"Log"` } // Config 配置 diff --git a/dtmsvr/svr.go b/dtmsvr/svr.go index 56f288c..0470f0a 100644 --- a/dtmsvr/svr.go +++ b/dtmsvr/svr.go @@ -20,12 +20,23 @@ import ( "github.com/dtm-labs/dtm/dtmutil" "github.com/dtm-labs/dtmdriver" grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware" + "github.com/natefinch/lumberjack" "google.golang.org/grpc" ) // StartSvr StartSvr func StartSvr() { logger.Infof("start dtmsvr") + if conf.Log.Output == "file" { + ll := lumberjack.Logger{ + Filename: conf.Log.FileName, + MaxSize: int(conf.Log.FileMaxSize), + MaxBackups: int(conf.Log.FileMaxBackups), + MaxAge: int(conf.Log.FileMaxAge), + Compress: conf.Log.FileCompress != 0, + } + logger.InitRotateLog(conf.Log.Level, conf.Log.Output, conf.Log.FileName, &ll) + } dtmcli.GetRestyClient().SetTimeout(time.Duration(conf.RequestTimeout) * time.Second) dtmgrpc.AddUnaryInterceptor(func(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error { ctx2, cancel := context.WithTimeout(ctx, time.Duration(conf.RequestTimeout)*time.Second) diff --git a/go.mod b/go.mod index ef2be14..baf57ea 100644 --- a/go.mod +++ b/go.mod @@ -16,6 +16,7 @@ require ( github.com/lib/pq v1.10.3 github.com/lithammer/shortuuid v2.0.3+incompatible github.com/lithammer/shortuuid/v3 v3.0.7 + github.com/natefinch/lumberjack v2.0.0+incompatible // indirect github.com/onsi/gomega v1.16.0 github.com/prometheus/client_golang v1.11.0 github.com/stretchr/testify v1.7.0 diff --git a/main.go b/main.go index 1b088e1..43ce895 100644 --- a/main.go +++ b/main.go @@ -59,7 +59,7 @@ func main() { } config.MustLoadConfig(*confFile) if *isDebug { - config.Config.LogLevel = "debug" + config.Config.Log.Level = "debug" } if *isReset { dtmsvr.PopulateDB(false)