如何禁用log.Logger

huangapple go评论142阅读模式
英文:

How to disable a log.Logger

问题

我有一些使用log包的代码,其中有很多仪器化的部分。现在是关闭日志记录的时候了,但我无法确定如何关闭标准日志记录器。

我有遗漏了什么吗?在进行日志调用之前,我应该检查一个标志,还是在生产环境中将它们注释掉?

英文:

I have some heavily instrumented code that makes use of the log package. Now it's come time to turn off the logging, and I can't determine how to turn off the standard logger.

Have I missed something? Should I be checking a flag before making log calls, or commenting them out in production?

答案1

得分: 129

没有理由为常见的io.Writer创建自己的类型,因为在io/ioutil包中已经存在一个。

import (
    "log"
    "io/ioutil"
)

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

从Go 1.16开始,只需使用io.Discard

> package ioutil // import "io/ioutil"
>
> var Discard io.Writer = io.Discard
> Discard是一个io.Writer,所有的写入调用都会成功,而不做任何操作。
>
> 已弃用:从Go 1.16开始,这个值只是io.Discard。

log.SetOutput(io.Discard)
英文:

No reason to create your own type for a common io.Writer when one exists in the io/ioutil package.

import (
    "log"
    "io/ioutil"
)

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

From Go 1.16, just use io.Discard

> package ioutil // import "io/ioutil"
>
> var Discard io.Writer = io.Discard
> Discard is an io.Writer on which all Write calls succeed without doing
> anything.
>
> Deprecated: As of Go 1.16, this value is simply io.Discard.

log.SetOutput(io.Discard)

答案2

得分: 41

要完全禁用日志,最好调用log.SetFlags(0)并将输出设置为一个无操作的io.Writer(即log.SetOutput(ioutil.Discard))。

但即使这样,操作仍会在[500-600 ns/op][2a]之间空闲<sup>1</sup>。

通过使用自定义的Logger实现,并将所有函数实现为无操作,可以将其缩短到约100 ns/op,如此处所示(仅为了简洁起见,只覆盖Println)。

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

请注意,其中一个常用的日志库([logrus][3])存在[性能问题][4],在[基准测试][6]中,它的性能为_3K+ ns/op_。

偏见观点:从基准测试中可以看出,当将Level设置为-1时,库[go-logging][5]的性能与自定义的Logger实现相当,无论后端和格式如何

(基准测试源代码可以在[这里][6]找到)

基准测试的输出如下:

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

<sup>#1:YMMV,在i7-4500U CPU @ 1.80GHz上进行了测试</sup>
[1]:https://stackoverflow.com/questions/10571182/go-disable-a-log-logger#comment43485550_10688098
[2a]:https://gist.github.com/Avinash-Bhat/48c4f06b0cc840d9fd6c#file-log_test-go "YMMV, tested on i7-4500U CPU @ 1.80GHz"
[2b]:https://gist.github.com/Avinash-Bhat/48c4f06b0cc840d9fd6c#file-log_test-go "benchmark for package log"
[3]:https://github.com/Sirupsen/logrus
[4]:https://github.com/Sirupsen/logrus/issues/125 "Issue #125"
[5]:https://github.com/op/go-logging
[6]:https://gist.github.com/Avinash-Bhat/48c4f06b0cc840d9fd6c "Gist"

英文:

For completely disabling logs, it's actually better to call log.SetFlags(0)<sup>[Joril][1]</sup> and set the output to a no-op io.Writer (i.e., log.SetOutput(ioutil.Discard))

But even after this, the operations will idle around [500-600 ns/op][2a]<sup>1</sup>

This can still be cut short (to around 100 ns/op) by using a custom Logger implementation, and implementing all the functions to be no-op -- as demonstrated [here][2b] (only overriding Println for bervity).

The alternative to all these is to use a custom logging framework with levels and set it to complete OFF.

Note though, one of the commonly used library for logging ([logrus][3]) has [performance implications][4] -- the same can be found in the [benchmarks][6] where it perform with 3K+ ns/op, regardless.

Biased opinion: from the benchmarks, the library [go-logging][5] performs in par with the custom Logger implementation when setting the Level to -1, regardless of the backend and formatting

(the benchmark source can be found [here][6])

the output of the benchmark is as follows:

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

<sup>#1: YMMV, tested on i7-4500U CPU @ 1.80GHz</sup>
[1]:https://stackoverflow.com/questions/10571182/go-disable-a-log-logger#comment43485550_10688098
[2a]:https://gist.github.com/Avinash-Bhat/48c4f06b0cc840d9fd6c#file-log_test-go "YMMV, tested on i7-4500U CPU @ 1.80GHz"
[2b]:https://gist.github.com/Avinash-Bhat/48c4f06b0cc840d9fd6c#file-log_test-go "benchmark for package log"
[3]:https://github.com/Sirupsen/logrus
[4]:https://github.com/Sirupsen/logrus/issues/125 "Issue #125"
[5]:https://github.com/op/go-logging
[6]:https://gist.github.com/Avinash-Bhat/48c4f06b0cc840d9fd6c "Gist"

答案3

得分: 6

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

// ...

log.SetOutput(new(NullWriter))

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

// ...

log.SetOutput(new(NullWriter))

答案4

得分: 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
}

<sub>其中some.Constant可以是在编译之前设置的常量(生成一个“生产”二进制文件),或者是在运行程序时通过命令行标志设置的变量(类似于myprogram --enable-logging=true)</sub>

使用这两种方法,您几乎可以完全不改动您当前的代码。

英文:

This approach allows you to turn logging on and off at runtime:

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
}

And this approach enables or disables logging for the entire runtime:

type LogWriter struct{}

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

<sub>Where some.Constant would be either a constant that you set before compiling (producing a "production" binary) or a variable that is set only once when running the program via command-line flags (something like myprogram --enable-logging=true)</sub>

With both approaches you can leave your current code almost entirely untouched.

答案5

得分: 2

由于SetOutput()仅适用于全局记录器,对于其他记录器来说,自定义的写入器仍然很方便。编写一个简短的写入器的方法如下:

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

Since SetOutput() is only defined for the global logger, a custom writer is still handy for other loggers. A short way of writing one is like this:

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

答案6

得分: 0

一个给其他人的提示,如果你来到这里寻找日志记录和其他日志设施的话:可以看一下log4go包,它涵盖了关闭日志记录、设置日志级别、日志轮转、重定向到文件等功能,可能会很有用。

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

英文:

A note for others coming here looking for this and other logging facilities: have a look at the log4go package as that covers turning off logging, setting log levels, log rotation, redirection to a file etc which might be useful.

See the doc at http://godoc.org/code.google.com/p/log4go

huangapple
  • 本文由 发表于 2012年5月13日 19:00:27
  • 转载请务必保留本文链接:https://go.coder-hub.com/10571182.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定