From 5f007728cf884deb77f033ff1a1f7fb2b6816725 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CWind=E2=80=9D?= <573966@qq.com> Date: Sun, 15 Oct 2023 15:09:25 +0800 Subject: [PATCH] Add log output option of config 1.Add log output option of config. 2.Minimal optimization code. --- cluster/log/logger.go | 64 +++++++++++++++++++++++--------- cmd/cluster/main.go | 15 +++++--- cmd/config/node1.yml | 25 +++++-------- cmd/config/node2.yml | 25 +++++-------- cmd/config/node3.yml | 25 +++++-------- cmd/config/node4.yml | 85 ------------------------------------------- cmd/config/single.yml | 24 +++++------- cmd/single/main.go | 16 +++++--- config/conf.yml | 5 ++- config/config.go | 5 --- 10 files changed, 104 insertions(+), 185 deletions(-) delete mode 100644 cmd/config/node4.yml diff --git a/cluster/log/logger.go b/cluster/log/logger.go index 2a93df1..73a1fb0 100644 --- a/cluster/log/logger.go +++ b/cluster/log/logger.go @@ -2,31 +2,43 @@ package log import ( "context" + "gopkg.in/natefinch/lumberjack.v2" "io" "log/slog" "os" - - "gopkg.in/natefinch/lumberjack.v2" ) // Constants for log formats const ( - Text = iota // Log format is TEXT. - Json // Log format is JSON. + FormatText = iota // Log format is TEXT. + FormatJson // Log format is JSON. +) + +// Constants for log output +const ( + OutputConsole = iota // Log output is Console. + OutputFile // Log output is File. + OutputBoth // Log output is Console and File. ) // Format represents the log format type. type Format int +// Output represents the log output type. +type Output int + // Options defines configuration options for the logger. type Options struct { // Indicates whether logging is enabled. - Disable bool `json:"disable" yaml:"disable"` + Enable bool `json:"enable" yaml:"enable"` // Log format, currently supports Text: 0 and JSON: 1, with Text as the default. Format Format `json:"format" yaml:"format"` + // Log output location Console: 0 or File: 1 or Both: 2, with Console as the default. + Output Output `json:"output" yaml:"output"` + // Log level, with supported values LevelDebug: 4, LevelInfo: 0, LevelWarn: 4, and LevelError: 8. Level int `json:"level" yaml:"level"` @@ -61,7 +73,8 @@ func DefaultOptions() *Options { MaxSize: 100, MaxAge: 30, MaxBackups: 1, - Format: Text, + Format: FormatText, + Output: OutputConsole, } } @@ -72,24 +85,39 @@ func New(opt *Options) *Logger { } var writer io.Writer - writer = os.Stdout + switch opt.Output { + case OutputConsole: + writer = os.Stdout + case OutputFile: + writer = createFileWriter(opt) + case OutputBoth: + if fileWriter := createFileWriter(opt); fileWriter != nil { + writer = io.MultiWriter(os.Stdout, fileWriter) + } + } + if writer == nil { + writer = os.Stdout + } + + return &Logger{ + writer: writer, + Logger: slog.New(NewHandler(opt, writer)), + opt: opt, + } +} + +func createFileWriter(opt *Options) (writer io.Writer) { if len(opt.Filename) != 0 { - fileWriter := &lumberjack.Logger{ + writer = &lumberjack.Logger{ Filename: opt.Filename, MaxSize: opt.MaxSize, MaxBackups: opt.MaxBackups, MaxAge: opt.MaxAge, Compress: opt.Compress, } - writer = io.MultiWriter(os.Stdout, fileWriter) - } - - return &Logger{ - writer: writer, - Logger: slog.New(NewHandler(opt, writer)), - opt: opt, } + return } // Logger is a wrapper for slog.Logger. @@ -110,12 +138,12 @@ func NewHandler(opt *Options, writer io.Writer) *Handler { var handler slog.Handler switch opt.Format { - case Text: + case FormatText: handler = slog.NewTextHandler(writer, &slog.HandlerOptions{ Level: slog.Level(opt.Level), }) - case Json: + case FormatJson: handler = slog.NewJSONHandler(writer, &slog.HandlerOptions{ Level: slog.Level(opt.Level), }) @@ -135,7 +163,7 @@ func NewHandler(opt *Options, writer io.Writer) *Handler { // Enabled reports whether the handler handles records at the given level. // The handler ignores records whose level is lower. func (h *Handler) Enabled(ctx context.Context, level slog.Level) bool { - return !h.opt.Disable && h.internal.Enabled(ctx, level) + return h.opt.Enable && h.internal.Enabled(ctx, level) } // Handle handles the Record. diff --git a/cmd/cluster/main.go b/cmd/cluster/main.go index c3799f5..f9e607e 100644 --- a/cmd/cluster/main.go +++ b/cmd/cluster/main.go @@ -75,12 +75,12 @@ func realMain(ctx context.Context) error { flag.StringVar(&cfg.Redis.Options.Addr, "redis", "127.0.0.1:6379", "redis address for cluster mode") flag.StringVar(&cfg.Redis.Options.Password, "redis-pass", "", "redis password for cluster mode") flag.IntVar(&cfg.Redis.Options.DB, "redis-db", 0, "redis db for cluster mode") - flag.BoolVar(&cfg.Log.Disable, "log-disable", false, "log disabled or not") + flag.BoolVar(&cfg.Log.Enable, "log-enable", true, "log enabled or not") flag.StringVar(&cfg.Log.Filename, "log-file", "./logs/comqtt.log", "log filename") //parse arguments flag.Parse() //load config file - if confFile != "" { + if len(confFile) > 0 { if cfg, err = config.Load(confFile); err != nil { return fmt.Errorf("load config file error: %w", err) } @@ -92,14 +92,17 @@ func realMain(ctx context.Context) error { } } - //init log - log.Init(&cfg.Log) - //enable pprof if cfg.PprofEnable { pprof() } + //init log + log.Init(&cfg.Log) + if cfg.Log.Enable && cfg.Log.Output == log.OutputFile { + fmt.Println("log output to the files, please check") + } + // create server instance and init hooks cfg.Mqtt.Options.Logger = log.Default() server := mqtt.New(&cfg.Mqtt.Options) @@ -149,7 +152,7 @@ func realMain(ctx context.Context) error { errCh <- err } }() - log.Info("comqtt server started") + log.Info("cluster node started") // exit select { diff --git a/cmd/config/node1.yml b/cmd/config/node1.yml index eb048c6..4c958f9 100644 --- a/cmd/config/node1.yml +++ b/cmd/config/node1.yml @@ -68,19 +68,12 @@ redis: prefix: comqtt log: - enable: true - env: 0 #0 dev or 1 prod - format: 0 #output format 0console or 1json - caller: false #whether to display code line number - info-file: ./logs/comqtt-info.log - error-file: ./logs/comqtt-error.log # level >= 3, 3Error(default) 4Fatal 5Panic 6NoLevel 7Off - thirdparty-file: ./logs/thirdparty.log # level 6NoLevel, logs of the third-party library - maxsize: 100 #100M - max-age: 30 #30day - max-backups: 10 #number of log files - localtime: true #true or false - compress: true #true or false - level: 1 #-1Trace 0Debug 1Info 2Warn 3Error(default) 4Fatal 5Panic 6NoLevel 7Off - sampler: #a maximum of three logs can be output every second - burst: 3 #log count - period: 1 #second + enable: true #Indicates whether logging is enabled. + format: 0 #Log format, currently supports Text: 0 and JSON: 1, with Text as the default. + output: 2 #Log output location Console: 0 or File: 1 or Both: 2, with Console as the default. + filename: ./logs/comqtt1.log #Filename is the file to write logs to + maxsize: 100 #MaxSize is the maximum size in megabytes of the log file before it gets rotated. It defaults to 100 megabytes. + max-age: 30 #MaxAge is the maximum number of days to retain old log files based on the timestamp encoded in their filename + max-backups: 10 #MaxBackups is the maximum number of old log files to retain + compress: true #Compress determines if the rotated log files should be compressed using gzip + level: 0 #Log level, with supported values LevelDebug: -4, LevelInfo: 0, LevelWarn: 4, and LevelError: 8. diff --git a/cmd/config/node2.yml b/cmd/config/node2.yml index f87d4dc..2c9537b 100644 --- a/cmd/config/node2.yml +++ b/cmd/config/node2.yml @@ -68,19 +68,12 @@ redis: prefix: comqtt log: - enable: true - env: 0 #0 dev or 1 prod - format: 0 #output format 0console or 1json - caller: false #whether to display code line number - info-file: ./logs/comqtt-info.log - error-file: ./logs/comqtt-error.log - thirdparty-file: ./logs/thirdparty.log # level 6NoLevel, logs of the third-party library - maxsize: 100 #100M - max-age: 30 #30day - max-backups: 10 #number of log files - localtime: true #true or false - compress: true #true or false - level: 1 #-1Trace 0Debug 1Info 2Warn 3Error(default) 4Fatal 5Panic 6NoLevel 7Off - sampler: #a maximum of three logs can be output every second - burst: 3 #log count - period: 1 #second + enable: true #Indicates whether logging is enabled. + format: 0 #Log format, currently supports Text: 0 and JSON: 1, with Text as the default. + output: 2 #Log output location Console: 0 or File: 1 or Both: 2, with Console as the default. + filename: ./logs/comqtt2.log #Filename is the file to write logs to + maxsize: 100 #MaxSize is the maximum size in megabytes of the log file before it gets rotated. It defaults to 100 megabytes. + max-age: 30 #MaxAge is the maximum number of days to retain old log files based on the timestamp encoded in their filename + max-backups: 10 #MaxBackups is the maximum number of old log files to retain + compress: true #Compress determines if the rotated log files should be compressed using gzip + level: 0 #Log level, with supported values LevelDebug: -4, LevelInfo: 0, LevelWarn: 4, and LevelError: 8. \ No newline at end of file diff --git a/cmd/config/node3.yml b/cmd/config/node3.yml index 10fdddc..c99fd6e 100644 --- a/cmd/config/node3.yml +++ b/cmd/config/node3.yml @@ -68,19 +68,12 @@ redis: prefix: comqtt log: - enable: true - env: 0 #0 dev or 1 prod - format: 0 #output format 0console or 1json - caller: false #whether to display code line number - info-file: ./logs/comqtt-info.log - error-file: ./logs/comqtt-error.log - thirdparty-file: ./logs/thirdparty.log # level 6NoLevel, logs of the third-party library - maxsize: 100 #100M - max-age: 30 #30day - max-backups: 10 #number of log files - localtime: true #true or false - compress: true #true or false - level: 1 #-1Trace 0Debug 1Info 2Warn 3Error(default) 4Fatal 5Panic 6NoLevel 7Off - sampler: #a maximum of three logs can be output every second - burst: 3 #log count - period: 1 #second + enable: true #Indicates whether logging is enabled. + format: 0 #Log format, currently supports Text: 0 and JSON: 1, with Text as the default. + output: 2 #Log output location Console: 0 or File: 1 or Both: 2, with Console as the default. + filename: ./logs/comqtt3.log #Filename is the file to write logs to + maxsize: 100 #MaxSize is the maximum size in megabytes of the log file before it gets rotated. It defaults to 100 megabytes. + max-age: 30 #MaxAge is the maximum number of days to retain old log files based on the timestamp encoded in their filename + max-backups: 10 #MaxBackups is the maximum number of old log files to retain + compress: true #Compress determines if the rotated log files should be compressed using gzip + level: 0 #Log level, with supported values LevelDebug: -4, LevelInfo: 0, LevelWarn: 4, and LevelError: 8. \ No newline at end of file diff --git a/cmd/config/node4.yml b/cmd/config/node4.yml deleted file mode 100644 index 44441d5..0000000 --- a/cmd/config/node4.yml +++ /dev/null @@ -1,85 +0,0 @@ -storage-way: 3 #Storage way optional items:0 memory、1 bolt、2 badger、3 redis;Only redis can be used in cluster mode. -bridge-way: 0 #Bridge way optional items:0 disable、1 kafka -bridge-path: ./cmd/config/bridge-kafka.yml #The bridge config file path - -auth: - way: 0 #Authentication way: 0 anonymous, 1 username and password, 2 clientid - datasource: 1 #Optional items:0 free、1 redis、2 mysql、3 postgresql、4 http ... - conf-path: ./cmd/config/auth-redis.yml #The config file path should correspond to the auth-datasource - blacklist-path: ./cmd/config/blacklist.yml #Special rules outside the usual rules (black and white list),this configuration is invalid for anonymous authentication - -cluster: - discovery-way: 0 #The node discovery way in the cluster: 0 serf、1 memberlist、2 mDNS - node-name: c04 #For versatility, use pure numbers. The name of node must be unique in the cluster. - bind-addr: 127.0.0.1 #Configuration related to what address to bind to and ports to listen on. - bind-port: 7949 #The port is used for both UDP and TCP gossip. Used for member discovery and join. - advertise-addr: #Configuration related to what address to advertise to other cluster members. Used for nat traversal. The default value is bind-addr. - advertise-port: #Used for member communication. If this port is not set, the default value is bind-port. - members: [127.0.0.1:7946] #Seeds member list, format such as 192.168.0.103:7946,192.168.0.104:7946 - queue-depth: 10240 #Size of memberlist internal channel which handles UDP messages. - raft-impl: 0 #The raft implementer: 0 hashicorp/raft, 1 etcd/raft - raft-port: 8949 #Distributed consistency coordination communication port - raft-dir: data/c04 #Distributed data storage directory - raft-bootstrap: false #Should be `true` for the first node of the cluster. It is required so that it can elect a leader without any other nodes being present. - grpc-enable: true #Grpc is used for raft transport and reliable communication between nodes - grpc-port: 17949 #Grpc communication port between nodes - inbound-pool-size: 40960 #The maximum number of goroutine to process incoming messages. - outbound-pool-size: 40960 #The maximum number of goroutine to process outgoing messages. - inout-pool-nonblocking: false #Pool size is unlimited, when inout-pool-nonblocking is true, inbound-pool-size and outbound-pool-size is inoperative. - -mqtt: - tcp: :1889 - ws: :1889 - http: :8083 - tls: - ca-cert: #CA root certificate file path. Not empty enable bidirectional authentication. - server-cert: #Server certificate file path - server-key: #server rsa private key file path - options: - client-write-buffer-size: 2048 #It is the number of individual workers and queues to initialize. - client-read-buffer-size: 2048 #It is the size of the queue per worker. - sys-topic-resend-interval: 1 #It specifies the interval between $SYS topic updates in seconds. - capabilities: - compatibilities: - obscure-not-authorized: false #Return unspecified errors instead of not authorized - passive-client-disconnect: false #Don't disconnect the client forcefully after sending disconnect packet (paho) - always-return-response: false #Always return response info (useful for testing) - restore-sys-info-restart: false #Restore system info from store as if server never stopped - maximum-message-expiry-interval: 86400 #Maximum message expiry if message expiry is 0 or over - maximum-session-expiry-interval: 4294967295 #Maximum number of seconds to keep disconnected sessions - maximum-client-writes-pending: 65535 #Maximum number of pending message writes for a client - maximum-packet-size: 0 #Maximum packet size, 0 unlimited - receive-maximum: 1024 #Maximum number of concurrent qos messages per client - topic-alias-maximum: 65535 #Maximum topic alias value - maximum-qos: 2 #Maxmimum qos value available to clients - retain-available: 1 #Retain messages is available - wildcard-sub-available: 1 #Wildcard subscriptions are available - sub-id-available: 1 #Subscription identifiers are available - shared-sub-available: 1 #Shared subscriptions are available - minimum-protocol-version: 3 #Minimum supported mqtt version (3.0.0) - -redis: - options: - addr: 127.0.0.1:6379 - username: - password: - db: 0 - prefix: comqtt - -log: - enable: true - env: 0 #0 dev or 1 prod - format: 0 #output format 0console or 1json - caller: false #whether to display code line number - info-file: ./logs/comqtt-info.log - error-file: ./logs/comqtt-error.log - thirdparty-file: ./logs/thirdparty.log # level 6NoLevel, logs of the third-party library - maxsize: 100 #100M - max-age: 30 #30day - max-backups: 10 #number of log files - localtime: true #true or false - compress: true #true or false - level: 1 #-1Trace 0Debug 1Info 2Warn 3Error(default) 4Fatal 5Panic 6NoLevel 7Off - sampler: #a maximum of three logs can be output every second - burst: 3 #log count - period: 1 #second diff --git a/cmd/config/single.yml b/cmd/config/single.yml index e1a6e7a..19d23ed 100644 --- a/cmd/config/single.yml +++ b/cmd/config/single.yml @@ -49,18 +49,12 @@ redis: prefix: comqtt log: - enable: true - env: 0 #0 dev or 1 prod - format: 1 #output format 0console or 1json - caller: false #whether to display code line number - info-file: ./logs/comqtt-info.log - error-file: ./logs/comqtt-error.log # level >= 3, 3Error(default) 4Fatal 5Panic 6NoLevel 7Off - maxsize: 100 #100M - max-age: 30 #30day - max-backups: 10 #number of log files - localtime: true #true or false - compress: true #true or false - level: 1 #-1Trace 0Debug 1Info 2Warn 3Error(default) 4Fatal 5Panic 6NoLevel 7Off - sampler: #a maximum of three logs can be output every second - burst: 3 #log count - period: 1 #second + enable: true #Indicates whether logging is enabled. + format: 1 #Log format, currently supports Text: 0 and JSON: 1, with Text as the default. + output: 2 #Log output location Console: 0 or File: 1 or Both: 2, with Console as the default. + filename: ./logs/comqtt.log #Filename is the file to write logs to + maxsize: 100 #MaxSize is the maximum size in megabytes of the log file before it gets rotated. It defaults to 100 megabytes. + max-age: 30 #MaxAge is the maximum number of days to retain old log files based on the timestamp encoded in their filename + max-backups: 10 #MaxBackups is the maximum number of old log files to retain + compress: true #Compress determines if the rotated log files should be compressed using gzip + level: 0 #Log level, with supported values LevelDebug: -4, LevelInfo: 0, LevelWarn: 4, and LevelError: 8. \ No newline at end of file diff --git a/cmd/single/main.go b/cmd/single/main.go index ae97a68..9df5068 100644 --- a/cmd/single/main.go +++ b/cmd/single/main.go @@ -7,6 +7,7 @@ package main import ( "context" "flag" + "fmt" "net/http" "os" "os/signal" @@ -57,25 +58,28 @@ func realMain(ctx context.Context) error { flag.StringVar(&cfg.Mqtt.TCP, "tcp", ":1883", "network address for Mqtt TCP listener") flag.StringVar(&cfg.Mqtt.WS, "ws", ":1882", "network address for Mqtt Websocket listener") flag.StringVar(&cfg.Mqtt.HTTP, "http", ":8080", "network address for web info dashboard listener") - flag.BoolVar(&cfg.Log.Disable, "log-disable", true, "log disabled or not") + flag.BoolVar(&cfg.Log.Enable, "log-enable", true, "log enabled or not") flag.StringVar(&cfg.Log.Filename, "log-file", "./logs/comqtt.log", "log filename") //parse arguments flag.Parse() //load config file - if confFile != "" { + if len(confFile) > 0 { if cfg, err = config.Load(confFile); err != nil { onError(err, "") } } - //init log - log.Init(&cfg.Log) - //enable pprof if cfg.PprofEnable { pprof() } + //init log + log.Init(&cfg.Log) + if cfg.Log.Enable && cfg.Log.Output == log.OutputFile { + fmt.Println("log output to the files, please check") + } + // create server instance and init hooks cfg.Mqtt.Options.Logger = log.Default() server := mqtt.New(&cfg.Mqtt.Options) @@ -115,7 +119,7 @@ func realMain(ctx context.Context) error { } }() - log.Info("comqtt server started") + //log.Info("comqtt server started") select { case err := <-errCh: diff --git a/config/conf.yml b/config/conf.yml index a864a19..ca07378 100644 --- a/config/conf.yml +++ b/config/conf.yml @@ -69,11 +69,12 @@ redis: prefix: comqtt log: - disable: false #Indicates whether logging is enabled. + enable: true #Indicates whether logging is enabled. format: 1 #Log format, currently supports Text: 0 and JSON: 1, with Text as the default. + output: 0 #Log output location Console: 0 or File: 1 or Both: 2, with Console as the default. filename: ./logs/comqtt.log #Filename is the file to write logs to maxsize: 100 #MaxSize is the maximum size in megabytes of the log file before it gets rotated. It defaults to 100 megabytes. max-age: 30 #MaxAge is the maximum number of days to retain old log files based on the timestamp encoded in their filename max-backups: 10 #MaxBackups is the maximum number of old log files to retain compress: true #Compress determines if the rotated log files should be compressed using gzip - level: 0 #Log level, with supported values LevelDebug: 4, LevelInfo: 0, LevelWarn: 4, and LevelError: 8. + level: 0 #Log level, with supported values LevelDebug: -4, LevelInfo: 0, LevelWarn: 4, and LevelError: 8. diff --git a/config/config.go b/config/config.go index a4a5cea..784f384 100644 --- a/config/config.go +++ b/config/config.go @@ -186,8 +186,3 @@ func GenTlsConfig(conf *Config) (*tls2.Config, error) { return tlsConfig, nil } - -type Sampler struct { - Burst int `json:"burst" yaml:"burst"` - Period int `json:"period" yaml:"period"` -}