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