1.介绍

logrus是目前 Github 上 star 数量最多的日志库,截止今天star数量为17.3k logrus功能强大,性能高效,而且具有高度灵活性,提供了自定义插件的功能。

logrus源码:https://github.com/sirupsen/logrus

1.特性总览

  • 完全兼容 golang 标准库日志模块,logrus 拥有六种日志级别:debug、info、warn、error、fatal 和 panic,这是 golang 标准库日志模块的API的超集.如果您的项目使用标准库日志模块,完全可以以最低的代价迁移到 logrus 上。
  • 可扩展的 Hook 机制:允许使用者通过 hook 的方式将日志分发到任意地方,如本地文件系统、标准输出、logstashelasticsearch或者mq等,或者通过 hook 定义日志内容和格式等.
  • 可选的日志输出格式:logrus 内置了两种日志格式,JSONFormatterTextFormatter,如果这两个格式不满足需求,可以自己动手实现接口 Formatter,来定义自己的日志格式.
  • Field机制:logrus鼓励通过 Field 机制进行精细化的、结构化的日志记录,而不是通过冗长的消息来记录日志.
  • logrus是一个可插拔的、结构化的日志框架.

2.安装

1
go get github.com/sirupsen/logrus

3.编写配置

3.1 编写*.ini

app/config/dev.ini

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
[log]
#日志目录
path=/Users/hui/Project/Go/self/goe/log
# 日志级别
level=debug
# 日志格式: json,text,customize
formatter=json
# 输出类型: 1:控制台,2:日志文件
output_type=2
# 打开日志记录的行数;true:开启,false:关闭。默认关闭
report_caller=true
# 日志后缀格式
suffix_format=%Y%m%d

3.2 编写配置结构体

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
/**
 * @description: 日志配置
 * @user: Shershon
 */
type LogrusConfig struct {
    Path         string `ini:"path"`
    Level        string `ini:"level"`
    Formatter    string `ini:"formatter"`
    OutputType   string `ini:"output_type"`
    ReportCaller bool   `ini:"report_caller"`
    Suffix       string `ini:"suffix_format"`
}

3.3 映射配置

app/app.go

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
// 定义全局变量
var LogrusConfigInstance = &config.LogrusConfig{}
// 把ini配置映射到结构体
func (app *App) loadConfig() {
    ...
    // 加载日志配置
    err = cfg.Section("log").MapTo(LogrusConfigInstance)
    if err != nil {
        BusErrorInstance.ThrowError(err)
    }
}

3.3 初始化全局Logger

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
func setLoggerInstance() {
    // 设置日志级别
    var level logrus.Level
    err := level.UnmarshalText([]byte(LogrusConfigInstance.Level))
    BusErrorInstance.ThrowError(err)
    LoggerClient.SetLevel(level)
    // 设置日志格式
    if LogrusConfigInstance.Formatter == "json" {
        LoggerClient.SetFormatter(&logrus.JSONFormatter{})
    } else if LogrusConfigInstance.Formatter == "text" {
        LoggerClient.SetFormatter(&logrus.TextFormatter{})
    } else if LogrusConfigInstance.Formatter == "customize" {
        LoggerClient.SetFormatter(&CustomizeFormat{})
    } else {
        BusErrorInstance.ThrowError(errors.New("log formatter must json|text|customize"))
    }
    // 打开日志记录的行数;true:开启,false:关闭。默认关闭
    if LogrusConfigInstance.ReportCaller {
        LoggerClient.SetReportCaller(LogrusConfigInstance.ReportCaller)
    }
    // 设置日志输出方式
    switch LogrusConfigInstance.OutputType {
    case "1":
        // 控制台
        LoggerClient.SetOutput(os.Stdout)
    case "2":
    // 文件(日志分类配置)
        Log2FileByClass()
    default:
        // 默认写到控制台
        LoggerClient.SetOutput(os.Stdout)
    }
}

3.4 日志分类和自定义格式

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
/**
 * @Author Shershon
 * @Description 日志相关
 * @Date 2021/3/8 2:35 下午
 **/
package common

import (
    "fmt"
    goFileRotatelogs "github.com/lestrrat/go-file-rotatelogs"
    "github.com/rifflock/lfshook"
    "github.com/sirupsen/logrus"
    "path"
    "strings"
    "time"
)

type CustomizeFormat struct {
}

/**
 * @description: 自定义格式输出
 * @user: Shershon
 * @receiver c CustomizeFormat
 * @param entry
 * @return []byte
 * @return error
 * @date 2021-03-08 15:53:29
 */
func (c CustomizeFormat) Format(entry *logrus.Entry) ([]byte, error) {
    msg := fmt.Sprintf("[%s] [%s] %s \n",
        time.Now().Local().Format("2006-01-02 15:04:05"),
        strings.ToUpper(entry.Level.String()),
        entry.Message,
    )
    return []byte(msg), nil
}

/**
 * @description: 写入日志并分割
 * @user: Shershon
 * @param save
 * @date 2021-03-08 15:16:32
 */
func Log2FileByClass() {
    lfhook := lfshook.NewHook(lfshook.WriterMap{
        logrus.DebugLevel: splitConfig("debug"),
        logrus.InfoLevel:  splitConfig("info"),
        logrus.WarnLevel:  splitConfig("warn"),
        logrus.ErrorLevel: splitConfig("error"),
        logrus.FatalLevel: splitConfig("fatal"),
        logrus.PanicLevel: splitConfig("painc"),
    }, LoggerClient.Formatter)
    LoggerClient.AddHook(lfhook)
}

/**
 * @description: 分割文件配置
 * @user: Shershon
 * @param level
 * @return *goFileRotatelogs.RotateLogs
 * @date 2021-03-08 15:49:08
 */
func splitConfig(level string) *goFileRotatelogs.RotateLogs {
    // 拼凑日志名
    logFile := path.Join(LogrusConfigInstance.Path, level)
    logs, err := goFileRotatelogs.New(
        // 文件名
        logFile+"-"+LogrusConfigInstance.Suffix,
        // 生成软链,指向最新日志文件
        goFileRotatelogs.WithLinkName(logFile),
    )
    BusErrorInstance.ThrowError(err)
    return logs
}

4.使用

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
/**
 * @Author Shershon
 * @Description 日志集成使用
 * @Date 2021/3/8 2:15 下午
 **/
package v1

import (
    "github.com/sirupsen/logrus"
    . "goe/app/common"
)
type LogController struct {
    BaseController
}
func init() {
    RouteListInstance.AddRoute("v1","log",&LogController{})
}
/**
 * @description: 测试logrus使用
 * @user: Shershon
 * @receiver l LogController
 * @return error
 * @date 2021-03-08 14:22:45
 */
func (l LogController) Test() error  {
    // 简短消息记录
    LoggerClient.Trace("这是Trace,日志信息")
    LoggerClient.Debug("这是Debug,日志信息")
    LoggerClient.Info("这是Info,日志信息")
    LoggerClient.Error("这是Error,日志信息")
    LoggerClient.Warn("这是Warn,日志信息")
    //记录结构化数据
    LoggerClient.WithFields(logrus.Fields{
        "uerName":"zhangsan",
        "age":28,
        "pice":500.12,
        "likes":[]string{"游戏","旅游"},
    }).Info("记录结构化数据")
    return  l.Success(nil)
}

5.效果图

image-20210308164422910