logrus日志自定义格式操作
作者:chen09122763 发布时间:2024-04-26 17:20:24
由于最近开始做一些go写的外围程序,因此开始关注go的日志,毕竟自带的logger模块功能较少。简单看了一些资料以后最开始使用seelog,性能感觉也不错,可以通过配置文件做很多额外处理。
但是由于协程的使用,需要日志标明协程号来方便日志查询请求应答。在一番尝试以后仍然没有解决,只能看看有没有其他日志库备选,因此选择了logrus(github上同类星星最多)
其实一开始看介绍时就看见过logrus这个库,但是之所以没有一开始考虑它, 是因为许多介绍都说它无法显示文件名和行号。不过时代是发展的,现在的logrus版本已经支持该设置。
logrus的基本使用这里就不再多说了,可以移步 https://www.aspxhome.com/article/168799.htm
1)设置行号
log.SetReportCaller(true)
log.WithFields(log.Fields{"animal": "walrus"}).Info("A walrus appears")
time="2020-03-29T15:58:09+08:00" level=info msg="A walrus appears" func=main.main file="F:/workspace/go/src/test/main.go:12" animal=walrus
设置行号通过SetRportCaller实现,但是发现一个问题默认的设置file是全路径的,这样实际在日志中输出的话,日志会有很多无用数据,针对于我自己的需求仅为需要提示go文件名以及行号和goid即可。
2)自定义格式
logrus提供了SetFormatter可以设置格式,logrus自带的格式为(JSONFormatter,TextFormatter)
func (s *LogFormatter) Format(entry *log.Entry) ([]byte, error) {
timestamp := //日期格式实现
entry.Caller //调用者信息
entry.Data //withfiled方式传入的数据
msg := 自己想要的格式输出内容
return []byte(msg), nil
}
func main() {
log.SetFormatter(new(LogFormatter)) //注册自定义格式
}
自定义格式可选取的素材是log.Entry中提供的,具体了解需要自行查看源码,这里仅简单介绍。其中Caller是调用信息,有文件名,函数名,行数等信息,但是需要注意的是如果没有设置SetRportCaller为true,这里无法获取改信息。
entry.Data信息为WithFields传入的map,如果需要一定的范式输出的话,可以好好利用。此外获取当前协程号也是在该函数中实现的,具体可以看文末的范例。定义完成后需要注册自定义格式。
3)日志写入文件
logrus默认是标准输出, SetOutput方法可以更换输出io,设置文件句柄就是写入文件了。网上能找到很多通过改写io.write或者hook的方式拆分文件,推送文件等等其他各种需要,总之非常强大,不过我因为没有试过,所以就不在本文中描述了。但是统一项目的日志都是在指定目录按日期目录存放的,因此需要实现io.write,针对日期来划分文件。
package gotools
import (
"bytes"
"errors"
"fmt"
"os"
"path/filepath"
"runtime"
"strconv"
"strings"
"time"
log "github.com/sirupsen/logrus"
)
//日志自定义格式
type LogFormatter struct{}
//格式详情
func (s *LogFormatter) Format(entry *log.Entry) ([]byte, error) {
timestamp := time.Now().Local().Format("0102-150405.000")
var file string
var len int
if entry.Caller != nil {
file = filepath.Base(entry.Caller.File)
len = entry.Caller.Line
}
//fmt.Println(entry.Data)
msg := fmt.Sprintf("%s [%s:%d][GOID:%d][%s] %s\n", timestamp, file, len, getGID(), strings.ToUpper(entry.Level.String()), entry.Message)
return []byte(msg), nil
}
func getGID() uint64 {
b := make([]byte, 64)
b = b[:runtime.Stack(b, false)]
b = bytes.TrimPrefix(b, []byte("goroutine "))
b = b[:bytes.IndexByte(b, ' ')]
n, _ := strconv.ParseUint(string(b), 10, 64)
return n
}
type logFileWriter struct {
file *os.File
logPath string
fileDate string //判断日期切换目录
appName string
encoding string
}
func (p *logFileWriter) Write(data []byte) (n int, err error) {
if p == nil {
return 0, errors.New("logFileWriter is nil")
}
if p.file == nil {
return 0, errors.New("file not opened")
}
//判断是否需要切换日期
fileDate := time.Now().Format("20060102")
if p.fileDate != fileDate {
p.file.Close()
err = os.MkdirAll(fmt.Sprintf("%s/%s", p.logPath, fileDate), os.ModePerm)
if err != nil {
return 0, err
}
filename := fmt.Sprintf("%s/%s/%s-%s.log", p.logPath, fileDate, p.appName, fileDate)
p.file, err = os.OpenFile(filename, os.O_WRONLY|os.O_APPEND|os.O_CREATE|os.O_SYNC, 0600)
if err != nil {
return 0, err
}
}
if p.encoding != "" {
dataToEncode := ConvertStringToByte(string(data), p.encoding)
n, e := p.file.Write(dataToEncode)
return n, e
}
n, e := p.file.Write(data)
return n, e
}
//初始化日志
func InitLog(logPath string, appName string, encoding string) {
fileDate := time.Now().Format("20060102")
//创建目录
err := os.MkdirAll(fmt.Sprintf("%s/%s", logPath, fileDate), os.ModePerm)
if err != nil {
log.Error(err)
return
}
filename := fmt.Sprintf("%s/%s/%s-%s.log", logPath, fileDate, appName, fileDate)
file, err := os.OpenFile(filename, os.O_WRONLY|os.O_APPEND|os.O_CREATE|os.O_SYNC, 0600)
if err != nil {
log.Error(err)
return
}
fileWriter := logFileWriter{file, logPath, fileDate, appName, encoding}
log.SetOutput(&fileWriter)
log.SetReportCaller(true)
log.SetFormatter(new(LogFormatter))
}
package main
import (
log "github.com/sirupsen/logrus"
"sand.com/gotools"
)
func main() {
gotools.InitLog("./log/", "test", "gb18030")
log.WithFields(log.Fields{"animal": "walrus"}).Info("A walrus appears")
log.Info("测试中文")
}
因为其他系统的日志都是gbk编码的,因此在io.write时做了编码转换,如果没有这样需要的话最好不要做这种转换影响性能
0329-163148.199 [main.go:11][GOID:1][INFO] A walrus appears
0329-163148.199 [main.go:12][GOID:1][INFO] 测试中文
补充知识: go使用logrus同时输出屏幕和文件日志
我就废话不多说了,大家还是直接看代码吧~
func InitLog() {
//设置输出样式,自带的只有两种样式logrus.JSONFormatter{}和logrus.TextFormatter{}
log.SetFormatter(&log.TextFormatter{})
log.SetOutput(os.Stdout)
//设置output,默认为stderr,可以为任何io.Writer,比如文件*os.File
file, err := os.OpenFile("checkemstools.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
writers := []io.Writer{
file,
os.Stdout}
//同时写文件和屏幕
fileAndStdoutWriter := io.MultiWriter(writers...)
if err == nil {
log.SetOutput(fileAndStdoutWriter)
} else {
log.Info("failed to log to file.")
}
//设置最低loglevel
log.SetLevel(log.InfoLevel)
}
来源:https://blog.csdn.net/chen09122763/article/details/105179886
![](https://www.aspxhome.com/images/zang.png)
![](https://www.aspxhome.com/images/jiucuo.png)
猜你喜欢
- PyTorch基础入门二:PyTorch搭建一维线性回归模型1)一维线性回归模型的理论基础给定数据集,线性回归希望能够优化出一个好的函数,使
- 很久以前我们在写sql的时候,最怕的一件事情就是sql莫名奇妙的超级慢,慢的是撸一管子回来,那个小球还在一直转。。。这个着急也只有当事人才明
- 传入参数一个,为元素的id值或元素本身,返回为元素的真实背景色值(字符串)。 值得一提的是IE里面返回的是16进制的值,而Mozi
- 除了使用 sys.exc_info() 方法获取更多的异常信息之外,还可以使用 traceback 模块,该模块可以用来查看异常的传播轨迹,
- 面临的问题在我设计一个分析系统中,我们公司的目标是能够处理来自数百万个端点的大量POST请求。web 网络处理程序将收到一个JSON文档,其
- 很多时候,设计师们都会通过各种渠道去了解用户的需求,然而从这些渠道反馈回来的信息大部分只是用户的期望并不是真正的用户需求,但是很多时候这些期
- 不同的数字之间使用 空格“ ”,“$”,"*"等隔开,支持带小数点的字符串NumArray=str2num(LineSt
- 之前看到过很多人写的飞机大战,当然了之前我也写过多个版本,总体来说功能是实现了,但总感觉不够“炫”今天浏览Python资料的时候,意外发现了
- 一、安装依赖包pip install --index https://pypi.mirrors.ustc.edu.cn/simple/ py
- 看代码吧~import torchprint(torch.__version__)补充:pytorch不同版本安装以及版本查看一:基于con
- 代码如下:# -*- coding: utf-8 -*-#!/usr/bin/python# filename: todo.py# code
- 前言在学习过程中发现有时候交换字典的键和值,会使得我们最后的输出结果更加直观明了,整理出以下四种交换方式(data是原字典,new_data
- 一。存储过程的创建和使用 1.创建程序包,并在程序中创建存储过程 create or replace PACKAGE NCS_ICP_TJ
- 今天来填坑, 昨天说playwright未必一定要使用pytest-playwright包。 它也可以和pyunit一起使用。那么今天,田辛
- 最近服务器时不时出现Nginx 502 Bad Gateway,如果在电脑旁边还好,要是半夜或者出去了,怎么办?没关系,写个脚本检测服务状态
- cvtColor函数这个函数有两个参数1,src 要进行变换的原图像2,code 转换代码标识例子:import cv2image=cv2.
- 本文实例讲述了Django框架静态文件处理、中间件、上传文件操作。分享给大家供大家参考,具体如下:Django静态文件处理、中间件、上传文件
- 感谢大家对《 CSS Sprites 样式生成工具 》的喜爱,综合了1.x版本时大家所提出来的意见和建议,2.0版本主要的改变有下面几点:修
- 初学python,我们必须干点有意思的事!从微信下手吧!头像集样例如下: 大家可以发朋友圈开启辨认大赛哈哈~话不多说,直接上代码,注释我写了
- 1.Fork出来的Git仓库同步代码背景:有的时候从原仓库fork出了一个新仓库,这个新仓库做了自己的修改。可是原仓库也进行了更新,比如修复