前言:

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. D. Time to go back(思维)

    题目链接:http://codeforces.com/gym/100952/problem/D 题目大意:n个礼物,m个人,要给m个人中的k个人买大于等于d的礼物,其他人随意,问你选择礼物的方案数(不 ...

  2. 黑马程序员_超全面的JavaWeb视频教程vedio--.ppt,.pptx,.doc,.txt,.docx列表

    \JavaWeb视频教程_day1-资料源码\day01-html目录.txt;\JavaWeb视频教程_day1-资料源码\PPT\HTML.ppt;\JavaWeb视频教程_day1-资料源码\资 ...

  3. Centos7 nginx报错403 forbidden

    参考链接:http://www.cnblogs.com/chinway/archive/2017/08/14/7356239.html 因为安全性的考虑这个也是默认会出现的错误,因为SELinux的存 ...

  4. ASP.NET MVC - NPOI读取Excel

    引入: using System; using System.Data; using System.IO; using NPOI.SS.UserModel; using NPOI.XSSF.UserM ...

  5. 为什么要重写equals和hashcode方法

    equals hashcode  当新建一个java类时,需要重写equals和hashcode方法,大家都知道!但是,为什么要重写呢? 需要保证对象调用equals方法为true时,hashcode ...

  6. 关于dubbo服务超时的讨论

    呵呵,偷点懒,直接把QQ上的讨论发下来. huxin  10:35:19你们现在超时了是咋办的,首先超时了,回复用户肯定是要的 huxin  10:36:14超时了用户实际是不知道这业务是成功还失败了 ...

  7. python模块之sniffio

    嗅探python用了哪个异步库 from sniffio import current_async_library import trio import asyncio async def print ...

  8. python3+selenium入门03-操作谷歌浏览器

    操作谷歌浏览器同样也需要下载相应的driver插件,官网下载.也可以从我的网盘下载,不过可能不是最新的,网盘地址.打开谷歌浏览器的操作和火狐的差不过. from selenium import web ...

  9. 【转】浅析SkipList跳跃表原理及代码实现

    SkipList在Leveldb以及lucence中都广为使用,是比较高效的数据结构.由于它的代码以及原理实现的简单性,更为人们所接受.首先看看SkipList的定义,为什么叫跳跃表? "S ...

  10. oracle 12514文件解决

    listener.ora的SID_LIST_LISTENER添加一下内容 (SID_DESC = (GLOBAL_DBNAME = ORCL) (ORACLE_HOME = f:\app\Admini ...