diff --git a/CHANGELOG.md b/CHANGELOG.md index b2424127..ba87b4f1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,8 @@ # ChangeLog +## v2.4.2 + +- now you can change name, level, etc. of log file via an external config file: `./config.yml` ## v2.4.1 - make `Influxdbv1Handler` as independent module, path: `github.com/wosai/ultron/handler/influxdbv1/v2` diff --git a/config.go b/config.go new file mode 100644 index 00000000..bcb23ff5 --- /dev/null +++ b/config.go @@ -0,0 +1,71 @@ +package ultron + +import ( + "fmt" + "os" + "path/filepath" + + "github.com/jacexh/multiconfig" +) + +type ( + Option struct { + Server ServerOption + Logger LoggerOption + } + + ServerOption struct { + HTTPAddr string `default:":2017" yaml:"http_addr,omitempty" json:"http_addr,omitempty" toml:"http_addr"` + GRPCAddr string `default:":2021" yaml:"grpc_addr,omitempty" json:"grpc_addr,omitempty" toml:"grpc_addr"` + } + + LoggerOption struct { + Level string `default:"info" yaml:"level,omitempty" json:"level,omitempty" toml:"level"` + FileName string `yaml:"filename,omitempty" json:"filename,omitempty" toml:"filename"` + MaxSize int `default:"100" yaml:"max_size,omitempty" json:"max_size,omitempty" toml:"max_size"` + MaxBackups int `default:"30" yaml:"max_backups,omitempty" json:"max_backups,omitempty" toml:"max_backups"` + } +) + +var ( + configFileBaseName = "config" + configFileFormat = "yml" + searchInPaths []string = []string{"."} +) + +var ( + loadedOption *Option +) + +func findInDir(dir string, file string) string { + fp := filepath.Join(dir, file) + fi, err := os.Stat(fp) + if err == nil && !fi.IsDir() { + return fp + } + return "" +} + +func findConfigFile() string { + fp := fmt.Sprintf("%s.%s", configFileBaseName, configFileFormat) + for _, dir := range searchInPaths { + if path := findInDir(dir, fp); path != "" { + return path + } + } + return "" +} + +func loadConfig() *Option { + f := findConfigFile() + opt := new(Option) + loader := multiconfig.NewWithPathAndEnvPrefix(f, "ULTRON") + loader.MustLoad(opt) + + buildLogger(opt.Logger) // todo + return opt +} + +func init() { + loadedOption = loadConfig() +} diff --git a/config.yaml b/config.yaml new file mode 100644 index 00000000..4cba78b2 --- /dev/null +++ b/config.yaml @@ -0,0 +1,3 @@ +logger: + level: "debug" + filename: "ultron.log" \ No newline at end of file diff --git a/go.mod b/go.mod index d62ebe39..6ef7915a 100644 --- a/go.mod +++ b/go.mod @@ -5,6 +5,7 @@ require ( github.com/golang/protobuf v1.5.0 github.com/google/uuid v1.3.0 github.com/jacexh/gopkg/chi-middleware v0.1.1 + github.com/jacexh/gopkg/zaprotate v0.1.1 github.com/jacexh/multiconfig v0.1.2 github.com/olekukonko/tablewriter v0.0.5 github.com/prometheus/client_golang v1.11.0 @@ -35,6 +36,7 @@ require ( golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40 // indirect golang.org/x/text v0.3.6 // indirect google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 // indirect + gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect gopkg.in/yaml.v2 v2.3.0 // indirect gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect ) diff --git a/go.sum b/go.sum index 2fe4f132..b56412de 100644 --- a/go.sum +++ b/go.sum @@ -77,6 +77,8 @@ github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+ github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/jacexh/gopkg/chi-middleware v0.1.1 h1:Q/A+gN2b5kQVGPsEfGsyc11umXHuXEnYPonrc+M7BH8= github.com/jacexh/gopkg/chi-middleware v0.1.1/go.mod h1:1ndyu3GrZbrLJJYo/jmqFHi6X936Y2pxguTIj7HqM6c= +github.com/jacexh/gopkg/zaprotate v0.1.1 h1:x0NG69xoA4JARtUFRqEFaRedezETiGizHrvUvPnU6CU= +github.com/jacexh/gopkg/zaprotate v0.1.1/go.mod h1:eiwQ+eqU4mbk2aBJYLm0sqro8bNWdyjmC+SqxVozun8= github.com/jacexh/multiconfig v0.1.2 h1:M7aIsBr1xUgfAfDrI0mHAHSyLicfiiVkejVWI7PmW+M= github.com/jacexh/multiconfig v0.1.2/go.mod h1:7YehB4JsdDB+GdIU9Zv2lNEWamSLd0YtKezoJzB8W4Q= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= @@ -265,6 +267,8 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8= +gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/log.go b/log.go index 12bc5e0b..2504396e 100644 --- a/log.go +++ b/log.go @@ -1,6 +1,9 @@ package ultron import ( + "sync" + + "github.com/jacexh/gopkg/zaprotate" "go.uber.org/zap" "go.uber.org/zap/zapcore" ) @@ -8,22 +11,30 @@ import ( var ( // Logger 全局日志 Logger *zap.Logger -) -func buildLogger() { - cfg := zap.NewProductionConfig() - // cfg.Encoding = "console" - cfg.EncoderConfig.TimeKey = "@timestamp" - cfg.EncoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder - cfg.Sampling = nil - - var err error - Logger, err = cfg.Build() //zap.AddCallerSkip(1) - if err != nil { - panic(err) + levelMapper = map[string]zapcore.Level{ + "info": zapcore.InfoLevel, + "debug": zapcore.DebugLevel, + "warn": zapcore.WarnLevel, + "error": zapcore.ErrorLevel, } -} -func init() { - buildLogger() + once sync.Once +) + +func buildLogger(opt LoggerOption) { + once.Do(func() { + cfg := zap.NewProductionConfig() + cfg.EncoderConfig.TimeKey = "@timestamp" + cfg.EncoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder + cfg.Sampling = nil + cfg.Level = zap.NewAtomicLevelAt(levelMapper[opt.Level]) + + Logger = zaprotate.BuildRotateLogger(cfg, zaprotate.RotatingFileConfig{ + LoggerName: "", + Filename: opt.FileName, + MaxSize: opt.MaxSize, + MaxBackups: opt.MaxBackups, + }) + }) } diff --git a/runner.go b/runner.go index 98fdd2e8..0f58ae54 100644 --- a/runner.go +++ b/runner.go @@ -10,7 +10,6 @@ import ( "syscall" "time" - "github.com/jacexh/multiconfig" "github.com/wosai/ultron/v2/pkg/genproto" "go.uber.org/zap" "google.golang.org/grpc" @@ -39,12 +38,6 @@ type ( StopPlan() } - RunnerConfig struct { - GRPCAddr string `json:"listern_addr,omitempty" default:":2021"` // 服务监听地址 - RESTAddr string `json:"rest_addr,omitempty" default:":2017"` // restful监听地址 - RunOnce bool `json:"run_once"` // 作用于LocalRunner,如果true,则执行完后退出ultron - } - masterRunner struct { scheduler *scheduler plan Plan @@ -61,13 +54,6 @@ type ( } ) -func loadRunnerConfigrations() *RunnerConfig { - conf := new(RunnerConfig) - loader := multiconfig.NewWithPathAndEnvPrefix("", "ULTRON") - loader.MustLoad(conf) - return conf -} - func NewMasterRunner() MasterRunner { runner := newMasterRunner() go func(r *masterRunner) { @@ -111,8 +97,8 @@ func newMasterRunner() *masterRunner { // Launch 主线程,如果发生错误则关闭 func (r *masterRunner) Launch(opts ...grpc.ServerOption) error { - conf := loadRunnerConfigrations() - Logger.Info("loaded configurations", zap.Any("configrations", conf)) + Logger.Info("loaded configurations", zap.Any("configrations", loadedOption)) + serverOption := loadedOption.Server // eventbus初始化 r.eventbus.subscribeReport(printReportToConsole(os.Stdout)) @@ -123,24 +109,24 @@ func (r *masterRunner) Launch(opts ...grpc.ServerOption) error { go func() { // http server router := buildHTTPRouter(r) r.rest = &http.Server{ - Addr: conf.RESTAddr, + Addr: serverOption.HTTPAddr, Handler: router, } - Logger.Info("ultron http server is running", zap.String("address", conf.RESTAddr)) + Logger.Info("ultron http server is running", zap.String("address", serverOption.HTTPAddr)) if err := r.rest.ListenAndServe(); err != nil { Logger.Fatal("a error has occurend inside http server", zap.Error(err)) } }() go func() { // grpc server - lis, err := net.Listen("tcp", conf.GRPCAddr) + lis, err := net.Listen("tcp", serverOption.GRPCAddr) if err != nil { Logger.Fatal("failed to launch grpc server", zap.Error(err)) } r.rpc = grpc.NewServer(opts...) r.supervisor = newSlaveSupervisor() genproto.RegisterUltronAPIServer(r.rpc, r.supervisor) - Logger.Info("ultron grpc server is running", zap.String("connect_address", conf.GRPCAddr)) + Logger.Info("ultron grpc server is running", zap.String("connect_address", serverOption.GRPCAddr)) start <- struct{}{} if err := r.rpc.Serve(lis); err != nil {