序
本文主要研究一下klog的LogFilter
LogFilterk8s.io/klog/[email protected]/klog.go
// LogFilter is a collection of functions that can filter all logging calls,// e.g. for sanitization of arguments and prevent accidental leaking of secrets.type LogFilter interface { Filter(args []interface{}) []interface{} FilterF(format string, args []interface{}) (string, []interface{}) FilterS(msg string, keysAndValues []interface{}) (string, []interface{})}func SetLogFilter(filter LogFilter) { logging.mu.Lock() defer logging.mu.Unlock() logging.filter = filter}
LogFilter介面定義了Filter、FilterF、FilterS方法用於過濾log
filter.Filterk8s.io/klog/[email protected]/klog.go
func (l *loggingT) println(s severity, logr logr.Logger, filter LogFilter, args ...interface{}) { buf, file, line := l.header(s, 0) // if logr is set, we clear the generated header as we rely on the backing // logr implementation to print headers if logr != nil { l.putBuffer(buf) buf = l.getBuffer() } if filter != nil { args = filter.Filter(args) } fmt.Fprintln(buf, args...) l.output(s, logr, buf, file, line, false)}func (l *loggingT) printDepth(s severity, logr logr.Logger, filter LogFilter, depth int, args ...interface{}) { buf, file, line := l.header(s, depth) // if logr is set, we clear the generated header as we rely on the backing // logr implementation to print headers if logr != nil { l.putBuffer(buf) buf = l.getBuffer() } if filter != nil { args = filter.Filter(args) } fmt.Fprint(buf, args...) if buf.Bytes()[buf.Len()-1] != '\n' { buf.WriteByte('\n') } l.output(s, logr, buf, file, line, false)}func (l *loggingT) printWithFileLine(s severity, logr logr.Logger, filter LogFilter, file string, line int, alsoToStderr bool, args ...interface{}) { buf := l.formatHeader(s, file, line) // if logr is set, we clear the generated header as we rely on the backing // logr implementation to print headers if logr != nil { l.putBuffer(buf) buf = l.getBuffer() } if filter != nil { args = filter.Filter(args) } fmt.Fprint(buf, args...) if buf.Bytes()[buf.Len()-1] != '\n' { buf.WriteByte('\n') } l.output(s, logr, buf, file, line, alsoToStderr)}
println、printDepth、printWithFileLine會透過filter.Filter(args)來過濾args
filter.FilterFk8s.io/klog/[email protected]/klog.go
func (l *loggingT) printf(s severity, logr logr.Logger, filter LogFilter, format string, args ...interface{}) { buf, file, line := l.header(s, 0) // if logr is set, we clear the generated header as we rely on the backing // logr implementation to print headers if logr != nil { l.putBuffer(buf) buf = l.getBuffer() } if filter != nil { format, args = filter.FilterF(format, args) } fmt.Fprintf(buf, format, args...) if buf.Bytes()[buf.Len()-1] != '\n' { buf.WriteByte('\n') } l.output(s, logr, buf, file, line, false)}
printf方法使用filter.FilterF(format, args)返回的format及args進行格式化
filter.FilterSk8s.io/klog/[email protected]/klog.go
func (l *loggingT) infoS(loggr logr.Logger, filter LogFilter, msg string, keysAndValues ...interface{}) { if filter != nil { msg, keysAndValues = filter.FilterS(msg, keysAndValues) } if loggr != nil { loggr.Info(msg, keysAndValues...) return } l.printS(nil, msg, keysAndValues...)}func (l *loggingT) errorS(err error, loggr logr.Logger, filter LogFilter, msg string, keysAndValues ...interface{}) { if filter != nil { msg, keysAndValues = filter.FilterS(msg, keysAndValues) } if loggr != nil { loggr.Error(err, msg, keysAndValues...) return } l.printS(err, msg, keysAndValues...)}
infoS及errorS方法會使用filter.FilterS(msg, keysAndValues)返回的msg及keysAndValues進行列印
例項type sampleLogFilter struct{}func (f *sampleLogFilter) Filter(args []interface{}) []interface{} { for i, arg := range args { v, ok := arg.(string) if ok && strings.Contains(v, "filter me") { args[i] = "[FILTERED]" } } return args}func (f *sampleLogFilter) FilterF(format string, args []interface{}) (string, []interface{}) { return strings.Replace(format, "filter me", "[FILTERED]", 1), f.Filter(args)}func (f *sampleLogFilter) FilterS(msg string, keysAndValues []interface{}) (string, []interface{}) { return strings.Replace(msg, "filter me", "[FILTERED]", 1), f.Filter(keysAndValues)}func TestLogFilter(t *testing.T) { setFlags() defer logging.swap(logging.newBuffers()) SetLogFilter(&sampleLogFilter{}) defer SetLogFilter(nil) funcs := []struct { name string logFunc func(args ...interface{}) severity severity }{{ name: "Info", logFunc: Info, severity: infoLog, }, { name: "InfoDepth", logFunc: func(args ...interface{}) { InfoDepth(1, args...) }, severity: infoLog, }, { name: "Infoln", logFunc: Infoln, severity: infoLog, }, { name: "Infof", logFunc: func(args ...interface{}) { Infof(args[0].(string), args[1:]...) }, severity: infoLog, }, { name: "InfoS", logFunc: func(args ...interface{}) { InfoS(args[0].(string), args[1:]...) }, severity: infoLog, }, { name: "Warning", logFunc: Warning, severity: warningLog, }, { name: "WarningDepth", logFunc: func(args ...interface{}) { WarningDepth(1, args...) }, severity: warningLog, }, { name: "Warningln", logFunc: Warningln, severity: warningLog, }, { name: "Warningf", logFunc: func(args ...interface{}) { Warningf(args[0].(string), args[1:]...) }, severity: warningLog, }, { name: "Error", logFunc: Error, severity: errorLog, }, { name: "ErrorDepth", logFunc: func(args ...interface{}) { ErrorDepth(1, args...) }, severity: errorLog, }, { name: "Errorln", logFunc: Errorln, severity: errorLog, }, { name: "Errorf", logFunc: func(args ...interface{}) { Errorf(args[0].(string), args[1:]...) }, severity: errorLog, }, { name: "ErrorS", logFunc: func(args ...interface{}) { ErrorS(errors.New("testerror"), args[0].(string), args[1:]...) }, severity: errorLog, }, { name: "V().Info", logFunc: func(args ...interface{}) { V(0).Info(args...) }, severity: infoLog, }, { name: "V().Infoln", logFunc: func(args ...interface{}) { V(0).Infoln(args...) }, severity: infoLog, }, { name: "V().Infof", logFunc: func(args ...interface{}) { V(0).Infof(args[0].(string), args[1:]...) }, severity: infoLog, }, { name: "V().InfoS", logFunc: func(args ...interface{}) { V(0).InfoS(args[0].(string), args[1:]...) }, severity: infoLog, }, { name: "V().Error", logFunc: func(args ...interface{}) { V(0).Error(errors.New("test error"), args[0].(string), args[1:]...) }, severity: errorLog, }, { name: "V().ErrorS", logFunc: func(args ...interface{}) { V(0).ErrorS(errors.New("test error"), args[0].(string), args[1:]...) }, severity: errorLog, }} testcases := []struct { name string args []interface{} expectFiltered bool }{{ args: []interface{}{"%s:%s", "foo", "bar"}, expectFiltered: false, }, { args: []interface{}{"%s:%s", "foo", "filter me"}, expectFiltered: true, }, { args: []interface{}{"filter me %s:%s", "foo", "bar"}, expectFiltered: true, }} for _, f := range funcs { for _, tc := range testcases { logging.newBuffers() f.logFunc(tc.args...) got := contains(f.severity, "[FILTERED]", t) if got != tc.expectFiltered { t.Errorf("%s filter application failed, got %v, want %v", f.name, got, tc.expectFiltered) } } }}
小結klog的LogFilter介面定義了Filter、FilterF、FilterS方法用於過濾log;println、printDepth、printWithFileLine會透過filter.Filter(args)來過濾args;printf方法使用filter.FilterF(format, args)返回的format及args進行格式化;infoS及errorS方法會使用filter.FilterS(msg, keysAndValues)返回的msg及keysAndValues進行列印。
docklog
最新評論