From d7a1bd132694a93cbdb38cb5ff4b0de128b68aa4 Mon Sep 17 00:00:00 2001 From: Jacek Olszak Date: Thu, 27 Jan 2022 10:02:38 +0100 Subject: [PATCH] split printer package to 3 packages Split printer package to 3 packages: printer, console and logadapter `printer` package is not very obvious to newcomers. If someone is searching for console or log adapters he will not realize that printer package does that. --- README.md | 11 +++--- adapter/console/_example/main.go | 24 +++++++++++++ adapter/console/console.go | 35 ++++++++++++++++++ adapter/console/console_bench_test.go | 21 +++++++++++ adapter/console/console_test.go | 20 +++++++++++ adapter/logadapter/_example/main.go | 28 +++++++++++++++ adapter/logadapter/logadapter.go | 12 +++++++ .../logadapter_bench_test.go} | 6 ++-- adapter/printer/_example/main.go | 36 ------------------- adapter/printer/printer.go | 25 ------------- adapter/printer/printer_test.go | 28 +++++++-------- logger/_examples/filter/main.go | 4 +-- logger/_examples/reuse/main.go | 4 +-- logger/_examples/tags/main.go | 4 +-- 14 files changed, 170 insertions(+), 88 deletions(-) create mode 100644 adapter/console/_example/main.go create mode 100644 adapter/console/console.go create mode 100644 adapter/console/console_bench_test.go create mode 100644 adapter/console/console_test.go create mode 100644 adapter/logadapter/_example/main.go create mode 100644 adapter/logadapter/logadapter.go rename adapter/{printer/printer_bench_test.go => logadapter/logadapter_bench_test.go} (65%) delete mode 100644 adapter/printer/_example/main.go diff --git a/README.md b/README.md index 19d508f..68fd31a 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ Tiny **structured logging** abstraction or facade for various logging libraries, ## Supported logging libraries (via adapters) -[logrus](adapter/logrusadapter), [zap](adapter/zapadapter), [zerolog](adapter/zerologadapter), [glog](adapter/glogadapter), [log15](adapter/log15adapter) and [standard fmt and log packages](adapter/printer) +[logrus](adapter/logrusadapter), [zap](adapter/zapadapter), [zerolog](adapter/zerologadapter), [glog](adapter/glogadapter), [log15](adapter/log15adapter), [standard log](adapter/logadapter) and [console](adapter/console) ## When to use? @@ -71,13 +71,13 @@ package main import ( "context" - "github.com/elgopher/yala/adapter/printer" + "github.com/elgopher/yala/adapter/console" "lib" ) // End user decides what library to plug in. func main() { - adapter := printer.StdoutAdapter() // will use fmt.Println + adapter := console.StdoutAdapter() // will print messages to console lib.SetLogAdapter(adapter) ctx := context.Background() @@ -114,14 +114,15 @@ func (l YourLib) Method(ctx context.Context) { // end user code -adapter := printer.StdoutAdapter() +adapter := console.StdoutAdapter() lib := NewLibrary(adapter) ``` ### How to use existing adapters * [Logrus](adapter/logrusadapter/_example/main.go) -* [fmt.Println and standard log package](adapter/printer/_example/main.go) +* [standard log package](adapter/logadapter/_example/main.go) +* [print logs to console using simplified adapter](adapter/console/_example/main.go) * [Zap](adapter/zapadapter/_example/main.go) * [Zerolog](adapter/zerologadapter/_example/main.go) * [glog](adapter/glogadapter/_example/main.go) diff --git a/adapter/console/_example/main.go b/adapter/console/_example/main.go new file mode 100644 index 0000000..ca5cc23 --- /dev/null +++ b/adapter/console/_example/main.go @@ -0,0 +1,24 @@ +package main + +import ( + "context" + "errors" + + "github.com/elgopher/yala/adapter/console" + "github.com/elgopher/yala/logger" +) + +var ErrSome = errors.New("ErrSome") + +// This example shows how to use yala with minimal console adapter +func main() { + ctx := context.Background() + + // log to console, stdout + log := logger.Local{Adapter: console.StdoutAdapter()} + + log.Debug(ctx, "Hello fmt") + log.With(ctx, "field_name", "field_value").Info("Some info") + log.With(ctx, "parameter", "some value").Warn("Deprecated configuration parameter. It will be removed.") + log.WithError(ctx, ErrSome).Error("Some error") +} diff --git a/adapter/console/console.go b/adapter/console/console.go new file mode 100644 index 0000000..c00401f --- /dev/null +++ b/adapter/console/console.go @@ -0,0 +1,35 @@ +// (c) 2022 Jacek Olszak +// This code is licensed under MIT license (see LICENSE for details) + +package console + +import ( + "fmt" + "io" + "os" + + "github.com/elgopher/yala/adapter/printer" + "github.com/elgopher/yala/logger" +) + +// StdoutAdapter returns a logger.Adapter implementation which prints log messages to stdout. +func StdoutAdapter() logger.Adapter { // nolint + return printer.Adapter{Printer: WriterPrinter{os.Stdout}} +} + +// StderrAdapter returns a logger.Adapter implementation which prints log messages to stderr. +func StderrAdapter() logger.Adapter { // nolint + return printer.Adapter{Printer: WriterPrinter{os.Stderr}} +} + +type WriterPrinter struct { + Writer io.Writer +} + +func (p WriterPrinter) Println(args ...interface{}) { + if p.Writer == nil { + return + } + + _, _ = fmt.Fprintln(p.Writer, args...) +} diff --git a/adapter/console/console_bench_test.go b/adapter/console/console_bench_test.go new file mode 100644 index 0000000..d382ba0 --- /dev/null +++ b/adapter/console/console_bench_test.go @@ -0,0 +1,21 @@ +// (c) 2022 Jacek Olszak +// This code is licensed under MIT license (see LICENSE for details) + +package console_test + +import ( + "testing" + + "github.com/elgopher/yala/adapter/console" + "github.com/elgopher/yala/adapter/internal/benchmark" + "github.com/elgopher/yala/adapter/printer" +) + +func BenchmarkPrinter(b *testing.B) { + adapter := printer.Adapter{ + Printer: console.WriterPrinter{ + Writer: benchmark.DiscardWriter{}, + }, + } + benchmark.Adapter(b, adapter) +} diff --git a/adapter/console/console_test.go b/adapter/console/console_test.go new file mode 100644 index 0000000..3489f2f --- /dev/null +++ b/adapter/console/console_test.go @@ -0,0 +1,20 @@ +// (c) 2022 Jacek Olszak +// This code is licensed under MIT license (see LICENSE for details) + +package console_test + +import ( + "testing" + + "github.com/elgopher/yala/adapter/console" + "github.com/stretchr/testify/assert" +) + +func TestWriterPrinter_Println(t *testing.T) { + t.Run("should not panic when Writer is nil", func(t *testing.T) { + p := console.WriterPrinter{Writer: nil} + assert.NotPanics(t, func() { + p.Println("") + }) + }) +} diff --git a/adapter/logadapter/_example/main.go b/adapter/logadapter/_example/main.go new file mode 100644 index 0000000..b34db4c --- /dev/null +++ b/adapter/logadapter/_example/main.go @@ -0,0 +1,28 @@ +package main + +import ( + "context" + "errors" + "log" + "os" + + "github.com/elgopher/yala/adapter/logadapter" + "github.com/elgopher/yala/logger" +) + +var ErrSome = errors.New("ErrSome") + +// This example shows how to use yala with standard `log` package +func main() { + ctx := context.Background() + + // log using standard log package + standardLog := log.New(os.Stdout, "", log.LstdFlags) + adapter := logadapter.Adapter(standardLog) + yalaLogger := logger.Local{Adapter: adapter} + + yalaLogger.Debug(ctx, "Hello standard log") + yalaLogger.With(ctx, "f1", "v1").With("f2", "f2").Info("Some info") + yalaLogger.With(ctx, "parameter", "some").Warn("Deprecated configuration parameter. It will be removed.") + yalaLogger.WithError(ctx, ErrSome).Error("Some error") +} diff --git a/adapter/logadapter/logadapter.go b/adapter/logadapter/logadapter.go new file mode 100644 index 0000000..b016a69 --- /dev/null +++ b/adapter/logadapter/logadapter.go @@ -0,0 +1,12 @@ +package logadapter + +import ( + "log" + + "github.com/elgopher/yala/adapter/printer" + "github.com/elgopher/yala/logger" +) + +func Adapter(l *log.Logger) logger.Adapter { // nolint + return printer.Adapter{Printer: l} +} diff --git a/adapter/printer/printer_bench_test.go b/adapter/logadapter/logadapter_bench_test.go similarity index 65% rename from adapter/printer/printer_bench_test.go rename to adapter/logadapter/logadapter_bench_test.go index 6c13b91..f90482e 100644 --- a/adapter/printer/printer_bench_test.go +++ b/adapter/logadapter/logadapter_bench_test.go @@ -1,9 +1,10 @@ // (c) 2022 Jacek Olszak // This code is licensed under MIT license (see LICENSE for details) -package printer_test +package logadapter_test import ( + "log" "testing" "github.com/elgopher/yala/adapter/internal/benchmark" @@ -11,6 +12,7 @@ import ( ) func BenchmarkPrinter(b *testing.B) { - adapter := printer.Adapter{Printer: printer.WriterPrinter{Writer: benchmark.DiscardWriter{}}} + standardLog := log.New(benchmark.DiscardWriter{}, "", log.LstdFlags) + adapter := printer.Adapter{Printer: standardLog} benchmark.Adapter(b, adapter) } diff --git a/adapter/printer/_example/main.go b/adapter/printer/_example/main.go deleted file mode 100644 index 9cde22f..0000000 --- a/adapter/printer/_example/main.go +++ /dev/null @@ -1,36 +0,0 @@ -package main - -import ( - "context" - "errors" - "log" - "os" - - "github.com/elgopher/yala/adapter/printer" - "github.com/elgopher/yala/logger" -) - -var ErrSome = errors.New("ErrSome") - -// This example shows how to use yala with standard fmt.Println and standard `log` package -func main() { - ctx := context.Background() - - // log using fmt.Println - yalaLogger := logger.Local{Adapter: printer.StdoutAdapter()} - - yalaLogger.Debug(ctx, "Hello fmt") - yalaLogger.With(ctx, "field_name", "field_value").Info("Some info") - yalaLogger.With(ctx, "parameter", "some value").Warn("Deprecated configuration parameter. It will be removed.") - yalaLogger.WithError(ctx, ErrSome).Error("Some error") - - // log using standard log package - standardLog := log.New(os.Stdout, "", log.LstdFlags) - adapter := printer.Adapter{Printer: standardLog} - yalaLogger = logger.Local{Adapter: adapter} - - yalaLogger.Debug(ctx, "Hello standard log") - yalaLogger.With(ctx, "f1", "v1").With("f2", "f2").Info("Some info") - yalaLogger.With(ctx, "parameter", "some").Warn("Deprecated configuration parameter. It will be removed.") - yalaLogger.WithError(ctx, ErrSome).Error("Some error") -} diff --git a/adapter/printer/printer.go b/adapter/printer/printer.go index 29d08c2..cb3ffc2 100644 --- a/adapter/printer/printer.go +++ b/adapter/printer/printer.go @@ -5,9 +5,6 @@ package printer import ( "context" - "fmt" - "io" - "os" "strings" "github.com/elgopher/yala/adapter/logfmt" @@ -28,28 +25,6 @@ type Printer interface { Println(...interface{}) } -// StderrAdapter returns a logger.Adapter implementation which prints log messages to stderr using `fmt` package. -func StderrAdapter() Adapter { - return Adapter{Printer: WriterPrinter{os.Stderr}} -} - -// StdoutAdapter returns a logger.Adapter implementation which prints log messages to stdout using `fmt` package. -func StdoutAdapter() Adapter { - return Adapter{Printer: WriterPrinter{os.Stdout}} -} - -type WriterPrinter struct { - Writer io.Writer -} - -func (p WriterPrinter) Println(args ...interface{}) { - if p.Writer == nil { - return - } - - _, _ = fmt.Fprintln(p.Writer, args...) -} - func (f Adapter) Log(ctx context.Context, entry logger.Entry) { if f.Printer == nil { return diff --git a/adapter/printer/printer_test.go b/adapter/printer/printer_test.go index 44a2af8..f1892ee 100644 --- a/adapter/printer/printer_test.go +++ b/adapter/printer/printer_test.go @@ -5,6 +5,8 @@ package printer_test import ( "context" + "fmt" + "io" "strings" "testing" @@ -65,14 +67,12 @@ func TestAdapter_Log(t *testing.T) { for name, test := range tests { t.Run(name, func(t *testing.T) { - var builder strings.Builder - adapter := printer.Adapter{ - Printer: printer.WriterPrinter{Writer: &builder}, - } + var actual strings.Builder + adapter := printer.Adapter{Printer: stringPrinter{&actual}} // when adapter.Log(ctx, test.entry) // then - assert.Equal(t, test.expectedMessage, builder.String()) + assert.Equal(t, test.expectedMessage, actual.String()) }) } @@ -87,17 +87,17 @@ func TestAdapter_Log(t *testing.T) { }) } -func TestWriterPrinter_Println(t *testing.T) { - t.Run("should not panic when Writer is nil", func(t *testing.T) { - p := printer.WriterPrinter{Writer: nil} - assert.NotPanics(t, func() { - p.Println("") - }) - }) -} - type stringError string func (e stringError) Error() string { return string(e) } + +type stringPrinter struct { + io.StringWriter +} + +func (p stringPrinter) Println(i ...interface{}) { + s := fmt.Sprintln(i...) + _, _ = p.WriteString(s) +} diff --git a/logger/_examples/filter/main.go b/logger/_examples/filter/main.go index ac59e89..b29ed92 100644 --- a/logger/_examples/filter/main.go +++ b/logger/_examples/filter/main.go @@ -4,13 +4,13 @@ import ( "context" "strings" - "github.com/elgopher/yala/adapter/printer" + "github.com/elgopher/yala/adapter/console" "github.com/elgopher/yala/logger" ) // This advanced example shows how to filter out messages starting with given prefix func main() { - adapter := printer.StdoutAdapter() + adapter := console.StdoutAdapter() // creates an adapter which filters out messages filterAdapter := FilterOutMessages{ diff --git a/logger/_examples/reuse/main.go b/logger/_examples/reuse/main.go index 0190aa5..cea2909 100644 --- a/logger/_examples/reuse/main.go +++ b/logger/_examples/reuse/main.go @@ -3,7 +3,7 @@ package main import ( "context" - "github.com/elgopher/yala/adapter/printer" + "github.com/elgopher/yala/adapter/console" "github.com/elgopher/yala/logger" ) @@ -11,7 +11,7 @@ import ( func main() { ctx := context.Background() - log := logger.Local{Adapter: printer.StdoutAdapter()} + log := logger.Local{Adapter: console.StdoutAdapter()} // requestLogger will log all messages with at least two fields: request_id and user requestLogger := log.With(ctx, "request_id", "123").With("user", "elgopher") diff --git a/logger/_examples/tags/main.go b/logger/_examples/tags/main.go index 093bfa9..b78655d 100644 --- a/logger/_examples/tags/main.go +++ b/logger/_examples/tags/main.go @@ -3,7 +3,7 @@ package main import ( "context" - "github.com/elgopher/yala/adapter/printer" + "github.com/elgopher/yala/adapter/console" "github.com/elgopher/yala/logger" ) @@ -11,7 +11,7 @@ const tag = "tag" // This advanced example shows how to log messages with additional field taken from context.Context func main() { - adapter := printer.StdoutAdapter() + adapter := console.StdoutAdapter() // creates an adapter which adds field from context to each logged message. addFieldAdapter := AddFieldFromContextAdapter{NextAdapter: adapter}