栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Go语言

golang日志框架--logrus+lfshook+file-rotatelogs

Go语言 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

golang日志框架--logrus+lfshook+file-rotatelogs

前文

  golang自带的log可以满足小部分场景,而如果我们需要有个比较完善的日志模块,推介用成熟的框架,这里推介组合:logrus+lfshook+file-rotatelogs。
  logrus目前是github点赞最多的日志仓库,达18k,其有丰富的hook,且可以自定义,并且天然兼容log模块;但缺点是不支持日志按文件生成,于是引入file-rotatelogs来支持日志按文件生成,且按天分割;最后引入lfshook来组合二者。

使用

  这里不详细介绍logrus的formatter(json和text两种),也不说hook的使用,网上很多资源,这里直接给出最简单的代码。
  先安装依赖:

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

  这里主要参照lfshook在github上的example,但很显然这个没有维护了,所以上面的example直接使用是会报错的,主要是rotatelogs.New()的时候需要返回writer, err,如下图:

  修改后应该如下:

func NewLogger() *logrus.Logger {
	filepaths := "./log/project.log"
	writer, _ := rotatelogs.New(
		filepaths+".%Y%m%d%H%M",
		rotatelogs.WithLinkName(filepaths),
		rotatelogs.WithMaxAge(time.Duration(604800)*time.Second),
		rotatelogs.WithRotationTime(time.Duration(86400)*time.Second),
	)
	writeMap := lfshook.WriterMap{
		logrus.InfoLevel:  writer,
		logrus.FatalLevel: writer,
		logrus.DebugLevel: writer,
		logrus.WarnLevel: writer,
		logrus.ErrorLevel: writer,
		logrus.PanicLevel: writer,
	}
	Log.SetReportCaller(true)
	lfHook := lfshook.NewHook(writeMap, &MyFormatter{})
	Log.AddHook(lfHook)
	return Log
}

  但是只有这些,是没有行号和文件名的;并且其他文件不能引用,行号和文件名的使用参考:https://cloud.tencent.com/developer/article/1830710。详细代码如下:

package logger

import (
	"bytes"
	"fmt"
	"github.com/lestrrat-go/file-rotatelogs"
	"github.com/rifflock/lfshook"
	"github.com/sirupsen/logrus"
	"path/filepath"
	"time"
)

var Log = logrus.New()

func init() {
	Log = NewLogger()
}

type MyFormatter struct {}
func (m *MyFormatter) Format(entry *logrus.Entry) ([]byte, error){
	var b *bytes.Buffer
	if entry.Buffer != nil {
		b = entry.Buffer
	} else {
		b = &bytes.Buffer{}
	}

	timestamp := entry.Time.Format("2006-01-02 15:04:05")
	var newLog string

	//HasCaller()为true才会有调用信息
	if entry.HasCaller() {
		fName := filepath.Base(entry.Caller.File)
		newLog = fmt.Sprintf("[%s] [%s] [%s:%d %s] %sn",
			timestamp, entry.Level, fName, entry.Caller.Line, entry.Caller.Function, entry.Message)
	} else{
		newLog = fmt.Sprintf("[%s] [%s] %sn", timestamp, entry.Level, entry.Message)
	}

	b.WriteString(newLog)
	return b.Bytes(), nil
}

func NewLogger() *logrus.Logger {
	filepaths := "./log/project.log"
	writer, _ := rotatelogs.New(
		filepaths+".%Y%m%d%H%M",
		rotatelogs.WithLinkName(filepaths),
		rotatelogs.WithMaxAge(time.Duration(604800)*time.Second),
		rotatelogs.WithRotationTime(time.Duration(86400)*time.Second),
	)
	writeMap := lfshook.WriterMap{
		logrus.InfoLevel:  writer,
		logrus.FatalLevel: writer,
		logrus.DebugLevel: writer,
		logrus.WarnLevel: writer,
		logrus.ErrorLevel: writer,
		logrus.PanicLevel: writer,
	}
	Log.SetReportCaller(true)
	lfHook := lfshook.NewHook(writeMap, &MyFormatter{})
	Log.AddHook(lfHook)
	return Log
}

  然后在main里可以这样引用:

package main

import (
	"project/logger"
)

func main() {
	logger.Log.Info("This is a logger")
	logger.Log.Error("is logger")
}

  执行go run main.go,会生成log目录和go.log以及go.log.xxx日期后缀。打开文件输出如下:

[2021-10-20 23:04:43] [info] [main.go:8 main.main] This is a logger
[2021-10-20 23:04:43] [error] [main.go:9 main.main] is logger

  至此则实现了日志记录和日志文件分割。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/903365.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号