49

我有一些使用该log包的大量检测代码。现在是时候关闭日志记录了,我无法确定如何关闭标准记录器。

我错过了什么吗?我应该在进行日志调用之前检查标志,还是在生产中将它们注释掉?

4

6 回答 6

122

当 io/ioutil 包中存在一个通用 io.Writer 时,没有理由为通用 io.Writer 创建自己的类型。

import (
    "log"
    "io/ioutil"
)

func init() {
    log.SetOutput(ioutil.Discard)
}
于 2012-05-21T15:25:03.397 回答
38

对于完全禁用日志,实际上最好调用log.SetFlags(0)Joril并将输出设置为无操作io.Writer(即,log.SetOutput(ioutil.Discard)

但即使在此之后,操作也会在500-600 ns/op 1左右空闲

这仍然可以通过使用自定义实现来缩短(到100 ns/opLogger左右) ,并将所有功能实现为无操作 - 如此处所示仅为Printlnbervity 覆盖)。

所有这些的替代方法是使用具有级别的自定义日志框架并将其设置为完全关闭。

但请注意,常用的日志记录库之一 ( logrus ) 具有性能影响——无论如何,在它使用3K+ ns/op执行的基准测试中都可以找到相同的内容。

有偏见的意见:从基准测试来看,无论后端和格式如何,库go-logging在设置toLogger时的性能与自定义实现相当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.80GHz 上测试

于 2015-12-24T21:10:33.247 回答
4
type NullWriter int
func (NullWriter) Write([]byte) (int, error) { return 0, nil }

// ...

log.SetOutput(new(NullWriter))
于 2012-05-13T11:06:42.467 回答
3

这种方法允许您在运行时打开和关闭日志记录:

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
}

wheresome.Constant将是您在编译之前设置的常量(生成“生产”二进制文件)或在通过命令行标志运行程序时仅设置一次的变量(类似于myprogram --enable-logging=true

使用这两种方法,您可以几乎完全保持当前代码不变。

于 2012-05-13T20:03:07.280 回答
2

由于SetOutput()仅为全局记录器定义,自定义编写器对于其他记录器仍然很方便。一个简短的写法是这样的:

type LogWriter struct{ io.Writer }
func (w *LogWriter) Enable()  { w.Writer = os.Stdout }
func (w *LogWriter) Disable() { w.Writer = ioutil.Discard }
于 2014-11-21T22:48:16.207 回答
0

其他人来这里寻找这个和其他日志记录工具的注意事项:看看 log4go 包,因为它包括关闭日志记录、设置日志级别、日志轮换、重定向到文件等可能有用。

请参阅http://godoc.org/code.google.com/p/log4go上的文档

于 2012-09-29T07:50:33.420 回答