golang常用库:日志记录库-logrus使用

介绍 logrus

它是一个结构化、插件化的日志记录库。完全兼容 golang 标准库中的日志模块。它还内置了 2 种日志输出格式 JSONFormatter 和 TextFormatter,来定义输出的日志格式。

github地址:https://github.com/sirupsen/logrus

logrus 使用

使用的版本:logrus v1.8.1

1. 开始使用

package main

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

func main() {
	log.WithFields(log.Fields{
		"animal": "walrus",
	}).Info("a walrus appears")
}

运行输出:

time="2021-11-11T17:41:48+08:00" level=info msg="a walrus appears" animal=walrus

2. 设置日志格式,日志级别,输出方式

设置日志格式

1)内置日志格式

log Formatter,logrus内置的formatter有 2 种,logrus.TextFormatter 和 logrus.JSONFormatter

  • logrus.JSONFormatter{}, 设置为 json 格式,所有设置选项在 logrus.JSONFormatter

    log.SetFormatter(&log.JSONFormatter{
        TimestampFormat: "2006-01-02 15:04:05", // 设置json里的日期输出格式
    })
    
    log.SetFormatter(&log.JSONFormatter{}) // 设置为json格式
    
  • logrus.TextFormatter{},设置为文本格式,所有的设置选项在 logrus.TextFormatter

    log.SetFormatter(&log.TextFormatter{
        TimestampFormat: "2006-01-02 15:04:05",
        ForceColors:  true,
        EnvironmentOverrideColors: true,
        // FullTimestamp:true,
        // DisableLevelTruncation:true,
    })
    

2)自定义日志格式

可以根据 Formatter 接口自定义日志格式,里面有一个 Format 方法,这个 Format 方法里有一个struct类型数据 *Entry, Entry.Data 是所有字段集合,Fields 类型为 map[string]interface{}。

比如:entry.Data["msg"],entry.Data["time"]`. The timestamp

package main

import (
	"fmt"

	jsoniter "github.com/json-iterator/go"
	log "github.com/sirupsen/logrus"
)

type MyJSONFormatter struct {
	JSONPrefix string
	Otherdata  string
}

func (my *MyJSONFormatter) Format(entry *log.Entry) ([]byte, error) {
	// fmt.Println(entry.Data["msg"])

	entry.Data["msg"] = fmt.Sprintf("%s%s", my.JSONPrefix, my.Otherdata)
	json, err := jsoniter.Marshal(&entry.Data)
	if err != nil {
		return nil, fmt.Errorf("failed to marshal fields to JSON , %w", err)
	}
	return append(json, '\n'), nil

}

func main() {
	formatter := &MyJSONFormatter{
		JSONPrefix: "jsonprefix-",
		Otherdata:  ":otherdata:",
	}

	log.SetFormatter(formatter)
	log.Info("this is customered formatter")
}

3)第三方自定义formatter设置日志格式

等等

设置日志级别

logrus日志一共7级别, 从高到低: panic, fatal, error, warn, info, debug, trace.

  • log.SetLevel(log.WarnLevel) // 设置输出警告级别

设置日志输出方式

  • log.SetOutput(os.Stdout) // 输入到 Stdout,默认输出到 Stderr
  • logfile, _ := os.OpenFile("./logrus.log", os.O_CREATE|os.O_RDWR|os.O_APPEND, 0644)
    logrus.SetOutput(logfile) // 输出到文件里

例子:

package main

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

func init() {
	log.SetFormatter(&log.JSONFormatter{}) // 设置 format json
	log.SetLevel(log.WarnLevel) // 设置输出警告级别
    // Output to stdout instead of the default stderr
    log.SetOutput(os.Stdout)
}

func main() {
	log.WithFields(log.Fields{
		"animal": "dog",
		"size":   10,
	}).Info("a group of dog emerges from the zoon")

	log.WithFields(log.Fields{
		"omg":    true,
		"number": 12,
	}).Warn("the group's number increased")

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

    // the logrus.Entry returned from WithFields()
	contextLogger := log.WithFields(log.Fields{
		"common": "this is a common filed",
		"other":  "i also should be logged always",
	})
	// 共同字段输出
	contextLogger.Info("I'll be logged with common and other field")
	contextLogger.Info("Me too")
}

运行输出:

{"level":"warning","msg":"the group's number increased","number":12,"omg":true,"time":"2021-11-11T18:00:55+08:00"}
{"level":"fatal","msg":"th ice breaks","number":100,"omg":true,"time":"2021-11-11T18:00:55+08:00"}

从输出的结果看出,Info 级别的日志信息都没有输出出来。

屏蔽设置日志级别的代码

func init() {
	log.SetFormatter(&log.JSONFormatter{}) // 设置 format json
	// log.SetLevel(log.WarnLevel)            // 设置输出警告级别
}

在运行输出:

{"animal":"dog","level":"info","msg":"a group of dog emerges from the zoon","size":10,"time":"2021-11-11T18:26:45+08:00"}
{"level":"warning","msg":"the group's number increased","number":12,"omg":true,"time":"2021-11-11T18:26:45+08:00"}
{"level":"fatal","msg":"th ice breaks","number":100,"omg":true,"time":"2021-11-11T18:26:45+08:00"}
exit status 1

从输出的日志信息来看,并没有输出 contextLogger 的日志info信息,日志信息没有输出,为啥没有输出日志?

把上面的 Fatal 输出日志屏蔽掉:

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

在运行输出:

{"animal":"dog","level":"info","msg":"a group of dog emerges from the zoon","size":10,"time":"2021-11-11T18:28:56+08:00"}
{"level":"warning","msg":"the group's number increased","number":12,"omg":true,"time":"2021-11-11T18:28:56+08:00"}
{"common":"this is a common filed","level":"info","msg":"I'll be logged with common and other field","other":"i also should be logged always","time":"2021-11-11T18:28:56+08:00"}
{"common":"this is a common filed","level":"info","msg":"Me too","other":"i also should be logged always","time":"2021-11-11T18:28:56+08:00"}

这时候可以输出 contextLogger 日志信息了。

3. logrus 的 Fatal 处理

上面的例子定义了输出 Fatal 日志后,其后的日志都不能输出了,这是为什么?日志后面有个信息 exit status 1

因为 logrus 的 Fatal 输出后,会执行 os.Exit(1)。那如果程序后面还有一些必要的程序要处理怎么办?

logrus 提供了 RegisterExitHandler 方法,在 fatal 异常时处理一些问题。

package main

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

func main() {
	log.SetFormatter(&log.TextFormatter{
		TimestampFormat: "2006-01-02 15:04:05",
	})

	log.RegisterExitHandler(func() {
		fmt.Println("发生了fatal异常,执行一些必要的处理工作")
	})

	log.Warn("warn")
	log.Fatal("fatal")
	log.Info("info") //不会执行
}

运行输出:

time="2021-11-11 21:48:25" level=warning msg=warn
time="2021-11-11 21:48:25" level=fatal msg=fatal
发生了fatal异常,执行一些必要的处理工作
exit status 1

4. 切分日志文件

如果日志文件太大了,想切分成小文件,但是 logrus 没有提供这个功能。

一种是借助linux系统的 logrotate 命令来切分 logrus 生成的日志文件。

另外一种是用 logrus 的 hook 功能,做一个切分日志的插件。找到了 file-rotatelogs,但是这个库状态

已经是 archived 状态,库作者现在不接受任何修改,他也不继续维护了。所以使用还是慎重些。

logrus issue 里找到了这个 https://github.com/natefinch/lumberjack 切割文件的库。

例子:

package main

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

	"gopkg.in/natefinch/lumberjack.v2"
)

func main() {
	logger := &lumberjack.Logger{
		Filename:   "./testlogrus.log",
		MaxSize:    500,  // 日志文件大小,单位是 MB
		MaxBackups: 3,    // 最大过期日志保留个数
		MaxAge:     28,   // 保留过期文件最大时间,单位 天
		Compress:   true, // 是否压缩日志,默认是不压缩。这里设置为true,压缩日志
	}

	log.SetOutput(logger) // logrus 设置日志的输出方式

}

5. 设置 logrus 实例

如果一个应用有多个地方使用日志,可以单独实例化一个 logrus,作为全局的日志实例。

package main

import (
	"os"

	"github.com/sirupsen/logrus"
)

var log = logrus.New()

func main() {
	log.Out = os.Stdout // 设置输出日志位置,可以设置日志到file里

	log.WithFields(logrus.Fields{
		"fruit": "apple",
		"size":  20,
	}).Info(" a lot of apples on the tree")
}

输出:

time="2021-11-11T18:39:15+08:00" level=info msg=" a lot of apples on the tree" fruit=apple size=20

6. fields

在使用 logrus 时,鼓励用 log.WithFields(log.Fields{}).Fatal() 这种方式替代 og.Fatalf("Failed to send event %s to topic %s with key %d"), 也就是不是用 %s,%d 这种方式格式化,而是直接传入变量 event,topic 给 log.Fields ,这样就显得结构化日志输出,很人性化美观。

log.WithFields(log.Fields{
  "event": event,
  "topic": topic,
  "key": key,
}).Fatal("Failed to send event")

7. 设置默认字段

比如在链路追踪里,会有一个 rquest_id ,trace_id 等,想这个 log 一直带有这 2 个字段,logrus 怎么设置?

可以用 log.WithFields(log.Fields{"request_id": request_id, "trace_id": trace_id})

requestLogger := log.WithFields(log.Fields{"request_id": request_id, "trace_id": trace_id})
requestLogger.Info("something happened on that request")
requestLogger.Warn("something not great happened")

例子:

package main

import (
	"github.com/google/uuid"
	log "github.com/sirupsen/logrus"
)

func main() {
	uid := uuid.New()
	request_id := uid
	trace_id := uid
	requestLogger := log.WithFields(log.Fields{"request_id": request_id, "trace_id": trace_id})
	requestLogger.Info("something happened on that request")
	requestLogger.Warn("something not great happened")
}

8. hook 钩子-扩展logrus功能

hook 给 logrus 提供了强大的可扩展功能.

用户可以给 logrus 编写钩子插件,根据自己的日志需求编写 hook。

logrus 也有一些内置插件hooks

第三方给 logrus 编写的 hook, 第三方hook列表

官方的 syslog hook example

package main

import (
	"log/syslog"

	"github.com/sirupsen/logrus"
	lSyslog "github.com/sirupsen/logrus/hooks/syslog"
)

func main() {
	log := logrus.New()
	hook, err := lSyslog.NewSyslogHook("", "", syslog.LOG_INFO, "")
	if err != nil {
		log.Hooks.Add(hook)
	}
}

参考

原文地址:https://www.cnblogs.com/jiujuan/p/15542743.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


咱们在vscode中使用copilot的过程中,有可能会涉及到个人账号和其他账号的互相切换,在网上找了半天都没找到相应的资料,于是就自己摸索了一下,终于找到了方法。解决思路:经过试验,github copilot插件是使用的vsc
这篇文章给大家介绍怎么在GitHub上快速找到实用资源,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。搜热门:GitHub Trend 和 GitHub Top...
这篇文章主要介绍“github缓存穿透的解决方法是什么”,在日常操作中,相信很多人在github缓存穿透的解决方法是什么问题上存在疑惑,小编查阅了各式资料,整理出...
本篇内容介绍了“github线性回归怎么实现”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧...
怎样使用GitHub,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。GitHub简介...
今天小编给大家分享一下GitHub的高级搜索方法有哪些的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下...
这期内容当中小编将会给大家带来有关Github 1.9K Star的数据治理框架Amundsen如何理解,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可...
本篇文章为大家展示了git如何设置代理提升github clone速度,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。github...
本篇内容介绍了“github怎么实现FaceU边框模糊效果”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理...
本篇内容介绍了“GitHub基础操作有哪些”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧...
这篇文章主要介绍了Github操作技巧实例分析的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Github操作技巧实例分析文章都会有
今天小编给大家分享一下github设备激活的方法的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大...
本文小编为大家详细介绍“GitHub的命令行工具有哪些”,内容详细,步骤清晰,细节处理妥当,希望这篇“GitHub的命令行工具有哪些”文章能帮助大家解决疑惑,下面...
本篇内容主要讲解“GitHub网页githubusercontent地址无法访问怎么解决”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大...
本文小编为大家详细介绍“怎么使用Github Action发布jar到Maven中央仓库”,内容详细,步骤清晰,细节处理妥当,希望这篇“怎么使用Github Action发布jar到Maven...
本文小编为大家详细介绍“GitHub中如何修改默认的分支”,内容详细,步骤清晰,细节处理妥当,希望这篇“GitHub中如何修改默认的分支”文章能帮助大家解决疑惑...
这篇“Github访问速度慢及图片加载慢问题怎么处理”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价
这篇文章主要介绍“vue项目打包上传github并制作预览链接的方法”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“vue...
这篇文章主要讲解了“访问不了github怎么处理”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“访问不了gith...
今天小编给大家分享一下GitHub访问不了怎么解决的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希