golang——工程组件logrus日志记录框架(结构化记录,支持文件切割,hook)

logrus

介绍一个golang 日志框架logrus

  • 支持文本与JSON数据格式
  • 支持结构化记录
  • 支持hook

文档介绍

logrus文档

std

官方案例介绍了如何配置std打印

package main

import (
  "os"
  log "github.com/sirupsen/logrus"
)

func init() {
  // Log as JSON instead of the default ASCII formatter.
  log.SetFormatter(&log.JSONFormatter{})

  // Output to stdout instead of the default stderr
  // Can be any io.Writer, see below for File example
  log.SetOutput(os.Stdout)

  // Only log the warning severity or above.
  log.SetLevel(log.WarnLevel)
}

func main() {
  log.WithFields(log.Fields{
    "animal": "walrus",
    "size":   10,
  }).Info("A group of walrus emerges from the ocean")

  log.WithFields(log.Fields{
    "omg":    true,
    "number": 122,
  }).Warn("The group's number increased tremendously!")

  log.WithFields(log.Fields{
    "omg":    true,
    "number": 100,
  }).Fatal("The ice breaks!")

  // A common pattern is to re-use fields between logging statements by re-using
  // the logrus.Entry returned from WithFields()
  contextLogger := log.WithFields(log.Fields{
    "common": "this is a common field",
    "other": "I also should be logged always",
  })

  contextLogger.Info("I'll be logged with common and other field")
  contextLogger.Info("Me too")
}

file

仔细观察,如果要输出到文件,只需要在logrus.SetOutput设置上对应的*os.File即可

文件切割

文件日志记录一般都是要切割的,不然文件太大不方便查看

采用的库

https://github.com/lestrrat-go/file-rotatelogs
案例

log.go

package logs

import (
    "fmt"
    "github.com/sirupsen/logrus"
    "log"
)

type Log struct {
    *logrus.Entry
    LogWriter
}


func (l *Log) Flush() {
    l.LogWriter.Flush()
}

type LogConf struct {
    Level       logrus.Level
    AdapterName string
    Hook        logrus.Hook
}



func InitLog(conf LogConf) *Log {
    adapterName := "std"
    if conf.AdapterName != "" {
        adapterName = conf.AdapterName
    }
    writer, ok := writerAdapter[adapterName]
    if !ok {
        adapterName = "std"
        writer, _ = writerAdapter[adapterName]
    }
    fmt.Println("adapterName:" + adapterName)
    log :=&Log{
        logrus.NewEntry(logrus.New()),
        writer(),  // 初始化writer
    }
    // Log as JSON instead of the default ASCII formatter.
    log.Logger.SetFormatter(&logrus.JSONFormatter{})

    // Output to stdout instead of the default stderr
    // Can be any io.Writer, see below for File example
    log.Logger.SetOutput(log.LogWriter)

    // Only log the warning severity or above.
    if conf.Level != 0 {
        log.Logger.SetLevel(conf.Level)
    } else {
        log.Logger.SetLevel(logrus.InfoLevel)
    }
    if conf.Hook != nil {
        log.Logger.AddHook(conf.Hook)
    }
    // 设置日志打印位置
    log.Logger.SetReportCaller(true)

    return log
}

type TestHook struct {

}

func (hook *TestHook) Levels() []logrus.Level {
    return []logrus.Level{logrus.InfoLevel}
}
func (hook *TestHook)  Fire(entry *logrus.Entry) error {
    log.Print("hook: %+v", entry)
    return nil
}

file_rotate.go

package logs

import (
    rotatelogs "github.com/lestrrat-go/file-rotatelogs"
    "log"
    "time"
)

type fileRotateWriter struct {
    *rotatelogs.RotateLogs
}

func (frw *fileRotateWriter) Flush() {
    frw.Close()
}

func newFileRotateWriter() LogWriter {
    writer, err := getRotateLogs()
    if err != nil {
        log.Fatal(err)
    }

    return &fileRotateWriter{
        writer,
    }
}

func getRotateLogs() (*rotatelogs.RotateLogs, error) {
    path := LOGPATH
    logf, err := rotatelogs.New(
        path + ".%Y%m%d%H%M", // 指定文件格式
        //rotatelogs.WithLinkName(path),           // 将最新文件软链到path,windows环境不支持
        rotatelogs.WithMaxAge(time.Second*1800),     // 日志最长保存时长
        rotatelogs.WithRotationTime(time.Second*60), // 日志切分时间间隔
    )
    return logf, err
}

func init() {
    RegisterInitWriterFunc("file-rotate", newFileRotateWriter)
}

main.go

package main

import (
    "logrus-practice/logs"
    "github.com/sirupsen/logrus"
)



func main() {
    conf := logs.LogConf{
        Level: logrus.InfoLevel,
        AdapterName: "file-rotate",
        Hook: &logs.TestHook{},
    }
    log := logs.InitLog(conf)
    log.WithFields(logrus.Fields{
        "animal": "walrus",
        "size":   10,
    }).Info("A group of walrus emerges from the ocean")

    log.WithFields(logrus.Fields{
        "omg":    true,
        "number": 122,
    }).Warn("The group's number increased tremendously!")

    log.WithFields(logrus.Fields{
        "omg":    true,
        "number": 100,
    }).Fatal("The ice breaks!")

    // A common pattern is to re-use fields between logging statements by re-using
    // the logrus.Entry returned from WithFields()
    contextLogger := log.WithFields(logrus.Fields{
        "common": "this is a common field",
        "other": "I also should be logged always",
    })

    contextLogger.Info("I'll be logged with common and other field")
    contextLogger.Info("Me too")
}

hook机制

框架支持,在不同level的日志打印中进行hook。我们可以根据传入的*logrus.Entry里用户自定义的field进行不同的业务处理

上面代码已经含有hook的使用

type TestHook struct {

}

func (hook *TestHook) Levels() []logrus.Level {
    return []logrus.Level{logrus.InfoLevel}
}
func (hook *TestHook)  Fire(entry *logrus.Entry) error {
    // 可以根据data字段里的field 去做操作
    log.Print("hook: %+v", entry)
    return nil
}

生成环境中,很多公司都会采用ELK那一套,把日志转发录入到ES中,在kibana按条件搜索

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值