klog: klog.SetOutput(ioutil.Discard) doesn't remove output

/kind bug

What steps did you take and what happened: calling klog.SetOutput(ioutil.Discard doesn’t remove logging output.

What did you expect to happen: No logging ouput.

Anything else you would like to add: In https://github.com/coredns/coredns/pull/3055 I want to test various things, but not clutter the output to much, so I call klog.SetOutput(ioutil.Discard), but the screen this is full off:

0810 07:23:54.827224    2826 reflector.go:126] pkg/mod/k8s.io/client-go@v11.0.0+incompatible/tools/cache/reflector.go:94: Failed to list *v1.Pod: Get https://127.0.0.1:443/api/v1/pods?fieldSelector=status.phase%21%3DSucceeded%2Cstatus.phase%21%3DFailed%2Cstatus.phase%21%3DUnknown&limit=500&resourceVersion=0: dial tcp 127.0.0.1:443: connect: connection refused
E0810 07:23:54.827224    2826 reflector.go:126] pkg/mod/k8s.io/client-go@v11.0.0+incompatible/tools/cache/reflector.go:94: Failed to list *v1.Pod: Get https://127.0.0.1:443/api/v1/pods?fieldSelector=status.phase%21%3DSucceeded%2Cstatus.phase%21%3DFailed%2Cstatus.phase%21%3DUnknown&limit=500&resourceVersion=0: dial tcp 127.0.0.1:443: connect: connection refused
E0810 07:23:54.827224    2826 reflector.go:126] pkg/mod/k8s.io/client-go@v11.0.0+incompatible/tools/cache/reflector.go:94: Failed to list *v1.Pod: Get https://127.0.0.1:443/api/v1/pods?fieldSelector=status.phase%21%3DSucceeded%2Cstatus.phase%21%3DFailed%2Cstatus.phase%21%3DUnknown&limit=500&resourceVersion=0: dial tcp 127.0.0.1:443: connect: connection refused
E0810 07:23:54.827224    2826 reflector.go:126] pkg/mod/k8s.io/client-go@v11.0.0+incompatible/tools/cache/reflector.go:94: Failed to list *v1.Pod: Get https://127.0.0.1:443/api/v1/pods?fieldSelector=status.phase%21%3DSucceeded%2Cstatus.phase%21%3DFailed%2Cstatus.phase%21%3DUnknown&limit=500&resourceVersion=0: dial tcp 127.0.0.1:443: connect: connection refused
E0810 07:23:54.829765    2826 reflector.go:126] pkg/mod/k8s.io/client-go@v11.0.0+incompatible/tools/cache/reflector.go:94: Failed to list *v1.Pod: Get https://127.0.0.1:443/api/v1/pods?fieldSelector=status.phase%21%3DSucceeded%2Cstatus.phase%21%3DFailed%2Cstatus.phase%21%3DUnknown&limit=500&resourceVersion=0: dial tcp 127.0.0.1:443: connect: connection refused
E0810 07:23:54.829765    2826 reflector.go:126] pkg/mod/k8s.io/client-go@v11.0.0+incompatible/tools/cache/reflector.go:94: Failed to list *v1.Pod: Get https://127.0.0.1:443/api/v1/pods?fieldSelector=status.phase%21%3DSucceeded%2Cstatus.phase%21%3DFailed%2Cstatus.phase%21%3DUnknown&limit=500&resourceVersion=0: dial tcp 127.0.0.1:443: connect: connection refused
E0810 07:23:54.829765    2826 reflector.go:126] pkg/mod/k8s.io/client-go@v11.0.0+incompatible/tools/cache/reflector.go:94: Failed to list *v1.Pod: Get https://127.0.0.1:443/api/v1/pods?fieldSelector=status.phase%21%3DSucceeded%2Cstatus.phase%21%3DFailed%2Cstatus.phase%21%3DUnknown&limit=500&resourceVersion=0: dial tcp 127.0.0.1:443: connect: connection refused
E0810 07:23:54.829765    2826 reflector.go:126] pkg/mod/k8s.io/client-go@v11.0.0+incompatible/tools/cache/reflector.go:94: Failed to list *v1.Pod: Get https://127.0.0.1:443/api/v1/pods?fieldSelector=status.phase%21%3DSucceeded%2Cstatus.phase%21%3DFailed%2Cstatus.phase%21%3DUnknown&limit=500&resourceVersion=0: dial tcp 127.0.0.1:443: connect: connection refused
~~~

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Reactions: 3
  • Comments: 15 (3 by maintainers)

Most upvoted comments

This worked for me:

	klog.SetOutput(io.Discard)
	flags := &flag.FlagSet{}
	klog.InitFlags(flags)
	flags.Set("logtostderr", "false")

It uses a custom flag set to avoid interactions with the normal flags of the program. flags.Set then suppresses the default output to stderr.

For what it’s worth, I ran into this issue today and I solved it like this

// TurnOffKlog supresses leaderelector.go's usage of klog
func TurnOffKlog() {
	klog.SetLogger(&EmptyLogger{})
}

// EmptyLogger implements logr.Logging
type EmptyLogger struct{}

// Enabled always returns false
func (e *EmptyLogger) Enabled() bool {
	return false
}

// Info does nothing
func (e *EmptyLogger) Info(msg string, keysAndValues ...interface{}) {}

// Error does nothing
func (e *EmptyLogger) Error(err error, msg string, keysAndValues ...interface{}) {}

// V returns itself
func (e *EmptyLogger) V(level int) logr.Logger {
	return e
}

// WithValues returns itself
func (e *EmptyLogger) WithValues(keysAndValues ...interface{}) logr.Logger {
	return e
}

// WithName returns itself
func (e *EmptyLogger) WithName(name string) logr.Logger {
	return e
}

I’m not re-opening this thread, just leaving this here in case it helps someone else (or me if I search for it again in the future):

flags := &flag.FlagSet{}
klog.InitFlags(flags)
flags.Set("logtostderr", "false")
flags.Set("alsologtostderr", "false")
flags.Set("stderrthreshold", "4")

This is to avoid this line from klog:

	if l.toStderr || l.alsoToStderr || s >= l.stderrThreshold.get() { ...

I didn’t explicitly have to “discard” the output, but error messages (intentional in tests) were making it to the logs.

Seems SetOutput only set the logging destination for file. To also impact the std stream, such as stderr, does below workaround work?

	klog.InitFlags(flag.CommandLine)
	flag.Parse()
	flag.Set("logtostderr", "false")
	flag.Set("alsologtostderr", "false")
	klog.SetOutput(ioutil.Discard)

Change current behaiour of SetOutput may be a breaking change, I suggest if we can provide another interface, or use a flag to tell if need to change behaiour.