1# Frequently Asked Questions 2 3## Design 4 5### Why spend so much effort on logger performance? 6 7Of course, most applications won't notice the impact of a slow logger: they 8already take tens or hundreds of milliseconds for each operation, so an extra 9millisecond doesn't matter. 10 11On the other hand, why *not* make structured logging fast? The `SugaredLogger` 12isn't any harder to use than other logging packages, and the `Logger` makes 13structured logging possible in performance-sensitive contexts. Across a fleet 14of Go microservices, making each application even slightly more efficient adds 15up quickly. 16 17### Why aren't `Logger` and `SugaredLogger` interfaces? 18 19Unlike the familiar `io.Writer` and `http.Handler`, `Logger` and 20`SugaredLogger` interfaces would include *many* methods. As [Rob Pike points 21out][go-proverbs], "The bigger the interface, the weaker the abstraction." 22Interfaces are also rigid — *any* change requires releasing a new major 23version, since it breaks all third-party implementations. 24 25Making the `Logger` and `SugaredLogger` concrete types doesn't sacrifice much 26abstraction, and it lets us add methods without introducing breaking changes. 27Your applications should define and depend upon an interface that includes 28just the methods you use. 29 30### Why sample application logs? 31 32Applications often experience runs of errors, either because of a bug or 33because of a misbehaving user. Logging errors is usually a good idea, but it 34can easily make this bad situation worse: not only is your application coping 35with a flood of errors, it's also spending extra CPU cycles and I/O logging 36those errors. Since writes are typically serialized, logging limits throughput 37when you need it most. 38 39Sampling fixes this problem by dropping repetitive log entries. Under normal 40conditions, your application writes out every entry. When similar entries are 41logged hundreds or thousands of times each second, though, zap begins dropping 42duplicates to preserve throughput. 43 44### Why do the structured logging APIs take a message in addition to fields? 45 46Subjectively, we find it helpful to accompany structured context with a brief 47description. This isn't critical during development, but it makes debugging 48and operating unfamiliar systems much easier. 49 50More concretely, zap's sampling algorithm uses the message to identify 51duplicate entries. In our experience, this is a practical middle ground 52between random sampling (which often drops the exact entry that you need while 53debugging) and hashing the complete entry (which is prohibitively expensive). 54 55### Why include package-global loggers? 56 57Since so many other logging packages include a global logger, many 58applications aren't designed to accept loggers as explicit parameters. 59Changing function signatures is often a breaking change, so zap includes 60global loggers to simplify migration. 61 62Avoid them where possible. 63 64### Why include dedicated Panic and Fatal log levels? 65 66In general, application code should handle errors gracefully instead of using 67`panic` or `os.Exit`. However, every rule has exceptions, and it's common to 68crash when an error is truly unrecoverable. To avoid losing any information 69— especially the reason for the crash — the logger must flush any 70buffered entries before the process exits. 71 72Zap makes this easy by offering `Panic` and `Fatal` logging methods that 73automatically flush before exiting. Of course, this doesn't guarantee that 74logs will never be lost, but it eliminates a common error. 75 76See the discussion in uber-go/zap#207 for more details. 77 78### What's `DPanic`? 79 80`DPanic` stands for "panic in development." In development, it logs at 81`PanicLevel`; otherwise, it logs at `ErrorLevel`. `DPanic` makes it easier to 82catch errors that are theoretically possible, but shouldn't actually happen, 83*without* crashing in production. 84 85If you've ever written code like this, you need `DPanic`: 86 87```go 88if err != nil { 89 panic(fmt.Sprintf("shouldn't ever get here: %v", err)) 90} 91``` 92 93## Installation 94 95### What does the error `expects import "go.uber.org/zap"` mean? 96 97Either zap was installed incorrectly or you're referencing the wrong package 98name in your code. 99 100Zap's source code happens to be hosted on GitHub, but the [import 101path][import-path] is `go.uber.org/zap`. This gives us, the project 102maintainers, the freedom to move the source code if necessary. However, it 103means that you need to take a little care when installing and using the 104package. 105 106If you follow two simple rules, everything should work: install zap with `go 107get -u go.uber.org/zap`, and always import it in your code with `import 108"go.uber.org/zap"`. Your code shouldn't contain *any* references to 109`github.com/uber-go/zap`. 110 111## Usage 112 113### Does zap support log rotation? 114 115Zap doesn't natively support rotating log files, since we prefer to leave this 116to an external program like `logrotate`. 117 118However, it's easy to integrate a log rotation package like 119[`gopkg.in/natefinch/lumberjack.v2`][lumberjack] as a `zapcore.WriteSyncer`. 120 121```go 122// lumberjack.Logger is already safe for concurrent use, so we don't need to 123// lock it. 124w := zapcore.AddSync(&lumberjack.Logger{ 125 Filename: "/var/log/myapp/foo.log", 126 MaxSize: 500, // megabytes 127 MaxBackups: 3, 128 MaxAge: 28, // days 129}) 130core := zapcore.NewCore( 131 zapcore.NewJSONEncoder(zap.NewProductionEncoderConfig()), 132 w, 133 zap.InfoLevel, 134) 135logger := zap.New(core) 136``` 137 138## Extensions 139 140We'd love to support every logging need within zap itself, but we're only 141familiar with a handful of log ingestion systems, flag-parsing packages, and 142the like. Rather than merging code that we can't effectively debug and 143support, we'd rather grow an ecosystem of zap extensions. 144 145We're aware of the following extensions, but haven't used them ourselves: 146 147| Package | Integration | 148| --- | --- | 149| `github.com/tchap/zapext` | Sentry, syslog | 150| `github.com/fgrosse/zaptest` | Ginkgo | 151| `github.com/blendle/zapdriver` | Stackdriver | 152 153[go-proverbs]: https://go-proverbs.github.io/ 154[import-path]: https://golang.org/cmd/go/#hdr-Remote_import_paths 155[lumberjack]: https://godoc.org/gopkg.in/natefinch/lumberjack.v2 156