Codebase list golang-go.uber-zap / 4a7873d
Add a gRPC compatibility wrapper (#402) Add a small `zapgrpc` package for gRPC compatibility. Peter Edge authored 7 years ago Akshay Shah committed 7 years ago
3 changed file(s) with 216 addition(s) and 1 deletion(s). Raw diff Collapse all Expand all
22 BENCH_FLAGS ?= -cpuprofile=cpu.pprof -memprofile=mem.pprof -benchmem
33 PKGS ?= $(shell glide novendor)
44 # Many Go tools take file globs or directories as arguments instead of packages.
5 PKG_FILES ?= *.go zapcore benchmarks buffer zaptest zaptest/observer internal/bufferpool internal/exit internal/multierror internal/color
5 PKG_FILES ?= *.go zapcore benchmarks buffer zapgrpc zaptest zaptest/observer internal/bufferpool internal/exit internal/multierror internal/color
66
77 COVERALLS_IGNORE := internal/readme/readme.go
88
0 // Copyright (c) 2016 Uber Technologies, Inc.
1 //
2 // Permission is hereby granted, free of charge, to any person obtaining a copy
3 // of this software and associated documentation files (the "Software"), to deal
4 // in the Software without restriction, including without limitation the rights
5 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
6 // copies of the Software, and to permit persons to whom the Software is
7 // furnished to do so, subject to the following conditions:
8 //
9 // The above copyright notice and this permission notice shall be included in
10 // all copies or substantial portions of the Software.
11 //
12 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
13 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
14 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
15 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
16 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
17 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
18 // THE SOFTWARE.
19
20 // Package zapgrpc provides a logger that is compatible with grpclog.
21 package zapgrpc // import "go.uber.org/zap/zapgrpc"
22
23 import "go.uber.org/zap"
24
25 // An Option overrides a Logger's default configuration.
26 type Option interface {
27 apply(*Logger)
28 }
29
30 type optionFunc func(*Logger)
31
32 func (f optionFunc) apply(log *Logger) {
33 f(log)
34 }
35
36 // WithDebug configures a Logger to print at zap's DebugLevel instead of
37 // InfoLevel.
38 func WithDebug() Option {
39 return optionFunc(func(logger *Logger) {
40 logger.print = (*zap.SugaredLogger).Debug
41 logger.printf = (*zap.SugaredLogger).Debugf
42 })
43 }
44
45 // NewLogger returns a new Logger.
46 //
47 // By default, Loggers print at zap's InfoLevel.
48 func NewLogger(l *zap.Logger, options ...Option) *Logger {
49 logger := &Logger{
50 log: l.Sugar(),
51 fatal: (*zap.SugaredLogger).Fatal,
52 fatalf: (*zap.SugaredLogger).Fatalf,
53 print: (*zap.SugaredLogger).Info,
54 printf: (*zap.SugaredLogger).Infof,
55 }
56 for _, option := range options {
57 option.apply(logger)
58 }
59 return logger
60 }
61
62 // Logger adapts zap's Logger to be compatible with grpclog.Logger.
63 type Logger struct {
64 log *zap.SugaredLogger
65 fatal func(*zap.SugaredLogger, ...interface{})
66 fatalf func(*zap.SugaredLogger, string, ...interface{})
67 print func(*zap.SugaredLogger, ...interface{})
68 printf func(*zap.SugaredLogger, string, ...interface{})
69 }
70
71 // Fatal implements grpclog.Logger.
72 func (l *Logger) Fatal(args ...interface{}) {
73 l.fatal(l.log, args...)
74 }
75
76 // Fatalf implements grpclog.Logger.
77 func (l *Logger) Fatalf(format string, args ...interface{}) {
78 l.fatalf(l.log, format, args...)
79 }
80
81 // Fatalln implements grpclog.Logger.
82 func (l *Logger) Fatalln(args ...interface{}) {
83 l.fatal(l.log, args...)
84 }
85
86 // Print implements grpclog.Logger.
87 func (l *Logger) Print(args ...interface{}) {
88 l.print(l.log, args...)
89 }
90
91 // Printf implements grpclog.Logger.
92 func (l *Logger) Printf(format string, args ...interface{}) {
93 l.printf(l.log, format, args...)
94 }
95
96 // Println implements grpclog.Logger.
97 func (l *Logger) Println(args ...interface{}) {
98 l.print(l.log, args...)
99 }
0 // Copyright (c) 2016 Uber Technologies, Inc.
1 //
2 // Permission is hereby granted, free of charge, to any person obtaining a copy
3 // of this software and associated documentation files (the "Software"), to deal
4 // in the Software without restriction, including without limitation the rights
5 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
6 // copies of the Software, and to permit persons to whom the Software is
7 // furnished to do so, subject to the following conditions:
8 //
9 // The above copyright notice and this permission notice shall be included in
10 // all copies or substantial portions of the Software.
11 //
12 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
13 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
14 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
15 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
16 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
17 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
18 // THE SOFTWARE.
19
20 package zapgrpc
21
22 import (
23 "testing"
24
25 "go.uber.org/zap"
26 "go.uber.org/zap/zapcore"
27 "go.uber.org/zap/zaptest/observer"
28
29 "github.com/stretchr/testify/require"
30 )
31
32 func TestLoggerInfoExpected(t *testing.T) {
33 checkMessages(t, zapcore.DebugLevel, nil, zapcore.InfoLevel, []string{
34 "hello",
35 "world",
36 "foo",
37 }, func(logger *Logger) {
38 logger.Print("hello")
39 logger.Printf("world")
40 logger.Println("foo")
41 })
42 }
43
44 func TestLoggerDebugExpected(t *testing.T) {
45 checkMessages(t, zapcore.DebugLevel, []Option{WithDebug()}, zapcore.DebugLevel, []string{
46 "hello",
47 "world",
48 "foo",
49 }, func(logger *Logger) {
50 logger.Print("hello")
51 logger.Printf("world")
52 logger.Println("foo")
53 })
54 }
55
56 func TestLoggerDebugSuppressed(t *testing.T) {
57 checkMessages(t, zapcore.InfoLevel, []Option{WithDebug()}, zapcore.DebugLevel, nil, func(logger *Logger) {
58 logger.Print("hello")
59 logger.Printf("world")
60 logger.Println("foo")
61 })
62 }
63
64 func TestLoggerFatalExpected(t *testing.T) {
65 checkMessages(t, zapcore.DebugLevel, nil, zapcore.FatalLevel, []string{
66 "hello",
67 "world",
68 "foo",
69 }, func(logger *Logger) {
70 logger.Fatal("hello")
71 logger.Fatalf("world")
72 logger.Fatalln("foo")
73 })
74 }
75
76 func checkMessages(
77 t testing.TB,
78 enab zapcore.LevelEnabler,
79 opts []Option,
80 expectedLevel zapcore.Level,
81 expectedMessages []string,
82 f func(*Logger),
83 ) {
84 if expectedLevel == zapcore.FatalLevel {
85 expectedLevel = zapcore.WarnLevel
86 }
87 withLogger(enab, opts, func(logger *Logger, observedLogs *observer.ObservedLogs) {
88 f(logger)
89 logEntries := observedLogs.All()
90 require.Equal(t, len(expectedMessages), len(logEntries))
91 for i, logEntry := range logEntries {
92 require.Equal(t, expectedLevel, logEntry.Level)
93 require.Equal(t, expectedMessages[i], logEntry.Message)
94 }
95 })
96 }
97
98 func withLogger(
99 enab zapcore.LevelEnabler,
100 opts []Option,
101 f func(*Logger, *observer.ObservedLogs),
102 ) {
103 core, observedLogs := observer.New(enab)
104 f(NewLogger(zap.New(core), append(opts, withWarn())...), observedLogs)
105 }
106
107 // withWarn redirects the fatal level to the warn level, which makes testing
108 // easier.
109 func withWarn() Option {
110 return optionFunc(func(logger *Logger) {
111 logger.fatal = (*zap.SugaredLogger).Warn
112 logger.fatalf = (*zap.SugaredLogger).Warnf
113 })
114 }