How to use configuration files to configure Logger elegantly while supporting log rotation

王林
Release: 2024-02-10 20:50:08
forward
920 people have browsed it

如何使用配置文件优雅地配置 Logger,同时支持日志轮转

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.

Question content

Problem description

  • Function: test1() is the log rotation and cutting library recommended by the official document ngopkg.in/natefinch/lumberjack.v2.
  • Function: 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.

My current requirements:

  1. 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.

  2. 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"}

  3. 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()
}
Copy after login

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'
Copy after login

Workaround

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()
}
Copy after login

And modify the configuration file to set outputpaths as follows:

outputPaths:
  - stdout
  - lumberjack://localhost/foo.log?maxSize=500&maxBackups=3&maxAge=28
Copy after login

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!

source:stackoverflow.com
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
About us Disclaimer Sitemap
php.cn:Public welfare online PHP training,Help PHP learners grow quickly!