golang中的log库


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")
}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 160,165评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,720评论 1 298
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,849评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,245评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,596评论 3 288
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,747评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,977评论 2 315
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,708评论 0 204
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,448评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,657评论 2 249
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,141评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,493评论 3 258
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,153评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,108评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,890评论 0 198
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,799评论 2 277
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,685评论 2 272