【go语言开发】loglus日志框架的使用

2023-12-05

本文将简单介绍loglus框架的基本使用,并给出demo

前言

Logrus 是一个用于 Go 语言的结构化日志框架,它提供了丰富的日志级别、钩子和格式化选项。
环境搭建:

go get github.com/sirupsen/logrus

代码中导入Loglus

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

Loglus常见用法

自定义日志级别

可以添加一个 TraceLevel 级别来更详细地跟踪程序的执行流程

package main

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

var TraceLevel = logrus.Level(6)

func main() {
	logger := logrus.New()
	logger.SetLevel(TraceLevel)
	logger.Trace("This is a trace level log")
}

使用字段钩子

使用字段钩子来在日志中添加额外的字段信息。例如,你可以添加一个钩子来记录每条日志的时间戳:

package main

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

func main() {
	logger := logrus.New()
	logger.SetFormatter(&logrus.JSONFormatter{})
	logger.AddHook(&logrus.FieldHook{
		Field: "timestamp",
		Func: func() (interface{}, error) {
			return time.Now().Format("2006-01-02T15:04:05.999Z07:00"), nil
		},
	})
	logger.Info("This is a log entry with timestamp field")
}

输出到多个位置

可以将日志同时输出到多个位置,比如标准输出和文件。以下是一个示例,将日志同时输出到控制台和文件中:

package main

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

func main() {
	logger := logrus.New()

	// 设置日志级别和输出格式

	// 输出到控制台
	logger.SetOutput(os.Stdout)

	// 输出到文件
	file, err := os.OpenFile("logfile.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
	if err == nil {
		mw := io.MultiWriter(os.Stdout, file)
		logger.SetOutput(mw)
	} else {
		logger.Info("Failed to log to file, using default stderr")
	}

	logger.Info("This log entry will be output to both console and file")
}

使用钩子实现自定义日志处理

使用钩子来实现自定义的日志处理逻辑。例如,你可以添加一个邮件钩子,在产生错误日志时发送邮件通知:

package main

import (
	"github.com/sirupsen/logrus"
	"net/smtp"
)

func main() {
	logger := logrus.New()

	// 设置日志级别和输出格式

	// 添加邮件钩子
	logger.AddHook(&logrus.Hook{
		Levels: []logrus.Level{logrus.ErrorLevel, logrus.FatalLevel},
		Fire: func(entry *logrus.Entry) error {
			sendEmailNotification(entry.Message)
			return nil
		},
	})

	logger.Error("An error occurred, email notification will be sent")
}

func sendEmailNotification(message string) {
	// 实现发送邮件的逻辑
}

demo

这里给出一个保存日志到项目log文件的示例:

package middleware

import (
	"fmt"
	"github.com/gin-gonic/gin"
	retalog "github.com/lestrrat-go/file-rotatelogs"
	"github.com/rifflock/lfshook"
	"github.com/sirupsen/logrus"
	"log"
	"math"
	"os"
	"path"
	"time"
)

// SetOutputFile 设置输出文件名称,如果没有就创建
func SetOutputFile() (*os.File, string, error) {
	now := time.Now()
	logFilePath := ""
	if dir, err := os.Getwd(); err == nil {
		logFilePath = dir + "/logs"
	}
	_, err := os.Stat(logFilePath)
	if os.IsNotExist(err) {
		if err := os.MkdirAll(logFilePath, 0777); err != nil {
			log.Println(err.Error())
			return nil, "", err
		}
	}
	logFileName := now.Format("2006-01-02") + ".log"
	filePath := path.Join(logFilePath, logFileName)
	if _, err := os.Stat(filePath); err != nil {
		if _, err := os.Create(filePath); err != nil {
			log.Println(err.Error())
			return nil, "", err
		}
	}
	src, err := os.OpenFile(filePath, os.O_RDWR|os.O_CREATE, 0755)
	if err != nil {
		fmt.Println("err: ", err)
		return nil, "", err
	}
	log.Println("create log path: ", filePath)
	return src, filePath, nil
}

// Logger 日志,此操作可以复用
func Logger() gin.HandlerFunc {
	//建立软连接,需要管理员权限
	linkName := "latest_log.log"
	//设置日志文件的路径
	src, filePath, _ := SetOutputFile()

	//创建日志
	logger := logrus.New()
	//输出
	logger.Out = src
	//设置日志级别
	logger.SetLevel(logrus.DebugLevel)
	// 显示日志行数
	//logger.SetReportCaller(true)
	//添加时间分割
	logWriter, _ := retalog.New(
		filePath,
		retalog.WithMaxAge(14*24*time.Hour),    //日志保留时间:2周
		retalog.WithRotationTime(24*time.Hour), //24小时分割一次
		retalog.WithLinkName(linkName),         //建立软连接
	)
	writeMap := lfshook.WriterMap{
		logrus.InfoLevel:  logWriter,
		logrus.FatalLevel: logWriter,
		logrus.DebugLevel: logWriter,
		logrus.WarnLevel:  logWriter,
		logrus.ErrorLevel: logWriter,
		logrus.PanicLevel: logWriter,
	}
	//实例化
	Hook := lfshook.NewHook(writeMap, &logrus.TextFormatter{
		TimestampFormat: "2006-01-02 15:04:05",
	})
	logger.AddHook(Hook)
	return func(c *gin.Context) {
		startTime := time.Now()
		c.Next()
		stopTime := time.Since(startTime)
		spendTime := fmt.Sprintf("%d ms", int(math.Ceil(float64(stopTime.Nanoseconds()/1000000.0))))
		hostName, err := os.Hostname()
		if err != nil {
			hostName = "unknown"
		}
		statusCode := c.Writer.Status()
		clientIp := c.ClientIP()
		//userAgent := c.Request.UserAgent()
		dataSize := c.Writer.Size()
		if dataSize < 0 {
			dataSize = 0
		}
		method := c.Request.Method
		requestPath := c.Request.RequestURI

		entry := logger.WithFields(logrus.Fields{
			"HostName":  hostName,
			"status":    statusCode,
			"SpendTime": spendTime,
			"Ip":        clientIp,
			"Method":    method,
			"Path":      requestPath,
			"DataSize":  dataSize,
			//"Agent":     userAgent, // TODO: UA
		})
		if len(c.Errors) > 0 {
			entry.Error(c.Errors.ByType(gin.ErrorTypePrivate).String())
		}
		if statusCode >= 500 {
			entry.Error()
		} else if statusCode >= 400 {
			entry.Warn()
		} else {
			entry.Info()
		}
	}
}

在gin中调用Logger()

	r := gin.New()
	r.Use(gin.Recovery())
	r.Use(middleware.Logger())
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【go语言开发】loglus日志框架的使用 的相关文章

随机推荐