Расширенная настройка логруса Golang (hook, logrotate)

задняя часть Go GitHub Linux

Предисловие:

В этот раз я расскажу об опыте использования логруса в последнее время, там нет продвинутого исходного кода, только некоторые относительно продвинутые конфигурации. Модуль журнала golang по умолчанию немного примитивен, и в нем нет даже базовой информации, предупреждений и методов печати ошибок, поэтому он не очень применим. До использования модуля логрус я использовал инкапсулированный мной модуль лог.Хотя у него не так много функций, как у логруса, но с ним проблем нет. 

Другими словами, существует всего несколько модулей логов с самым высоким рейтингом в сообществе golang, logrus, log4j... Просто глядя на активность github, logrus становится еще более очевидным. Большинство известных проектов с открытым исходным кодом golang в стране и за рубежом представляют собой измельчение бревен, реализованное ими самими.

Эта статья будет обновлена ​​позже, оригинальный адресxiaorui.cc/?p=4963

     

функция сегментации журнала logrus?

Да у логруса по умолчанию нет функции нарезки лога как у logrotate.Я как-то спрашивал sirupsen в теме,почему нет базового logrotate для логов?Его ответ сказал что нет необходимости в расщеплении.Важно то что автор рекомендует выводить журналы на другие серверы журналов, такие как filebeat, logstash, syslog, rsyslog, Fluentd и так далее. Logrus официально поддерживает множество сервисов журналов, насколько мы можем о них думать.

Итак, если я сейчас реализую сегментацию логов в logrus, что мне делать? Два метода. 


Первый, с помощью команды linux logrotate.

/devops/app/go/src/task_dispatcher/logs/*.log
{
    daily
    sharedscripts
    dateext
    nocompress
    size 1G
    missingok
    notifempty
    copytruncate
    rotate 3

Второй способ, использовать хук logrus для загрузки модуля github.com/lestrrat/go-file-rotatelogs.Каждый раз, когда мы пишем лог, logrus будет вызывать go-file-rotatelogs, чтобы определить, нужно ли разбивать лог… go -file-rotatelogs может реализовать большинство функций Linux lograte.

package context

import (
    "github.com/lestrrat/go-file-rotatelogs"
    "github.com/rifflock/lfshook"
    log "github.com/sirupsen/logrus"
    "github.com/pkg/errors"
    "path"
    "time"
    "os"
    "fmt"
    "bufio"
)

func InitLogger() {
    baseLogPath := path.Join(GlobalConfig.LogConf.Logdir,
        GlobalConfig.LogConf.Filename)
    writer, err := rotatelogs.New(
        baseLogPath+".%Y%m%d%H%M",
        rotatelogs.WithLinkName(baseLogPath),      // 生成软链,指向最新日志文件
        rotatelogs.WithMaxAge(7*24*time.Hour),     // 文件最大保存时间
        rotatelogs.WithRotationTime(24*time.Hour), // 日志切割时间间隔
    )
    if err != nil {
        log.Errorf("config local file system logger error. %v", errors.WithStack(err))
    }

    //log.SetFormatter(&log.TextFormatter{})
    switch level := GlobalConfig.LogConf.LogLevel; level {
    /*
    如果日志级别不是debug就不要打印日志到控制台了
     */
    case "debug":
        log.SetLevel(log.DebugLevel)
        log.SetOutput(os.Stderr)
    case "info":
        setNull()
        log.SetLevel(log.InfoLevel)
    case "warn":
        setNull()
        log.SetLevel(log.WarnLevel)
    case "error":
        setNull()
        log.SetLevel(log.ErrorLevel)
    default:
        setNull()
        log.SetLevel(log.InfoLevel)
    }

    lfHook := lfshook.NewHook(lfshook.WriterMap{
        log.DebugLevel: writer, // 为不同级别设置不同的输出目的
        log.InfoLevel:  writer,
        log.WarnLevel:  writer,
        log.ErrorLevel: writer,
        log.FatalLevel: writer,
        log.PanicLevel: writer,
    })
    log.AddHook(lfHook)
}

func setNull() {
    src, err := os.OpenFile(os.DevNull, os.O_APPEND|os.O_WRONLY, os.ModeAppend)
    if err!= nil{
        fmt.Println("err", err)
    }
    writer := bufio.NewWriter(src)
    log.SetOutput(writer)
}

Так как автор рекомендует использовать логрус хук для расширения функции лога, как можно самому написать хук модуль?Это на самом деле очень просто, нужно только реализовать эти методы, в основном смотрите на функцию Fire... Когда мы вызываем логрус .addHook для размещения После загрузки пользовательского хука метод Fire будет вызываться каждый раз, когда мы пишем лог. 

Хук logrus — это дизайн, который стоит изучить подробно, и вы можете легко применить его для записи нескольких файлов. Например, журналы ошибок выводятся в файл error.log независимо друг от друга, а остальные объединяются.

package syslog

import (
    "fmt"
    "log/syslog"
    "os"

    "github.com/sirupsen/logrus"
)


type SyslogHook struct {
    Writer        *syslog.Writer
    SyslogNetwork string
    SyslogRaddr   string
}

func NewSyslogHook(network, raddr string, priority syslog.Priority, tag string) (*SyslogHook, error) {
    w, err := syslog.Dial(network, raddr, priority, tag)
    return &SyslogHook{w, network, raddr}, err
}

func (hook *SyslogHook) Fire(entry *logrus.Entry) error {
    line, err := entry.String()
    if err != nil {
        fmt.Fprintf(os.Stderr, "Unable to read entry, %v", err)
        return err
    }

    switch entry.Level {
    case logrus.PanicLevel:
        return hook.Writer.Crit(line)
    case logrus.FatalLevel:
        return hook.Writer.Crit(line)
    case logrus.ErrorLevel:
        return hook.Writer.Err(line)
    case logrus.WarnLevel:
        return hook.Writer.Warning(line)
    case logrus.InfoLevel:
        return hook.Writer.Info(line)
    case logrus.DebugLevel:
        return hook.Writer.Debug(line)
    default:
        return nil
    }
}

func (hook *SyslogHook) Levels() []logrus.Level {
    return logrus.AllLevels
}

Подводя итог, я не очень доволен функциями логруса, есть много функций, которые вообще не используются, а функции, которые действительно используются, не являются простыми и способными. Что касается вопроса о рубке логруса, то я дважды упомянул его автору, а автор мелькнул и закрыл вопрос.

END.