github.com/Laisky/zap@v1.27.0/zapgrpc/zapgrpc.go (about) 1 // Copyright (c) 2016 Uber Technologies, Inc. 2 // 3 // Permission is hereby granted, free of charge, to any person obtaining a copy 4 // of this software and associated documentation files (the "Software"), to deal 5 // in the Software without restriction, including without limitation the rights 6 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 // copies of the Software, and to permit persons to whom the Software is 8 // furnished to do so, subject to the following conditions: 9 // 10 // The above copyright notice and this permission notice shall be included in 11 // all copies or substantial portions of the Software. 12 // 13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 // THE SOFTWARE. 20 21 // Package zapgrpc provides a logger that is compatible with grpclog. 22 package zapgrpc // import "github.com/Laisky/zap/zapgrpc" 23 24 import ( 25 "fmt" 26 27 "github.com/Laisky/zap" 28 "github.com/Laisky/zap/zapcore" 29 ) 30 31 // See https://github.com/grpc/grpc-go/blob/v1.35.0/grpclog/loggerv2.go#L77-L86 32 const ( 33 grpcLvlInfo int = iota 34 grpcLvlWarn 35 grpcLvlError 36 grpcLvlFatal 37 ) 38 39 // _grpcToZapLevel maps gRPC log levels to zap log levels. 40 // See https://pkg.go.dev/github.com/Laisky/zap@v1.16.0/zapcore#Level 41 var _grpcToZapLevel = map[int]zapcore.Level{ 42 grpcLvlInfo: zapcore.InfoLevel, 43 grpcLvlWarn: zapcore.WarnLevel, 44 grpcLvlError: zapcore.ErrorLevel, 45 grpcLvlFatal: zapcore.FatalLevel, 46 } 47 48 // An Option overrides a Logger's default configuration. 49 type Option interface { 50 apply(*Logger) 51 } 52 53 type optionFunc func(*Logger) 54 55 func (f optionFunc) apply(log *Logger) { 56 f(log) 57 } 58 59 // WithDebug configures a Logger to print at zap's DebugLevel instead of 60 // InfoLevel. 61 // It only affects the Printf, Println and Print methods, which are only used in the gRPC v1 grpclog.Logger API. 62 // 63 // Deprecated: use grpclog.SetLoggerV2() for v2 API. 64 func WithDebug() Option { 65 return optionFunc(func(logger *Logger) { 66 logger.print = &printer{ 67 enab: logger.levelEnabler, 68 level: zapcore.DebugLevel, 69 print: logger.delegate.Debug, 70 printf: logger.delegate.Debugf, 71 } 72 }) 73 } 74 75 // withWarn redirects the fatal level to the warn level, which makes testing 76 // easier. This is intentionally unexported. 77 func withWarn() Option { 78 return optionFunc(func(logger *Logger) { 79 logger.fatal = &printer{ 80 enab: logger.levelEnabler, 81 level: zapcore.WarnLevel, 82 print: logger.delegate.Warn, 83 printf: logger.delegate.Warnf, 84 } 85 }) 86 } 87 88 // NewLogger returns a new Logger. 89 func NewLogger(l *zap.Logger, options ...Option) *Logger { 90 logger := &Logger{ 91 delegate: l.Sugar(), 92 levelEnabler: l.Core(), 93 } 94 logger.print = &printer{ 95 enab: logger.levelEnabler, 96 level: zapcore.InfoLevel, 97 print: logger.delegate.Info, 98 printf: logger.delegate.Infof, 99 } 100 logger.fatal = &printer{ 101 enab: logger.levelEnabler, 102 level: zapcore.FatalLevel, 103 print: logger.delegate.Fatal, 104 printf: logger.delegate.Fatalf, 105 } 106 for _, option := range options { 107 option.apply(logger) 108 } 109 return logger 110 } 111 112 // printer implements Print, Printf, and Println operations for a Zap level. 113 // 114 // We use it to customize Debug vs Info, and Warn vs Fatal for Print and Fatal 115 // respectively. 116 type printer struct { 117 enab zapcore.LevelEnabler 118 level zapcore.Level 119 print func(...interface{}) 120 printf func(string, ...interface{}) 121 } 122 123 func (v *printer) Print(args ...interface{}) { 124 v.print(args...) 125 } 126 127 func (v *printer) Printf(format string, args ...interface{}) { 128 v.printf(format, args...) 129 } 130 131 func (v *printer) Println(args ...interface{}) { 132 if v.enab.Enabled(v.level) { 133 v.print(sprintln(args)) 134 } 135 } 136 137 // Logger adapts zap's Logger to be compatible with grpclog.LoggerV2 and the deprecated grpclog.Logger. 138 type Logger struct { 139 delegate *zap.SugaredLogger 140 levelEnabler zapcore.LevelEnabler 141 print *printer 142 fatal *printer 143 // printToDebug bool 144 // fatalToWarn bool 145 } 146 147 // Print implements grpclog.Logger. 148 // 149 // Deprecated: use [Logger.Info]. 150 func (l *Logger) Print(args ...interface{}) { 151 l.print.Print(args...) 152 } 153 154 // Printf implements grpclog.Logger. 155 // 156 // Deprecated: use [Logger.Infof]. 157 func (l *Logger) Printf(format string, args ...interface{}) { 158 l.print.Printf(format, args...) 159 } 160 161 // Println implements grpclog.Logger. 162 // 163 // Deprecated: use [Logger.Info]. 164 func (l *Logger) Println(args ...interface{}) { 165 l.print.Println(args...) 166 } 167 168 // Info implements grpclog.LoggerV2. 169 func (l *Logger) Info(args ...interface{}) { 170 l.delegate.Info(args...) 171 } 172 173 // Infoln implements grpclog.LoggerV2. 174 func (l *Logger) Infoln(args ...interface{}) { 175 if l.levelEnabler.Enabled(zapcore.InfoLevel) { 176 l.delegate.Info(sprintln(args)) 177 } 178 } 179 180 // Infof implements grpclog.LoggerV2. 181 func (l *Logger) Infof(format string, args ...interface{}) { 182 l.delegate.Infof(format, args...) 183 } 184 185 // Warning implements grpclog.LoggerV2. 186 func (l *Logger) Warning(args ...interface{}) { 187 l.delegate.Warn(args...) 188 } 189 190 // Warningln implements grpclog.LoggerV2. 191 func (l *Logger) Warningln(args ...interface{}) { 192 if l.levelEnabler.Enabled(zapcore.WarnLevel) { 193 l.delegate.Warn(sprintln(args)) 194 } 195 } 196 197 // Warningf implements grpclog.LoggerV2. 198 func (l *Logger) Warningf(format string, args ...interface{}) { 199 l.delegate.Warnf(format, args...) 200 } 201 202 // Error implements grpclog.LoggerV2. 203 func (l *Logger) Error(args ...interface{}) { 204 l.delegate.Error(args...) 205 } 206 207 // Errorln implements grpclog.LoggerV2. 208 func (l *Logger) Errorln(args ...interface{}) { 209 if l.levelEnabler.Enabled(zapcore.ErrorLevel) { 210 l.delegate.Error(sprintln(args)) 211 } 212 } 213 214 // Errorf implements grpclog.LoggerV2. 215 func (l *Logger) Errorf(format string, args ...interface{}) { 216 l.delegate.Errorf(format, args...) 217 } 218 219 // Fatal implements grpclog.LoggerV2. 220 func (l *Logger) Fatal(args ...interface{}) { 221 l.fatal.Print(args...) 222 } 223 224 // Fatalln implements grpclog.LoggerV2. 225 func (l *Logger) Fatalln(args ...interface{}) { 226 l.fatal.Println(args...) 227 } 228 229 // Fatalf implements grpclog.LoggerV2. 230 func (l *Logger) Fatalf(format string, args ...interface{}) { 231 l.fatal.Printf(format, args...) 232 } 233 234 // V implements grpclog.LoggerV2. 235 func (l *Logger) V(level int) bool { 236 return l.levelEnabler.Enabled(_grpcToZapLevel[level]) 237 } 238 239 func sprintln(args []interface{}) string { 240 s := fmt.Sprintln(args...) 241 // Drop the new line character added by Sprintln 242 return s[:len(s)-1] 243 }