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 are some of my logs missing?
31
32Logs are dropped intentionally by zap when sampling is enabled. The production
33configuration (as returned by `NewProductionConfig()` enables sampling which will
34cause repeated logs within a second to be sampled. See more details on why sampling
35is enabled in [Why sample application logs](https://github.com/uber-go/zap/blob/master/FAQ.md#why-sample-application-logs).
36
37### Why sample application logs?
38
39Applications often experience runs of errors, either because of a bug or
40because of a misbehaving user. Logging errors is usually a good idea, but it
41can easily make this bad situation worse: not only is your application coping
42with a flood of errors, it's also spending extra CPU cycles and I/O logging
43those errors. Since writes are typically serialized, logging limits throughput
44when you need it most.
45
46Sampling fixes this problem by dropping repetitive log entries. Under normal
47conditions, your application writes out every entry. When similar entries are
48logged hundreds or thousands of times each second, though, zap begins dropping
49duplicates to preserve throughput.
50
51### Why do the structured logging APIs take a message in addition to fields?
52
53Subjectively, we find it helpful to accompany structured context with a brief
54description. This isn't critical during development, but it makes debugging
55and operating unfamiliar systems much easier.
56
57More concretely, zap's sampling algorithm uses the message to identify
58duplicate entries. In our experience, this is a practical middle ground
59between random sampling (which often drops the exact entry that you need while
60debugging) and hashing the complete entry (which is prohibitively expensive).
61
62### Why include package-global loggers?
63
64Since so many other logging packages include a global logger, many
65applications aren't designed to accept loggers as explicit parameters.
66Changing function signatures is often a breaking change, so zap includes
67global loggers to simplify migration.
68
69Avoid them where possible.
70
71### Why include dedicated Panic and Fatal log levels?
72
73In general, application code should handle errors gracefully instead of using
74`panic` or `os.Exit`. However, every rule has exceptions, and it's common to
75crash when an error is truly unrecoverable. To avoid losing any information
76— especially the reason for the crash — the logger must flush any
77buffered entries before the process exits.
78
79Zap makes this easy by offering `Panic` and `Fatal` logging methods that
80automatically flush before exiting. Of course, this doesn't guarantee that
81logs will never be lost, but it eliminates a common error.
82
83See the discussion in uber-go/zap#207 for more details.
84
85### What's `DPanic`?
86
87`DPanic` stands for "panic in development." In development, it logs at
88`PanicLevel`; otherwise, it logs at `ErrorLevel`. `DPanic` makes it easier to
89catch errors that are theoretically possible, but shouldn't actually happen,
90*without* crashing in production.
91
92If you've ever written code like this, you need `DPanic`:
93
94```go
95if err != nil {
96 panic(fmt.Sprintf("shouldn't ever get here: %v", err))
97}
98```
99
100## Installation
101
102### What does the error `expects import "go.uber.org/zap"` mean?
103
104Either zap was installed incorrectly or you're referencing the wrong package
105name in your code.
106
107Zap's source code happens to be hosted on GitHub, but the [import
108path][import-path] is `go.uber.org/zap`. This gives us, the project
109maintainers, the freedom to move the source code if necessary. However, it
110means that you need to take a little care when installing and using the
111package.
112
113If you follow two simple rules, everything should work: install zap with `go
114get -u go.uber.org/zap`, and always import it in your code with `import
115"go.uber.org/zap"`. Your code shouldn't contain *any* references to
116`github.com/uber-go/zap`.
117
118## Usage
119
120### Does zap support log rotation?
121
122Zap doesn't natively support rotating log files, since we prefer to leave this
123to an external program like `logrotate`.
124
125However, it's easy to integrate a log rotation package like
126[`gopkg.in/natefinch/lumberjack.v2`][lumberjack] as a `zapcore.WriteSyncer`.
127
128```go
129// lumberjack.Logger is already safe for concurrent use, so we don't need to
130// lock it.
131w := zapcore.AddSync(&lumberjack.Logger{
132 Filename: "/var/log/myapp/foo.log",
133 MaxSize: 500, // megabytes
134 MaxBackups: 3,
135 MaxAge: 28, // days
136})
137core := zapcore.NewCore(
138 zapcore.NewJSONEncoder(zap.NewProductionEncoderConfig()),
139 w,
140 zap.InfoLevel,
141)
142logger := zap.New(core)
143```
144
145## Extensions
146
147We'd love to support every logging need within zap itself, but we're only
148familiar with a handful of log ingestion systems, flag-parsing packages, and
149the like. Rather than merging code that we can't effectively debug and
150support, we'd rather grow an ecosystem of zap extensions.
151
152We're aware of the following extensions, but haven't used them ourselves:
153
154| Package | Integration |
155| --- | --- |
156| `github.com/tchap/zapext` | Sentry, syslog |
157| `github.com/fgrosse/zaptest` | Ginkgo |
158| `github.com/blendle/zapdriver` | Stackdriver |
159| `github.com/moul/zapgorm` | Gorm |
160| `github.com/moul/zapfilter` | Advanced filtering rules |
161
162[go-proverbs]: https://go-proverbs.github.io/
163[import-path]: https://golang.org/cmd/go/#hdr-Remote_import_paths
164[lumberjack]: https://godoc.org/gopkg.in/natefinch/lumberjack.v2
View as plain text