Go开源日志库Logrus的使用

news2024/11/15 15:30:11

一、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() []Level
	Fire(*Entry) error
}
  • 注册hook
logrus.AddHook()

 完整代码:

package main

import (
	"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() {
	// 注册hook
	logrus.AddHook(&simpleHook{})

	logrus.Info("测试钩子")
	// 只有 error 级别的日志才显示 appName = test
	logrus.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 main

import (
	"io"
	"path/filepath"
	"time"

	rotatelogs "github.com/lestrrat-go/file-rotatelogs"
	"github.com/rifflock/lfshook"
	"github.com/sirupsen/logrus"
)

func main() {
	// 创建一个 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), // 日志分割时间:10秒
	)
	if err != nil {
		panic(err)
	}

	// 新建Hook,将 otatelogs作为 writer
	hook := lfshook.NewHook(logWriter,
		&logrus.TextFormatter{
			TimestampFormat: "2006-01-02 15:04:05",
			FullTimestamp:   true,
		},
	)

	// 创建一个 logger
	logger := logrus.New()
	logger.SetReportCaller(true)
	logger.SetOutput(io.Discard)

	// 注册 hook
	logger.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 main

import (
	"io"
	"path/filepath"
	"time"

	rotatelogs "github.com/lestrrat-go/file-rotatelogs"
	"github.com/rifflock/lfshook"
	"github.com/sirupsen/logrus"
)

func main() {
	// 创建一个 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), // 日志分割时间:10s
	)
	if err != nil {
		panic(err)
	}

	// 创建一个 Error 级别的 writer
	errorWriter, 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,按日志级别匹配 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",
		},
	)

	// 创建一个 logger
	logger := logrus.New()
	logger.SetReportCaller(true)
	logger.SetOutput(io.Discard)

	// 注册 hook
	logger.AddHook(hook)

	// 记录日志
	for i := 0; i < 10; i++ {
		logger.Info("Hello world!!")
		logger.Error("这是报错信息")
		time.Sleep(3 * time.Second)
	}
}

 效果示例:

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2117328.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

深入理解数据库的 4NF:多值依赖与消除数据异常

在数据库设计中&#xff0c; "范式" 是一个常常被提到的重要概念。许多初学者在学习数据库设计时&#xff0c;经常听到第一范式&#xff08;1NF&#xff09;、第二范式&#xff08;2NF&#xff09;、第三范式&#xff08;3NF&#xff09;以及 BCNF&#xff08;Boyce-…

RESTful 还是 JSON-RPC

前言 RESTful 比较简单地说就是&#xff0c;大家请求一样的url&#xff08;GET方法有一个例外&#xff0c;url中带了一个id&#xff09;&#xff0c;通过不同的请求方法&#xff0c;分别进行不同的操作&#xff08;CRUD&#xff09;。 JSON-RPC JSON-RPC是一个无状态且轻量级…

SpringBoot学习(7)(Bean对象注册)(自定义组合注解)

目录 一、引言 二、案例学习 &#xff08;一&#xff09;Bean &#xff08;二&#xff09;Import 三、补充 &#xff08;1&#xff09;关于Java中collection.toArray(new String[0])解释 &#xff08;2&#xff09;组合注解 一、引言 上次学习了解到&#xff0c;springb…

基于机器学习的阿尔兹海默症智能分析预测系统

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长 QQ 名片 :) 1. 项目简介 阿尔兹海默症&#xff08;Alzheimers Disease, AD&#xff09;是一种常见的神经退行性疾病&#xff0c;主要影响老年人的认知功能。随着全球人口老龄化的加剧&#xff0c;阿尔兹海默症的患病率逐年…

nodejs 使用kafka案例,node-red配置kafka案例,从安装配置kafka开始

生产者测试&#xff1a; bin/kafka-console-producer.sh --broker-list 1.2.3.4:9092 --topic test-topic消费者测试&#xff1a; bin/kafka-console-consumer.sh --bootstrap-server 1.2.3.4:9092 --topic test-topic --from-beginningconst { Kafka } require(kafkajs)con…

【AIGC数字人】EchoMimic:基于可编辑关键点条件的类人音频驱动肖像动画

GitHub&#xff1a;https://github.com/BadToBest/EchoMimic 论文&#xff1a; https://arxiv.org/pdf/2407.08136 comfyui&#xff1a; https://github.com/smthemex/ComfyUI_EchoMimic 相关工作 Wav2Lip Wav2Lip是一个开创性的工作 &#xff0c;但输出会出现面部模糊或扭…

粒子群算法原理的示例介绍

一&#xff1a;粒子群优化算法的介绍 粒子群优化算法&#xff08;PSO&#xff09;是一种基于群体智能的优化算法&#xff0c;于1995年提出。它受到鸟群狩猎行为的启发&#xff0c;通过模拟鸟群或鱼群的社会行为来进行问题的求解。 基本原理 粒子群算法中&#xff0c;每个解决…

顶刊算法 | Matlab实现鹈鹕算法POA-CNN-LSTM-Multihead-Attention多头注意力机制多变量时间序列预测,优化前后对比

顶刊算法 | Matlab实现鹈鹕算法POA-CNN-LSTM-Multihead-Attention多头注意力机制多变量时间序列预测&#xff0c;优化前后对比 目录 顶刊算法 | Matlab实现鹈鹕算法POA-CNN-LSTM-Multihead-Attention多头注意力机制多变量时间序列预测&#xff0c;优化前后对比预测效果基本介绍…

一种小众且适合发文的智能优化算法应用——三维TSP问题

声明&#xff1a;文章是从本人公众号中复制而来&#xff0c;因此&#xff0c;想最新最快了解各类智能优化算法及其改进的朋友&#xff0c;可关注我的公众号&#xff1a;强盛机器学习&#xff0c;不定期会有很多免费代码分享~ 今天给大家介绍一种非常小众的智能优化算法应用&am…

【LabVIEW学习篇 - 21】:DLL与API的调用

文章目录 DLL与API调用DLLAPIDLL的调用 DLL与API调用 LabVIEW虽然已经足够强大&#xff0c;但不同的语言在不同领域都有着自己的优势&#xff0c;为了强强联合&#xff0c;LabVIEW提供了强大的外部程序接口能力&#xff0c;包括DLL、CIN(C语言接口)、ActiveX、.NET、MATLAB等等…

2024/9/9 408“回头看”:

B树是什么&#xff1f;有什么作用&#xff1f;B树的插入和删除具体细节是什么&#xff1f;除了B树还有一个是B&#xff0b;树、还是B-树&#xff0c;他们有什么区别&#xff0c;又有什么相同点&#xff1f; b树在王道考研查找这一章&#xff0c;所以他的主要作用就是查找。 在…

MySQL中binary放在判断语句之前有什么作用

为什么要加binary进行判断 ① 因为 mysql中等号比较是不区分大小写的&#xff0c;select aA这个输出结果为1。 ② 在判断语句之前 加上binary可以以区分大小写比较 &#xff0c;因为这样底层会用二进制形式比较&#xff0c;实现精确匹配。 代码比较 忽略大小写比较 select …

Ftrans跨域文件传输方案,数据流动无阻的高效路径

大型集团企业由于其规模庞大、业务广泛且往往将分支机构、办事处分布在多个地域&#xff0c;因此会涉及到跨域文件传输的需求。主要源于以下几个方面&#xff1a; 1.业务协同&#xff1a;集团内部的不同部门或子公司可能位于不同的地理位置&#xff0c;但需要进行紧密的业务协…

【C++】STL学习——priority_queue(了解仿函数)

目录 priority_queue介绍迭代器种类priority_queue实现仿函数仿函数的使用 priority_queue介绍 优先队列是一种容器适配器&#xff0c;根据严格的弱排序标准&#xff0c;它的第一个元素总是它所包含的元素中最大的。此上下文类似于堆&#xff0c;在堆中可以随时插入元素&#x…

Linux 磁盘管理-RAID磁盘冗余阵列看这一篇就够了

今天给伙伴们分享一下Linux 磁盘管理-RAID磁盘冗余阵列&#xff0c;希望看了有所收获。 我是公众号「想吃西红柿」「云原生运维实战派」作者&#xff0c;对云原生运维感兴趣&#xff0c;也保持时刻学习&#xff0c;后续会分享工作中用到的运维技术&#xff0c;在运维的路上得到…

机器学习深度学习

版权声明 本文原创作者:谷哥的小弟作者博客地址:http://blog.csdn.net/lfdfhl1. 深度学习概述 1.1 定义与历史背景 深度学习作为机器学习领域的一个重要分支,其核心在于构建由多层(深层)的人工神经网络组成的计算模型,这些模型能够学习数据的多层次抽象表示。深度学习的…

东大成贤资源库-数据挖掘技术与应用 实验一:数据预处理_熟悉数据挖掘数据预处理流程。 基于给定的数据集(csv)文件,完成下列数据处理。 1

【实验内容】 程序清单 import pandas as pd import numpy as np# 读入文件&#xff0c;存放在字典data里 data pd.read_csv("D:\\Desktop\\data1.csv")# 填入Id列空缺的值 for i in range(1,len(data)):if pd.isnull(data[Id][i]):data[Id][i]i1# Id属性列去重&a…

虚拟机的安装步骤

我这里使用的是VMware 1.下载centos7 2.配置 跟这图来就好 开启虚拟机 第一个页面直接回车,忘了截图 等待安装 选择语言,看自己 点击完成 点击继续安装 设置账号密码 然后等待就行 安装完成之后会有一个重启,点击(又忘了截图) 完成许可和网络 最后就可以了

AI(文生语音)-TTS 技术线路探索学习:从拼接式参数化方法到Tacotron端到端输出

AI(文生语音)-TTS 技术线路探索学习:从拼接式参数化方法到Tacotron端到端输出 在数字化时代&#xff0c;文本到语音&#xff08;Text-to-Speech, TTS&#xff09;技术已成为人机交互的关键桥梁&#xff0c;无论是为视障人士提供辅助阅读&#xff0c;还是为智能助手注入声音的灵…

数据权限的设计与实现系列7——前端筛选器组件Everright-filter用法说明

背景 官方给了全局性的介绍和示例&#xff0c;不过到了具体使用环节&#xff0c;介绍就不是那么清楚明确了&#xff0c;往往是直接放 demo&#xff0c;需要去推测和揣测&#xff0c;然后动手验证。去百度了下&#xff0c;也没找到现成的对该组件的使用说明&#xff0c;得以开荒…