44

golang中的log库

 5 years ago
source link: https://studygolang.com/articles/14186?amp%3Butm_medium=referral
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

golang中有很多优秀的第三方开源库,比如

  • go-slog , 这个是笔者自己开源的一个简单的日志库
  • logrus
  • zap
  • oklog
  • glog
  • seelog
  • zerolog
    都是很优秀的开源库,功能也很强大,很多都支持以txt的方式输入日志或者json的方式输出日志,我简单的试了下几个日志库

1. logrus

package main

import (
    "flag"
    "fmt"
    "os"
    "path"
    "runtime"
    "strings"
    "time"

    "github.com/Sirupsen/logrus"
)

func logrus_test() {

    fmt.Printf("<<<<<<<<<logrus test>>>>>>>>>>>>>>\n")

    logrus.WithFields(logrus.Fields{
        "sb": "sbvalue",
    }).Info("A walrus appears")

    log1 := logrus.New()
    fmt.Printf("log1 level: %d\n", log1.Level)
    log1.Debug("log1 debug")
    log1.Debugf("log1 debug f, %d", 10)
    log1.Info("log1 info")
    log1.Warn("log1 warn")
    log1.Error("log1 error")
    // log1.Panic("log1 panic")

    log1.SetLevel(logrus.ErrorLevel)
    fmt.Printf("after set log1 level to errorlevel\n")
    log1.Debug("log1 debug")

    fmt.Printf("-------------test formater-------------\n")
    log1.SetLevel(logrus.DebugLevel)
    log1.Formatter = &logrus.TextFormatter{
        DisableColors:  true,
        FullTimestamp:  true,
        DisableSorting: true,
    }

    log1.Debug("log text formatter test")

    fmt.Printf("-----------json formatter-------------\n")
    log1.Formatter = &logrus.JSONFormatter{}
    log1.Debug("log json formatter test")

    fmt.Printf("-----------log to file test-----------\n")
    log2 := logrus.New()
    log2.SetLevel(logrus.DebugLevel)
    log2.Formatter = &logrus.TextFormatter{
        DisableColors:  true,
        FullTimestamp:  true,
        DisableSorting: true,
    }

    logger_name := "logrus"
    cur_time := time.Now()
    log_file_name := fmt.Sprintf("%s_%04d-%02d-%02d-%02d-%02d.txt",
        logger_name, cur_time.Year(), cur_time.Month(), cur_time.Day(), cur_time.Hour(), cur_time.Minute())
    log_file, err := os.OpenFile(log_file_name, os.O_CREATE|os.O_APPEND|os.O_WRONLY, os.ModeExclusive)
    if err != nil {
        fmt.Printf("try create logfile[%s] error[%s]\n", log_file_name, err.Error())
        return
    }

    defer log_file.Close()

    log2.SetOutput(log_file)

    for i := 0; i < 10; i++ {
        log2.Debugf("logrus to file test %d", i)
    }

}

使用起来很简单,输出样式多样化

2. zap

package main

import (
    "flag"
    "fmt"
    "os"
    "path"
    "runtime"
    "strings"
    "time"

    "github.com/golang/glog"
)

func zap_log_test() {
    fmt.Printf("<<<<<<<<<zap log test>>>>>>>>>>>\n")
    logger := zap.NewExample()
    defer logger.Sync()

    const url = "http://example.com"

    // In most circumstances, use the SugaredLogger. It's 4-10x faster than most
    // other structured logging packages and has a familiar, loosely-typed API.
    sugar := logger.Sugar()
    sugar.Infow("Failed to fetch URL.",
        // Structured context as loosely typed key-value pairs.
        "url", url,
        "attempt", 3,
        "backoff", time.Second,
    )
    sugar.Infof("Failed to fetch URL: %s", url)

    // In the unusual situations where every microsecond matters, use the
    // Logger. It's even faster than the SugaredLogger, but only supports
    // structured logging.
    logger.Info("Failed to fetch URL.",
        // Structured context as strongly typed fields.
        zap.String("url", url),
        zap.Int("attempt", 3),
        zap.Duration("backoff", time.Second),
    )
}

zap的性能应该只这些库里面最高的

3. glog

package main

import (
    "flag"
    "fmt"
    "os"
    "path"
    "runtime"
    "strings"
    "time"

    "github.com/golang/glog"
)

func glog_test() {
    fmt.Printf("<<<<<<<glog_test>>>>>>>>>>\n")
    flag.Parse()

    defer glog.Flush()

    glog.Info("glog info test")
    glog.Warning("glog warn test")
    // glog.Error("glog error test")
    // glog.Fatal("glog fatal test")
}

glog就更轻量化,就两个文件,是google的c++日志库 glog 的golang版本

用了下这几个库,虽然都很强大,但是感觉跟我的需求不太符合,我需要能够每日一个文件或者每个小时一个文件或者限定文件格式动态rotating的功能,但是好像没有(或者我没有发现),然后日志的输出格式也不是我习惯的,所有没办法,就花了一两天时间自己写了个简单的符合我自己要求的日志库 go-slog ,有兴趣的同学可以clone下来试试看,O(∩_∩)O

4. slog

因为上面的几个日志库,感觉不太符合我自己的口味,就自己写了个简单的日志库,下载地址: https://github.com/yandaren/go-slog , 有兴趣的同学可以clone下来试试,代码很简单,下面给出一些

example

package slog_example

import (
    "fmt"
    "go-slog/slog"
    "time"
)

func Slog_test() {
    for _, lg_lvl := range slog.AllLogLevels {
        fmt.Printf("%d = %s\n", lg_lvl, lg_lvl.String())
    }

    fmt.Printf("----------------------------------\n")
    var lvl_strings = []string{
        "debug",
        "info",
        "warn",
        "warning",
        "error",
        "fatal",
        "none",
        "sblv",
    }

    for _, lg_lvl_str := range lvl_strings {
        lg_lvl, err := slog.ParseLevel(lg_lvl_str)
        if err != nil {
            fmt.Printf("parse lg_lvl_str[%s] error[%s]\n", lg_lvl_str, err.Error())
        } else {
            fmt.Printf("log_lvl_str[%s] = %d\n", lg_lvl_str, lg_lvl)
        }
    }

    fmt.Printf("---------------slog test---------------\n")
    logger := slog.NewStdoutLoggerSt("stdout_logger")

    logger.Debug("slog stdoutlogger test")
    logger.Info("slog stdoutlogger test")
    logger.Warn("slog stdoutlogger test, %d", 3)

    stderr_logger := slog.NewStderrLoggerSt("stderr_logger")
    stderr_logger.Debug("slog stderr_logger test")
    stderr_logger.Info("slog stderr_logger test")
    stderr_logger.Warn("slog stderr_logger test, %d", 3)
}

func File_writer_test() {
    fmt.Printf("file_writer_test\n")

    fwriter := slog.NewFileWriter()

    file_name := "file_writer_test.txt"

    if !fwriter.Open(file_name, false) {
        fmt.Printf("create file[%s] failed\n", file_name)
        return
    }

    defer fwriter.Close()

    for i := 0; i < 10; i++ {
        fwriter.Write([]byte("11111111111111111111\n"))
    }

    file_name1 := "file_writer_test1.txt"

    if !fwriter.Open(file_name1, false) {
        fmt.Printf("create file[%s] failed\n", file_name1)
        return
    }

    defer fwriter.Close()

    for i := 0; i < 10; i++ {
        fwriter.Write([]byte("2222222222222222222222\n"))
    }
}

// 这个就是最简单的单个文件的logger
func Simple_file_logger_test() {
    fmt.Printf("simple_file_logger_test\n")

    logger := slog.NewBasicLoggerSt("base_logger", "basic_logger.txt")

    for i := 0; i < 10; i++ {
        logger.Debug("base logger debug log test")
        logger.Info("base logger info log test")
        logger.Warn("base logger warn log test")
    }
}

// 这个指定每个文件的最大大小,以及维护的最大文件格式
// 当前文件大小到达指定的最大文件大小之后,就会进行一次rotating
// 比如最多保留3个文件的话
// Rotate files:
// log.txt -> log.1.txt
// log.1.txt -> log.2.txt
// log.2.txt -> log.3.txt
// log.3.txt -> delete
func Rotating_logger_test() {
    fmt.Printf("rotating_logger_test\n")

    logger := slog.NewRotatingLoggerSt("rotating_logger", "rotating_logger.txt", 500, 5)

    for i := 0; i < 20; i++ {
        logger.Debug("rorating msg xxx now_time[%s]", time.Now().String())
    }
}

// 这个是每日一个文件的logger
func Daily_logger_test() {
    fmt.Printf("daily_logger_test\n")

    logger := slog.NewDailyLoggerSt("daily_logger", "daily_logger.txt", 12, 30)

    for i := 0; i < 20; i++ {
        logger.Debug("daily_logger test")
    }
}

// 这个是每个小时会重新生成一个文件的logger
func Hourly_logger_test() {
    fmt.Printf("Hourly_logger_test\n")

    logger := slog.NewHourlyLoggerSt("houly_logger", "houly_logger.txt")

    for i := 0; i < 20; i++ {
        logger.Debug("houlry_logger test")
    }
}

// 你创建的一个logger,同一条日志可以根据需要打印到多个地方
// 比如stdout, stderr, file 之类的
func Muti_sink_test() {
    logger := slog.NewLogger("muti_logger")
    sink1 := slog.NewSimpleFileSinkSt("muti_sink_logger.txt")
    sink2 := slog.NewHourlyFileSinkSt("muti_hourly_logger.txt")
    sink3 := slog.NewStdoutSinkSt()

    logger.AppendSink(sink1).AppendSink(sink2).AppendSink(sink3)

    for i := 0; i < 20; i++ {
        logger.Debug("muti_sink_test test")
    }
}

func logger_log_test(gid int, logger *slog.Logger) {

    fmt.Printf("logger_log_test gid[%d]\n", gid)

    for i := 0; i < 5; i++ {
        logger.Debug("logger_log_test gid[%d] msgid[%d]", gid, i)
    }
}

func Muti_goroutine_stdout_test_nolock() {

    fmt.Printf("Muti_goroutine_stdout_test_nolock")

    logger := slog.NewStdoutLoggerSt("Muti_goroutine_test_nolock")

    for i := 0; i < 5; i++ {
        go logger_log_test(i, logger)
    }

    fmt.Printf("try sleep for a while\n")
    time.Sleep(time.Millisecond * 100)
    fmt.Printf("sleep finished, Muti_goroutine_test_nolock end\n")
}

func Muti_goroutine_stdout_test_lock() {
    fmt.Printf("Muti_goroutine_stdout_test_lock")

    logger := slog.NewStdoutLoggerMt("Muti_goroutine_test_lock")

    for i := 0; i < 5; i++ {
        go logger_log_test(i, logger)
    }

    fmt.Printf("try sleep for a while\n")
    time.Sleep(time.Millisecond * 100)
    fmt.Printf("sleep finished, Muti_goroutine_test_nolock end\n")
}

func Muti_goroutine_log_file_test_nolock() {

    fmt.Printf("Muti_goroutine_log_file_test_nolock")

    logger := slog.NewBasicLoggerSt("Muti_goroutine_log_file_test_nolock", "Muti_goroutine_log_file_test_nolock.txt")

    for i := 0; i < 5; i++ {
        go logger_log_test(i, logger)
    }

    fmt.Printf("try sleep for a while\n")
    time.Sleep(time.Millisecond * 100)
    fmt.Printf("sleep finished, Muti_goroutine_test_nolock end\n")
}

func Muti_goroutine_log_file_test_lock() {
    fmt.Printf("Muti_goroutine_log_file_test_lock")

    logger := slog.NewBasicLoggerMt("Muti_goroutine_log_file_test_lock", "Muti_goroutine_log_file_test_lock.txt")

    for i := 0; i < 5; i++ {
        go logger_log_test(i, logger)
    }

    fmt.Printf("try sleep for a while\n")
    time.Sleep(time.Millisecond * 100)
    fmt.Printf("sleep finished, Muti_goroutine_test_nolock end\n")
}

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK