@@ -22,9 +22,12 @@ package zap
22
22
23
23
import (
24
24
"fmt"
25
- "time"
25
+
26
+ "go.uber.org/zap/zapcore"
26
27
)
27
28
29
+ const oddNumberErrMsg = "Passed an odd number of keys and values to SugaredLogger, ignoring last."
30
+
28
31
// A SugaredLogger wraps the core Logger functionality in a slower, but less
29
32
// verbose, API.
30
33
type SugaredLogger struct {
@@ -33,19 +36,20 @@ type SugaredLogger struct {
33
36
34
37
// Sugar converts a Logger to a SugaredLogger.
35
38
func Sugar (core Logger ) * SugaredLogger {
39
+ // TODO: increment caller skip.
36
40
return & SugaredLogger {core }
37
41
}
38
42
39
43
// Desugar unwraps a SugaredLogger, exposing the original Logger.
40
44
func Desugar (s * SugaredLogger ) Logger {
45
+ // TODO: decrement caller skip.
41
46
return s .core
42
47
}
43
48
44
49
// With adds a variadic number of key-value pairs to the logging context.
45
50
// Even-indexed arguments are treated as keys, and are converted to strings
46
51
// (with fmt.Sprint) if necessary. The keys are then zipped with the
47
- // odd-indexed values into typed fields, falling back to a reflection-based
48
- // encoder if necessary.
52
+ // odd-indexed values into typed fields using the Any field constructor.
49
53
//
50
54
// For example,
51
55
// sugaredLogger.With(
@@ -65,165 +69,146 @@ func (s *SugaredLogger) With(args ...interface{}) *SugaredLogger {
65
69
return & SugaredLogger {core : s .core .With (sweetenFields (args , s .core )... )}
66
70
}
67
71
68
- // WithStack adds a complete stack trace to the logger's context, using the key
69
- // "stacktrace" .
70
- func (s * SugaredLogger ) WithStack ( ) * SugaredLogger {
71
- return & SugaredLogger {core : s .core .With (Stack () )}
72
+ // WithFields adds structured fields to the logger's context, just like the
73
+ // standard Logger's With method .
74
+ func (s * SugaredLogger ) WithFields ( fs ... zapcore. Field ) * SugaredLogger {
75
+ return & SugaredLogger {core : s .core .With (fs ... )}
72
76
}
73
77
74
78
// Debug logs a message and some key-value pairs at DebugLevel. Keys and values
75
79
// are treated as they are in the With method.
76
80
func (s * SugaredLogger ) Debug (msg interface {}, keysAndValues ... interface {}) {
77
- s .core .Debug (sweetenMsg (msg ), sweetenFields (keysAndValues , s .core )... )
81
+ if ce := s .core .Check (DebugLevel , sweetenMsg (msg )); ce != nil {
82
+ ce .Write (sweetenFields (keysAndValues , s .core )... )
83
+ }
78
84
}
79
85
80
86
// Debugf uses fmt.Sprintf to construct a dynamic message and logs it at
81
87
// DebugLevel. It doesn't add to the message's structured context.
82
88
func (s * SugaredLogger ) Debugf (template string , args ... interface {}) {
83
- s .Debug (fmt .Sprintf (template , args ... ))
89
+ if ce := s .core .Check (DebugLevel , fmt .Sprintf (template , args ... )); ce != nil {
90
+ ce .Write ()
91
+ }
84
92
}
85
93
86
94
// Info logs a message and some key-value pairs at InfoLevel. Keys and values
87
95
// are treated as they are in the With method.
88
96
func (s * SugaredLogger ) Info (msg interface {}, keysAndValues ... interface {}) {
89
- s .core .Info (sweetenMsg (msg ), sweetenFields (keysAndValues , s .core )... )
97
+ if ce := s .core .Check (InfoLevel , sweetenMsg (msg )); ce != nil {
98
+ ce .Write (sweetenFields (keysAndValues , s .core )... )
99
+ }
90
100
}
91
101
92
102
// Infof uses fmt.Sprintf to construct a dynamic message and logs it at
93
103
// InfoLevel. It doesn't add to the message's structured context.
94
104
func (s * SugaredLogger ) Infof (template string , args ... interface {}) {
95
- s .Info (fmt .Sprintf (template , args ... ))
105
+ if ce := s .core .Check (InfoLevel , fmt .Sprintf (template , args ... )); ce != nil {
106
+ ce .Write ()
107
+ }
96
108
}
97
109
98
110
// Warn logs a message and some key-value pairs at WarnLevel. Keys and values
99
111
// are treated as they are in the With method.
100
112
func (s * SugaredLogger ) Warn (msg interface {}, keysAndValues ... interface {}) {
101
- s .core .Warn (sweetenMsg (msg ), sweetenFields (keysAndValues , s .core )... )
113
+ if ce := s .core .Check (WarnLevel , sweetenMsg (msg )); ce != nil {
114
+ ce .Write (sweetenFields (keysAndValues , s .core )... )
115
+ }
102
116
}
103
117
104
118
// Warnf uses fmt.Sprintf to construct a dynamic message and logs it at
105
119
// WarnLevel. It doesn't add to the message's structured context.
106
120
func (s * SugaredLogger ) Warnf (template string , args ... interface {}) {
107
- s .Warn (fmt .Sprintf (template , args ... ))
121
+ if ce := s .core .Check (WarnLevel , fmt .Sprintf (template , args ... )); ce != nil {
122
+ ce .Write ()
123
+ }
108
124
}
109
125
110
126
// Error logs a message and some key-value pairs at ErrorLevel. Keys and values
111
127
// are treated as they are in the With method.
112
128
func (s * SugaredLogger ) Error (msg interface {}, keysAndValues ... interface {}) {
113
- s .core .Error (sweetenMsg (msg ), sweetenFields (keysAndValues , s .core )... )
129
+ if ce := s .core .Check (ErrorLevel , sweetenMsg (msg )); ce != nil {
130
+ ce .Write (sweetenFields (keysAndValues , s .core )... )
131
+ }
114
132
}
115
133
116
134
// Errorf uses fmt.Sprintf to construct a dynamic message and logs it at
117
135
// ErrorLevel. It doesn't add to the message's structured context.
118
136
func (s * SugaredLogger ) Errorf (template string , args ... interface {}) {
119
- s .Error (fmt .Sprintf (template , args ... ))
137
+ if ce := s .core .Check (ErrorLevel , fmt .Sprintf (template , args ... )); ce != nil {
138
+ ce .Write ()
139
+ }
140
+ }
141
+
142
+ // DPanic logs a message and some key-value pairs using the underlying logger's
143
+ // DPanic method. Keys and values are treated as they are in the With
144
+ // method. (See Logger.DPanic for details.)
145
+ func (s * SugaredLogger ) DPanic (msg interface {}, keysAndValues ... interface {}) {
146
+ if ce := s .core .Check (DPanicLevel , sweetenMsg (msg )); ce != nil {
147
+ ce .Write (sweetenFields (keysAndValues , s .core )... )
148
+ }
149
+ }
150
+
151
+ // DPanicf uses fmt.Sprintf to construct a dynamic message, which is passed to
152
+ // the underlying Logger's DPanic method. (See Logger.DPanic for details.) It
153
+ // doesn't add to the message's structured context.
154
+ func (s * SugaredLogger ) DPanicf (template string , args ... interface {}) {
155
+ if ce := s .core .Check (DPanicLevel , fmt .Sprintf (template , args ... )); ce != nil {
156
+ ce .Write ()
157
+ }
120
158
}
121
159
122
160
// Panic logs a message and some key-value pairs at PanicLevel, then panics.
123
161
// Keys and values are treated as they are in the With method.
124
162
func (s * SugaredLogger ) Panic (msg interface {}, keysAndValues ... interface {}) {
125
- s .core .Panic (sweetenMsg (msg ), sweetenFields (keysAndValues , s .core )... )
163
+ if ce := s .core .Check (PanicLevel , sweetenMsg (msg )); ce != nil {
164
+ ce .Write (sweetenFields (keysAndValues , s .core )... )
165
+ }
126
166
}
127
167
128
168
// Panicf uses fmt.Sprintf to construct a dynamic message and logs it at
129
169
// PanicLevel, then panics. It doesn't add to the message's structured context.
130
170
func (s * SugaredLogger ) Panicf (template string , args ... interface {}) {
131
- s .Panic (fmt .Sprintf (template , args ... ))
171
+ if ce := s .core .Check (PanicLevel , fmt .Sprintf (template , args ... )); ce != nil {
172
+ ce .Write ()
173
+ }
132
174
}
133
175
134
176
// Fatal logs a message and some key-value pairs at FatalLevel, then calls
135
177
// os.Exit(1). Keys and values are treated as they are in the With method.
136
178
func (s * SugaredLogger ) Fatal (msg interface {}, keysAndValues ... interface {}) {
137
- s .core .Fatal (sweetenMsg (msg ), sweetenFields (keysAndValues , s .core )... )
179
+ if ce := s .core .Check (FatalLevel , sweetenMsg (msg )); ce != nil {
180
+ ce .Write (sweetenFields (keysAndValues , s .core )... )
181
+ }
138
182
}
139
183
140
184
// Fatalf uses fmt.Sprintf to construct a dynamic message and logs it at
141
185
// FatalLevel, then calls os.Exit(1). It doesn't add to the message's
142
186
// structured context.
143
187
func (s * SugaredLogger ) Fatalf (template string , args ... interface {}) {
144
- s .Fatal (fmt .Sprintf (template , args ... ))
145
- }
146
-
147
- // DFatal logs a message and some key-value pairs using the underlying logger's
148
- // DFatal method. Keys and values are treated as they are in the With
149
- // method. (See Logger.DFatal for details.)
150
- func (s * SugaredLogger ) DFatal (msg interface {}, keysAndValues ... interface {}) {
151
- s .core .DFatal (sweetenMsg (msg ), sweetenFields (keysAndValues , s .core )... )
152
- }
153
-
154
- // DFatalf uses fmt.Sprintf to construct a dynamic message, which is passed to
155
- // the underlying Logger's DFatal method. (See Logger.DFatal for details.) It
156
- // doesn't add to the message's structured context.
157
- func (s * SugaredLogger ) DFatalf (template string , args ... interface {}) {
158
- s .DFatal (fmt .Sprintf (template , args ... ))
188
+ if ce := s .core .Check (FatalLevel , fmt .Sprintf (template , args ... )); ce != nil {
189
+ ce .Write ()
190
+ }
159
191
}
160
192
161
- func sweetenFields (args []interface {}, errLogger Logger ) []Field {
193
+ func sweetenFields (args []interface {}, errLogger Logger ) []zapcore. Field {
162
194
if len (args ) == 0 {
163
195
return nil
164
196
}
165
197
if len (args )% 2 == 1 {
166
- errLogger .DFatal (
167
- "Passed an odd number of keys and values to SugaredLogger, ignoring last." ,
168
- Object ("ignored" , args [len (args )- 1 ]),
169
- )
198
+ errLogger .DPanic (oddNumberErrMsg , Any ("ignored" , args [len (args )- 1 ]))
170
199
}
171
200
172
- fields := make ([]Field , len (args )/ 2 )
201
+ fields := make ([]zapcore. Field , len (args )/ 2 )
173
202
for i := range fields {
174
203
key := sweetenMsg (args [2 * i ])
175
-
176
- switch val := args [2 * i + 1 ].(type ) {
177
- case LogMarshaler :
178
- fields [i ] = Marshaler (key , val )
179
- case bool :
180
- fields [i ] = Bool (key , val )
181
- case float64 :
182
- fields [i ] = Float64 (key , val )
183
- case float32 :
184
- fields [i ] = Float64 (key , float64 (val ))
185
- case int :
186
- fields [i ] = Int (key , val )
187
- case int64 :
188
- fields [i ] = Int64 (key , val )
189
- case int32 :
190
- fields [i ] = Int64 (key , int64 (val ))
191
- case int16 :
192
- fields [i ] = Int64 (key , int64 (val ))
193
- case int8 :
194
- fields [i ] = Int64 (key , int64 (val ))
195
- case uint :
196
- fields [i ] = Uint (key , val )
197
- case uint64 :
198
- fields [i ] = Uint64 (key , val )
199
- case uint32 :
200
- fields [i ] = Uint64 (key , uint64 (val ))
201
- case uint16 :
202
- fields [i ] = Uint64 (key , uint64 (val ))
203
- case uint8 :
204
- fields [i ] = Uint64 (key , uint64 (val ))
205
- case uintptr :
206
- fields [i ] = Uintptr (key , val )
207
- case string :
208
- fields [i ] = String (key , val )
209
- case time.Time :
210
- fields [i ] = Time (key , val )
211
- case time.Duration :
212
- fields [i ] = Duration (key , val )
213
- case error :
214
- fields [i ] = String (key , val .Error ())
215
- case fmt.Stringer :
216
- fields [i ] = String (key , val .String ())
217
- default :
218
- fields [i ] = Object (key , val )
219
- }
204
+ fields [i ] = Any (key , args [2 * i + 1 ])
220
205
}
221
206
return fields
222
207
}
223
208
224
209
func sweetenMsg (msg interface {}) string {
225
- if m , ok := msg .(string ); ok {
226
- return m
210
+ if str , ok := msg .(string ); ok {
211
+ return str
227
212
}
228
213
return fmt .Sprint (msg )
229
214
}
0 commit comments