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 的方式将日志分发到任意地方,如本地文件系统、标准输出、logstash、elasticsearch或者mq等,或者通过 hook 定义日志内容和格式等.
  • 可选的日志输出格式:logrus 内置了两种日志格式,JSONFormatter和TextFormatter,如果这两个格式不满足需求,可以自己动手实现接口 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

源文件:https://github.com/shershon1991/goe/blob/master/app/initialize.go

 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 日志分类和自定义格式

源文件:https://github.com/shershon1991/goe/blob/master/app/initialize.go

 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