-
Notifications
You must be signed in to change notification settings - Fork 0
/
interface.go
371 lines (328 loc) · 11.8 KB
/
interface.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
/*
* Copyright 2022 Mandelsoft. All rights reserved.
* This file is licensed under the Apache Software License, v. 2 except as noted
* otherwise in the LICENSE file
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package logging
import (
"fmt"
"strconv"
"strings"
"github.com/go-logr/logr"
)
// FieldKeyRealm is the name of the logr field set to the realm of a logging
// message.
const FieldKeyRealm = "realm"
// These are the different logging levels. You can set the logging level to log
// on your instance of logger.
const (
// None level. No logging,
None = iota
// ErrorLevel level. Logs. Used for errors that should definitely be noted.
// Commonly used for hooks to send errors to an error tracking service.
ErrorLevel
// WarnLevel level. Non-critical entries that deserve eyes.
WarnLevel
// InfoLevel level. General operational entries about what's going on inside the
// application.
InfoLevel
// DebugLevel level. Usually only enabled when debugging. Very verbose logging.
DebugLevel
// TraceLevel level. Designates finer-grained informational events than the Debug.
TraceLevel
)
// ParseLevel maps a string representation of a log level to
// it internal value. It also accepts the representation as
// number.
func ParseLevel(s string) (int, error) {
switch strings.ToLower(strings.TrimSpace(s)) {
case "error":
return ErrorLevel, nil
case "warn":
return WarnLevel, nil
case "info":
return InfoLevel, nil
case "debug":
return DebugLevel, nil
case "trace":
return TraceLevel, nil
default:
v, err := strconv.ParseInt(s, 10, 32)
if err != nil || v < 0 {
return 0, fmt.Errorf("invalid log level %q", s)
}
return int(v), nil
}
}
// LevelName returns the logical name of a log level.
// It can be parsed again with ParseLevel.
func LevelName(l int) string {
switch l {
case ErrorLevel:
return "Error"
case WarnLevel:
return "Warn"
case InfoLevel:
return "Info"
case DebugLevel:
return "Debug"
case TraceLevel:
return "Trace"
default:
return fmt.Sprintf("%d", l)
}
}
// Logger is the main logging interface.
// It is used to issue log messages.
// Additionally, it provides methods
// to create loggers with extend names
// and key/value pairs.
type Logger interface {
// LogError logs a given error with additional context.
LogError(err error, msg string, keypairs ...interface{})
// Error logs an error message.
Error(msg string, keypairs ...interface{})
// Warn logs a warning message.
Warn(msg string, keypairs ...interface{})
// Error logs an info message
Info(msg string, keypairs ...interface{})
// Debug logs a debug message.
Debug(msg string, keypairs ...interface{})
// Trace logs an trace message.
Trace(msg string, keypairs ...interface{})
// NewName return a new logger with an extended name,
// but the same logging activation.
WithName(name string) Logger
// WithValues return a new logger with more standard key/value pairs,
// but the same logging activation.
WithValues(keypairs ...interface{}) Logger
// Enabled check whether the logger is active for a dedicated level.
Enabled(level int) bool
// V returns a logr logger with the same activation state
// like the actual logger at call time.
V(delta int) logr.Logger
}
// UnboundLogger is a logger, which is never bound to
// the settings of a matching rule at the time of
// its creation. It therefore always reflects the
// state of the rule settings valid at the time
// of issuing log messages. They are more expensive than regular
// loggers, but they can be created and configured once
// and stored in long living variables.
//
// When passing loggers down a dynamic call tree, to control
// the logging here, only temporary (bound) loggers should be used
// (as provided by a logging context) to improve performance.
//
// Such a logger can be reused for multiple independent call trees
// without losing track to the config.
// Regular loggers provided by a context keep their setting from the
// matching rule valid during its creation.
//
// An unbound logger can be created with function DynamicLogger
// for a logging context.
type UnboundLogger interface {
ContextProvider
AttributionContextProvider
Logger
GetMessageContext() []MessageContext
WithContext(messageContext ...MessageContext) UnboundLogger
BoundLogger() Logger
}
// MessageContext is an object providing context information for
// a log message.
type MessageContext interface {
}
// Condition matches a given message context.
// It returns true, if the condition matches the context.
type Condition interface {
Match(...MessageContext) bool
}
// Rule matches a given message context and returns
// an appropriate logger
type Rule interface {
Match(SinkFunc, ...MessageContext) Logger
}
// UpdatableRule is the optional interface for a rule
// which might replace an old one.
// If a rule decides to supersede an old one when
// adding to a ruleset is may return true.
// Typically, a rule should only supersede rules
// of its own type.
type UpdatableRule interface {
Rule
MatchRule(Rule) bool
}
// ContextProvider is able to provide access to a logging context.
type ContextProvider interface {
LoggingContext() Context
}
// AttributionContextProvider is an interface
// for all object able to provide acces to an AttributionContext.
type AttributionContextProvider interface {
AttributionContext() AttributionContext
}
type LevelFunc func() int
type SinkFunc func() logr.LogSink
// MessageContextProvider is an interface for objects providing
// a message context.
// An [UnboundLogger] or a [Context] is such a provider.
// A provider can again be used wherever a message context is
// required.
type MessageContextProvider interface {
GetMessageContext() []MessageContext
}
// LoggerProvider is the interface to gain access to a logger
// from some logger source. It is implemented by [Context]
// and [AttributionContext].
type LoggerProvider interface {
// Logger return the effective logger for the given message context.
Logger(...MessageContext) Logger
// V returns the effective logr.Logger for the given message context with
// the given base level.
V(level int, mctx ...MessageContext) logr.Logger
// LoggerFor provides a logger according to rules for a dedicated message
// context. There is no default level and no log context involved,
// only the base logr sink is used.
// If no rule matches the [NonLoggingLogger] is returned.
LoggerFor(messageContext ...MessageContext) Logger
}
// AttributionContext describes a [Context], a
// [MessageContext] and a set of preset values.
// which can be used to gain a [Logger] or
// a subsequent [AttributionContext].
type AttributionContext interface {
ContextProvider
AttributionContextProvider
MessageContextProvider
LoggerProvider
// WithContext provides a new logging Context enriched by the given standard
// message context
WithContext(messageContext ...MessageContext) AttributionContext
// WithName provides a new AttributionContext adding
// a name component to provided [Logger] objects.
WithName(name string) AttributionContext
// WithValues adds keypairs implicitly used for [Logger] object
// creation..
WithValues(keypairs ...interface{}) AttributionContext
// Match evaluates a condition against the message context.
Match(cond Condition) bool
}
// Context describes the interface of a logging context.
// A logging context determines effective loggers for
// a given message context based on a set of rules used
// to map a message context to an effective logger.
type Context interface {
ContextProvider
AttributionContextProvider
MessageContextProvider
LoggerProvider
// GetSink returns the effective logr.LOgSink used as base logger
// for this context.
// In case of a nested context, this is the locally set sink, if set,
// or the sink of the base context.
GetSink() logr.LogSink
// GetDefaultLevel returns the default log level effective, if no rule matches.
// These may be locally defined rules, or, in case of a nested logger,
// rules of the base context, also.
GetDefaultLevel() int
// GetDefaultLogger return the effective default logger used if no rule matches
// a message context.
GetDefaultLogger() Logger
// SetDefaultLevel sets the default logging level to use for provided
// Loggers, if no rule matches.
SetDefaultLevel(level int)
// SetBaseLogger sets a new base logger.
// If the optional parameter plain is set to true, the base logger
// is rebased to the absolute logr level 0.
// Otherwise, the base log level is taken from the given logger. This means
// ErrorLevel is mapped to the log level of the given logger.
// Although the error output is filtered by this log level by the
// original sink, error level output, if enabled, is passed as Error to the sink.
SetBaseLogger(logger logr.Logger, plain ...bool)
// AddRule adds a rule to the actual context.
// It may decide to supersede already existing rules. In
// such case all matching rules (interface UpdatableRule)
// will be deleted from the active rule set.
AddRule(...Rule)
// ResetRules deletes the actual rule set.
ResetRules()
// AddRulesTo add the actual rules to another logging context.
AddRulesTo(ctx Context)
// WithContext provides a new logging Context enriched by the given standard
// message context
WithContext(messageContext ...MessageContext) Context
// Evaluate returns the effective logger for the given message context
// based on the given logr.LogSink.
Evaluate(SinkFunc, ...MessageContext) Logger
// Match evaluates a condition against the message context.
Match(cond Condition) bool
// Tree provides an interface for the context intended for
// context implementations to work together in a context tree.
Tree() ContextSupport
}
// LoggingContext returns a default logging context for an
// arbitrary object. If the object supports the LoggingProvider
// interface, it is used to determine the context. If not,
// the default logging context is returned.
func LoggingContext(p interface{}) Context {
if p != nil {
if cp, ok := p.(ContextProvider); ok {
return cp.LoggingContext()
}
}
return DefaultContext()
}
// Attacher is an optional interface, which can be implemented by a dedicated
// type of message context. If available it is used to enrich the attributes
// of a determined logger to describe the given context.
type Attacher interface {
Attach(l Logger) Logger
}
// Realm is some kind of tag, which can be used as
// message context or logging condition.
// If used as message context it will be attached to
// the logging message as additional logger name.
type Realm = realm
var (
_ Condition = Realm("")
_ Attacher = Realm("")
)
// RealmPrefix is used as logging condition to
// match a realm of the message context by
// checking its value to be a path prefix.
type RealmPrefix = realmprefix
var _ Condition = RealmPrefix("")
// Attribute is a key/value pair usable
// as logging condition or message context.
// If used as message context it will be attached to
// the logging message as additional value.
type Attribute interface {
Condition
Attacher
Name() string
Value() interface{}
}
// Tag is a simple string value, which can be used as
// message context or logging condition.
// If used as message context it will not be attached to
// the logging message at all.
type Tag = tag
var _ Condition = Tag("")
// Name is a simple string value, which can be used as
// message context.
// It will not be attached to the logger's name.
type Name = name
var _ Attacher = Name("")