Go开源日志库Logrus的使用

embedded/2024/12/22 23:43:48/

一、Logrus简介

Logrus 是一个流行的 Go 语言日志库,以其功能强大、性能高效和高度灵活性而闻名。有关更多介绍可查看 Logrus。

主要特点
  • 丰富的日志级别:Logrus 支持多种日志级别,包括 Debug、Info、Warn、Error、Fatal 和 Panic,以及更细粒度的 Trace 级别。这些级别可以帮助开发者根据日志的严重程度进行筛选和处理。
  • 多种输出格式:Logrus 支持文本(TextFormatter)和 JSON(JSONFormatter)两种内置的日志格式,并且允许用户通过实现 Formatter 接口来自定义日志格式。
  • 结构化日志记录:Logrus 的 Field 机制允许用户为日志添加自定义字段,这些字段将作为日志消息的一部分被记录,使得日志信息更加结构化和易于查询。
  • 可扩展的钩子机制:Logrus 提供了钩子(hook)机制,允许用户通过编写自定义的 hook 来扩展日志的功能,例如将日志发送到远程服务器、写入文件等。
  • 预设日志字段:Logrus 的 Default Fields 机制可以给一部分或全部日志统一添加共同的日志字段,如请求ID、用户IP等。

二、Logrus基本用法

1、安装logrus

go get github.com/sirupsen/logrus

2、引入logrus

import "github.com/sirupsen/logrus"

3、设置日志级别

logrus.SetLevel(log.DebugLevel)

4、设置日志格式化器

logrus.SetFormatter(&logrus.TextFormatter{FullTimestamp:   true,                  // 完整时间TimestampFormat: "2006-01-02 15:04:05", // 时间格式ForceColors:     true,                  //显示颜色
})

5、设置日志输出类型

// 创建日志文件
file, _ := os.OpenFile("logs/application.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)// 设置日志输出到文件
// logrus.SetOutput(file)// 日志输出到文件和控制台
logrus.SetOutput(io.MultiWriter(file, os.Stdout))// 输出到控制台
// logrus.SetOutput(os.Stdout)

6、记录日志

logrus.WithField("appName", "测试logrus").Debug("这是一条Debug日志")
logrus.WithField("appName", "测试logrus").Info("这是一条Info日志")
logrus.WithFields(logrus.Fields{"appName": "测试logrus","appId":   101,
}).Info("这是一条Info日志")

效果示例:

三、Logrus进阶用法 

1、显示行号

// 显示行号
logrus.SetReportCaller(true)

效果演示: 

 2、hook机制

在 logrus 中,钩子(Hooks)是一种在日志条目(log entry)被处理之前或之后执行自定义逻辑的机制。你可以使用钩子来执行诸如将日志发送到外部服务(如 Sentry、Splunk 等)、修改日志消息、添加额外的日志上下文等任务。

使用方法:

  • 定义hook

实现logrus.Hook接口,其接口定义为:

type Hook interface {Levels() []LevelFire(*Entry) error
}
  • 注册hook
logrus.AddHook()

 完整代码:

package mainimport ("os""github.com/sirupsen/logrus"
)// 自定义hook
type simpleHook struct {
}// 实现logrus.Hook接口
func (h *simpleHook) Levels() []logrus.Level {// 只有日志级别为 ErrorLevel 的日志执行 Fire 中定义的操作return []logrus.Level{logrus.ErrorLevel}
}func (h *simpleHook) Fire(entry *logrus.Entry) error {// 在日志条目被处理时执行的逻辑entry.Data["appName"] = "test"// 将错误级别的日志添加单独的错误文件中file, _ := os.OpenFile("logs/error.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)defer file.Close()line, _ := entry.String()file.Write([]byte(line))return nil
}func main() {// 注册hooklogrus.AddHook(&simpleHook{})logrus.Info("测试钩子")// 只有 error 级别的日志才显示 appName = testlogrus.Error("测试钩子---错误信息")
}

效果演示: 

 错误信息被单独写入logs/error.log文件中,如下:

3、按时间分割日志

Logrus本身不支持日志轮转切割功能,需要配合 file-rotatelogs 包来实现。

  • 下载 file-rotatelogs 包
go get github.com/lestrrat-go/file-rotatelogs
  • 新建 RotateLogs(实现了 io.Writer 的 Write 方法)
// 创建一个 writer
logWriter, err := rotatelogs.New(filepath.Join("logs", "syslog_%Y%m%d%H%M%S.log"), //日志路径rotatelogs.WithLinkName(filepath.Join("logs", "syslog.log")),rotatelogs.WithMaxAge(7*24*time.Hour),       // 最大保留天数:7天rotatelogs.WithRotationTime(10*time.Second), // 日志分割时间:1分钟
)
if err != nil {panic(err)
}
  • 新建 NewHook()
// 新建Hook,将 otatelogs作为 writer
hook := lfshook.NewHook(logWriter,&logrus.TextFormatter{TimestampFormat: "2006-01-02 15:04:05",FullTimestamp:   true,},
)
  • 注册 Hook
// 注册 hook
logger.AddHook(hook)

完整代码:

package mainimport ("io""path/filepath""time"rotatelogs "github.com/lestrrat-go/file-rotatelogs""github.com/rifflock/lfshook""github.com/sirupsen/logrus"
)func main() {// 创建一个 writerlogWriter, err := rotatelogs.New(filepath.Join("logs", "syslog_%Y%m%d%H%M%S.log"), //日志路径rotatelogs.WithLinkName(filepath.Join("logs", "syslog.log")),rotatelogs.WithMaxAge(7*24*time.Hour),       // 最大保留天数:7天rotatelogs.WithRotationTime(10*time.Second), // 日志分割时间:10秒)if err != nil {panic(err)}// 新建Hook,将 otatelogs作为 writerhook := lfshook.NewHook(logWriter,&logrus.TextFormatter{TimestampFormat: "2006-01-02 15:04:05",FullTimestamp:   true,},)// 创建一个 loggerlogger := logrus.New()logger.SetReportCaller(true)logger.SetOutput(io.Discard)// 注册 hooklogger.AddHook(hook)// 记录日志for i := 0; i < 10; i++ {logger.Info("Hello world!!")time.Sleep(3 * time.Second)}
}

 效果示例:

4、按日志级别分割日志

按日志级别分割日志,可以将错误信息单独写入一个文件。

方法为:新建hook时,将不同日志级别匹配到不同的writer,如下:

// 新建Hook,按日志级别匹配 writer
hook := lfshook.NewHook(lfshook.WriterMap{logrus.DebugLevel: logWriter,logrus.InfoLevel:  logWriter,logrus.WarnLevel:  logWriter,logrus.ErrorLevel: errorWriter,},&logrus.TextFormatter{TimestampFormat: "2006-01-02 15:04:05",},
)

完整代码:

package mainimport ("io""path/filepath""time"rotatelogs "github.com/lestrrat-go/file-rotatelogs""github.com/rifflock/lfshook""github.com/sirupsen/logrus"
)func main() {// 创建一个 writerlogWriter, err := rotatelogs.New(filepath.Join("logs", "syslog_%Y%m%d%H%M%S.log"), //日志路径rotatelogs.WithLinkName(filepath.Join("logs", "syslog.log")),rotatelogs.WithMaxAge(7*24*time.Hour),       // 最大保留天数:7天rotatelogs.WithRotationTime(10*time.Second), // 日志分割时间:10s)if err != nil {panic(err)}// 创建一个 Error 级别的 writererrorWriter, err := rotatelogs.New(filepath.Join("logs", "sysError_%Y%m%d%H%M%S.log"), //日志路径rotatelogs.WithLinkName(filepath.Join("logs", "sysError.log")),rotatelogs.WithMaxAge(7*24*time.Hour),       // 最大保留天数:7天rotatelogs.WithRotationTime(10*time.Second), // 日志分割时间:1分钟)if err != nil {panic(err)}// 新建Hook,按日志级别匹配 writerhook := lfshook.NewHook(lfshook.WriterMap{logrus.DebugLevel: logWriter,logrus.InfoLevel:  logWriter,logrus.WarnLevel:  logWriter,logrus.ErrorLevel: errorWriter,},&logrus.TextFormatter{TimestampFormat: "2006-01-02 15:04:05",},)// 创建一个 loggerlogger := logrus.New()logger.SetReportCaller(true)logger.SetOutput(io.Discard)// 注册 hooklogger.AddHook(hook)// 记录日志for i := 0; i < 10; i++ {logger.Info("Hello world!!")logger.Error("这是报错信息")time.Sleep(3 * time.Second)}
}

 效果示例:

 


http://www.ppmy.cn/embedded/111414.html

相关文章

图文讲解HarmonyOS应用发布流程

HarmonyOS应用的开发和发布过程可以分为以下几个步骤&#xff1a;证书生成、应用开发、应用签名和发布。 1. 证书生成&#xff1a; 在开始开发HarmonyOS应用之前&#xff0c;首先需要生成一个开发者证书。开发者证书用于标识应用的开发者身份并确保应用的安全性。可以通过Har…

如何在@GenericGenerator中显式指定schema

现在的情况是&#xff0c;在MySQL中有db1和db2两个数据库。项目使用Hibernate&#xff0c;可同时访问db1和db2&#xff0c;默认数据库为db1。表table2在db2中。且table2的主键名为ids&#xff0c;是自增长字段&#xff08;Auto Increment&#xff09;。 table2和ids的定义为&a…

Python习题 179:用 pathlib 模块列出指定目录下的所有子目录

(编码题)请写一个 Python 函数,使用 pathlib 模块列出指定目录下的所有子目录,并统计它们的总数。 参考答案Python 代码如下from pathlib import Pathdef list_files_and_directories(directory_path):"""列出指定目录下的所有子目录,并统计它们的总数。参…

Spring-bean的生命周期-前篇

Spring bean生命周期12个环节 1.阶段1&#xff1a;Bean元信息配置阶段 2.阶段2&#xff1a;Bean元信息解析阶段 3.阶段3&#xff1a;将Bean注册到容器中 4.阶段4&#xff1a;BeanDefinition合并阶段 阶段5&#xff1a;Bean Class加载阶段 6.阶段6&#xff1a;Bean实例化阶…

笔试强训day11

游游的水果大礼包 #include <iostream> #define int long longusing namespace std; int n, m, a, b;signed main() {cin>>n>>m>>a>>b;int ret 0;for(int x 0; x < min(n / 2, m); x) // 枚举 1 号礼包的个数{int y min(n - x * 2, (m - …

ASP.NET Core 入门教学二十九 DDD设计

在软件开发中&#xff0c;领域驱动设计&#xff08;Domain-Driven Design&#xff0c;简称DDD&#xff09;是一种重要的软件设计方法论&#xff0c;它强调通过深入理解业务领域来构建高质量的软件系统。DDD的核心思想是将复杂的业务逻辑集中在领域模型中&#xff0c;并通过分层…

计算机毕业设计选题推荐-农家乐综合服务系统-乡村游乐购系统-田园休闲生活系统-Java/Python项目实战

✨作者主页&#xff1a;IT毕设梦工厂✨ 个人简介&#xff1a;曾从事计算机专业培训教学&#xff0c;擅长Java、Python、微信小程序、Golang、安卓Android等项目实战。接项目定制开发、代码讲解、答辩教学、文档编写、降重等。 ☑文末获取源码☑ 精彩专栏推荐⬇⬇⬇ Java项目 Py…

软件开发人员的真实面

我相信我们都看过视频上那些名为“软件工程师的一天”的视频。这些视频通常只展示一些日常任务&#xff0c;比如吃饭、打字和参加会议。我对这些视频未能展示软件开发工作的真实内容感到失望。这些内容往往只关注表面活动&#xff0c;却忽略了工作中的思维挑战和解决问题的部分…