mirror of
https://github.com/minio/minio.git
synced 2024-12-26 23:25:54 -05:00
2aa18cafc6
With CoreDNS now supporting etcdv3 as the DNS backend, we can update our federation target to etcdv3. Users will now be able to use etcdv3 server as the federation backbone. Minio will update bucket data to etcdv3 and CoreDNS can pick that data up and serve it as bucket style DNS path.
156 lines
6.0 KiB
Markdown
156 lines
6.0 KiB
Markdown
# Frequently Asked Questions
|
|
|
|
## Design
|
|
|
|
### Why spend so much effort on logger performance?
|
|
|
|
Of course, most applications won't notice the impact of a slow logger: they
|
|
already take tens or hundreds of milliseconds for each operation, so an extra
|
|
millisecond doesn't matter.
|
|
|
|
On the other hand, why *not* make structured logging fast? The `SugaredLogger`
|
|
isn't any harder to use than other logging packages, and the `Logger` makes
|
|
structured logging possible in performance-sensitive contexts. Across a fleet
|
|
of Go microservices, making each application even slightly more efficient adds
|
|
up quickly.
|
|
|
|
### Why aren't `Logger` and `SugaredLogger` interfaces?
|
|
|
|
Unlike the familiar `io.Writer` and `http.Handler`, `Logger` and
|
|
`SugaredLogger` interfaces would include *many* methods. As [Rob Pike points
|
|
out][go-proverbs], "The bigger the interface, the weaker the abstraction."
|
|
Interfaces are also rigid — *any* change requires releasing a new major
|
|
version, since it breaks all third-party implementations.
|
|
|
|
Making the `Logger` and `SugaredLogger` concrete types doesn't sacrifice much
|
|
abstraction, and it lets us add methods without introducing breaking changes.
|
|
Your applications should define and depend upon an interface that includes
|
|
just the methods you use.
|
|
|
|
### Why sample application logs?
|
|
|
|
Applications often experience runs of errors, either because of a bug or
|
|
because of a misbehaving user. Logging errors is usually a good idea, but it
|
|
can easily make this bad situation worse: not only is your application coping
|
|
with a flood of errors, it's also spending extra CPU cycles and I/O logging
|
|
those errors. Since writes are typically serialized, logging limits throughput
|
|
when you need it most.
|
|
|
|
Sampling fixes this problem by dropping repetitive log entries. Under normal
|
|
conditions, your application writes out every entry. When similar entries are
|
|
logged hundreds or thousands of times each second, though, zap begins dropping
|
|
duplicates to preserve throughput.
|
|
|
|
### Why do the structured logging APIs take a message in addition to fields?
|
|
|
|
Subjectively, we find it helpful to accompany structured context with a brief
|
|
description. This isn't critical during development, but it makes debugging
|
|
and operating unfamiliar systems much easier.
|
|
|
|
More concretely, zap's sampling algorithm uses the message to identify
|
|
duplicate entries. In our experience, this is a practical middle ground
|
|
between random sampling (which often drops the exact entry that you need while
|
|
debugging) and hashing the complete entry (which is prohibitively expensive).
|
|
|
|
### Why include package-global loggers?
|
|
|
|
Since so many other logging packages include a global logger, many
|
|
applications aren't designed to accept loggers as explicit parameters.
|
|
Changing function signatures is often a breaking change, so zap includes
|
|
global loggers to simplify migration.
|
|
|
|
Avoid them where possible.
|
|
|
|
### Why include dedicated Panic and Fatal log levels?
|
|
|
|
In general, application code should handle errors gracefully instead of using
|
|
`panic` or `os.Exit`. However, every rule has exceptions, and it's common to
|
|
crash when an error is truly unrecoverable. To avoid losing any information
|
|
— especially the reason for the crash — the logger must flush any
|
|
buffered entries before the process exits.
|
|
|
|
Zap makes this easy by offering `Panic` and `Fatal` logging methods that
|
|
automatically flush before exiting. Of course, this doesn't guarantee that
|
|
logs will never be lost, but it eliminates a common error.
|
|
|
|
See the discussion in uber-go/zap#207 for more details.
|
|
|
|
### What's `DPanic`?
|
|
|
|
`DPanic` stands for "panic in development." In development, it logs at
|
|
`PanicLevel`; otherwise, it logs at `ErrorLevel`. `DPanic` makes it easier to
|
|
catch errors that are theoretically possible, but shouldn't actually happen,
|
|
*without* crashing in production.
|
|
|
|
If you've ever written code like this, you need `DPanic`:
|
|
|
|
```go
|
|
if err != nil {
|
|
panic(fmt.Sprintf("shouldn't ever get here: %v", err))
|
|
}
|
|
```
|
|
|
|
## Installation
|
|
|
|
### What does the error `expects import "go.uber.org/zap"` mean?
|
|
|
|
Either zap was installed incorrectly or you're referencing the wrong package
|
|
name in your code.
|
|
|
|
Zap's source code happens to be hosted on GitHub, but the [import
|
|
path][import-path] is `go.uber.org/zap`. This gives us, the project
|
|
maintainers, the freedom to move the source code if necessary. However, it
|
|
means that you need to take a little care when installing and using the
|
|
package.
|
|
|
|
If you follow two simple rules, everything should work: install zap with `go
|
|
get -u go.uber.org/zap`, and always import it in your code with `import
|
|
"go.uber.org/zap"`. Your code shouldn't contain *any* references to
|
|
`github.com/uber-go/zap`.
|
|
|
|
## Usage
|
|
|
|
### Does zap support log rotation?
|
|
|
|
Zap doesn't natively support rotating log files, since we prefer to leave this
|
|
to an external program like `logrotate`.
|
|
|
|
However, it's easy to integrate a log rotation package like
|
|
[`gopkg.in/natefinch/lumberjack.v2`][lumberjack] as a `zapcore.WriteSyncer`.
|
|
|
|
```go
|
|
// lumberjack.Logger is already safe for concurrent use, so we don't need to
|
|
// lock it.
|
|
w := zapcore.AddSync(&lumberjack.Logger{
|
|
Filename: "/var/log/myapp/foo.log",
|
|
MaxSize: 500, // megabytes
|
|
MaxBackups: 3,
|
|
MaxAge: 28, // days
|
|
})
|
|
core := zapcore.NewCore(
|
|
zapcore.NewJSONEncoder(zap.NewProductionEncoderConfig()),
|
|
w,
|
|
zap.InfoLevel,
|
|
)
|
|
logger := zap.New(core)
|
|
```
|
|
|
|
## Extensions
|
|
|
|
We'd love to support every logging need within zap itself, but we're only
|
|
familiar with a handful of log ingestion systems, flag-parsing packages, and
|
|
the like. Rather than merging code that we can't effectively debug and
|
|
support, we'd rather grow an ecosystem of zap extensions.
|
|
|
|
We're aware of the following extensions, but haven't used them ourselves:
|
|
|
|
| Package | Integration |
|
|
| --- | --- |
|
|
| `github.com/tchap/zapext` | Sentry, syslog |
|
|
| `github.com/fgrosse/zaptest` | Ginkgo |
|
|
| `github.com/blendle/zapdriver` | Stackdriver |
|
|
|
|
[go-proverbs]: https://go-proverbs.github.io/
|
|
[import-path]: https://golang.org/cmd/go/#hdr-Remote_import_paths
|
|
[lumberjack]: https://godoc.org/gopkg.in/natefinch/lumberjack.v2
|