github.hscsec.cn/openshift/source-to-image@v1.2.0/pkg/util/log/log.go (about) 1 package log 2 3 import ( 4 "bufio" 5 "fmt" 6 "io" 7 "os" 8 "strings" 9 "sync" 10 11 "k8s.io/klog" 12 ) 13 14 // Logger is a simple interface that is roughly equivalent to klog. 15 type Logger interface { 16 Is(level int32) bool 17 V(level int32) VerboseLogger 18 Infof(format string, args ...interface{}) 19 Info(args ...interface{}) 20 Warningf(format string, args ...interface{}) 21 Warning(args ...interface{}) 22 Errorf(format string, args ...interface{}) 23 Error(args ...interface{}) 24 Fatalf(format string, args ...interface{}) 25 Fatal(args ...interface{}) 26 } 27 28 // VerboseLogger is roughly equivalent to klog's Verbose. 29 type VerboseLogger interface { 30 Infof(format string, args ...interface{}) 31 Info(args ...interface{}) 32 } 33 34 // ToFile creates a logger that will log any items at level or below to file, and defer 35 // any other output to klog (no matter what the level is). 36 func ToFile(x io.Writer, level int32) Logger { 37 return &FileLogger{ 38 &sync.Mutex{}, 39 bufio.NewWriter(x), 40 level, 41 } 42 } 43 44 var ( 45 // None implements the Logger interface but does nothing with the log output. 46 None Logger = discard{} 47 // StderrLog implements the Logger interface for stderr. 48 StderrLog = ToFile(os.Stderr, 2) 49 ) 50 51 // discard is a Logger that outputs nothing. 52 type discard struct{} 53 54 // Is returns whether the current logging level is greater than or equal to the parameter. 55 func (discard) Is(level int32) bool { 56 return false 57 } 58 59 // V will returns a logger which will discard output if the specified level is greater than the current logging level. 60 func (discarding discard) V(level int32) VerboseLogger { 61 return discarding 62 } 63 64 // Infof records an info log entry. 65 func (discard) Infof(string, ...interface{}) { 66 } 67 68 // Info records an info log entry. 69 func (discard) Info(...interface{}) { 70 } 71 72 // Errorf records an error log entry. 73 func (discard) Errorf(string, ...interface{}) { 74 } 75 76 // Error records an error log entry. 77 func (discard) Error(...interface{}) { 78 } 79 80 // Warningf records an warning log entry. 81 func (discard) Warningf(string, ...interface{}) { 82 } 83 84 // Warning records an warning log entry. 85 func (discard) Warning(...interface{}) { 86 } 87 88 // Fatalf records a fatal log entry. 89 func (discard) Fatalf(string, ...interface{}) { 90 } 91 92 // Fatal records a fatal log entry. 93 func (discard) Fatal(...interface{}) { 94 } 95 96 // FileLogger logs the provided messages at level or below to the writer, or delegates 97 // to klog. 98 type FileLogger struct { 99 mutex *sync.Mutex 100 w *bufio.Writer 101 level int32 102 } 103 104 // Is returns whether the current logging level is greater than or equal to the parameter. 105 func (f *FileLogger) Is(level int32) bool { 106 return level <= f.level 107 } 108 109 // V will returns a logger which will discard output if the specified level is greater than the current logging level. 110 func (f *FileLogger) V(level int32) VerboseLogger { 111 // Is the loglevel set verbose enough to accept the forthcoming log statement 112 if klog.V(klog.Level(level)) { 113 return f 114 } 115 // Otherwise discard 116 return None 117 } 118 119 type severity int32 120 121 const ( 122 infoLog severity = iota 123 warningLog 124 errorLog 125 fatalLog 126 ) 127 128 // Elevated logger methods output a detailed prefix for each logging statement. 129 // At present, we delegate to klog to accomplish this. 130 type elevated func(int, ...interface{}) 131 132 type severityDetail struct { 133 prefix string 134 delegateFn elevated 135 } 136 137 var severities = []severityDetail{ 138 infoLog: {"", klog.InfoDepth}, 139 warningLog: {"WARNING: ", klog.WarningDepth}, 140 errorLog: {"ERROR: ", klog.ErrorDepth}, 141 fatalLog: {"FATAL: ", klog.FatalDepth}, 142 } 143 144 func (f *FileLogger) writeln(sev severity, line string) { 145 severity := severities[sev] 146 147 // If the loglevel has been elevated above this file logger's verbosity (generally set to 2) 148 // then delegate ALL messages to elevated logger in order to leverage its file/line/timestamp 149 // prefix information. 150 if klog.V(klog.Level(f.level + 1)) { 151 severity.delegateFn(3, line) 152 } else { 153 // buf.io is not threadsafe, so serialize access to the stream 154 f.mutex.Lock() 155 defer f.mutex.Unlock() 156 f.w.WriteString(severity.prefix) 157 f.w.WriteString(line) 158 if !strings.HasSuffix(line, "\n") { 159 f.w.WriteByte('\n') 160 } 161 f.w.Flush() 162 } 163 } 164 165 func (f *FileLogger) outputf(sev severity, format string, args ...interface{}) { 166 f.writeln(sev, fmt.Sprintf(format, args...)) 167 } 168 169 func (f *FileLogger) output(sev severity, args ...interface{}) { 170 f.writeln(sev, fmt.Sprint(args...)) 171 } 172 173 // Infof records an info log entry. 174 func (f *FileLogger) Infof(format string, args ...interface{}) { 175 f.outputf(infoLog, format, args...) 176 } 177 178 // Info records an info log entry. 179 func (f *FileLogger) Info(args ...interface{}) { 180 f.output(infoLog, args...) 181 } 182 183 // Warningf records an warning log entry. 184 func (f *FileLogger) Warningf(format string, args ...interface{}) { 185 f.outputf(warningLog, format, args...) 186 } 187 188 // Warning records an warning log entry. 189 func (f *FileLogger) Warning(args ...interface{}) { 190 f.output(warningLog, args...) 191 } 192 193 // Errorf records an error log entry. 194 func (f *FileLogger) Errorf(format string, args ...interface{}) { 195 f.outputf(errorLog, format, args...) 196 } 197 198 // Error records an error log entry. 199 func (f *FileLogger) Error(args ...interface{}) { 200 f.output(errorLog, args...) 201 } 202 203 // Fatalf records a fatal log entry and terminates the program. 204 func (f *FileLogger) Fatalf(format string, args ...interface{}) { 205 defer os.Exit(1) 206 f.outputf(fatalLog, format, args...) 207 } 208 209 // Fatal records a fatal log entry and terminates the program. 210 func (f *FileLogger) Fatal(args ...interface{}) { 211 defer os.Exit(1) 212 f.output(fatalLog, args...) 213 }