1/* 2Copyright 2020 The Kubernetes Authors. 3 4Licensed under the Apache License, Version 2.0 (the "License"); 5you may not use this file except in compliance with the License. 6You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10Unless required by applicable law or agreed to in writing, software 11distributed under the License is distributed on an "AS IS" BASIS, 12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13See the License for the specific language governing permissions and 14limitations under the License. 15*/ 16 17package logs 18 19import ( 20 "flag" 21 "fmt" 22 "strings" 23 24 "github.com/go-logr/logr" 25 "github.com/spf13/pflag" 26 27 "k8s.io/component-base/logs/sanitization" 28 "k8s.io/klog/v2" 29) 30 31const ( 32 logFormatFlagName = "logging-format" 33 defaultLogFormat = "text" 34) 35 36// List of logs (k8s.io/klog + k8s.io/component-base/logs) flags supported by all logging formats 37var supportedLogsFlags = map[string]struct{}{ 38 "v": {}, 39 // TODO: support vmodule after 1.19 Alpha 40} 41 42// Options has klog format parameters 43type Options struct { 44 LogFormat string 45 LogSanitization bool 46} 47 48// NewOptions return new klog options 49func NewOptions() *Options { 50 return &Options{ 51 LogFormat: defaultLogFormat, 52 } 53} 54 55// Validate verifies if any unsupported flag is set 56// for non-default logging format 57func (o *Options) Validate() []error { 58 errs := []error{} 59 if o.LogFormat != defaultLogFormat { 60 allFlags := unsupportedLoggingFlags() 61 for _, fname := range allFlags { 62 if flagIsSet(fname) { 63 errs = append(errs, fmt.Errorf("non-default logging format doesn't honor flag: %s", fname)) 64 } 65 } 66 } 67 if _, err := o.Get(); err != nil { 68 errs = append(errs, fmt.Errorf("unsupported log format: %s", o.LogFormat)) 69 } 70 return errs 71} 72 73func flagIsSet(name string) bool { 74 f := flag.Lookup(name) 75 if f != nil { 76 return f.DefValue != f.Value.String() 77 } 78 pf := pflag.Lookup(name) 79 if pf != nil { 80 return pf.DefValue != pf.Value.String() 81 } 82 panic("failed to lookup unsupported log flag") 83} 84 85// AddFlags add logging-format flag 86func (o *Options) AddFlags(fs *pflag.FlagSet) { 87 unsupportedFlags := fmt.Sprintf("--%s", strings.Join(unsupportedLoggingFlags(), ", --")) 88 formats := fmt.Sprintf(`"%s"`, strings.Join(logRegistry.List(), `", "`)) 89 fs.StringVar(&o.LogFormat, logFormatFlagName, defaultLogFormat, fmt.Sprintf("Sets the log format. Permitted formats: %s.\nNon-default formats don't honor these flags: %s.\nNon-default choices are currently alpha and subject to change without warning.", formats, unsupportedFlags)) 90 91 // No new log formats should be added after generation is of flag options 92 logRegistry.Freeze() 93 fs.BoolVar(&o.LogSanitization, "experimental-logging-sanitization", o.LogSanitization, `[Experimental] When enabled prevents logging of fields tagged as sensitive (passwords, keys, tokens). 94Runtime log sanitization may introduce significant computation overhead and therefore should not be enabled in production.`) 95} 96 97// Apply set klog logger from LogFormat type 98func (o *Options) Apply() { 99 // if log format not exists, use nil loggr 100 loggr, _ := o.Get() 101 klog.SetLogger(loggr) 102 if o.LogSanitization { 103 klog.SetLogFilter(&sanitization.SanitizingFilter{}) 104 } 105} 106 107// Get logger with LogFormat field 108func (o *Options) Get() (logr.Logger, error) { 109 return logRegistry.Get(o.LogFormat) 110} 111 112func unsupportedLoggingFlags() []string { 113 allFlags := []string{} 114 115 // k8s.io/klog flags 116 fs := &flag.FlagSet{} 117 klog.InitFlags(fs) 118 fs.VisitAll(func(flag *flag.Flag) { 119 if _, found := supportedLogsFlags[flag.Name]; !found { 120 allFlags = append(allFlags, flag.Name) 121 } 122 }) 123 124 // k8s.io/component-base/logs flags 125 pfs := &pflag.FlagSet{} 126 AddFlags(pfs) 127 pfs.VisitAll(func(flag *pflag.Flag) { 128 if _, found := supportedLogsFlags[flag.Name]; !found { 129 allFlags = append(allFlags, flag.Name) 130 } 131 }) 132 return allFlags 133} 134