当前位置: 首页 > article >正文

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

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

文章目录

  • 前言
  • 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())

http://www.kler.cn/a/155413.html

相关文章:

  • 【最新版】Stable Diffusion4.9(AI绘画)下载及安装教程(附软件安装包)!
  • 免费,WPS Office教育考试专用版
  • 力扣515:在每个树行中找最大值
  • Ubuntu安装MySQL8
  • 040 线程池
  • AI 扩展开发者思维方式:以 SQL 查询优化为例
  • mysql8.0 提取json数据转为行
  • 基于SpringBoot+Vue实现的前后端分离课程管理系统
  • 树与二叉树堆:经典OJ题集(2)
  • 2023.12.03 homework
  • 1094. 拼车 --力扣 --JAVA
  • PostgreSQL日志中的SQL记录时机 —— log_statement 和 log_min_duration_statement
  • Session 与 JWT 的对决:谁是身份验证的王者? (下)
  • 中序和前/后序遍历构造二叉树———通用做法
  • 15个Pandas代码片段助力数据分析
  • MySQL索引:优化数据访问的双面剑
  • LeetCode:2336. 无限集中的最小数字(hash模拟 C++)
  • ZooKeeper的分布式锁---客户端命令行测试(实操课程)
  • 9-4 函数输入信息,函数输出信息
  • pytest系列——allure之在测试用例添加标题(@allure.title())
  • KALI LINUX高级话题
  • LeetCode二分查找:x 的平方根
  • 什么是npm?能干什么?
  • 不得不说,HelpLook真的是一个很懂用户的文档管理工具
  • Uniapp
  • 调优--学习笔记