blob: 682de254de20c22fc341537ad90846ad83c0a645 [file] [log] [blame]
Abhay Kumar40252eb2025-10-13 13:25:53 +00001// 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.
22package zapgrpc // import "go.uber.org/zap/zapgrpc"
23
24import (
25 "fmt"
26
27 "go.uber.org/zap"
28 "go.uber.org/zap/zapcore"
29)
30
31// See https://github.com/grpc/grpc-go/blob/v1.35.0/grpclog/loggerv2.go#L77-L86
32const (
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/go.uber.org/zap@v1.16.0/zapcore#Level
41var _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.
49type Option interface {
50 apply(*Logger)
51}
52
53type optionFunc func(*Logger)
54
55func (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.
64func 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.
77func 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.
89func 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.
116type printer struct {
117 enab zapcore.LevelEnabler
118 level zapcore.Level
119 print func(...interface{})
120 printf func(string, ...interface{})
121}
122
123func (v *printer) Print(args ...interface{}) {
124 v.print(args...)
125}
126
127func (v *printer) Printf(format string, args ...interface{}) {
128 v.printf(format, args...)
129}
130
131func (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.
138type 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].
150func (l *Logger) Print(args ...interface{}) {
151 l.print.Print(args...)
152}
153
154// Printf implements grpclog.Logger.
155//
156// Deprecated: use [Logger.Infof].
157func (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].
164func (l *Logger) Println(args ...interface{}) {
165 l.print.Println(args...)
166}
167
168// Info implements grpclog.LoggerV2.
169func (l *Logger) Info(args ...interface{}) {
170 l.delegate.Info(args...)
171}
172
173// Infoln implements grpclog.LoggerV2.
174func (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.
181func (l *Logger) Infof(format string, args ...interface{}) {
182 l.delegate.Infof(format, args...)
183}
184
185// Warning implements grpclog.LoggerV2.
186func (l *Logger) Warning(args ...interface{}) {
187 l.delegate.Warn(args...)
188}
189
190// Warningln implements grpclog.LoggerV2.
191func (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.
198func (l *Logger) Warningf(format string, args ...interface{}) {
199 l.delegate.Warnf(format, args...)
200}
201
202// Error implements grpclog.LoggerV2.
203func (l *Logger) Error(args ...interface{}) {
204 l.delegate.Error(args...)
205}
206
207// Errorln implements grpclog.LoggerV2.
208func (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.
215func (l *Logger) Errorf(format string, args ...interface{}) {
216 l.delegate.Errorf(format, args...)
217}
218
219// Fatal implements grpclog.LoggerV2.
220func (l *Logger) Fatal(args ...interface{}) {
221 l.fatal.Print(args...)
222}
223
224// Fatalln implements grpclog.LoggerV2.
225func (l *Logger) Fatalln(args ...interface{}) {
226 l.fatal.Println(args...)
227}
228
229// Fatalf implements grpclog.LoggerV2.
230func (l *Logger) Fatalf(format string, args ...interface{}) {
231 l.fatal.Printf(format, args...)
232}
233
234// V implements grpclog.LoggerV2.
235func (l *Logger) V(level int) bool {
236 return l.levelEnabler.Enabled(_grpcToZapLevel[level])
237}
238
239func 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}