Skip to content

Commit d7fc505

Browse files
authored
Merge pull request #363 from pohly/textlogger-backend
textlogger write through
2 parents e37f9fe + 7a9f099 commit d7fc505

File tree

5 files changed

+114
-49
lines changed

5 files changed

+114
-49
lines changed

contextual.go

+28-2
Original file line numberDiff line numberDiff line change
@@ -70,11 +70,14 @@ func SetLogger(logger logr.Logger) {
7070
// routing log entries through klogr into klog and then into the actual Logger
7171
// backend.
7272
func SetLoggerWithOptions(logger logr.Logger, opts ...LoggerOption) {
73-
logging.logger = &logger
7473
logging.loggerOptions = loggerOptions{}
7574
for _, opt := range opts {
7675
opt(&logging.loggerOptions)
7776
}
77+
logging.logger = &logWriter{
78+
Logger: logger,
79+
writeKlogBuffer: logging.loggerOptions.writeKlogBuffer,
80+
}
7881
}
7982

8083
// ContextualLogger determines whether the logger passed to
@@ -93,13 +96,36 @@ func FlushLogger(flush func()) LoggerOption {
9396
}
9497
}
9598

99+
// WriteKlogBuffer sets a callback that will be invoked by klog to write output
100+
// produced by non-structured log calls like Infof.
101+
//
102+
// The buffer will contain exactly the same data that klog normally would write
103+
// into its own output stream(s). In particular this includes the header, if
104+
// klog is configured to write one. The callback then can divert that data into
105+
// its own output streams. The buffer may or may not end in a line break.
106+
//
107+
// Without such a callback, klog will call the logger's Info or Error method
108+
// with just the message string (i.e. no header).
109+
func WriteKlogBuffer(write func([]byte)) LoggerOption {
110+
return func(o *loggerOptions) {
111+
o.writeKlogBuffer = write
112+
}
113+
}
114+
96115
// LoggerOption implements the functional parameter paradigm for
97116
// SetLoggerWithOptions.
98117
type LoggerOption func(o *loggerOptions)
99118

100119
type loggerOptions struct {
101120
contextualLogger bool
102121
flush func()
122+
writeKlogBuffer func([]byte)
123+
}
124+
125+
// logWriter combines a logger (always set) with a write callback (optional).
126+
type logWriter struct {
127+
Logger
128+
writeKlogBuffer func([]byte)
103129
}
104130

105131
// ClearLogger removes a backing Logger implementation if one was set earlier
@@ -152,7 +178,7 @@ func Background() Logger {
152178
if logging.loggerOptions.contextualLogger {
153179
// Is non-nil because logging.loggerOptions.contextualLogger is
154180
// only true if a logger was set.
155-
return *logging.logger
181+
return logging.logger.Logger
156182
}
157183

158184
return klogLogger

klog.go

+54-43
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,6 @@ import (
9191
"sync/atomic"
9292
"time"
9393

94-
"github.com/go-logr/logr"
95-
9694
"k8s.io/klog/v2/internal/buffer"
9795
"k8s.io/klog/v2/internal/clock"
9896
"k8s.io/klog/v2/internal/dbg"
@@ -453,7 +451,7 @@ type settings struct {
453451

454452
// logger is the global Logger chosen by users of klog, nil if
455453
// none is available.
456-
logger *Logger
454+
logger *logWriter
457455

458456
// loggerOptions contains the options that were supplied for
459457
// globalLogger.
@@ -525,6 +523,11 @@ func (s settings) deepCopy() settings {
525523
}
526524
s.vmodule.filter = filter
527525

526+
if s.logger != nil {
527+
logger := *s.logger
528+
s.logger = &logger
529+
}
530+
528531
return s
529532
}
530533

@@ -668,15 +671,16 @@ func (l *loggingT) formatHeader(s severity.Severity, file string, line int) *buf
668671
return buf
669672
}
670673

671-
func (l *loggingT) println(s severity.Severity, logger *logr.Logger, filter LogFilter, args ...interface{}) {
674+
func (l *loggingT) println(s severity.Severity, logger *logWriter, filter LogFilter, args ...interface{}) {
672675
l.printlnDepth(s, logger, filter, 1, args...)
673676
}
674677

675-
func (l *loggingT) printlnDepth(s severity.Severity, logger *logr.Logger, filter LogFilter, depth int, args ...interface{}) {
678+
func (l *loggingT) printlnDepth(s severity.Severity, logger *logWriter, filter LogFilter, depth int, args ...interface{}) {
676679
buf, file, line := l.header(s, depth)
677-
// if logger is set, we clear the generated header as we rely on the backing
678-
// logger implementation to print headers
679-
if logger != nil {
680+
// If a logger is set and doesn't support writing a formatted buffer,
681+
// we clear the generated header as we rely on the backing
682+
// logger implementation to print headers.
683+
if logger != nil && logger.writeKlogBuffer == nil {
680684
buffer.PutBuffer(buf)
681685
buf = buffer.GetBuffer()
682686
}
@@ -687,15 +691,16 @@ func (l *loggingT) printlnDepth(s severity.Severity, logger *logr.Logger, filter
687691
l.output(s, logger, buf, depth, file, line, false)
688692
}
689693

690-
func (l *loggingT) print(s severity.Severity, logger *logr.Logger, filter LogFilter, args ...interface{}) {
694+
func (l *loggingT) print(s severity.Severity, logger *logWriter, filter LogFilter, args ...interface{}) {
691695
l.printDepth(s, logger, filter, 1, args...)
692696
}
693697

694-
func (l *loggingT) printDepth(s severity.Severity, logger *logr.Logger, filter LogFilter, depth int, args ...interface{}) {
698+
func (l *loggingT) printDepth(s severity.Severity, logger *logWriter, filter LogFilter, depth int, args ...interface{}) {
695699
buf, file, line := l.header(s, depth)
696-
// if logr is set, we clear the generated header as we rely on the backing
697-
// logr implementation to print headers
698-
if logger != nil {
700+
// If a logger is set and doesn't support writing a formatted buffer,
701+
// we clear the generated header as we rely on the backing
702+
// logger implementation to print headers.
703+
if logger != nil && logger.writeKlogBuffer == nil {
699704
buffer.PutBuffer(buf)
700705
buf = buffer.GetBuffer()
701706
}
@@ -709,15 +714,16 @@ func (l *loggingT) printDepth(s severity.Severity, logger *logr.Logger, filter L
709714
l.output(s, logger, buf, depth, file, line, false)
710715
}
711716

712-
func (l *loggingT) printf(s severity.Severity, logger *logr.Logger, filter LogFilter, format string, args ...interface{}) {
717+
func (l *loggingT) printf(s severity.Severity, logger *logWriter, filter LogFilter, format string, args ...interface{}) {
713718
l.printfDepth(s, logger, filter, 1, format, args...)
714719
}
715720

716-
func (l *loggingT) printfDepth(s severity.Severity, logger *logr.Logger, filter LogFilter, depth int, format string, args ...interface{}) {
721+
func (l *loggingT) printfDepth(s severity.Severity, logger *logWriter, filter LogFilter, depth int, format string, args ...interface{}) {
717722
buf, file, line := l.header(s, depth)
718-
// if logr is set, we clear the generated header as we rely on the backing
719-
// logr implementation to print headers
720-
if logger != nil {
723+
// If a logger is set and doesn't support writing a formatted buffer,
724+
// we clear the generated header as we rely on the backing
725+
// logger implementation to print headers.
726+
if logger != nil && logger.writeKlogBuffer == nil {
721727
buffer.PutBuffer(buf)
722728
buf = buffer.GetBuffer()
723729
}
@@ -734,11 +740,12 @@ func (l *loggingT) printfDepth(s severity.Severity, logger *logr.Logger, filter
734740
// printWithFileLine behaves like print but uses the provided file and line number. If
735741
// alsoLogToStderr is true, the log message always appears on standard error; it
736742
// will also appear in the log file unless --logtostderr is set.
737-
func (l *loggingT) printWithFileLine(s severity.Severity, logger *logr.Logger, filter LogFilter, file string, line int, alsoToStderr bool, args ...interface{}) {
743+
func (l *loggingT) printWithFileLine(s severity.Severity, logger *logWriter, filter LogFilter, file string, line int, alsoToStderr bool, args ...interface{}) {
738744
buf := l.formatHeader(s, file, line)
739-
// if logr is set, we clear the generated header as we rely on the backing
740-
// logr implementation to print headers
741-
if logger != nil {
745+
// If a logger is set and doesn't support writing a formatted buffer,
746+
// we clear the generated header as we rely on the backing
747+
// logger implementation to print headers.
748+
if logger != nil && logger.writeKlogBuffer == nil {
742749
buffer.PutBuffer(buf)
743750
buf = buffer.GetBuffer()
744751
}
@@ -753,7 +760,7 @@ func (l *loggingT) printWithFileLine(s severity.Severity, logger *logr.Logger, f
753760
}
754761

755762
// if loggr is specified, will call loggr.Error, otherwise output with logging module.
756-
func (l *loggingT) errorS(err error, logger *logr.Logger, filter LogFilter, depth int, msg string, keysAndValues ...interface{}) {
763+
func (l *loggingT) errorS(err error, logger *logWriter, filter LogFilter, depth int, msg string, keysAndValues ...interface{}) {
757764
if filter != nil {
758765
msg, keysAndValues = filter.FilterS(msg, keysAndValues)
759766
}
@@ -765,7 +772,7 @@ func (l *loggingT) errorS(err error, logger *logr.Logger, filter LogFilter, dept
765772
}
766773

767774
// if loggr is specified, will call loggr.Info, otherwise output with logging module.
768-
func (l *loggingT) infoS(logger *logr.Logger, filter LogFilter, depth int, msg string, keysAndValues ...interface{}) {
775+
func (l *loggingT) infoS(logger *logWriter, filter LogFilter, depth int, msg string, keysAndValues ...interface{}) {
769776
if filter != nil {
770777
msg, keysAndValues = filter.FilterS(msg, keysAndValues)
771778
}
@@ -846,7 +853,7 @@ func LogToStderr(stderr bool) {
846853
}
847854

848855
// output writes the data to the log files and releases the buffer.
849-
func (l *loggingT) output(s severity.Severity, log *logr.Logger, buf *buffer.Buffer, depth int, file string, line int, alsoToStderr bool) {
856+
func (l *loggingT) output(s severity.Severity, logger *logWriter, buf *buffer.Buffer, depth int, file string, line int, alsoToStderr bool) {
850857
var isLocked = true
851858
l.mu.Lock()
852859
defer func() {
@@ -862,13 +869,17 @@ func (l *loggingT) output(s severity.Severity, log *logr.Logger, buf *buffer.Buf
862869
}
863870
}
864871
data := buf.Bytes()
865-
if log != nil {
866-
// TODO: set 'severity' and caller information as structured log info
867-
// keysAndValues := []interface{}{"severity", severityName[s], "file", file, "line", line}
868-
if s == severity.ErrorLog {
869-
logging.logger.WithCallDepth(depth+3).Error(nil, string(data))
872+
if logger != nil {
873+
if logger.writeKlogBuffer != nil {
874+
logger.writeKlogBuffer(data)
870875
} else {
871-
log.WithCallDepth(depth + 3).Info(string(data))
876+
// TODO: set 'severity' and caller information as structured log info
877+
// keysAndValues := []interface{}{"severity", severityName[s], "file", file, "line", line}
878+
if s == severity.ErrorLog {
879+
logger.WithCallDepth(depth+3).Error(nil, string(data))
880+
} else {
881+
logger.WithCallDepth(depth + 3).Info(string(data))
882+
}
872883
}
873884
} else if l.toStderr {
874885
os.Stderr.Write(data)
@@ -1277,15 +1288,15 @@ func (l *loggingT) setV(pc uintptr) Level {
12771288
// See the documentation of V for more information.
12781289
type Verbose struct {
12791290
enabled bool
1280-
logr *logr.Logger
1291+
logger *logWriter
12811292
}
12821293

12831294
func newVerbose(level Level, b bool) Verbose {
12841295
if logging.logger == nil {
12851296
return Verbose{b, nil}
12861297
}
12871298
v := logging.logger.V(int(level))
1288-
return Verbose{b, &v}
1299+
return Verbose{b, &logWriter{Logger: v, writeKlogBuffer: logging.loggerOptions.writeKlogBuffer}}
12891300
}
12901301

12911302
// V reports whether verbosity at the call site is at least the requested level.
@@ -1359,55 +1370,55 @@ func (v Verbose) Enabled() bool {
13591370
// See the documentation of V for usage.
13601371
func (v Verbose) Info(args ...interface{}) {
13611372
if v.enabled {
1362-
logging.print(severity.InfoLog, v.logr, logging.filter, args...)
1373+
logging.print(severity.InfoLog, v.logger, logging.filter, args...)
13631374
}
13641375
}
13651376

13661377
// InfoDepth is equivalent to the global InfoDepth function, guarded by the value of v.
13671378
// See the documentation of V for usage.
13681379
func (v Verbose) InfoDepth(depth int, args ...interface{}) {
13691380
if v.enabled {
1370-
logging.printDepth(severity.InfoLog, v.logr, logging.filter, depth, args...)
1381+
logging.printDepth(severity.InfoLog, v.logger, logging.filter, depth, args...)
13711382
}
13721383
}
13731384

13741385
// Infoln is equivalent to the global Infoln function, guarded by the value of v.
13751386
// See the documentation of V for usage.
13761387
func (v Verbose) Infoln(args ...interface{}) {
13771388
if v.enabled {
1378-
logging.println(severity.InfoLog, v.logr, logging.filter, args...)
1389+
logging.println(severity.InfoLog, v.logger, logging.filter, args...)
13791390
}
13801391
}
13811392

13821393
// InfolnDepth is equivalent to the global InfolnDepth function, guarded by the value of v.
13831394
// See the documentation of V for usage.
13841395
func (v Verbose) InfolnDepth(depth int, args ...interface{}) {
13851396
if v.enabled {
1386-
logging.printlnDepth(severity.InfoLog, v.logr, logging.filter, depth, args...)
1397+
logging.printlnDepth(severity.InfoLog, v.logger, logging.filter, depth, args...)
13871398
}
13881399
}
13891400

13901401
// Infof is equivalent to the global Infof function, guarded by the value of v.
13911402
// See the documentation of V for usage.
13921403
func (v Verbose) Infof(format string, args ...interface{}) {
13931404
if v.enabled {
1394-
logging.printf(severity.InfoLog, v.logr, logging.filter, format, args...)
1405+
logging.printf(severity.InfoLog, v.logger, logging.filter, format, args...)
13951406
}
13961407
}
13971408

13981409
// InfofDepth is equivalent to the global InfofDepth function, guarded by the value of v.
13991410
// See the documentation of V for usage.
14001411
func (v Verbose) InfofDepth(depth int, format string, args ...interface{}) {
14011412
if v.enabled {
1402-
logging.printfDepth(severity.InfoLog, v.logr, logging.filter, depth, format, args...)
1413+
logging.printfDepth(severity.InfoLog, v.logger, logging.filter, depth, format, args...)
14031414
}
14041415
}
14051416

14061417
// InfoS is equivalent to the global InfoS function, guarded by the value of v.
14071418
// See the documentation of V for usage.
14081419
func (v Verbose) InfoS(msg string, keysAndValues ...interface{}) {
14091420
if v.enabled {
1410-
logging.infoS(v.logr, logging.filter, 0, msg, keysAndValues...)
1421+
logging.infoS(v.logger, logging.filter, 0, msg, keysAndValues...)
14111422
}
14121423
}
14131424

@@ -1421,22 +1432,22 @@ func InfoSDepth(depth int, msg string, keysAndValues ...interface{}) {
14211432
// See the documentation of V for usage.
14221433
func (v Verbose) InfoSDepth(depth int, msg string, keysAndValues ...interface{}) {
14231434
if v.enabled {
1424-
logging.infoS(v.logr, logging.filter, depth, msg, keysAndValues...)
1435+
logging.infoS(v.logger, logging.filter, depth, msg, keysAndValues...)
14251436
}
14261437
}
14271438

14281439
// Deprecated: Use ErrorS instead.
14291440
func (v Verbose) Error(err error, msg string, args ...interface{}) {
14301441
if v.enabled {
1431-
logging.errorS(err, v.logr, logging.filter, 0, msg, args...)
1442+
logging.errorS(err, v.logger, logging.filter, 0, msg, args...)
14321443
}
14331444
}
14341445

14351446
// ErrorS is equivalent to the global Error function, guarded by the value of v.
14361447
// See the documentation of V for usage.
14371448
func (v Verbose) ErrorS(err error, msg string, keysAndValues ...interface{}) {
14381449
if v.enabled {
1439-
logging.errorS(err, v.logr, logging.filter, 0, msg, keysAndValues...)
1450+
logging.errorS(err, v.logger, logging.filter, 0, msg, keysAndValues...)
14401451
}
14411452
}
14421453

klog_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -2196,7 +2196,7 @@ func TestSettingsDeepCopy(t *testing.T) {
21962196
logger := logr.Discard()
21972197

21982198
settings := settings{
2199-
logger: &logger,
2199+
logger: &logWriter{Logger: logger},
22002200
vmodule: moduleSpec{
22012201
filter: []modulePat{
22022202
{pattern: "a"},

0 commit comments

Comments
 (0)