• logrus 学习笔记


    logrus

    实现多个实例

    func New() *Logger {
    	return &Logger{
    		Out:          os.Stderr,
    		Formatter:    new(TextFormatter),
    		Hooks:        make(LevelHooks),
    		Level:        InfoLevel,
    		ExitFunc:     os.Exit,
    		ReportCaller: false,
    	}
    }
    

    默认实例

    var (
    	// std is the name of the standard logger in stdlib `log`
    	std = New()
    )
    

    Pool 使用

    
    // Reusable empty entry
    entryPool sync.Pool
        
    func (logger *Logger) newEntry() *Entry {
    	entry, ok := logger.entryPool.Get().(*Entry)
    	if ok {
    		return entry
    	}
    	return NewEntry(logger)
    }
    
    func (logger *Logger) releaseEntry(entry *Entry) {
    	entry.Data = map[string]interface{}{}
    	logger.entryPool.Put(entry)
    }
    

    核心代码

    entry log

    // This function is not declared with a pointer value because otherwise
    // race conditions will occur when using multiple goroutines
    func (entry Entry) log(level Level, msg string) {
    	var buffer *bytes.Buffer
    
    	// Default to now, but allow users to override if they want.
    	//
    	// We don't have to worry about polluting future calls to Entry#log()
    	// with this assignment because this function is declared with a
    	// non-pointer receiver.
    	if entry.Time.IsZero() {
    		entry.Time = time.Now()
    	}
    
    	entry.Level = level
    	entry.Message = msg
    	entry.Logger.mu.Lock()
    	if entry.Logger.ReportCaller {
    		entry.Caller = getCaller()
    	}
    	entry.Logger.mu.Unlock()
    
    	entry.fireHooks()
    
    	buffer = getBuffer()
    	defer func() {
    		entry.Buffer = nil
    		putBuffer(buffer)
    	}()
    	buffer.Reset()
    	entry.Buffer = buffer
    
    	entry.write()
    
    	entry.Buffer = nil
    
    	// To avoid Entry#log() returning a value that only would make sense for
    	// panic() to use in Entry#Panic(), we avoid the allocation by checking
    	// directly here.
    	if level <= PanicLevel {
    		panic(&entry)
    	}
    }
    
    

    扩展实现

    统一接口,面向接口开发

    type Hook interface {
    	Levels() []Level
    	Fire(*Entry) error
    }
    type Formatter interface {
    	Format(*Entry) ([]byte, error)
    }
    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
    ", err)
    	}
    }
    
    func (entry *Entry) write() {
    	entry.Logger.mu.Lock()
    	defer entry.Logger.mu.Unlock()
    	serialized, err := entry.Logger.Formatter.Format(entry)
    	if err != nil {
    		fmt.Fprintf(os.Stderr, "Failed to obtain reader, %v
    ", err)
    		return
    	}
    	if _, err = entry.Logger.Out.Write(serialized); err != nil {
    		fmt.Fprintf(os.Stderr, "Failed to write to log, %v
    ", err)
    	}
    }
    
  • 相关阅读:
    React性能优化 渲染20000多条checkbox组件,点击选择checkbox组件的时候特别卡,解决办法
    react网页多语言(react-intl-universal)
    个人作品
    程序员和产品经理的那些事
    three.js 根据不同的图片做不同的动画特效 科技感十足
    互联网行业最佳产品开发流程 推荐!
    类似于YouTube、Medium、知乎等网站使用的进度条插件 NProgress
    js模拟点击下载文件到本地
    MySQL记录操作(增删改)
    MySQL表的操作
  • 原文地址:https://www.cnblogs.com/SLchuck/p/13986077.html
Copyright © 2020-2023  润新知