From 1797f10be48155bace6e6c7c1cc363ac9e4fd9cd Mon Sep 17 00:00:00 2001 From: Abhinav Gupta Date: Mon, 28 Jun 2021 09:37:08 -0700 Subject: [PATCH 1/2] zapio/writer: More documentation and example test Add more documentation and an example test for zapio.Writer to demonstrate its usage. --- zapio/example_test.go | 47 +++++++++++++++++++++++++++++++++++++++++++ zapio/writer.go | 38 +++++++++++++++++++++++++++++----- 2 files changed, 80 insertions(+), 5 deletions(-) create mode 100644 zapio/example_test.go diff --git a/zapio/example_test.go b/zapio/example_test.go new file mode 100644 index 000000000..e9565dbd7 --- /dev/null +++ b/zapio/example_test.go @@ -0,0 +1,47 @@ +// Copyright (c) 2021 Uber Technologies, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +package zapio_test + +import ( + "io" + "log" + + "go.uber.org/zap" + "go.uber.org/zap/zapio" +) + +func ExampleWriter() { + logger := zap.NewExample() + w := &zapio.Writer{Log: logger} + + io.WriteString(w, "starting up\n") + io.WriteString(w, "running\n") + io.WriteString(w, "shutting down\n") + + if err := w.Close(); err != nil { + log.Fatal(err) + } + + // Output: + // {"level":"info","msg":"starting up"} + // {"level":"info","msg":"running"} + // {"level":"info","msg":"shutting down"} +} diff --git a/zapio/writer.go b/zapio/writer.go index 29699c86d..bb3de3e57 100644 --- a/zapio/writer.go +++ b/zapio/writer.go @@ -29,12 +29,34 @@ import ( ) // Writer is an io.Writer that writes to the provided Zap logger, splitting log -// messages on line boundaries. +// messages on line boundaries. The Writer will buffer writes in memory until +// it encounters a newline, or the caller calls Sync or Close. +// +// Use the Writer with packages like os/exec where an io.Writer is required, +// and you want to log the output using your existing logger configuration. For +// example, +// +// writer := &zapio.Writer{Log: logger, Level: zap.DebugLevel} +// defer writer.Close() +// +// cmd := exec.CommandContext(ctx, ...) +// cmd.Stdout = writer +// cmd.Stderr = writer +// if err := cmd.Run(); err != nil { +// return err +// } // // Writer must be closed when finished to flush buffered data to the logger. type Writer struct { - Log *zap.Logger // log to write to - Level zapcore.Level // log level to write at + // Log specifies the logger to which the Writer will write messages. + // + // The Writer will panic if Log is unspecified. + Log *zap.Logger + + // Log level for the messages written to the provided logger. + // + // If unspecifies, defaults to Info. + Level zapcore.Level buff bytes.Buffer } @@ -46,6 +68,9 @@ var ( // Write writes the provided bytes to the underlying logger at the configured // log level and returns the length of the bytes. +// +// Write will split the input on newlines and post each line as a new log entry +// to the logger. func (w *Writer) Write(bs []byte) (n int, err error) { // Skip all checks if the level isn't enabled. if !w.Log.Core().Enabled(w.Level) { @@ -90,12 +115,15 @@ func (w *Writer) writeLine(line []byte) (remaining []byte) { } // Close closes the writer, flushing any buffered data in the process. +// +// Always call Close once you're done with the Writer to ensure that it flushes +// all data. func (w *Writer) Close() error { return w.Sync() } -// Sync flushes the buffered data from the writer, even if it doesn't end with -// a newline. +// Sync flushes buffered data to the logger as a new log entry even if it +// doesn't contain a newline. func (w *Writer) Sync() error { // Don't allow empty messages on explicit Sync calls or on Close // because we don't want an extraneous empty message at the end of the From 80f724f58279327e5223a86ad43051549cac2880 Mon Sep 17 00:00:00 2001 From: Abhinav Gupta Date: Mon, 28 Jun 2021 09:23:04 -0700 Subject: [PATCH 2/2] Prepare release v1.18.0 This release contains the following API changes per apidiff: ``` --- go.uber.org/zap --- Compatible changes: - WithClock: added --- go.uber.org/zap/buffer --- Compatible changes: - (*Buffer).WriteByte: added - (*Buffer).WriteString: added --- go.uber.org/zap/zapcore --- Compatible changes: - BufferedWriteSyncer: added - Clock: added - DefaultClock: added --- go.uber.org/zap/zaptest/observer --- Compatible changes: - (*ObservedLogs).Filter: added - (*ObservedLogs).FilterLevelExact: added ``` In addition to that, this release contains the new `zapio` package which, being a completely new package, is also a compatible change. --- CHANGELOG.md | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3b99bf0ac..811bafbb9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,30 @@ # Changelog +## 1.18.0 (28 Jun 2021) + +Enhancements: +* [#961][]: Add `zapcore.BufferedWriteSyncer`, a new `WriteSyncer` that buffers + messages in-memory and flushes them periodically. +* [#971][]: Add `zapio.Writer` to use a Zap logger as an `io.Writer`. +* [#897][]: Add `zap.WithClock` option to control the source of time via the + new `zapcore.Clock` interface. +* [#949][]: Avoid panicking in `zap.SugaredLogger` when arguments of `*w` + methods don't match expectations. +* [#943][]: Add support for filtering by level or arbitrary matcher function to + `zaptest/observer`. +* [#691][]: Comply with `io.StringWriter` and `io.ByteWriter` in Zap's + `buffer.Buffer`. + +Thanks to @atrn0, @ernado, @heyanfu, @hnlq715, @zchee +for their contributions to this release. + +[#691]: https://github.com/uber-go/zap/pull/691 +[#897]: https://github.com/uber-go/zap/pull/897 +[#943]: https://github.com/uber-go/zap/pull/943 +[#949]: https://github.com/uber-go/zap/pull/949 +[#961]: https://github.com/uber-go/zap/pull/961 +[#971]: https://github.com/uber-go/zap/pull/971 + ## 1.17.0 (25 May 2021) Bugfixes: