前言:

logrus是go中比较好的一个log模块.github上的很多开源项目都在使用这个模块, 我在写这个博文时, github上的logrus的stars数已经有8214了.最近在用这个模块时,发现不能打印日志所在文件和行数.在开发过程中, 感觉这就不是很友好了.

项目地址: logrus github 地址

提醒:此方法在并发情况下, 会导致系统奔溃. 请谨慎使用

不记录文件名和行号处理办法

logrus支持自定义的hook, 我这里就是使用hook的方式来记录

一个Entry为一条日志记录, 我们的Hook需要做的就是在每一个条的日志记录里面添加调用时的文件名和行号. 核心就是实现自己的Fire方法, 以下是参考实现:

1. 我们新建一个hook的文件. 写入如下代码

package hooks

import (
"fmt"
"runtime"
"strings"
"github.com/sirupsen/logrus"
)
// ContextHook for log the call context
type contextHook struct {
Field string
Skip int
levels []logrus.Level
}
// NewContextHook use to make an hook
// 根据上面的推断, 我们递归深度可以设置到5即可.
func NewContextHook(levels ...logrus.Level) logrus.Hook {
hook := contextHook{
Field: "line",
Skip: ,
levels: levels,
}
if len(hook.levels) == {
hook.levels = logrus.AllLevels
}
return &hook
} // Levels implement levels
func (hook contextHook) Levels() []logrus.Level {
return logrus.AllLevels
} // Fire implement fire
func (hook contextHook) Fire(entry *logrus.Entry) error {
entry.Data[hook.Field] = findCaller(hook.Skip)
return nil
}
// 对caller进行递归查询, 直到找到非logrus包产生的第一个调用.
// 因为filename我获取到了上层目录名, 因此所有logrus包的调用的文件名都是 logrus/...
// 因此通过排除logrus开头的文件名, 就可以排除所有logrus包的自己的函数调用
func findCaller(skip int) string {
file := ""
line :=
for i := ; i < ; i++ {
file, line = getCaller(skip + i)
if !strings.HasPrefix(file, "logrus") {
break
}
}
return fmt.Sprintf("%s:%d", file, line)
}
// 这里其实可以获取函数名称的: fnName := runtime.FuncForPC(pc).Name()
// 但是我觉得有 文件名和行号就够定位问题, 因此忽略了caller返回的第一个值:pc
// 在标准库log里面我们可以选择记录文件的全路径或者文件名, 但是在使用过程成并发最合适的,
// 因为文件的全路径往往很长, 而文件名在多个包中往往有重复, 因此这里选择多取一层, 取到文件所在的上层目录那层.
func getCaller(skip int) (string, int) {
_, file, line, ok := runtime.Caller(skip)
//fmt.Println(file)
//fmt.Println(line)
if !ok {
return "",
}
n :=
for i := len(file) - ; i > ; i-- {
if file[i] == '/' {
n++
if n >= {
file = file[i+:]
break
}
}
}
return file, line
}

2. 添加hook到logrus  -- ( logrus定义为了全局使用 )

package main

import (
log "github.com/sirupsen/logrus"
zzxHook "study/ginStudy/hook"
) func main() {
var Logger = log.New()
Logger.Hooks.Add(zzxHook.NewContextHook())
Logger.WithFields(log.Fields{
"animal": "walrus",
}).Info("A walrus appears")
}

效果:

2. 添加hook到logrus  -- ( logrus普通使用方式 )

package main

import (
log "github.com/sirupsen/logrus"
zzxHook "study/ginStudy/hook"
) func main() {
log.AddHook(zzxHook.NewContextHook())
log.WithFields(log.Fields{
"animal": "walrus",
}).Info("A walrus appears") }

效果:

go包之logrus显示日志文件与行号的更多相关文章

  1. __file__, sys._getframe().f_lineno 当前文件的行号

    当前文件的行号 try: f = open(sys.argv[1], "rb") address_book.ParseFromString(f.read()) f.close()e ...

  2. NO17 第二关考试: 返回上次目录和ls -lrt倒序看文件--删除7天前的日志--查看日志更新--记录行号

    第二题:不用cd /ildboy命令如何回到上一次的目录: 假如当前目录是: [root@localhost oldboy]# pwd/oldboy现在因为需要进入到了/tmp目录下进行操作,执行的命 ...

  3. log4j日志文件名与行号显示乱码? 问号? 参数问号? 日志问号?【转】【补】

    log4j本来设置了要打印行号与文件名的,结果有的能打印出来,有的却是乱码,查了些文档之后才发现,原来打印问题是因为编绎时没有编绎进去调试信息,所以没办法打印,好像有的系统又会显示(Unknown S ...

  4. 技巧:Python中print打印信息的同时打印文件、行号

    import sys def Log(msg): print('Print Message: '+msg+' ,File: "'+__file__+'", Line '+str(s ...

  5. 网上都没有提到的教程:python捕获异常后,怎么输出错误文件和行号

    1.假设输出不存在的变量 a try: print(a) except NameError as e: print('发生错误的文件:', e.__traceback__.tb_frame.f_glo ...

  6. php:file()与file_get_contents():讲日志文件没行读为数组形式

    file()与file_get_contents()一样,都是读取某文件的内容.file_get_contents()输出的是整个文件(不能读取TXT里的首行缩进和换行符). file() 函数把整个 ...

  7. Gin 框架 - 使用 logrus 进行日志记录

    目录 概述 日志格式 Logrus 使用 推荐阅读 概述 上篇文章分享了 Gin 框架的路由配置,这篇文章分享日志记录. 查了很多资料,Go 的日志记录用的最多的还是 github.com/sirup ...

  8. Gin框架 - 使用 Logrus 进行日志记录

    概述 上篇文章分享了 Gin 框架的路由配置,这篇文章分享日志记录. 查了很多资料,Go 的日志记录用的最多的还是 github.com/sirupsen/logrus. Logrus is a st ...

  9. 使用jar包格式化Docker 容器日志

    前面使用JS格式化textarea中的日志内容,但局限于JS语言性能,在日志内容较多时效率无法接受,建议日志内容大于5000行时转投本java程序,文末提供jar包下载. LogsFormat.jav ...

随机推荐

  1. STL之permutation/ equal_range/ binary_range学习

    1,is_permutation 函数,判断其中一个序列是不是另外一个序列的全排列. 包括四个参数,前两个是第一个数组需要判断的起始位置和终止位置.后两个是第二个数组需要判断的起始位置和终止位置. # ...

  2. C++ operator(重载操作符) 【转】

    转自:http://www.cnblogs.com/xiangxiaodong/archive/2012/02/12/2348144.html operator是C++的关键字,它和运算符一起使用,表 ...

  3. OGG-01168

    https://blog.csdn.net/zhrzhl/article/details/21698659

  4. kali linux 安装 matlab2016Rb

    分享安装包: https://pan.baidu.com/s/1hrBd3Li 密码:u9q3 由于Linux版的分为两个镜像,需要挂载后合并: mount R2016b_glnxa64_dvd1.i ...

  5. 【ARTS】01_19_左耳听风-20190318~20190324

    ARTS: Algrothm: leetcode算法题目 Review: 阅读并且点评一篇英文技术文章 Tip/Techni: 学习一个技术技巧 Share: 分享一篇有观点和思考的技术文章 Algo ...

  6. eMMC基础技术9:分区管理

    [转]http://www.wowotech.net/basic_tech/emmc_partitions.html 0.前言 eMMC 标准中,将内部的 Flash Memory 划分为 4 类区域 ...

  7. oracle监控

    python代码 #!/usr/bin/env python # -*- coding: UTF-8 -*- import subprocess import sys import re def ru ...

  8. HTTP请求头信息

    常用请求头 User-Agent : 浏览器信息Host : 服务区域名Referer : 通过哪里的链接过来的Origin : 跨域相关Content-Type : POST和PUT请求的数据类型C ...

  9. 修改docker image存放位置

    修改镜像和容器的默认存放路径 指定镜像和容器存放路径的参数是--graph=/var/lib/docker,我们只需要修改配置文件指定启动参数即可.刚好有个300g盘的挂在/data目录上,所以在这个 ...

  10. Fiddler对https抓包时,提示"HTTPS decryption is disabled."

    安装了fiddlercertmaker.exe 后,对 https://www.baidu.com 进行抓包时,右侧界面提示"HTTPS decryption is disabled.&qu ...