logrus 通过实现 Hook接口扩展 hook 机制,可以根据需求将日志分发到任意的存储介质, 比如 es, mq 或者监控报警系统,及时获取异常日志。可以说极大的提高了日志系统的可扩展性。

hook 内部实现

Hook 接口定义如下:

type Hook interface {
// 定义哪些等级的日志触发 hook 机制
Levels() []Level
// hook 触发器的具体执行操作
// 如果 Fire 执行失败,错误日志会重定向到标准错误流
Fire(*Entry) error
}

logrus的内部是怎么实现触发的呢, logrus中有个内部结构LevelHooks用来存储所有定义的 hook 函数。

// 存储全局 hooks, 以日志等级为键聚合存储
type LevelHooks map[Level][]Hook
// 添加 hooks
func (hooks LevelHooks) Add(hook Hook) {
for _, level := range hook.Levels() {
hooks[level] = append(hooks[level], hook)
}
} // 根据日志等级触发 hooks
func (hooks LevelHooks) Fire(level Level, entry *Entry) error {
for _, hook := range hooks[level] {
if err := hook.Fire(entry); err != nil {
return err
}
} return nil
}

在打印日志时, entry会调用 fireHooks()函数,该函数会触发所有对应的日志等级 的 hook 逻辑。

// 触发 hooks
func (entry *Entry) fireHooks() {
entry.Logger.mu.Lock()
defer entry.Logger.mu.Unlock()
err := entry.Logger.Hooks.Fire(entry.Level, entry)
if err != nil {
fmt.Fprintf(os.Stderr, "Failed to fire hook: %v\n", err)
}
}

自定义 hook

说了这么多,我们写一个简单的自定义 hook 的例子。在这个例子中我们希望当系统发生error或者panic的时候,将错误日志打印到单独的 err.log 文件中便于我们排查错误(实际开发中不会这么做)

// MyHook ...
type MyHook struct {
} // Levels 只定义 error 和 panic 等级的日志,其他日志等级不会触发 hook
func (h *MyHook) Levels() []log.Level {
return []log.Level{
log.ErrorLevel,
log.PanicLevel,
}
} // Fire 将异常日志写入到指定日志文件中
func (h *MyHook) Fire(entry *log.Entry) error {
f, err := os.OpenFile("err.log", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0644)
if err != nil {
return err
}
if _, err := f.Write([]byte(entry.Message)); err != nil {
return err
}
return nil
}
func main() {
log.AddHook(&MyHook{})
log.Error("some errors\n")
log.Panic("some panic\n")
log.Print("hello world\n")
}

运行后会创建一个 err.log 文件,文件中存储了:

some errors
some panic

结构符合我们的预期,至此一个自定义的logrus hook就完成了。

logrus 剖析之 hook的更多相关文章

  1. logrus 剖析之滚动日志

    在实际开发过程中,为了节省磁盘,日志需要按照时间或者大小维度进行切割分成多分,归档过期的日志,删除久远的日志.这个就是在日常开发中经常遇见的日志滚动(log rotation) 那么在 logrus ...

  2. logrus 剖析之 formatter

    使用 logrus 通过 formatter 来定义输出日志的格式,具体例子如下: package main import ( log "github.com/Sirupsen/logrus ...

  3. go包之logrus显示日志文件与行号

    前言: logrus是go中比较好的一个log模块.github上的很多开源项目都在使用这个模块, 我在写这个博文时, github上的logrus的stars数已经有8214了.最近在用这个模块时, ...

  4. logrus日志使用详解

    1.logrus特点 golang标准库的日志框架很简单,logrus框架的特点: 1)完全兼容标准日志库 六种日志级别:debug, info, warn, error, fatal, panic ...

  5. golang常用库:日志记录库-logrus使用

    介绍 logrus 它是一个结构化.插件化的日志记录库.完全兼容 golang 标准库中的日志模块.它还内置了 2 种日志输出格式 JSONFormatter 和 TextFormatter,来定义输 ...

  6. HBase - Phoenix剖析

    1.概述 在<Hadoop-Drill深度剖析>一文当中,给大家介绍了Drill的相关内容,就实时查询来说,Drill基本能够满足要求,同时还可以做一个简单业务上的聚合,如果在使用Hive ...

  7. DuiLib消息处理剖析

    本来想自己写写duilib的消息机制来帮助duilib的新手朋友,不过今天发现已经有人写过了,而且写得很不错,把duilib的主干消息机制都说明了,我就直接转载过来了,原地址:http://blog. ...

  8. CI框架剖析一

            CodeIgniter 是一个小巧但功能强大的 PHP 框架,作为一个简单而"优雅"的工具包,它可以为开发者们建立功能完善的 Web 应用程序.本人使用CI框架有一 ...

  9. [Android] Toast问题深度剖析(二)

    欢迎大家前往云+社区,获取更多腾讯海量技术实践干货哦~ 作者: QQ音乐技术团队 题记 Toast 作为 Android 系统中最常用的类之一,由于其方便的api设计和简洁的交互体验,被我们所广泛采用 ...

随机推荐

  1. oracle的一些状态查询

  2. Min25筛

    Min25筛 我是沙雕... 从yyb博客蒯的 要求:\(\sum_{i=1}^nF(x)\) \(F(x)\)是积性函数. \(Min25\)筛能用的前提:质数处的\(f(p)\)值是关于\(p\) ...

  3. CSS3 之filter毛玻璃效果弹窗

    先看效果: 效果主要用css3的滤镜属性实现,代码如下: <!DOCTYPE html> <html lang="en"> <head> < ...

  4. LOJ6437. 「PKUSC2018」PKUSC [计算几何]

    LOJ 思路 显然多边形旋转可以变成点旋转,不同的点的贡献可以分开计算. 然后就变成了要求一个圆在多边形内的弧长. 考虑把交点全都求出来,那么两个交点之间的状态显然是相同的,可以直接把圆弧上的中点的状 ...

  5. [SNOI2019]纸牌

    传送门 Description 有一副纸牌.牌一共有\(n\)种,分别标有 \(1,2,...,n\),每种有\(C\)张.故这副牌共有\(nC\)张. 三张连号的牌(\(i,i+1,i+2\))或三 ...

  6. C++ STL 知识小结

    qwq...接近联赛,就在这里对STL做一点知识小结吧,因为STL曾经失分很多. 简介 (来自Baidu) STL是Standard Template Library的简称,中文名标准模板库,惠普实验 ...

  7. 使用建造者模式和Lombok简化代码

    在项目开发中,我们经常需要构建对象.常见的做法有getter/setter,或者构造器构建对象. 可能会有人写出类似如下的代码: Company company=new Company(); comp ...

  8. 多线程 fork/join 并行计算

    1. 什么是Fork/Join框架 Fork/Join框架是Java7提供了的一个用于并行执行任务的框架, 是一个把大任务分割成若干个小任务,最终汇总每个小任务结果后得到大任务结果的框架. 我们再通过 ...

  9. 还在用难用的AssetBundle?快来运用Unity新的可寻址资源系统,助力游戏开发

    Unity Addressables可寻址资源系统是一个强大的Unity资源包,它能够帮助解决游戏开发中最重要的一些挑战:高效率和轻松的内容管理. 在管理游戏资源时,往往很难维持好的标准,从而避免让项 ...

  10. Nginx配置简单基于域名的虚拟主机

    首先修改hosts文件,让浏览器在看到a.com或是www.a.com的网址时知道上哪里去找: # Copyright (c) 1993-2009 Microsoft Corp. # # This i ...