Как отключить журнал.

У меня есть очень сложный код, который использует пакет log. Теперь пришло время отключить ведение журнала, и я не могу определить, как отключить стандартный регистратор.

Я что-то пропустил? Должен ли я проверять флаг перед вызовом журнала или комментировать их в процессе производства?

Ответ 1

Для полного отключения журналов на самом деле лучше вызвать log.SetFlags(0) Joril и установить вывод в no-op io.Writer (то есть log.SetOutput(ioutil.Discard))

Но даже после этого операции будут работать около 500-600 нс/оп 1

Это все еще может быть прервано (до около 100 нсов/оп) с помощью настраиваемой Logger реализации и выполнения всех функций быть не оп - как показано здесь (только переопределение Println для bervity).

Альтернативой всем этим является использование пользовательской среды ведения журнала с уровнями и установка ее завершения.

Однако обратите внимание, что одна из часто используемых библиотек для ведения журнала (logrus) имеет последствия для производительности - то же самое можно найти в тестах, где она выполняется с 3K+ ns/op, независимо.

Предвзятое мнение: по сравнению с -1, протоколирование библиотеки выполняется в соответствии с пользовательской реализацией Logger при установке Level на -1 независимо от бэкэнд и форматирования

(исходный источник можно найти здесь)

выход эталонного теста выглядит следующим образом:

testing: warning: no tests to run
PASS
BenchmarkGoLogging-4                                             1000000          2068 ns/op
BenchmarkGoLoggingNullBackend-4                                  5000000           308 ns/op
BenchmarkGoLoggingNullBackendWithFancyFormatter-4                3000000           435 ns/op
BenchmarkGoLoggingOffLevel-4                                    20000000           109 ns/op
BenchmarkGoLoggingNullBackendAndOffLevel-4                      20000000           108 ns/op
BenchmarkGoLoggingNullBackendWithFancyFormatterAndOffLevel-4    20000000           109 ns/op
BenchmarkLog15-4                                                  200000          7359 ns/op
BenchmarkLog15WithDiscardHandler-4                               2000000           922 ns/op
BenchmarkLog15WithDiscardHandlerAndOffLevel-4                    2000000           926 ns/op
BenchmarkLog15WithNopLogger-4                                   20000000           108 ns/op
BenchmarkLog15WithNopLoggerDiscardHandlerA-4                    20000000           112 ns/op
BenchmarkLog15WithNopLoggerAndDiscardHandlerAndOffLevel-4       20000000           112 ns/op
BenchmarkLog-4                                                   1000000          1217 ns/op
BenchmarkLogIoDiscardWriter-4                                    2000000           724 ns/op
BenchmarkLogIoDiscardWriterWithoutFlags-4                        3000000           543 ns/op
BenchmarkLogCustomNullWriter-4                                   2000000           731 ns/op
BenchmarkLogCustomNullWriterWithoutFlags-4                       3000000           549 ns/op
BenchmarkNopLogger-4                                            20000000           113 ns/op
BenchmarkNopLoggerWithoutFlags-4                                20000000           112 ns/op
BenchmarkLogrus-4                                                 300000          3832 ns/op
BenchmarkLogrusWithDiscardWriter-4                                500000          3032 ns/op
BenchmarkLogrusWithNullFormatter-4                                500000          3814 ns/op
BenchmarkLogrusWithPanicLevel-4                                   500000          3872 ns/op
BenchmarkLogrusWithDiscardWriterAndPanicLevel-4                   500000          3085 ns/op
BenchmarkLogrusWithDiscardWriterAndNullFormatterAndPanicLevel-4   500000          3064 ns/op
ok      log-benchmarks  51.378s
go test -bench .  62.17s user 3.90s system 126% cpu 52.065 total

# 1: YMMV, протестирован на i7-4500U CPU @1,80 ГГц

Ответ 2

Нет причин создавать свой собственный тип для обычного io.Writer, если он существует в пакете io/ioutil.

import (
    "log"
    "io/ioutil"
)

func init() {
    log.SetOutput(ioutil.Discard)
}

Ответ 3

type NullWriter int
func (NullWriter) Write([]byte) (int, error) { return 0, nil }

// ...

log.SetOutput(new(NullWriter))

Ответ 4

Этот подход позволяет включать и отключать ведение журнала во время выполнения:

type LogWriter struct{
    enabled bool
}

func (l *LogWriter) Enable() {
    l.enabled = true
}

func (l *LogWriter) Disable() {
    l.enabled = false
}

func (l *LogWriter) Write([]byte) (int, error) {
    if l.enabled {
        //...
    }
    return 0, nil
}

И этот подход включает или отключает ведение журнала для всего времени выполнения:

type LogWriter struct{}

func (l *LogWriter) Write([]byte) (int, error) {
    if some.Constant {
        //...
    }
    return 0, nil
}

Где some.Constant будет либо константой, которую вы задали перед компиляцией (созданием "производственного" двоичного кода), либо переменной, которая устанавливается только один раз при запуске программы с помощью флагов командной строки (что-то вроде myprogram --enable-logging=true)

С обоими подходами вы можете оставить свой текущий код почти полностью нетронутым.

Ответ 5

Поскольку SetOutput() определен только для глобального регистратора, пользовательский писатель по-прежнему удобен для других регистраторов. Короткий способ написания:

type LogWriter struct{ io.Writer }
func (w *LogWriter) Enable()  { w.Writer = os.Stdout }
func (w *LogWriter) Disable() { w.Writer = ioutil.Discard }

Ответ 6

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

См. Документ на странице http://godoc.org/code.google.com/p/log4go.