logrus 剖析之 hook
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的更多相关文章
- logrus 剖析之滚动日志
		在实际开发过程中,为了节省磁盘,日志需要按照时间或者大小维度进行切割分成多分,归档过期的日志,删除久远的日志.这个就是在日常开发中经常遇见的日志滚动(log rotation) 那么在 logrus ... 
- logrus 剖析之 formatter
		使用 logrus 通过 formatter 来定义输出日志的格式,具体例子如下: package main import ( log "github.com/Sirupsen/logrus ... 
- go包之logrus显示日志文件与行号
		前言: logrus是go中比较好的一个log模块.github上的很多开源项目都在使用这个模块, 我在写这个博文时, github上的logrus的stars数已经有8214了.最近在用这个模块时, ... 
- logrus日志使用详解
		1.logrus特点 golang标准库的日志框架很简单,logrus框架的特点: 1)完全兼容标准日志库 六种日志级别:debug, info, warn, error, fatal, panic ... 
- golang常用库:日志记录库-logrus使用
		介绍 logrus 它是一个结构化.插件化的日志记录库.完全兼容 golang 标准库中的日志模块.它还内置了 2 种日志输出格式 JSONFormatter 和 TextFormatter,来定义输 ... 
- HBase - Phoenix剖析
		1.概述 在<Hadoop-Drill深度剖析>一文当中,给大家介绍了Drill的相关内容,就实时查询来说,Drill基本能够满足要求,同时还可以做一个简单业务上的聚合,如果在使用Hive ... 
- DuiLib消息处理剖析
		本来想自己写写duilib的消息机制来帮助duilib的新手朋友,不过今天发现已经有人写过了,而且写得很不错,把duilib的主干消息机制都说明了,我就直接转载过来了,原地址:http://blog. ... 
- CI框架剖析一
		CodeIgniter 是一个小巧但功能强大的 PHP 框架,作为一个简单而"优雅"的工具包,它可以为开发者们建立功能完善的 Web 应用程序.本人使用CI框架有一 ... 
- [Android] Toast问题深度剖析(二)
		欢迎大家前往云+社区,获取更多腾讯海量技术实践干货哦~ 作者: QQ音乐技术团队 题记 Toast 作为 Android 系统中最常用的类之一,由于其方便的api设计和简洁的交互体验,被我们所广泛采用 ... 
随机推荐
- 通过USB 2.0电缆手动设置内核模式调试
			Windows的调试工具支持通过USB 2.0电缆进行内核调试.本文介绍如何手动设置USB 2.0调试.通过USB 2.0电缆进行调试需要以下硬件: USB 2.0调试电缆.此电缆不是标准USB 2. ... 
- pgloader 学习(九) pg 2 pg  使用with 参数控制同步逻辑
			pgloader 支持比较丰富的配置参数,同时默认数据在同步的时候是会进行索.schema 以及数据的同步对于实际我们可能存在需要进行控制,我们可以通过with 参数方便的处理 参考配置 load 文 ... 
- GoCN每日新闻(2019-10-11)
			GoCN每日新闻(2019-10-11) GoCN每日新闻(2019-10-11) 1. golang 将数据库转换为gorm结构 https://studygolang.com/articles/2 ... 
- Linux进阶之Shell编程
			1.什么是Shell Shell是一个命名行解释器,它为用户提供一个向Linux内核发送请求以便运行程序的界面系统级程序,用户可以用Shell来启动.挂起.停止甚至是编写一些程序. 2.Shell脚本 ... 
- gitlab备份恢复
			1.Gitlab 创建备份1.1 创建备份文件 首先我们得把老服务器上的Gitlab整体备份,使用Gitlab一键安装包安装Gitlab非常简单, 同样的备份恢复与迁移也非常简单. 使用一条命令即可创 ... 
- DIV块中 元素垂直居中
			1 DIV块中 元素垂直居中 作者:知乎用户链接:https://www.zhihu.com/question/20543196/answer/99429177来源:知乎著作权归作者所有.商业转载请联 ... 
- 团队作业-Beta冲刺(1/4)
			队名:软工9组 组长博客:https://www.cnblogs.com/cmlei/ 作业博客:https://edu.cnblogs.com/campus/fzu/SoftwareEngineer ... 
- Python多进程和多线程是鸡肋嘛?【转】
			GIL是什么 Python的代码执行由 Python虚拟机(也叫解释器主循环,CPython版本)来控制,Python在设计之初就考虑到在解释器的主循环中,同时只有一个线程在运行.即每个CPU在任意时 ... 
- MySQL导入csv文件内容到Table及数据库的自增主键设置
			写在前面 目的是测试将csv文件内容导入到表中, 同时记录一下自增主键的设置. 测试采用MySQL8.0. 新建表customer_info如下, 未设置主键. 修改上表, 添加主键id, 并设置为自 ... 
- Xamarin图表开发基础教程(4)OxyPlot框架
			Xamarin图表开发基础教程(4)OxyPlot框架 XamaminAndroid中绘制线图OxyPlotAndroidDemo [示例1-1:OxyPlotAndroidDemo]下面实现线图的绘 ... 
