Golang中日志使用详解

 更新时间:2024年01月19日 08:48:33   作者:莫忘初心丶  
这篇文章记录了Golang项目中日志使用,以及结合Gin框架记录请求日志,文中通过代码示例介绍的非常详细,对大家的学习或工作有一定的帮助,需要的朋友可以参考下

日志库介绍

  1. rotatelogs "github.com/lestrrat-go/file-rotatelogs

  2. github.com/rifflock/lfshook

  3. github.com/sirupsen/logrus
    这三个包通常被一起使用是为了实现日志文件的轮转(log rotation)功能。解释一下它们的作用:

  4. github.com/lestrrat-go/file-rotatelogs

    • 这是一个用于文件日志轮转的 Go 语言包。它允许你创建按时间轮转的日志文件,确保日志文件不会无限制地增长,而是会按照一定的规则进行切割,例如按天、按小时等。
  5. github.com/rifflock/lfshook

    • 这是 Logrus(一个 Go 语言的日志库)的一个钩子(hook)。Logrus 是一个功能强大的日志库,而 lfshook 允许你将 Logrus 的日志输出写入到文件,并且可以结合 github.com/lestrrat-go/file-rotatelogs 这个包,实现日志文件的定期轮转。
  6. github.com/sirupsen/logrus

    • Logrus 是一个非常流行的 Go 语言日志库,提供了丰富的日志功能。它支持日志级别、字段结构化输出等特性,使得日志记录变得更加灵活和可定制。

综合使用这三个包的方式,你可以在应用程序中使用 Logrus 进行日志记录,并通过 lfshook 将日志输出到文件,同时利用 file-rotatelogs 来管理日志文件的轮转,以防止日志文件无限增长而导致的存储问题。这样的组合可以确保你的应用程序能够高效地记录日志,并在需要时保持日志文件的可管理性。

简单日志记录

这是一个简单的日志包(clog)的实现,使用 Logrus、file-rotatelogs 和 lfshook 这三个包来实现日志记录和轮转的功能。

package clog

import (
	"fmt"
	"os"
	"path"
	"time"

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

// 日志文件路径和文件名
var (
	logFilePath = "./log/"
	logFileName = "system.log"
)

// Logger 是日志记录器实例
var Logger *logrus.Logger

// init 函数在包被导入时执行,用于初始化日志设置
func init() {
	// 初始化日志记录器
	Logger = logrus.New()

	// 设置日志级别为 Debug
	Logger.SetLevel(logrus.DebugLevel)

	// 设置输出到文件
	fileName := path.Join(logFilePath, logFileName)
	src, err := os.OpenFile(fileName, os.O_APPEND|os.O_WRONLY, os.ModeAppend)
	if err != nil {
		fmt.Println("err", err)
	}
	Logger.Out = src

	// 设置 rotatelogs,实现日志文件轮转
	logWriter, _ := rotatelogs.New(
		fileName+".%Y%m%d.log",
		rotatelogs.WithLinkName(fileName),
		rotatelogs.WithMaxAge(15*24*time.Hour),
		rotatelogs.WithRotationTime(24*time.Hour),
	)

	// 配置 lfshook,将不同日志级别的日志写入同一个文件
	writeMap := lfshook.WriterMap{
		logrus.InfoLevel:  logWriter,
		logrus.FatalLevel: logWriter,
		logrus.DebugLevel: logWriter,
		logrus.WarnLevel:  logWriter,
		logrus.ErrorLevel: logWriter,
		logrus.PanicLevel: logWriter,
	}

	// 添加 lfshook 到 Logger
	Logger.AddHook(lfshook.NewHook(writeMap, &logrus.TextFormatter{
		TimestampFormat: "2006-01-02 15:04:05",
	}))
}

// Add 函数用于添加日志记录
func Add(requestId, info string, err error) {
	if err != nil {
		// 如果有错误,记录 Error 级别的日志
		Logger.WithFields(logrus.Fields{
			"request_id": requestId,
			"info":       info,
			"error":      err.Error(),
		}).Error()
	} else {
		// 如果没有错误,记录 Info 级别的日志
		Logger.WithFields(logrus.Fields{
			"request_id": requestId,
			"info":       info,
			"error":      "",
		}).Info()
	}
}
  • logFilePath 和 logFileName 定义了日志文件的路径和名称。
  • Logger 是 logrus 的日志记录器实例。
  • init 函数在包被导入时执行,用于初始化 Logger、设置日志级别、输出到文件、配置文件轮转等。
  • rotatelogs.New 创建了一个按时间轮转的日志写入器。
  • lfshook.WriterMap 定义了不同日志级别对应的写入器,确保不同级别的日志写入到同一个文件。
  • lfshook.NewHook 创建了一个 lfshook 钩子,将其添加到 Logger 中。
  • Add 函数用于添加日志记录,根据是否有错误来选择记录 Info 或 Error 级别的日志。

结合Gin框架使用

这是一个基于 Gin 框架的中间件(LoggerMiddleware),用于记录请求的相关信息

package auth

import (
	"encoding/json"
	"fmt"
	"time"

	"go-yinhe-cloud/middleware/clog"
	"go-yinhe-cloud/models"
	"go-yinhe-cloud/pkg/util"

	"github.com/gin-gonic/gin"
	"github.com/sirupsen/logrus"
)

// LoggerMiddleware 返回一个 Gin 中间件,用于记录请求日志
func LoggerMiddleware() gin.HandlerFunc {
	return func(c *gin.Context) {
		// 记录请求开始时间
		startTime := time.Now()

		// 处理请求
		c.Next()

		// 记录请求结束时间
		endTime := time.Now()

		// 计算请求执行时间
		latencyTime := endTime.Sub(startTime)

		// 获取请求相关信息
		reqMethod := c.Request.Method        // 请求方式
		reqUrl := c.Request.RequestURI       // 请求路由
		statusCode := c.Writer.Status()      // 状态码
		clientIP := c.ClientIP()             // 请求IP
		header := c.GetHeader("User-Agent") + "@@" + c.GetHeader("token") // 请求头
		_ = c.Request.ParseMultipartForm(128)
		reqForm := c.Request.Form
		var reqJsonStr string

		// 将请求数据转为 JSON 字符串
		if len(reqForm) > 0 {
			reqJsonByte, _ := json.Marshal(reqForm)
			reqJsonStr = string(reqJsonByte)
		}

		// 获取请求中的 requestId
		requestId := c.GetString("requestId")

		// 获取 Gin 中间件中的错误信息
		var errorsStr string
		for _, err := range c.Errors.Errors() {
			errorsStr += err + "; "
		}

		// 记录请求日志到文件
		clog.Logger.WithFields(logrus.Fields{
			"request_id":   requestId,
			"status_code":  statusCode,
			"latency_time": latencyTime,
			"client_ip":    clientIP,
			"req_method":   reqMethod,
			"ua_token":     header,
			"req_uri":      reqUrl,
			"body":         reqJsonStr,
			"err_str":		errorsStr,
		}).Info()
	}
}
  • LoggerMiddleware 返回一个 Gin 中间件函数。
  • 记录请求开始时间和结束时间,计算请求执行时间。
  • 获取请求的方法、路由、状态码、IP、请求头等信息。
  • 将请求数据转为 JSON 字符串。
  • 获取 Gin 中间件中的错误信息,并拼接成字符串。
  • 记录请求日志到文件,使用 clog.Logger。

以上就是Golang中日志使用详解的详细内容,更多关于Golang日志使用的资料请关注脚本之家其它相关文章!

相关文章

  • go语言使用中提示%!(NOVERB)的解决方案

    go语言使用中提示%!(NOVERB)的解决方案

    o语言的设计目标是提供一种简单易用的编程语言,同时保持高效性和可扩展性,它支持垃圾回收机制,具有强大的并发编程能力,可以轻松处理大规模的并发任务,Go语言还拥有丰富的标准库和活跃的开发社区,使得开发者能够快速构建出高质量的应用程序,需要的朋友可以参考下
    2023-10-10
  • Go 语言中静态类型和动态类型的使用

    Go 语言中静态类型和动态类型的使用

    本文主要介绍了Go语言中的静态类型和动态类型,静态类型在编译时确定,提供了类型安全,性能优化和代码清晰,而动态类型在运行时确定,提供了更高的灵活性,但可能引发运行时错误,下面就来介绍一下,感兴趣的可以了解一下
    2024-10-10
  • Go语言排序算法之插入排序与生成随机数详解

    Go语言排序算法之插入排序与生成随机数详解

    从这篇文章开始将带领大家学习Go语言的经典排序算法,比如插入排序、选择排序、冒泡排序、希尔排序、归并排序、堆排序和快排,二分搜索,外部排序和MapReduce等,本文将先详细介绍插入排序,并给大家分享了go语言生成随机数的方法,下面来一起看看吧。
    2017-11-11
  • golang进行简单权限认证的实现

    golang进行简单权限认证的实现

    本文主要介绍了golang简单权限认证的实现,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-09-09
  • 使用go语言解析xml的实现方法(必看篇)

    使用go语言解析xml的实现方法(必看篇)

    下面小编就为大家带来一篇使用go语言解析xml的实现方法(必看篇)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-06-06
  • go mod 使用旧版本 版本号指定方式

    go mod 使用旧版本 版本号指定方式

    这篇文章主要介绍了go mod 使用旧版本 版本号指定方式,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-05-05
  • 为什么GO不支持循环引用

    为什么GO不支持循环引用

    这篇文章主要介绍的是为什么GO不支持循环引用,学习 Go 语言的开发者越来越多了,很多小伙伴在使用时,就会遇到种种不理解的问题,其中一点就是包的循环引用的报错,下main文章我们一起来看看学习原因
    2021-10-10
  • Go语言参数传递是传值还是传引用

    Go语言参数传递是传值还是传引用

    Go 语言到底是传值(值传递),还是传引用(引用传递)?本文就详细介绍一下,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-12-12
  • Golang中的Unicode与字符串示例详解

    Golang中的Unicode与字符串示例详解

    这篇文章主要给大家介绍了关于Golang中Unicode与字符串的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用Golang具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2020-05-05
  • golang实现对JavaScript代码混淆

    golang实现对JavaScript代码混淆

    在Go语言中,你可以使用一些工具来混淆JavaScript代码,一个常用的工具是Terser,它可以用于压缩和混淆JavaScript代码,你可以通过Go语言的`os/exec`包来调用Terser工具,本文给通过一个简单的示例给大家介绍一下,感兴趣的朋友可以参考下
    2024-01-01

最新评论