logrus特性学习
核心源码
//想要嵌入新的功能,只需要实现这个接口就可以啦
type Hook interface {
Levels() []Level //返回需要被处理的日志级别列表
Fire(*Entry) error //通过Entry来对日志信息做各种处理,包括内容定制,输出到不同对象(文件,io流,日志中心,或elk日志分析系统等)
}
// Internal type for storing the hooks on a logger instance.
type LevelHooks map[Level][]Hook
// Add a hook to an instance of logger. This is called with
// `log.Hooks.Add(new(MyHook))` where `MyHook` implements the `Hook` interface.
func (hooks LevelHooks) Add(hook Hook) {
for _, level := range hook.Levels() {
hooks[level] = append(hooks[level], hook)
}
}
// Fire all the hooks for the passed level. Used by `entry.log` to fire
// appropriate hooks for a log entry.
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
}
可插拔式日志处理功能实现原理
通过实现Hook接口(主要有Levels和Fire两个接口)
Hook.Fire()调用并未加锁
func (entry *Entry) fireHooks() {
var tmpHooks LevelHooks
entry.Logger.mu.Lock()
tmpHooks = make(LevelHooks, len(entry.Logger.Hooks))
for k, v := range entry.Logger.Hooks {
tmpHooks[k] = v
}
entry.Logger.mu.Unlock()
//对于用户实现的hook.Fire方法并未加锁,所以需要用户自己控制Fire方法本身的线程安全
err := tmpHooks.Fire(entry.Level, entry)
if err != nil {
fmt.Fprintf(os.Stderr, "Failed to fire hook: %v\n", err)
}
}
可插拔式日志处理功能实现原理
用户通过实现Hook接口(主要有Levels和Fire两个接口)
Hook.Fire()调用并未加锁
func (entry *Entry) fireHooks() {
var tmpHooks LevelHooks
entry.Logger.mu.Lock()
tmpHooks = make(LevelHooks, len(entry.Logger.Hooks))
for k, v := range entry.Logger.Hooks {
tmpHooks[k] = v
}
entry.Logger.mu.Unlock()
//对于用户实现的hook.Fire方法并未加锁,所以需要用户自己控制Fire方法本身的线程安全
err := tmpHooks.Fire(entry.Level, entry)
if err != nil {
fmt.Fprintf(os.Stderr, "Failed to fire hook: %v\n", err)
}
}