Skip to content

Commit

Permalink
textlogger: write unstructured klog output directly
Browse files Browse the repository at this point in the history
Textlogger can (but doesn't have to) be used to write klog's unstructured
output from calls like Infof directly to the output stream. This has two
advantages:
- traditional output remains exactly the same as before, which is particularly
  important for multi-line messages because those get quoted otherwise
- performance is better because re-encoding the output string is avoided
  • Loading branch information
pohly committed Jan 24, 2023
1 parent 81f97ff commit 7a9f099
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 3 deletions.
20 changes: 17 additions & 3 deletions test/output.go
Expand Up @@ -39,6 +39,7 @@ import (
"github.com/go-logr/logr"

"k8s.io/klog/v2"
"k8s.io/klog/v2/textlogger"
)

// InitKlog must be called in a test to configure klog for testing.
Expand Down Expand Up @@ -577,7 +578,7 @@ func Output(t *testing.T, config OutputConfig) {

if config.AsBackend {
testOutput(t, printWithKlogLine-1, func(buffer *bytes.Buffer) {
klog.SetLogger(config.NewLogger(buffer, 10, test.vmodule))
setLogger(config.NewLogger(buffer, 10, test.vmodule))
printWithKlog(test)
})
return
Expand Down Expand Up @@ -765,10 +766,11 @@ func Output(t *testing.T, config OutputConfig) {
for i, test := range tests {
t.Run(test.name, func(t *testing.T) {
var buffer bytes.Buffer
haveWriteKlogBuffer := false
if config.NewLogger == nil {
klog.SetOutput(&buffer)
} else {
klog.SetLogger(config.NewLogger(&buffer, 10, ""))
haveWriteKlogBuffer = setLogger(config.NewLogger(&buffer, 10, ""))
defer klog.ClearLogger()
}
test.logFunc()
Expand All @@ -789,6 +791,7 @@ func Output(t *testing.T, config OutputConfig) {
// result, including a trailing newline, to
// Logger.Info.
if config.NewLogger != nil &&
!haveWriteKlogBuffer &&
!strings.HasSuffix(test.name, "S") &&
!strings.HasSuffix(test.name, "SDepth") {
// klog: I output.go:<LINE>] hello world
Expand Down Expand Up @@ -851,7 +854,7 @@ func Benchmark(b *testing.B, config OutputConfig) {
}

if config.AsBackend {
klog.SetLogger(config.NewLogger(io.Discard, 10, ""))
setLogger(config.NewLogger(io.Discard, 10, ""))
for i := 0; i < b.N; i++ {
printWithKlog(test)
}
Expand All @@ -871,6 +874,17 @@ func Benchmark(b *testing.B, config OutputConfig) {
}
}

func setLogger(logger logr.Logger) bool {
haveWriteKlogBuffer := false
var opts []klog.LoggerOption
if writer, ok := logger.GetSink().(textlogger.KlogBufferWriter); ok {
opts = append(opts, klog.WriteKlogBuffer(writer.WriteKlogBuffer))
haveWriteKlogBuffer = true
}
klog.SetLoggerWithOptions(logger, opts...)
return haveWriteKlogBuffer
}

func copySlice(in []interface{}) []interface{} {
return append([]interface{}{}, in...)
}
Expand Down
14 changes: 14 additions & 0 deletions textlogger/textlogger.go
Expand Up @@ -134,6 +134,10 @@ func (l *tlogger) print(err error, s severity.Severity, msg string, kvList []int
l.config.co.output.Write(b.Bytes())
}

func (l *tlogger) WriteKlogBuffer(data []byte) {
l.config.co.output.Write(data)
}

// WithName returns a new logr.Logger with the specified name appended. klogr
// uses '/' characters to separate name elements. Callers should not pass '/'
// in the provided name string, but this library does not actually enforce that.
Expand All @@ -152,5 +156,15 @@ func (l *tlogger) WithValues(kvList ...interface{}) logr.LogSink {
return &new
}

// KlogBufferWriter is implemented by the textlogger LogSink.
type KlogBufferWriter interface {
// WriteKlogBuffer takes a pre-formatted buffer prepared by klog and
// writes it unchanged to the output stream. Can be used with
// klog.WriteKlogBuffer when setting a logger through
// klog.SetLoggerWithOptions.
WriteKlogBuffer([]byte)
}

var _ logr.LogSink = &tlogger{}
var _ logr.CallDepthLogSink = &tlogger{}
var _ KlogBufferWriter = &tlogger{}

0 comments on commit 7a9f099

Please sign in to comment.