github.com/minio/console@v1.4.1/pkg/logger/console.go (about) 1 // This file is part of MinIO Console Server 2 // Copyright (c) 2022 MinIO, Inc. 3 // 4 // This program is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Affero General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // This program is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Affero General Public License for more details. 13 // 14 // You should have received a copy of the GNU Affero General Public License 15 // along with this program. If not, see <http://www.gnu.org/licenses/>. 16 17 package logger 18 19 import ( 20 "encoding/json" 21 "fmt" 22 "os" 23 "strings" 24 "time" 25 26 "github.com/minio/console/pkg/logger/color" 27 "github.com/minio/console/pkg/logger/message/log" 28 c "github.com/minio/pkg/v3/console" 29 ) 30 31 // Logger interface describes the methods that need to be implemented to satisfy the interface requirements. 32 type Logger interface { 33 json(msg string, args ...interface{}) 34 quiet(msg string, args ...interface{}) 35 pretty(msg string, args ...interface{}) 36 } 37 38 func consoleLog(console Logger, msg string, args ...interface{}) { 39 switch { 40 case jsonFlag: 41 // Strip escape control characters from json message 42 msg = ansiRE.ReplaceAllLiteralString(msg, "") 43 console.json(msg, args...) 44 case quietFlag: 45 console.quiet(msg+"\n", args...) 46 default: 47 console.pretty(msg+"\n", args...) 48 } 49 } 50 51 // Fatal prints only fatal errors message with no stack trace 52 // it will be called for input validation failures 53 func Fatal(err error, msg string, data ...interface{}) { 54 fatal(err, msg, data...) 55 } 56 57 func fatal(err error, msg string, data ...interface{}) { 58 var errMsg string 59 if msg != "" { 60 errMsg = errorFmtFunc(fmt.Sprintf(msg, data...), err, jsonFlag) 61 } else { 62 errMsg = err.Error() 63 } 64 consoleLog(fatalMessage, errMsg) 65 } 66 67 var fatalMessage fatalMsg 68 69 type fatalMsg struct{} 70 71 func (f fatalMsg) json(msg string, args ...interface{}) { 72 var message string 73 if msg != "" { 74 message = fmt.Sprintf(msg, args...) 75 } else { 76 message = fmt.Sprint(args...) 77 } 78 logJSON, err := json.Marshal(&log.Entry{ 79 Level: FatalLvl.String(), 80 Message: message, 81 Time: time.Now().UTC(), 82 Trace: &log.Trace{Message: message, Source: []string{getSource(6)}}, 83 }) 84 if err != nil { 85 panic(err) 86 } 87 fmt.Println(string(logJSON)) 88 89 os.Exit(1) 90 } 91 92 func (f fatalMsg) quiet(msg string, args ...interface{}) { 93 f.pretty(msg, args...) 94 } 95 96 var ( 97 logTag = "ERROR" 98 logBanner = color.BgRed(color.FgWhite(color.Bold(logTag))) + " " 99 emptyBanner = color.BgRed(strings.Repeat(" ", len(logTag))) + " " 100 bannerWidth = len(logTag) + 1 101 ) 102 103 func (f fatalMsg) pretty(msg string, args ...interface{}) { 104 // Build the passed errors message 105 errMsg := fmt.Sprintf(msg, args...) 106 107 tagPrinted := false 108 109 // Print the errors message: the following code takes care 110 // of splitting errors text and always pretty printing the 111 // red banner along with the errors message. Since the errors 112 // message itself contains some colored text, we needed 113 // to use some ANSI control escapes to cursor color state 114 // and freely move in the screen. 115 for _, line := range strings.Split(errMsg, "\n") { 116 if len(line) == 0 { 117 // No more text to print, just quit. 118 break 119 } 120 121 for { 122 // Save the attributes of the current cursor helps 123 // us save the text color of the passed errors message 124 ansiSaveAttributes() 125 // Print banner with or without the log tag 126 if !tagPrinted { 127 c.Print(logBanner) 128 tagPrinted = true 129 } else { 130 c.Print(emptyBanner) 131 } 132 // Restore the text color of the errors message 133 ansiRestoreAttributes() 134 ansiMoveRight(bannerWidth) 135 // Continue errors message printing 136 c.Println(line) 137 break 138 } 139 } 140 141 // Exit because this is a fatal errors message 142 os.Exit(1) 143 } 144 145 type infoMsg struct{} 146 147 var info infoMsg 148 149 func (i infoMsg) json(msg string, args ...interface{}) { 150 var message string 151 if msg != "" { 152 message = fmt.Sprintf(msg, args...) 153 } else { 154 message = fmt.Sprint(args...) 155 } 156 logJSON, err := json.Marshal(&log.Entry{ 157 Level: InformationLvl.String(), 158 Message: message, 159 Time: time.Now().UTC(), 160 }) 161 if err != nil { 162 panic(err) 163 } 164 fmt.Println(string(logJSON)) 165 } 166 167 func (i infoMsg) quiet(_ string, _ ...interface{}) { 168 } 169 170 func (i infoMsg) pretty(msg string, args ...interface{}) { 171 if msg == "" { 172 c.Println(args...) 173 } 174 c.Printf(msg, args...) 175 } 176 177 type errorMsg struct{} 178 179 var errorm errorMsg 180 181 func (i errorMsg) json(msg string, args ...interface{}) { 182 var message string 183 if msg != "" { 184 message = fmt.Sprintf(msg, args...) 185 } else { 186 message = fmt.Sprint(args...) 187 } 188 logJSON, err := json.Marshal(&log.Entry{ 189 Level: ErrorLvl.String(), 190 Message: message, 191 Time: time.Now().UTC(), 192 Trace: &log.Trace{Message: message, Source: []string{getSource(6)}}, 193 }) 194 if err != nil { 195 panic(err) 196 } 197 fmt.Println(string(logJSON)) 198 } 199 200 func (i errorMsg) quiet(msg string, args ...interface{}) { 201 i.pretty(msg, args...) 202 } 203 204 func (i errorMsg) pretty(msg string, args ...interface{}) { 205 if msg == "" { 206 c.Println(args...) 207 } 208 c.Printf(msg, args...) 209 c.Printf("\n") 210 } 211 212 // Error : 213 func Error(msg string, data ...interface{}) { 214 consoleLog(errorm, msg, data...) 215 } 216 217 // Info : 218 func Info(msg string, data ...interface{}) { 219 consoleLog(info, msg, data...) 220 }