Logrus — это структурированный логгер для Go (golang), полностью совместимый с API стандартного логгера библиотеки.
Logrus находится в режиме обслуживания. Мы не будем вводить новые функции. Слишком сложно сделать это так, чтобы не нарушить работу многих проектов, а это последнее, что вы хотите от своей библиотеки логирования (опять же...).
Это не значит, что Logrus мёртв. Logrus будет продолжать поддерживаться в плане безопасности, (обратной совместимости) исправлений ошибок и производительности (где мы ограничены интерфейсом).
Я считаю, что самый большой вклад Logrus заключается в том, что он сыграл свою роль в сегодняшнем широком использовании структурированного логирования в Golang. Кажется, нет причин делать серьёзную, ломающую итерацию в Logrus V2, поскольку фантастическое сообщество Go создало их самостоятельно. Появилось много фантастических альтернатив. Logrus выглядел бы как они, если бы был перепроектирован с учётом того, что мы знаем о структурированном логировании в Go сегодня. Посмотрите, например, Zerolog, Zap и Apex.
Видите странные проблемы с чувствительностью к регистру? Раньше можно было импортировать Logrus как в верхнем, так и в нижнем регистре. Из-за среды пакета Go это вызывало проблемы в сообществе, и нам нужен был стандарт. В некоторых средах возникали проблемы с вариантом в верхнем регистре, поэтому был выбран нижний регистр. Всё, что использует logrus, должно использовать нижний регистр: github.com/sirupsen/logrus. Любой пакет, который этого не делает, должен быть изменён.
Чтобы исправить Glide, см. эти комментарии. Для подробного объяснения проблемы с регистром см. этот комментарий.
Красиво раскрашен при разработке (когда подключён TTY, в противном случае просто текст):
С log.SetFormatter(&log.JSONFormatter{}), для лёгкого разбора logstash или Splunk:
{"animal":"walrus","level":"info","msg":"A group of walrus emerges from the ocean","size":10,"time":"2014-03-10 19:57:38.562264131 -0400 EDT"}
{"level":"warning","msg":"The group's number increased tremendously!", "number":122,"omg":true,"time":"2014-03-10 19:57:38.562471297 -0400 EDT"}
{"animal":"walrus","level":"info","msg":"A giant walrus appears!", "size":10,"time":"2014-03-10 19:57:38.562500591 -0400 EDT"}
{"animal":"walrus","level":"info","msg":"Tremendously sized cow enters the ocean.", "size":9,"time":"2014-03-10 19:57:38.562527896 -0400 EDT"}
{"level":"fatal","msg":"The ice breaks!","number":100,"omg":true, "time":"2014-03-10 19:57:38.562543128 -0400 EDT"}
Со стандартным log.SetFormatter(&log.TextFormatter{}), когда TTY не подключён, вывод совместим с форматом logfmt:
time="2015-03-26T01:27:38-04:00" level=debug msg="Started observing beach" animal=walrus number=8
time="2015-03-26T01:27:38-04:00" level=info msg="A group of walrus emerges from the ocean" animal=walrus size=10
time="2015-03-26T01:27:38-04:00" level=warning msg="The group's number increased tremendously!" number=122 omg=true
time="2015-03-26T01:27:38-04:00" level=debug msg="Temperature changes" temperature=-4
time="2015-03-26T01:27:38-04:00" level=panic msg="It's over 9000!" animal=orca size=9009
time="2015-03-26T01:27:38-04:00" level=fatal msg="The ice breaks!" err=&{0x2082280c0 map[animal:orca size:9009] 2015-03-26 01:27:38.441574009 -0400 EDT panic It's over 9000!} Мы обнаружили, что этот API заставляет вас думать о логировании таким образом, который создаёт гораздо более полезные сообщения. Мы были в бесчисленных ситуациях, когда всего лишь одно добавленное поле к уже существующему сообщению журнала сэкономило бы нам часы. Вызов WithFields является необязательным.
В общем, при использовании Logrus использование любых функций семейства printf следует рассматривать как подсказку о том, что вы должны добавить поле, однако вы всё равно можете использовать функции семейства printf с Logrus.
#### Стандартные поля
Часто бывает полезно всегда иметь поля, прикреплённые к сообщениям журнала в приложении или его частях. Например, вы можете захотеть всегда регистрировать request_id и user_ip в контексте запроса. Вместо того чтобы писать log.WithFields(log.Fields{"request_id": request_id, "user_ip": user_ip}) на каждой строке, вы можете создать logrus.Entry для передачи:
```go
requestLogger := log.WithFields(log.Fields{"request_id": request_id, "user_ip": user_ip})
requestLogger.Info("something happened on that request") # will log request_id and user_ip
requestLogger.Warn("something not great happened")
Вы можете добавлять перехватчики для уровней логирования. Например, чтобы отправлять ошибки в службу отслеживания исключений на Error, Fatal и Panic, информацию в StatsD или регистрировать в нескольких местах одновременно, например, в syslog.
Logrus поставляется со встроенными перехватчиками (hooks/). Добавьте их или свой собственный перехватчик в init:
import (
log "github.com/sirupsen/logrus"
"gopkg.in/gemnasium/logrus-airbrake-hook.v2" // the package is named "airbrake"
logrus_syslog "github.com/sirupsen/logrus/hooks/syslog"
"log/syslog"
)
func init() {
// Используйте перехватчик Airbrake, чтобы сообщать об ошибках, которые имеют уровень серьёзности Error или выше, службе отслеживания исключений. Вы можете создавать собственные перехватчики, см. раздел «Перехватчики».
log.AddHook(airbrake.NewHook(123, "xyz", "production"))
hook, err := logrus_syslog.NewSyslogHook("udp", "localhost:514", syslog.LOG_INFO, "")
if err != nil {
log.Error("Unable to connect to local syslog daemon")
} else {
log.AddHook(hook)
}
}
Примечание: Syslog hook также поддерживает подключение к локальному syslog (например, "/dev/log" или "/var/run/syslog" или "/var/run/log"). Для получения подробной информации ознакомьтесь с README syslog hook (hooks/syslog/README.md).
Список известных служб перехватчиков можно найти на этой вики-странице (https://github.com/sirupsen/logrus/wiki/Hooks).
У Logrus есть семь уровней логирования: Trace, Debug, Info, Warning, Error, Fatal и Panic.
log.Trace("Something very low level.")
log.Debug("Useful debugging information.")
log.Info("Something noteworthy happened!")
log.Warn("You should probably take a look at this.")
log.Error("Something failed but I'm not quitting.")
// Calls os.Exit(1) after logging
log.Fatal("Bye.")
// Calls panic() after logging
log.Panic("I'm bailing.")
Вы можете установить уровень логирования для Logger, после чего он будет регистрировать только записи с этим уровнем серьёзности или любым выше него:
// Будет регистрировать всё, что является информацией или выше (предупреждение, ошибка, фатальная ошибка, паника). По умолчанию.
log.SetLevel(log.InfoLevel)
Может быть полезно установить log.Level = logrus.DebugLevel в среде отладки или подробного описания, если ваше приложение имеет такую возможность.
Примечание: Если вы хотите разные уровни логирования для глобального (log.SetLevel(...)) и системного логирования, пожалуйста, ознакомьтесь с README системного перехватчика (hooks/syslog/README.md#different-log-levels-for-local-and-remote-logging).
Помимо полей, добавленных с помощью WithField или WithFields, некоторые поля автоматически добавляются ко всем событиям логирования:
У Logrus нет понятия среды.
Если вы хотите, чтобы перехватчики и форматировщики использовались только в определённых средах, вам следует справиться с этим самостоятельно. Например, если у вашего приложения есть глобальная переменная Environment, которая представляет собой строковое представление среды, вы могли бы сделать следующее: ``` лог "github.com/sirupsen/logrus" )
func init() { // делаем что-то здесь, чтобы установить окружение в зависимости от переменной окружения // или флага командной строки if Environment == "production" { лог.SetFormatter(&лог.JSONFormatter{}) } else { // TextFormatter используется по умолчанию, на самом деле вам не нужно этого делать. лог.SetFormatter(&лог.TextFormatter{})
Эта конфигурация предназначена для использования `logrus`, но JSON в
производстве в основном полезен только если вы выполняете агрегацию журналов с помощью таких инструментов, как
Splunk или Logstash.
#### Форматировщики
Встроенные форматировщики журналов:
* `logrus.TextFormatter`. Регистрирует событие в цвете, если stdout является tty, в противном случае
без цвета.
* *Примечание:* чтобы принудительно выводить цветной вывод, когда нет TTY, установите поле `ForceColors`
в `true`. Чтобы принудительно отключить цветной вывод, даже если есть TTY, установите поле `DisableColors` в `true`. Для Windows см.
[github.com/mattn/go-colorable](https://github.com/mattn/go-colorable).
* По умолчанию уровни усекаются до 4 символов. Чтобы отключить
усечение, установите для поля `DisableLevelTruncation` значение `true`.
* При выводе на TTY часто бывает полезно визуально сканировать вниз по столбцу, где все уровни имеют одинаковую ширину. Установка поля `PadLevelText` в `true` включает это поведение, добавляя отступ к тексту уровня.
* Все параметры перечислены в [сгенерированных документах](https://godoc.org/github.com/sirupsen/logrus#TextFormatter).
* `logrus.JSONFormatter`. Записывает поля в формате JSON.
* Все опции перечислены в [сгенерированных документах](https://godoc.org/github.com/sirupsen/logrus#JSONFormatter).
Сторонние форматировщики журналов:
* [`FluentdFormatter`](https://github.com/joonix/log). Форматирует записи, которые могут быть проанализированы Kubernetes и Google Container Engine.
* [`GELF`](https://github.com/fabienm/go-logrus-formatters). Форматирует записи в соответствии со спецификацией Graylog's [GELF 1.1](http://docs.graylog.org/en/2.4/pages/gelf.html).
* [`logstash`](https://github.com/bshuster-repo/logrus-logstash-hook). Записывает поля как события [Logstash](http://logstash.net).
* [`prefixed`](https://github.com/x-cray/logrus-prefixed-formatter). Отображает источник записи вместе с альтернативным макетом.
* [`zalgo`](https://github.com/aybabtme/logzalgo). Вызов силы Зальго.
* [`nested-logrus-formatter`](https://github.com/antonfisher/nested-logrus-formatter). Преобразует поля logrus в вложенную структуру.
* [`powerful-logrus-formatter`](https://github.com/zput/zxcTool). Получает имя файла, номер строки журнала и имя последней функции при печати журнала; сохраняет журнал в файлы.
* [`caption-json-formatter`](https://github.com/nolleh/caption_json_formatter). Форматер сообщений logrus с добавлением удобочитаемой подписи.
Вы можете определить свой собственный форматировщик, реализовав интерфейс `Formatter`, требующий метода `Format`. `Формат` принимает `*Entry`. `entry.Data` — это тип `Fields` (`map[string]interface{}`) со всеми вашими полями, а также с полями по умолчанию (см. раздел «Записи» выше):
```go
type MyJSONFormatter struct {
}
лог.SetFormatter(new(MyJSONFormatter))
func (f *MyJSONFormatter) Format(entry *Entry) ([]byte, error) {
// Обратите внимание, что это не включает Time, Level и Message, которые доступны в
// Entry. Обратитесь к `godoc` за информацией об этих полях или прочитайте исходный код официальных регистраторов.
serialized, err := json.Marshal(entry.Data)
if err != nil {
return nil, fmt.Errorf("Не удалось маршалировать поля в JSON, %w", err)
}
return append(serialized, '\n'), nil
}
io.Writer
Logrus можно преобразовать в io.Writer
. Этот писатель является концом io.Pipe
, и вы должны закрыть его.
w := logger.Writer()
defer w.Close()
srv := http.Server{
// создать стандартный регистратор log.Logger, который записывает в
// logrus.Logger.
ErrorLog: log.New(w, "", 0),
}
Каждая строка, записанная в этот писатель, будет напечатана обычным способом с использованием форматировщиков
и хуков. Уровень для этих записей — info
.
Это означает, что мы можем легко переопределить стандартный библиотечный регистратор: logger := logrus.New()
logger.Formatter = &logrus.JSONFormatter{}
// Используем logrus для стандартного вывода логов
// Обратите внимание, что здесь log
ссылается на стандартный библиотечный log
, а не на logrus, импортированный под именем log
.
log.SetOutput(logger.Writer())
Logrus не предоставляет ротацию логов. Ротацию логов должна выполнять внешняя программа (например, logrotate(8)
), которая может сжимать и удалять старые записи логов. Это не должно быть функцией регистратора уровня приложения.
Инструмент | Описание |
---|---|
Logrus Mate | Logrus mate — это инструмент для Logrus, который позволяет управлять регистраторами. Вы можете настроить уровень, хук и форматировщик регистратора через конфигурационный файл. Регистратор будет создан с различными конфигурациями в разных средах. |
Logrus Viper Helper | Помощник для Logrus, чтобы работать с spf13/Viper для загрузки конфигурации с fangs! И упростить конфигурацию Logrus, используя некоторые функции Logrus Mate. Пример |
В Logrus есть встроенная функция для проверки наличия сообщений логов, реализованная через хук test
и предоставляющая:
test.NewLocal
и test.NewGlobal
), которые просто добавляют хук test
;test.NewNullLogger
), который просто записывает сообщения логов (и не выводит их):import(
"github.com/sirupsen/logrus"
"github.com/sirupsen/logrus/hooks/test"
"github.com/stretchr/testify/assert"
"testing"
)
func TestSomething(t*testing.T){
logger, hook := test.NewNullLogger()
logger.Error("Helloerror")
assert.Equal(t, 1, len(hook.Entries))
assert.Equal(t, logrus.ErrorLevel, hook.LastEntry().Level)
assert.Equal(t, "Helloerror", hook.LastEntry().Message)
hook.Reset()
assert.Nil(t, hook.LastEntry())
}
Logrus может регистрировать одну или несколько функций, которые будут вызываться при регистрации любого сообщения уровня fatal
. Зарегистрированные обработчики будут выполняться перед тем, как logrus выполнит os.Exit(1)
. Такое поведение может быть полезно, если вызывающим объектам необходимо корректно завершить работу. В отличие от вызова panic("Something went wrong...")
, который можно перехватить с помощью отложенного recover
, вызов os.Exit(1)
не может быть перехвачен.
...
handler := func() {
// корректно завершаем работу...
}
logrus.RegisterExitHandler(handler)
...
По умолчанию Logger защищён мьютексом для одновременной записи. Мьютекс удерживается при вызове хуков и записи логов. Если вы уверены, что такая блокировка не требуется, вы можете вызвать logger.SetNoLock(), чтобы отключить блокировку.
Ситуация, когда блокировка не нужна, включает:
O_APPEND
, и каждая запись меньше 4k. (Это позволяет многопоточную/многопроцессную запись)
(См. http://www.notthewizard.com/2014/06/17/are-files-appends-really-atomic/)Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Комментарии ( 0 )