adding in logging
This commit is contained in:
327
vendor/go.uber.org/zap/example_test.go
generated
vendored
Normal file
327
vendor/go.uber.org/zap/example_test.go
generated
vendored
Normal file
@@ -0,0 +1,327 @@
|
||||
// Copyright (c) 2016 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 zap_test
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"go.uber.org/zap"
|
||||
"go.uber.org/zap/zapcore"
|
||||
)
|
||||
|
||||
func Example_presets() {
|
||||
// Using zap's preset constructors is the simplest way to get a feel for the
|
||||
// package, but they don't allow much customization.
|
||||
logger := zap.NewExample() // or NewProduction, or NewDevelopment
|
||||
defer logger.Sync()
|
||||
|
||||
const url = "http://example.com"
|
||||
|
||||
// In most circumstances, use the SugaredLogger. It's 4-10x faster than most
|
||||
// other structured logging packages and has a familiar, loosely-typed API.
|
||||
sugar := logger.Sugar()
|
||||
sugar.Infow("Failed to fetch URL.",
|
||||
// Structured context as loosely typed key-value pairs.
|
||||
"url", url,
|
||||
"attempt", 3,
|
||||
"backoff", time.Second,
|
||||
)
|
||||
sugar.Infof("Failed to fetch URL: %s", url)
|
||||
|
||||
// In the unusual situations where every microsecond matters, use the
|
||||
// Logger. It's even faster than the SugaredLogger, but only supports
|
||||
// structured logging.
|
||||
logger.Info("Failed to fetch URL.",
|
||||
// Structured context as strongly typed fields.
|
||||
zap.String("url", url),
|
||||
zap.Int("attempt", 3),
|
||||
zap.Duration("backoff", time.Second),
|
||||
)
|
||||
// Output:
|
||||
// {"level":"info","msg":"Failed to fetch URL.","url":"http://example.com","attempt":3,"backoff":"1s"}
|
||||
// {"level":"info","msg":"Failed to fetch URL: http://example.com"}
|
||||
// {"level":"info","msg":"Failed to fetch URL.","url":"http://example.com","attempt":3,"backoff":"1s"}
|
||||
}
|
||||
|
||||
func Example_basicConfiguration() {
|
||||
// For some users, the presets offered by the NewProduction, NewDevelopment,
|
||||
// and NewExample constructors won't be appropriate. For most of those
|
||||
// users, the bundled Config struct offers the right balance of flexibility
|
||||
// and convenience. (For more complex needs, see the AdvancedConfiguration
|
||||
// example.)
|
||||
//
|
||||
// See the documentation for Config and zapcore.EncoderConfig for all the
|
||||
// available options.
|
||||
rawJSON := []byte(`{
|
||||
"level": "debug",
|
||||
"encoding": "json",
|
||||
"outputPaths": ["stdout", "/tmp/logs"],
|
||||
"errorOutputPaths": ["stderr"],
|
||||
"initialFields": {"foo": "bar"},
|
||||
"encoderConfig": {
|
||||
"messageKey": "message",
|
||||
"levelKey": "level",
|
||||
"levelEncoder": "lowercase"
|
||||
}
|
||||
}`)
|
||||
|
||||
var cfg zap.Config
|
||||
if err := json.Unmarshal(rawJSON, &cfg); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
logger, err := cfg.Build()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer logger.Sync()
|
||||
|
||||
logger.Info("logger construction succeeded")
|
||||
// Output:
|
||||
// {"level":"info","message":"logger construction succeeded","foo":"bar"}
|
||||
}
|
||||
|
||||
func Example_advancedConfiguration() {
|
||||
// The bundled Config struct only supports the most common configuration
|
||||
// options. More complex needs, like splitting logs between multiple files
|
||||
// or writing to non-file outputs, require use of the zapcore package.
|
||||
//
|
||||
// In this example, imagine we're both sending our logs to Kafka and writing
|
||||
// them to the console. We'd like to encode the console output and the Kafka
|
||||
// topics differently, and we'd also like special treatment for
|
||||
// high-priority logs.
|
||||
|
||||
// First, define our level-handling logic.
|
||||
highPriority := zap.LevelEnablerFunc(func(lvl zapcore.Level) bool {
|
||||
return lvl >= zapcore.ErrorLevel
|
||||
})
|
||||
lowPriority := zap.LevelEnablerFunc(func(lvl zapcore.Level) bool {
|
||||
return lvl < zapcore.ErrorLevel
|
||||
})
|
||||
|
||||
// Assume that we have clients for two Kafka topics. The clients implement
|
||||
// zapcore.WriteSyncer and are safe for concurrent use. (If they only
|
||||
// implement io.Writer, we can use zapcore.AddSync to add a no-op Sync
|
||||
// method. If they're not safe for concurrent use, we can add a protecting
|
||||
// mutex with zapcore.Lock.)
|
||||
topicDebugging := zapcore.AddSync(ioutil.Discard)
|
||||
topicErrors := zapcore.AddSync(ioutil.Discard)
|
||||
|
||||
// High-priority output should also go to standard error, and low-priority
|
||||
// output should also go to standard out.
|
||||
consoleDebugging := zapcore.Lock(os.Stdout)
|
||||
consoleErrors := zapcore.Lock(os.Stderr)
|
||||
|
||||
// Optimize the Kafka output for machine consumption and the console output
|
||||
// for human operators.
|
||||
kafkaEncoder := zapcore.NewJSONEncoder(zap.NewProductionEncoderConfig())
|
||||
consoleEncoder := zapcore.NewConsoleEncoder(zap.NewDevelopmentEncoderConfig())
|
||||
|
||||
// Join the outputs, encoders, and level-handling functions into
|
||||
// zapcore.Cores, then tee the four cores together.
|
||||
core := zapcore.NewTee(
|
||||
zapcore.NewCore(kafkaEncoder, topicErrors, highPriority),
|
||||
zapcore.NewCore(consoleEncoder, consoleErrors, highPriority),
|
||||
zapcore.NewCore(kafkaEncoder, topicDebugging, lowPriority),
|
||||
zapcore.NewCore(consoleEncoder, consoleDebugging, lowPriority),
|
||||
)
|
||||
|
||||
// From a zapcore.Core, it's easy to construct a Logger.
|
||||
logger := zap.New(core)
|
||||
defer logger.Sync()
|
||||
logger.Info("constructed a logger")
|
||||
}
|
||||
|
||||
func ExampleNamespace() {
|
||||
logger := zap.NewExample()
|
||||
defer logger.Sync()
|
||||
|
||||
logger.With(
|
||||
zap.Namespace("metrics"),
|
||||
zap.Int("counter", 1),
|
||||
).Info("tracked some metrics")
|
||||
// Output:
|
||||
// {"level":"info","msg":"tracked some metrics","metrics":{"counter":1}}
|
||||
}
|
||||
|
||||
func ExampleNewStdLog() {
|
||||
logger := zap.NewExample()
|
||||
defer logger.Sync()
|
||||
|
||||
std := zap.NewStdLog(logger)
|
||||
std.Print("standard logger wrapper")
|
||||
// Output:
|
||||
// {"level":"info","msg":"standard logger wrapper"}
|
||||
}
|
||||
|
||||
func ExampleRedirectStdLog() {
|
||||
logger := zap.NewExample()
|
||||
defer logger.Sync()
|
||||
|
||||
undo := zap.RedirectStdLog(logger)
|
||||
defer undo()
|
||||
|
||||
log.Print("redirected standard library")
|
||||
// Output:
|
||||
// {"level":"info","msg":"redirected standard library"}
|
||||
}
|
||||
|
||||
func ExampleReplaceGlobals() {
|
||||
logger := zap.NewExample()
|
||||
defer logger.Sync()
|
||||
|
||||
undo := zap.ReplaceGlobals(logger)
|
||||
defer undo()
|
||||
|
||||
zap.L().Info("replaced zap's global loggers")
|
||||
// Output:
|
||||
// {"level":"info","msg":"replaced zap's global loggers"}
|
||||
}
|
||||
|
||||
func ExampleAtomicLevel() {
|
||||
atom := zap.NewAtomicLevel()
|
||||
|
||||
// To keep the example deterministic, disable timestamps in the output.
|
||||
encoderCfg := zap.NewProductionEncoderConfig()
|
||||
encoderCfg.TimeKey = ""
|
||||
|
||||
logger := zap.New(zapcore.NewCore(
|
||||
zapcore.NewJSONEncoder(encoderCfg),
|
||||
zapcore.Lock(os.Stdout),
|
||||
atom,
|
||||
))
|
||||
defer logger.Sync()
|
||||
|
||||
logger.Info("info logging enabled")
|
||||
|
||||
atom.SetLevel(zap.ErrorLevel)
|
||||
logger.Info("info logging disabled")
|
||||
// Output:
|
||||
// {"level":"info","msg":"info logging enabled"}
|
||||
}
|
||||
|
||||
func ExampleAtomicLevel_config() {
|
||||
// The zap.Config struct includes an AtomicLevel. To use it, keep a
|
||||
// reference to the Config.
|
||||
rawJSON := []byte(`{
|
||||
"level": "info",
|
||||
"outputPaths": ["stdout"],
|
||||
"errorOutputPaths": ["stderr"],
|
||||
"encoding": "json",
|
||||
"encoderConfig": {
|
||||
"messageKey": "message",
|
||||
"levelKey": "level",
|
||||
"levelEncoder": "lowercase"
|
||||
}
|
||||
}`)
|
||||
var cfg zap.Config
|
||||
if err := json.Unmarshal(rawJSON, &cfg); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
logger, err := cfg.Build()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer logger.Sync()
|
||||
|
||||
logger.Info("info logging enabled")
|
||||
|
||||
cfg.Level.SetLevel(zap.ErrorLevel)
|
||||
logger.Info("info logging disabled")
|
||||
// Output:
|
||||
// {"level":"info","message":"info logging enabled"}
|
||||
}
|
||||
|
||||
func ExampleLogger_Check() {
|
||||
logger := zap.NewExample()
|
||||
defer logger.Sync()
|
||||
|
||||
if ce := logger.Check(zap.DebugLevel, "debugging"); ce != nil {
|
||||
// If debug-level log output isn't enabled or if zap's sampling would have
|
||||
// dropped this log entry, we don't allocate the slice that holds these
|
||||
// fields.
|
||||
ce.Write(
|
||||
zap.String("foo", "bar"),
|
||||
zap.String("baz", "quux"),
|
||||
)
|
||||
}
|
||||
|
||||
// Output:
|
||||
// {"level":"debug","msg":"debugging","foo":"bar","baz":"quux"}
|
||||
}
|
||||
|
||||
func ExampleLogger_Named() {
|
||||
logger := zap.NewExample()
|
||||
defer logger.Sync()
|
||||
|
||||
// By default, Loggers are unnamed.
|
||||
logger.Info("no name")
|
||||
|
||||
// The first call to Named sets the Logger name.
|
||||
main := logger.Named("main")
|
||||
main.Info("main logger")
|
||||
|
||||
// Additional calls to Named create a period-separated path.
|
||||
main.Named("subpackage").Info("sub-logger")
|
||||
// Output:
|
||||
// {"level":"info","msg":"no name"}
|
||||
// {"level":"info","logger":"main","msg":"main logger"}
|
||||
// {"level":"info","logger":"main.subpackage","msg":"sub-logger"}
|
||||
}
|
||||
|
||||
func ExampleWrapCore_replace() {
|
||||
// Replacing a Logger's core can alter fundamental behaviors. For example,
|
||||
// example, it can convert a Logger to a no-op.
|
||||
nop := zap.WrapCore(func(zapcore.Core) zapcore.Core {
|
||||
return zapcore.NewNopCore()
|
||||
})
|
||||
|
||||
logger := zap.NewExample()
|
||||
defer logger.Sync()
|
||||
|
||||
logger.Info("working")
|
||||
logger.WithOptions(nop).Info("no-op")
|
||||
logger.Info("original logger still works")
|
||||
// Output:
|
||||
// {"level":"info","msg":"working"}
|
||||
// {"level":"info","msg":"original logger still works"}
|
||||
}
|
||||
|
||||
func ExampleWrapCore_wrap() {
|
||||
// Wrapping a Logger's core can extend its functionality. As a trivial
|
||||
// example, it can double-write all logs.
|
||||
doubled := zap.WrapCore(func(c zapcore.Core) zapcore.Core {
|
||||
return zapcore.NewTee(c, c)
|
||||
})
|
||||
|
||||
logger := zap.NewExample()
|
||||
defer logger.Sync()
|
||||
|
||||
logger.Info("single")
|
||||
logger.WithOptions(doubled).Info("doubled")
|
||||
// Output:
|
||||
// {"level":"info","msg":"single"}
|
||||
// {"level":"info","msg":"doubled"}
|
||||
// {"level":"info","msg":"doubled"}
|
||||
}
|
||||
Reference in New Issue
Block a user