zapgrpc.go 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  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. // Package zapgrpc provides a logger that is compatible with grpclog.
  21. package zapgrpc // import "go.uber.org/zap/zapgrpc"
  22. import (
  23. "fmt"
  24. "go.uber.org/zap"
  25. "go.uber.org/zap/zapcore"
  26. )
  27. // See https://github.com/grpc/grpc-go/blob/v1.35.0/grpclog/loggerv2.go#L77-L86
  28. const (
  29. grpcLvlInfo = 0
  30. grpcLvlWarn = 1
  31. grpcLvlError = 2
  32. grpcLvlFatal = 3
  33. )
  34. var (
  35. // _grpcToZapLevel maps gRPC log levels to zap log levels.
  36. // See https://pkg.go.dev/go.uber.org/zap@v1.16.0/zapcore#Level
  37. _grpcToZapLevel = map[int]zapcore.Level{
  38. grpcLvlInfo: zapcore.InfoLevel,
  39. grpcLvlWarn: zapcore.WarnLevel,
  40. grpcLvlError: zapcore.ErrorLevel,
  41. grpcLvlFatal: zapcore.FatalLevel,
  42. }
  43. )
  44. // An Option overrides a Logger's default configuration.
  45. type Option interface {
  46. apply(*Logger)
  47. }
  48. type optionFunc func(*Logger)
  49. func (f optionFunc) apply(log *Logger) {
  50. f(log)
  51. }
  52. // WithDebug configures a Logger to print at zap's DebugLevel instead of
  53. // InfoLevel.
  54. // It only affects the Printf, Println and Print methods, which are only used in the gRPC v1 grpclog.Logger API.
  55. // Deprecated: use grpclog.SetLoggerV2() for v2 API.
  56. func WithDebug() Option {
  57. return optionFunc(func(logger *Logger) {
  58. logger.print = &printer{
  59. enab: logger.levelEnabler,
  60. level: zapcore.DebugLevel,
  61. print: logger.delegate.Debug,
  62. printf: logger.delegate.Debugf,
  63. }
  64. })
  65. }
  66. // withWarn redirects the fatal level to the warn level, which makes testing
  67. // easier. This is intentionally unexported.
  68. func withWarn() Option {
  69. return optionFunc(func(logger *Logger) {
  70. logger.fatal = &printer{
  71. enab: logger.levelEnabler,
  72. level: zapcore.WarnLevel,
  73. print: logger.delegate.Warn,
  74. printf: logger.delegate.Warnf,
  75. }
  76. })
  77. }
  78. // NewLogger returns a new Logger.
  79. func NewLogger(l *zap.Logger, options ...Option) *Logger {
  80. logger := &Logger{
  81. delegate: l.Sugar(),
  82. levelEnabler: l.Core(),
  83. }
  84. logger.print = &printer{
  85. enab: logger.levelEnabler,
  86. level: zapcore.InfoLevel,
  87. print: logger.delegate.Info,
  88. printf: logger.delegate.Infof,
  89. }
  90. logger.fatal = &printer{
  91. enab: logger.levelEnabler,
  92. level: zapcore.FatalLevel,
  93. print: logger.delegate.Fatal,
  94. printf: logger.delegate.Fatalf,
  95. }
  96. for _, option := range options {
  97. option.apply(logger)
  98. }
  99. return logger
  100. }
  101. // printer implements Print, Printf, and Println operations for a Zap level.
  102. //
  103. // We use it to customize Debug vs Info, and Warn vs Fatal for Print and Fatal
  104. // respectively.
  105. type printer struct {
  106. enab zapcore.LevelEnabler
  107. level zapcore.Level
  108. print func(...interface{})
  109. printf func(string, ...interface{})
  110. }
  111. func (v *printer) Print(args ...interface{}) {
  112. v.print(args...)
  113. }
  114. func (v *printer) Printf(format string, args ...interface{}) {
  115. v.printf(format, args...)
  116. }
  117. func (v *printer) Println(args ...interface{}) {
  118. if v.enab.Enabled(v.level) {
  119. v.print(sprintln(args))
  120. }
  121. }
  122. // Logger adapts zap's Logger to be compatible with grpclog.LoggerV2 and the deprecated grpclog.Logger.
  123. type Logger struct {
  124. delegate *zap.SugaredLogger
  125. levelEnabler zapcore.LevelEnabler
  126. print *printer
  127. fatal *printer
  128. // printToDebug bool
  129. // fatalToWarn bool
  130. }
  131. // Print implements grpclog.Logger.
  132. // Deprecated: use Info().
  133. func (l *Logger) Print(args ...interface{}) {
  134. l.print.Print(args...)
  135. }
  136. // Printf implements grpclog.Logger.
  137. // Deprecated: use Infof().
  138. func (l *Logger) Printf(format string, args ...interface{}) {
  139. l.print.Printf(format, args...)
  140. }
  141. // Println implements grpclog.Logger.
  142. // Deprecated: use Info().
  143. func (l *Logger) Println(args ...interface{}) {
  144. l.print.Println(args...)
  145. }
  146. // Info implements grpclog.LoggerV2.
  147. func (l *Logger) Info(args ...interface{}) {
  148. l.delegate.Info(args...)
  149. }
  150. // Infoln implements grpclog.LoggerV2.
  151. func (l *Logger) Infoln(args ...interface{}) {
  152. if l.levelEnabler.Enabled(zapcore.InfoLevel) {
  153. l.delegate.Info(sprintln(args))
  154. }
  155. }
  156. // Infof implements grpclog.LoggerV2.
  157. func (l *Logger) Infof(format string, args ...interface{}) {
  158. l.delegate.Infof(format, args...)
  159. }
  160. // Warning implements grpclog.LoggerV2.
  161. func (l *Logger) Warning(args ...interface{}) {
  162. l.delegate.Warn(args...)
  163. }
  164. // Warningln implements grpclog.LoggerV2.
  165. func (l *Logger) Warningln(args ...interface{}) {
  166. if l.levelEnabler.Enabled(zapcore.WarnLevel) {
  167. l.delegate.Warn(sprintln(args))
  168. }
  169. }
  170. // Warningf implements grpclog.LoggerV2.
  171. func (l *Logger) Warningf(format string, args ...interface{}) {
  172. l.delegate.Warnf(format, args...)
  173. }
  174. // Error implements grpclog.LoggerV2.
  175. func (l *Logger) Error(args ...interface{}) {
  176. l.delegate.Error(args...)
  177. }
  178. // Errorln implements grpclog.LoggerV2.
  179. func (l *Logger) Errorln(args ...interface{}) {
  180. if l.levelEnabler.Enabled(zapcore.ErrorLevel) {
  181. l.delegate.Error(sprintln(args))
  182. }
  183. }
  184. // Errorf implements grpclog.LoggerV2.
  185. func (l *Logger) Errorf(format string, args ...interface{}) {
  186. l.delegate.Errorf(format, args...)
  187. }
  188. // Fatal implements grpclog.LoggerV2.
  189. func (l *Logger) Fatal(args ...interface{}) {
  190. l.fatal.Print(args...)
  191. }
  192. // Fatalln implements grpclog.LoggerV2.
  193. func (l *Logger) Fatalln(args ...interface{}) {
  194. l.fatal.Println(args...)
  195. }
  196. // Fatalf implements grpclog.LoggerV2.
  197. func (l *Logger) Fatalf(format string, args ...interface{}) {
  198. l.fatal.Printf(format, args...)
  199. }
  200. // V implements grpclog.LoggerV2.
  201. func (l *Logger) V(level int) bool {
  202. return l.levelEnabler.Enabled(_grpcToZapLevel[level])
  203. }
  204. func sprintln(args []interface{}) string {
  205. s := fmt.Sprintln(args...)
  206. // Drop the new line character added by Sprintln
  207. return s[:len(s)-1]
  208. }