Codebase list golang-github-go-logr-logr / 8ae88f1
Update upstream source from tag 'upstream/0.4.0' Update to upstream version '0.4.0' with Debian dir 25e56222fd52ad2f68f16b2311c4832fa4e006d1 Arthur Diniz 3 years ago
6 changed file(s) with 326 addition(s) and 59 deletion(s). Raw diff Collapse all Expand all
4040 - **log** (the Go standard library logger):
4141 [stdr](https://github.com/go-logr/stdr)
4242 - **github.com/sirupsen/logrus**: [logrusr](https://github.com/bombsimon/logrusr)
43 - **github.com/wojas/genericr**: [genericr](https://github.com/wojas/genericr) (makes it easy to implement your own backend)
44 - **logfmt** (Heroku style [logging](https://www.brandur.org/logfmt)): [logfmtr](https://github.com/iand/logfmtr)
4345
4446 # FAQ
4547
0 /*
1 Copyright 2020 The logr Authors.
2
3 Licensed under the Apache License, Version 2.0 (the "License");
4 you may not use this file except in compliance with the License.
5 You may obtain a copy of the License at
6
7 http://www.apache.org/licenses/LICENSE-2.0
8
9 Unless required by applicable law or agreed to in writing, software
10 distributed under the License is distributed on an "AS IS" BASIS,
11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 See the License for the specific language governing permissions and
13 limitations under the License.
14 */
15
16 package logr
17
18 // Discard returns a valid Logger that discards all messages logged to it.
19 // It can be used whenever the caller is not interested in the logs.
20 func Discard() Logger {
21 return DiscardLogger{}
22 }
23
24 // DiscardLogger is a Logger that discards all messages.
25 type DiscardLogger struct{}
26
27 func (l DiscardLogger) Enabled() bool {
28 return false
29 }
30
31 func (l DiscardLogger) Info(msg string, keysAndValues ...interface{}) {
32 }
33
34 func (l DiscardLogger) Error(err error, msg string, keysAndValues ...interface{}) {
35 }
36
37 func (l DiscardLogger) V(level int) Logger {
38 return l
39 }
40
41 func (l DiscardLogger) WithValues(keysAndValues ...interface{}) Logger {
42 return l
43 }
44
45 func (l DiscardLogger) WithName(name string) Logger {
46 return l
47 }
48
49 // Verify that it actually implements the interface
50 var _ Logger = DiscardLogger{}
0 /*
1 Copyright 2020 The logr Authors.
2
3 Licensed under the Apache License, Version 2.0 (the "License");
4 you may not use this file except in compliance with the License.
5 You may obtain a copy of the License at
6
7 http://www.apache.org/licenses/LICENSE-2.0
8
9 Unless required by applicable law or agreed to in writing, software
10 distributed under the License is distributed on an "AS IS" BASIS,
11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 See the License for the specific language governing permissions and
13 limitations under the License.
14 */
15
16 package logr
17
18 import (
19 "errors"
20 "testing"
21 )
22
23 func TestDiscard(t *testing.T) {
24 l := Discard()
25 if _, ok := l.(DiscardLogger); !ok {
26 t.Error("did not return the expected underlying type")
27 }
28 // Verify that none of the methods panic, there is not more we can test.
29 l.WithName("discard").WithValues("z", 5).Info("Hello world")
30 l.Info("Hello world", "x", 1, "y", 2)
31 l.V(1).Error(errors.New("foo"), "a", 123)
32 if l.Enabled() {
33 t.Error("discard logger must always say it is disabled")
34 }
35 }
1313 limitations under the License.
1414 */
1515
16 // This design derives from Dave Cheney's blog:
17 // http://dave.cheney.net/2015/11/05/lets-talk-about-logging
18 //
19 // This is a BETA grade API. Until there is a significant 2nd implementation,
20 // I don't really know how it will change.
21
1622 // Package logr defines abstract interfaces for logging. Packages can depend on
1723 // these interfaces and callers can implement logging in whatever way is
1824 // appropriate.
1925 //
20 // This design derives from Dave Cheney's blog:
21 // http://dave.cheney.net/2015/11/05/lets-talk-about-logging
22 //
23 // This is a BETA grade API. Until there is a significant 2nd implementation,
24 // I don't really know how it will change.
25 //
26 // The logging specifically makes it non-trivial to use format strings, to encourage
27 // attaching structured information instead of unstructured format strings.
28 //
2926 // Usage
3027 //
3128 // Logging is done using a Logger. Loggers can have name prefixes and named
3936 // we want to log that we've made some decision.
4037 //
4138 // With the traditional log package, we might write:
42 // log.Printf(
43 // "decided to set field foo to value %q for object %s/%s",
39 // log.Printf("decided to set field foo to value %q for object %s/%s",
4440 // targetValue, object.Namespace, object.Name)
4541 //
4642 // With logr's structured logging, we'd write:
47 // // elsewhere in the file, set up the logger to log with the prefix of "reconcilers",
48 // // and the named value target-type=Foo, for extra context.
49 // log := mainLogger.WithName("reconcilers").WithValues("target-type", "Foo")
50 //
51 // // later on...
52 // log.Info("setting field foo on object", "value", targetValue, "object", object)
43 // // elsewhere in the file, set up the logger to log with the prefix of
44 // // "reconcilers", and the named value target-type=Foo, for extra context.
45 // log := mainLogger.WithName("reconcilers").WithValues("target-type", "Foo")
46 //
47 // // later on...
48 // log.Info("setting foo on object", "value", targetValue, "object", object)
5349 //
5450 // Depending on our logging implementation, we could then make logging decisions
5551 // based on field values (like only logging such events for objects in a certain
7773 // Each log message from a Logger has four types of context:
7874 // logger name, log verbosity, log message, and the named values.
7975 //
80 // The Logger name constists of a series of name "segments" added by successive
76 // The Logger name consists of a series of name "segments" added by successive
8177 // calls to WithName. These name segments will be joined in some way by the
82 // underlying implementation. It is strongly reccomended that name segements
78 // underlying implementation. It is strongly recommended that name segments
8379 // contain simple identifiers (letters, digits, and hyphen), and do not contain
8480 // characters that could muddle the log output or confuse the joining operation
8581 // (e.g. whitespace, commas, periods, slashes, brackets, quotes, etc).
9086 // and log messages for users to filter on. It's illegal to pass a log level
9187 // below zero.
9288 //
93 // The log message consists of a constant message attached to the the log line.
94 // This should generally be a simple description of what's occuring, and should
89 // The log message consists of a constant message attached to the log line.
90 // This should generally be a simple description of what's occurring, and should
9591 // never be a format string.
9692 //
9793 // Variable information can then be attached using named values (key/value
114110 // generally best to avoid using the following keys, as they're frequently used
115111 // by implementations:
116112 //
117 // - `"caller"`: the calling information (file/line) of a particular log line.
118 // - `"error"`: the underlying error value in the `Error` method.
119 // - `"level"`: the log level.
120 // - `"logger"`: the name of the associated logger.
121 // - `"msg"`: the log message.
122 // - `"stacktrace"`: the stack trace associated with a particular log line or
123 // error (often from the `Error` message).
124 // - `"ts"`: the timestamp for a log line.
113 // * `"caller"`: the calling information (file/line) of a particular log line.
114 // * `"error"`: the underlying error value in the `Error` method.
115 // * `"level"`: the log level.
116 // * `"logger"`: the name of the associated logger.
117 // * `"msg"`: the log message.
118 // * `"stacktrace"`: the stack trace associated with a particular log line or
119 // error (often from the `Error` message).
120 // * `"ts"`: the timestamp for a log line.
125121 //
126122 // Implementations are encouraged to make use of these keys to represent the
127 // above concepts, when neccessary (for example, in a pure-JSON output form, it
123 // above concepts, when necessary (for example, in a pure-JSON output form, it
128124 // would be necessary to represent at least message and timestamp as ordinary
129125 // named values).
126 //
127 // Implementations may choose to give callers access to the underlying
128 // logging implementation. The recommended pattern for this is:
129 // // Underlier exposes access to the underlying logging implementation.
130 // // Since callers only have a logr.Logger, they have to know which
131 // // implementation is in use, so this interface is less of an abstraction
132 // // and more of way to test type conversion.
133 // type Underlier interface {
134 // GetUnderlying() <underlying-type>
135 // }
130136 package logr
137
138 import (
139 "context"
140 )
131141
132142 // TODO: consider adding back in format strings if they're really needed
133143 // TODO: consider other bits of zap/zapcore functionality like ObjectMarshaller (for arbitrary objects)
134 // TODO: consider other bits of glog functionality like Flush, InfoDepth, OutputStats
144 // TODO: consider other bits of glog functionality like Flush, OutputStats
135145
136146 // Logger represents the ability to log messages, both errors and not.
137147 type Logger interface {
170180
171181 // WithName adds a new element to the logger's name.
172182 // Successive calls with WithName continue to append
173 // suffixes to the logger's name. It's strongly reccomended
183 // suffixes to the logger's name. It's strongly recommended
174184 // that name segments contain only letters, digits, and hyphens
175185 // (see the package documentation for more information).
176186 WithName(name string) Logger
177187 }
188
189 // InfoLogger provides compatibility with code that relies on the v0.1.0
190 // interface.
191 //
192 // Deprecated: InfoLogger is an artifact of early versions of this API. New
193 // users should never use it and existing users should use Logger instead. This
194 // will be removed in a future release.
195 type InfoLogger = Logger
196
197 type contextKey struct{}
198
199 // FromContext returns a Logger constructed from ctx or nil if no
200 // logger details are found.
201 func FromContext(ctx context.Context) Logger {
202 if v, ok := ctx.Value(contextKey{}).(Logger); ok {
203 return v
204 }
205
206 return nil
207 }
208
209 // FromContextOrDiscard returns a Logger constructed from ctx or a Logger
210 // that discards all messages if no logger details are found.
211 func FromContextOrDiscard(ctx context.Context) Logger {
212 if v, ok := ctx.Value(contextKey{}).(Logger); ok {
213 return v
214 }
215
216 return Discard()
217 }
218
219 // NewContext returns a new context derived from ctx that embeds the Logger.
220 func NewContext(ctx context.Context, l Logger) context.Context {
221 return context.WithValue(ctx, contextKey{}, l)
222 }
223
224 // CallDepthLogger represents a Logger that knows how to climb the call stack
225 // to identify the original call site and can offset the depth by a specified
226 // number of frames. This is useful for users who have helper functions
227 // between the "real" call site and the actual calls to Logger methods.
228 // Implementations that log information about the call site (such as file,
229 // function, or line) would otherwise log information about the intermediate
230 // helper functions.
231 //
232 // This is an optional interface and implementations are not required to
233 // support it.
234 type CallDepthLogger interface {
235 Logger
236
237 // WithCallDepth returns a Logger that will offset the call stack by the
238 // specified number of frames when logging call site information. If depth
239 // is 0 the attribution should be to the direct caller of this method. If
240 // depth is 1 the attribution should skip 1 call frame, and so on.
241 // Successive calls to this are additive.
242 WithCallDepth(depth int) Logger
243 }
244
245 // WithCallDepth returns a Logger that will offset the call stack by the
246 // specified number of frames when logging call site information, if possible.
247 // This is useful for users who have helper functions between the "real" call
248 // site and the actual calls to Logger methods. If depth is 0 the attribution
249 // should be to the direct caller of this function. If depth is 1 the
250 // attribution should skip 1 call frame, and so on. Successive calls to this
251 // are additive.
252 //
253 // If the underlying log implementation supports the CallDepthLogger interface,
254 // the WithCallDepth method will be called and the result returned. If the
255 // implementation does not support CallDepthLogger, the original Logger will be
256 // returned.
257 //
258 // Callers which care about whether this was supported or not should test for
259 // CallDepthLogger support themselves.
260 func WithCallDepth(logger Logger, depth int) Logger {
261 if decorator, ok := logger.(CallDepthLogger); ok {
262 return decorator.WithCallDepth(depth)
263 }
264 return logger
265 }
0 /*
1 Copyright 2021 The logr Authors.
2
3 Licensed under the Apache License, Version 2.0 (the "License");
4 you may not use this file except in compliance with the License.
5 You may obtain a copy of the License at
6
7 http://www.apache.org/licenses/LICENSE-2.0
8
9 Unless required by applicable law or agreed to in writing, software
10 distributed under the License is distributed on an "AS IS" BASIS,
11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 See the License for the specific language governing permissions and
13 limitations under the License.
14 */
15
16 package logr
17
18 import (
19 "context"
20 "testing"
21 )
22
23 // testLogger is a Logger just for testing that does nothing.
24 type testLogger struct{}
25
26 func (l *testLogger) Enabled() bool {
27 return false
28 }
29
30 func (l *testLogger) Info(msg string, keysAndValues ...interface{}) {
31 }
32
33 func (l *testLogger) Error(err error, msg string, keysAndValues ...interface{}) {
34 }
35
36 func (l *testLogger) V(level int) Logger {
37 return l
38 }
39
40 func (l *testLogger) WithValues(keysAndValues ...interface{}) Logger {
41 return l
42 }
43
44 func (l *testLogger) WithName(name string) Logger {
45 return l
46 }
47
48 // Verify that it actually implements the interface
49 var _ Logger = &testLogger{}
50
51 func TestContext(t *testing.T) {
52 ctx := context.TODO()
53
54 if out := FromContext(ctx); out != nil {
55 t.Errorf("expected nil logger, got %#v", out)
56 }
57 if out := FromContextOrDiscard(ctx); out == nil {
58 t.Errorf("expected non-nil logger")
59 } else if _, ok := out.(DiscardLogger); !ok {
60 t.Errorf("expected a DiscardLogger, got %#v", out)
61 }
62
63 logger := &testLogger{}
64 lctx := NewContext(ctx, logger)
65 if out := FromContext(lctx); out == nil {
66 t.Errorf("expected non-nil logger")
67 } else if out.(*testLogger) != logger {
68 t.Errorf("expected output to be the same as input: got in=%p, out=%p", logger, out)
69 }
70 if out := FromContextOrDiscard(lctx); out == nil {
71 t.Errorf("expected non-nil logger")
72 } else if out.(*testLogger) != logger {
73 t.Errorf("expected output to be the same as input: got in=%p, out=%p", logger, out)
74 }
75 }
76
77 // testCallDepthLogger is a Logger just for testing that does nothing.
78 type testCallDepthLogger struct {
79 *testLogger
80 depth int
81 }
82
83 func (l *testCallDepthLogger) WithCallDepth(depth int) Logger {
84 return &testCallDepthLogger{l.testLogger, l.depth + depth}
85 }
86
87 // Verify that it actually implements the interface
88 var _ CallDepthLogger = &testCallDepthLogger{}
89
90 func TestWithCallDepth(t *testing.T) {
91 // Test an impl that does not support it.
92 t.Run("not supported", func(t *testing.T) {
93 in := &testLogger{}
94 out := WithCallDepth(in, 42)
95 if out.(*testLogger) != in {
96 t.Errorf("expected output to be the same as input: got in=%p, out=%p", in, out)
97 }
98 })
99
100 // Test an impl that does support it.
101 t.Run("supported", func(t *testing.T) {
102 in := &testCallDepthLogger{&testLogger{}, 0}
103 out := WithCallDepth(in, 42)
104 if out.(*testCallDepthLogger) == in {
105 t.Errorf("expected output to be different than input: got in=out=%p", in)
106 }
107 if cdl := out.(*testCallDepthLogger); cdl.depth != 42 {
108 t.Errorf("expected depth=42, got %d", cdl.depth)
109 }
110 })
111 }
1818 import "github.com/go-logr/logr"
1919
2020 // NullLogger is a logr.Logger that does nothing.
21 type NullLogger struct{}
22
23 var _ logr.Logger = NullLogger{}
24
25 func (_ NullLogger) Info(_ string, _ ...interface{}) {
26 // Do nothing.
27 }
28
29 func (_ NullLogger) Enabled() bool {
30 return false
31 }
32
33 func (_ NullLogger) Error(_ error, _ string, _ ...interface{}) {
34 // Do nothing.
35 }
36
37 func (log NullLogger) V(_ int) logr.Logger {
38 return log
39 }
40
41 func (log NullLogger) WithName(_ string) logr.Logger {
42 return log
43 }
44
45 func (log NullLogger) WithValues(_ ...interface{}) logr.Logger {
46 return log
47 }
21 //
22 // Deprecated: NullLogger is idenitcal to logr.DiscardLogger. It is retained
23 // for backwards compatibility, but new users should use logr.DiscardLogger
24 // instead.
25 type NullLogger = logr.DiscardLogger