php editor Zimo will share with you how to use configuration files to elegantly configure Logger and implement log rotation. Logger is a commonly used logging tool that can help us record the running status of applications to facilitate troubleshooting and log tracking. When using Logger, you can flexibly define the log format, output target, log level, etc. through the configuration file. You can also configure log rotation rules to achieve automatic management and storage of logs. Through reasonable configuration, we can achieve more flexible and efficient logging and management. In this article, we will introduce in detail how to use configuration files to elegantly configure Logger and support log rotation.
test1()
is the log rotation and cutting library recommended by the official document ngopkg.in/natefinch/lumberjack.v2
. test2()
is a logger that uses yaml to read the configuration according to the basic configuration in the official document. After executing the main function,
Output in the console:
2023-05-15t08:49:16.555 0800 |info|Logger build successful: configuration from yaml | {"app":"jpz"}
Output in the log file foo.log
:
{"level":"info","ts":1684111756.5545945,"msg":"Logger built successfully: lumberjack.logger"}
These two logs are definitely different.
Both support using the configuration file config_log_zap.yaml
to make all configurations effective and let lumberjack
complete the log rotation and splitting work.
The console and log file output should be the same so I can quickly apply what I need via the config file. The console and log files are needed because I need to follow and record past output messages during development.
Output in the console:
2023-05-15t08:49:16.555 0800 |info|Logger build successful: configuration from yaml | {"app":"jpz"}
Output in the log file foo.log
:
2023-05-15t08:49:16.555 0800 |info|Logger build successful: configuration from yaml | {"app":"jpz"}
How to combine test1()
and test2()
into one function test0()
to satisfy the above two requirements?
Please give me some help, I've been working on this for a long time.
main.go
package main import ( "gopkg.in/yaml.v3" "os" "go.uber.org/zap" "go.uber.org/zap/zapcore" "gopkg.in/natefinch/lumberjack.v2" ) func test1() { // lumberjack.logger is already safe for concurrent use, so we don't need to // lock it. w := zapcore.addsync(&lumberjack.logger{ filename: "./foo.log", maxsize: 500, // megabytes maxbackups: 3, maxage: 28, // days }) core := zapcore.newcore( zapcore.newjsonencoder(zap.newproductionencoderconfig()), w, zap.infolevel, ) logger := zap.new(core) logger.info("logger construction succeeded:lumberjack.logger") } func test2() { var cfg zap.config yamlfile, _ := os.readfile("./config_log_zap.yaml") if err := yaml.unmarshal(yamlfile, &cfg); err != nil { panic(err) } logger := zap.must(cfg.build()) defer logger.sync() logger.info("logger construction succeeded:config from yaml") } func main() { test1() test2() }
config_log_zap.yaml
# For the full description for the configuration, see # https://github.com/uber-go/zap/blob/382e2511e51cda8afde24f9e6e741f934308edfa/config.go#L58-L94 level: 'debug' development: true disableCaller: true disableStacktrace: false sampling: initial: 100 thereafter: 100 encoding: 'console' encoderConfig: messageKey: 'msg' levelKey: 'level' timeKey: 'ts' nameKey: 'logger' callerKey: 'caller' functionKey: 'function' stacktraceKey: 'stacktrace' skipLineEnding: false lineEnding: "\n" levelEncoder: 'capital' timeEncoder: 'iso8601' durationEncoder: 'string' callerEncoder: 'full' nameEncoder: 'full' consoleSeparator: ' | ' outputPaths: - 'stdout' - './foo.log' errorOutputPaths: - 'stderr' - './error_logs' initialFields: app: 'jpz'
Use zap.registersink to register the lumberjack
logger as a new sink:
package main import ( "net/url" "os" "strconv" "strings" "gopkg.in/yaml.v3" "go.uber.org/zap" "gopkg.in/natefinch/lumberjack.v2" ) type lumberjacksink struct { lumberjack.logger } func (l *lumberjacksink) sync() error { return nil } func parsenumber(s string, fallback int) int { v, err := strconv.atoi(s) if err == nil { return v } return fallback } func test0() { if err := zap.registersink("lumberjack", func(u *url.url) (zap.sink, error) { // read parameters from url: // lumberjack://localhost/foo.log?maxsize=500&maxbackups=3&maxage=28 filename := strings.trimleft(u.path, "/") if filename == "" { filename = "foo.log" } q := u.query() l := &lumberjacksink{ logger: lumberjack.logger{ filename: filename, maxsize: parsenumber(q.get("maxsize"), 500), maxbackups: parsenumber(q.get("maxbackups"), 3), maxage: parsenumber(q.get("maxage"), 28), }, } return l, nil }); err != nil { panic(err) } var cfg zap.config yamlfile, _ := os.readfile("./config_log_zap.yaml") if err := yaml.unmarshal(yamlfile, &cfg); err != nil { panic(err) } logger := zap.must(cfg.build()) defer logger.sync() logger.info("logger construction succeeded:config from yaml") } func main() { test0() }
And modify the configuration file to set outputpaths
as follows:
outputPaths: - stdout - lumberjack://localhost/foo.log?maxSize=500&maxBackups=3&maxAge=28
The above is the detailed content of How to use configuration files to configure Logger elegantly while supporting log rotation. For more information, please follow other related articles on the PHP Chinese website!