log/levels: mv to deprecated_levels
Peter Bourgon
7 years ago
0 | package levels | |
1 | ||
2 | import "github.com/go-kit/kit/log" | |
3 | ||
4 | // Levels provides a leveled logging wrapper around a logger. It has five | |
5 | // levels: debug, info, warning (warn), error, and critical (crit). If you | |
6 | // want a different set of levels, you can create your own levels type very | |
7 | // easily, and you can elide the configuration. | |
8 | type Levels struct { | |
9 | ctx *log.Context | |
10 | levelKey string | |
11 | ||
12 | // We have a choice between storing level values in string fields or | |
13 | // making a separate context for each level. When using string fields the | |
14 | // Log method must combine the base context, the level data, and the | |
15 | // logged keyvals; but the With method only requires updating one context. | |
16 | // If we instead keep a separate context for each level the Log method | |
17 | // must only append the new keyvals; but the With method would have to | |
18 | // update all five contexts. | |
19 | ||
20 | // Roughly speaking, storing multiple contexts breaks even if the ratio of | |
21 | // Log/With calls is more than the number of levels. We have chosen to | |
22 | // make the With method cheap and the Log method a bit more costly because | |
23 | // we do not expect most applications to Log more than five times for each | |
24 | // call to With. | |
25 | ||
26 | debugValue string | |
27 | infoValue string | |
28 | warnValue string | |
29 | errorValue string | |
30 | critValue string | |
31 | } | |
32 | ||
33 | // New creates a new leveled logger, wrapping the passed logger. | |
34 | func New(logger log.Logger, options ...Option) Levels { | |
35 | l := Levels{ | |
36 | ctx: log.NewContext(logger), | |
37 | levelKey: "level", | |
38 | ||
39 | debugValue: "debug", | |
40 | infoValue: "info", | |
41 | warnValue: "warn", | |
42 | errorValue: "error", | |
43 | critValue: "crit", | |
44 | } | |
45 | for _, option := range options { | |
46 | option(&l) | |
47 | } | |
48 | return l | |
49 | } | |
50 | ||
51 | // With returns a new leveled logger that includes keyvals in all log events. | |
52 | func (l Levels) With(keyvals ...interface{}) Levels { | |
53 | return Levels{ | |
54 | ctx: l.ctx.With(keyvals...), | |
55 | levelKey: l.levelKey, | |
56 | debugValue: l.debugValue, | |
57 | infoValue: l.infoValue, | |
58 | warnValue: l.warnValue, | |
59 | errorValue: l.errorValue, | |
60 | critValue: l.critValue, | |
61 | } | |
62 | } | |
63 | ||
64 | // Debug returns a debug level logger. | |
65 | func (l Levels) Debug() log.Logger { | |
66 | return l.ctx.WithPrefix(l.levelKey, l.debugValue) | |
67 | } | |
68 | ||
69 | // Info returns an info level logger. | |
70 | func (l Levels) Info() log.Logger { | |
71 | return l.ctx.WithPrefix(l.levelKey, l.infoValue) | |
72 | } | |
73 | ||
74 | // Warn returns a warning level logger. | |
75 | func (l Levels) Warn() log.Logger { | |
76 | return l.ctx.WithPrefix(l.levelKey, l.warnValue) | |
77 | } | |
78 | ||
79 | // Error returns an error level logger. | |
80 | func (l Levels) Error() log.Logger { | |
81 | return l.ctx.WithPrefix(l.levelKey, l.errorValue) | |
82 | } | |
83 | ||
84 | // Crit returns a critical level logger. | |
85 | func (l Levels) Crit() log.Logger { | |
86 | return l.ctx.WithPrefix(l.levelKey, l.critValue) | |
87 | } | |
88 | ||
89 | // Option sets a parameter for leveled loggers. | |
90 | type Option func(*Levels) | |
91 | ||
92 | // Key sets the key for the field used to indicate log level. By default, | |
93 | // the key is "level". | |
94 | func Key(key string) Option { | |
95 | return func(l *Levels) { l.levelKey = key } | |
96 | } | |
97 | ||
98 | // DebugValue sets the value for the field used to indicate the debug log | |
99 | // level. By default, the value is "debug". | |
100 | func DebugValue(value string) Option { | |
101 | return func(l *Levels) { l.debugValue = value } | |
102 | } | |
103 | ||
104 | // InfoValue sets the value for the field used to indicate the info log level. | |
105 | // By default, the value is "info". | |
106 | func InfoValue(value string) Option { | |
107 | return func(l *Levels) { l.infoValue = value } | |
108 | } | |
109 | ||
110 | // WarnValue sets the value for the field used to indicate the warning log | |
111 | // level. By default, the value is "warn". | |
112 | func WarnValue(value string) Option { | |
113 | return func(l *Levels) { l.warnValue = value } | |
114 | } | |
115 | ||
116 | // ErrorValue sets the value for the field used to indicate the error log | |
117 | // level. By default, the value is "error". | |
118 | func ErrorValue(value string) Option { | |
119 | return func(l *Levels) { l.errorValue = value } | |
120 | } | |
121 | ||
122 | // CritValue sets the value for the field used to indicate the critical log | |
123 | // level. By default, the value is "crit". | |
124 | func CritValue(value string) Option { | |
125 | return func(l *Levels) { l.critValue = value } | |
126 | } |
0 | package levels_test | |
1 | ||
2 | import ( | |
3 | "bytes" | |
4 | "os" | |
5 | "testing" | |
6 | ||
7 | "github.com/go-kit/kit/log" | |
8 | levels "github.com/go-kit/kit/log/deprecated_levels" | |
9 | ) | |
10 | ||
11 | func TestDefaultLevels(t *testing.T) { | |
12 | buf := bytes.Buffer{} | |
13 | logger := levels.New(log.NewLogfmtLogger(&buf)) | |
14 | ||
15 | logger.Debug().Log("msg", "résumé") // of course you'd want to do this | |
16 | if want, have := "level=debug msg=résumé\n", buf.String(); want != have { | |
17 | t.Errorf("want %#v, have %#v", want, have) | |
18 | } | |
19 | ||
20 | buf.Reset() | |
21 | logger.Info().Log("msg", "Åhus") | |
22 | if want, have := "level=info msg=Åhus\n", buf.String(); want != have { | |
23 | t.Errorf("want %#v, have %#v", want, have) | |
24 | } | |
25 | ||
26 | buf.Reset() | |
27 | logger.Error().Log("msg", "© violation") | |
28 | if want, have := "level=error msg=\"© violation\"\n", buf.String(); want != have { | |
29 | t.Errorf("want %#v, have %#v", want, have) | |
30 | } | |
31 | ||
32 | buf.Reset() | |
33 | logger.Crit().Log("msg", " ") | |
34 | if want, have := "level=crit msg=\"\\t\"\n", buf.String(); want != have { | |
35 | t.Errorf("want %#v, have %#v", want, have) | |
36 | } | |
37 | } | |
38 | ||
39 | func TestModifiedLevels(t *testing.T) { | |
40 | buf := bytes.Buffer{} | |
41 | logger := levels.New( | |
42 | log.NewJSONLogger(&buf), | |
43 | levels.Key("l"), | |
44 | levels.DebugValue("dbg"), | |
45 | levels.InfoValue("nfo"), | |
46 | levels.WarnValue("wrn"), | |
47 | levels.ErrorValue("err"), | |
48 | levels.CritValue("crt"), | |
49 | ) | |
50 | logger.With("easter_island", "176°").Debug().Log("msg", "moai") | |
51 | if want, have := `{"easter_island":"176°","l":"dbg","msg":"moai"}`+"\n", buf.String(); want != have { | |
52 | t.Errorf("want %#v, have %#v", want, have) | |
53 | } | |
54 | } | |
55 | ||
56 | func ExampleLevels() { | |
57 | logger := levels.New(log.NewLogfmtLogger(os.Stdout)) | |
58 | logger.Debug().Log("msg", "hello") | |
59 | logger.With("context", "foo").Warn().Log("err", "error") | |
60 | ||
61 | // Output: | |
62 | // level=debug msg=hello | |
63 | // level=warn context=foo err=error | |
64 | } |
0 | package levels | |
1 | ||
2 | import "github.com/go-kit/kit/log" | |
3 | ||
4 | // Levels provides a leveled logging wrapper around a logger. It has five | |
5 | // levels: debug, info, warning (warn), error, and critical (crit). If you | |
6 | // want a different set of levels, you can create your own levels type very | |
7 | // easily, and you can elide the configuration. | |
8 | type Levels struct { | |
9 | ctx *log.Context | |
10 | levelKey string | |
11 | ||
12 | // We have a choice between storing level values in string fields or | |
13 | // making a separate context for each level. When using string fields the | |
14 | // Log method must combine the base context, the level data, and the | |
15 | // logged keyvals; but the With method only requires updating one context. | |
16 | // If we instead keep a separate context for each level the Log method | |
17 | // must only append the new keyvals; but the With method would have to | |
18 | // update all five contexts. | |
19 | ||
20 | // Roughly speaking, storing multiple contexts breaks even if the ratio of | |
21 | // Log/With calls is more than the number of levels. We have chosen to | |
22 | // make the With method cheap and the Log method a bit more costly because | |
23 | // we do not expect most applications to Log more than five times for each | |
24 | // call to With. | |
25 | ||
26 | debugValue string | |
27 | infoValue string | |
28 | warnValue string | |
29 | errorValue string | |
30 | critValue string | |
31 | } | |
32 | ||
33 | // New creates a new leveled logger, wrapping the passed logger. | |
34 | func New(logger log.Logger, options ...Option) Levels { | |
35 | l := Levels{ | |
36 | ctx: log.NewContext(logger), | |
37 | levelKey: "level", | |
38 | ||
39 | debugValue: "debug", | |
40 | infoValue: "info", | |
41 | warnValue: "warn", | |
42 | errorValue: "error", | |
43 | critValue: "crit", | |
44 | } | |
45 | for _, option := range options { | |
46 | option(&l) | |
47 | } | |
48 | return l | |
49 | } | |
50 | ||
51 | // With returns a new leveled logger that includes keyvals in all log events. | |
52 | func (l Levels) With(keyvals ...interface{}) Levels { | |
53 | return Levels{ | |
54 | ctx: l.ctx.With(keyvals...), | |
55 | levelKey: l.levelKey, | |
56 | debugValue: l.debugValue, | |
57 | infoValue: l.infoValue, | |
58 | warnValue: l.warnValue, | |
59 | errorValue: l.errorValue, | |
60 | critValue: l.critValue, | |
61 | } | |
62 | } | |
63 | ||
64 | // Debug returns a debug level logger. | |
65 | func (l Levels) Debug() log.Logger { | |
66 | return l.ctx.WithPrefix(l.levelKey, l.debugValue) | |
67 | } | |
68 | ||
69 | // Info returns an info level logger. | |
70 | func (l Levels) Info() log.Logger { | |
71 | return l.ctx.WithPrefix(l.levelKey, l.infoValue) | |
72 | } | |
73 | ||
74 | // Warn returns a warning level logger. | |
75 | func (l Levels) Warn() log.Logger { | |
76 | return l.ctx.WithPrefix(l.levelKey, l.warnValue) | |
77 | } | |
78 | ||
79 | // Error returns an error level logger. | |
80 | func (l Levels) Error() log.Logger { | |
81 | return l.ctx.WithPrefix(l.levelKey, l.errorValue) | |
82 | } | |
83 | ||
84 | // Crit returns a critical level logger. | |
85 | func (l Levels) Crit() log.Logger { | |
86 | return l.ctx.WithPrefix(l.levelKey, l.critValue) | |
87 | } | |
88 | ||
89 | // Option sets a parameter for leveled loggers. | |
90 | type Option func(*Levels) | |
91 | ||
92 | // Key sets the key for the field used to indicate log level. By default, | |
93 | // the key is "level". | |
94 | func Key(key string) Option { | |
95 | return func(l *Levels) { l.levelKey = key } | |
96 | } | |
97 | ||
98 | // DebugValue sets the value for the field used to indicate the debug log | |
99 | // level. By default, the value is "debug". | |
100 | func DebugValue(value string) Option { | |
101 | return func(l *Levels) { l.debugValue = value } | |
102 | } | |
103 | ||
104 | // InfoValue sets the value for the field used to indicate the info log level. | |
105 | // By default, the value is "info". | |
106 | func InfoValue(value string) Option { | |
107 | return func(l *Levels) { l.infoValue = value } | |
108 | } | |
109 | ||
110 | // WarnValue sets the value for the field used to indicate the warning log | |
111 | // level. By default, the value is "warn". | |
112 | func WarnValue(value string) Option { | |
113 | return func(l *Levels) { l.warnValue = value } | |
114 | } | |
115 | ||
116 | // ErrorValue sets the value for the field used to indicate the error log | |
117 | // level. By default, the value is "error". | |
118 | func ErrorValue(value string) Option { | |
119 | return func(l *Levels) { l.errorValue = value } | |
120 | } | |
121 | ||
122 | // CritValue sets the value for the field used to indicate the critical log | |
123 | // level. By default, the value is "crit". | |
124 | func CritValue(value string) Option { | |
125 | return func(l *Levels) { l.critValue = value } | |
126 | } |
0 | package levels_test | |
1 | ||
2 | import ( | |
3 | "bytes" | |
4 | "os" | |
5 | "testing" | |
6 | ||
7 | "github.com/go-kit/kit/log" | |
8 | "github.com/go-kit/kit/log/levels" | |
9 | ) | |
10 | ||
11 | func TestDefaultLevels(t *testing.T) { | |
12 | buf := bytes.Buffer{} | |
13 | logger := levels.New(log.NewLogfmtLogger(&buf)) | |
14 | ||
15 | logger.Debug().Log("msg", "résumé") // of course you'd want to do this | |
16 | if want, have := "level=debug msg=résumé\n", buf.String(); want != have { | |
17 | t.Errorf("want %#v, have %#v", want, have) | |
18 | } | |
19 | ||
20 | buf.Reset() | |
21 | logger.Info().Log("msg", "Åhus") | |
22 | if want, have := "level=info msg=Åhus\n", buf.String(); want != have { | |
23 | t.Errorf("want %#v, have %#v", want, have) | |
24 | } | |
25 | ||
26 | buf.Reset() | |
27 | logger.Error().Log("msg", "© violation") | |
28 | if want, have := "level=error msg=\"© violation\"\n", buf.String(); want != have { | |
29 | t.Errorf("want %#v, have %#v", want, have) | |
30 | } | |
31 | ||
32 | buf.Reset() | |
33 | logger.Crit().Log("msg", " ") | |
34 | if want, have := "level=crit msg=\"\\t\"\n", buf.String(); want != have { | |
35 | t.Errorf("want %#v, have %#v", want, have) | |
36 | } | |
37 | } | |
38 | ||
39 | func TestModifiedLevels(t *testing.T) { | |
40 | buf := bytes.Buffer{} | |
41 | logger := levels.New( | |
42 | log.NewJSONLogger(&buf), | |
43 | levels.Key("l"), | |
44 | levels.DebugValue("dbg"), | |
45 | levels.InfoValue("nfo"), | |
46 | levels.WarnValue("wrn"), | |
47 | levels.ErrorValue("err"), | |
48 | levels.CritValue("crt"), | |
49 | ) | |
50 | logger.With("easter_island", "176°").Debug().Log("msg", "moai") | |
51 | if want, have := `{"easter_island":"176°","l":"dbg","msg":"moai"}`+"\n", buf.String(); want != have { | |
52 | t.Errorf("want %#v, have %#v", want, have) | |
53 | } | |
54 | } | |
55 | ||
56 | func ExampleLevels() { | |
57 | logger := levels.New(log.NewLogfmtLogger(os.Stdout)) | |
58 | logger.Debug().Log("msg", "hello") | |
59 | logger.With("context", "foo").Warn().Log("err", "error") | |
60 | ||
61 | // Output: | |
62 | // level=debug msg=hello | |
63 | // level=warn context=foo err=error | |
64 | } |