diff options
Diffstat (limited to 'vendor/go.uber.org/zap')
56 files changed, 8651 insertions, 0 deletions
diff --git a/vendor/go.uber.org/zap/.codecov.yml b/vendor/go.uber.org/zap/.codecov.yml new file mode 100644 index 0000000..8e5ca7d --- /dev/null +++ b/vendor/go.uber.org/zap/.codecov.yml @@ -0,0 +1,17 @@ +coverage: +  range: 80..100 +  round: down +  precision: 2 + +  status: +    project:                   # measuring the overall project coverage +      default:                 # context, you can create multiple ones with custom titles +        enabled: yes           # must be yes|true to enable this status +        target: 95%            # specify the target coverage for each commit status +                               #   option: "auto" (must increase from parent commit or pull request base) +                               #   option: "X%" a static target percentage to hit +        if_not_found: success  # if parent is not found report status as success, error, or failure +        if_ci_failed: error    # if ci fails report status as success, error, or failure +ignore: +  - internal/readme/readme.go + diff --git a/vendor/go.uber.org/zap/.gitignore b/vendor/go.uber.org/zap/.gitignore new file mode 100644 index 0000000..da9d9d0 --- /dev/null +++ b/vendor/go.uber.org/zap/.gitignore @@ -0,0 +1,32 @@ +# Compiled Object files, Static and Dynamic libs (Shared Objects) +*.o +*.a +*.so + +# Folders +_obj +_test +vendor + +# Architecture specific extensions/prefixes +*.[568vq] +[568vq].out + +*.cgo1.go +*.cgo2.c +_cgo_defun.c +_cgo_gotypes.go +_cgo_export.* + +_testmain.go + +*.exe +*.test +*.prof +*.pprof +*.out +*.log + +/bin +cover.out +cover.html diff --git a/vendor/go.uber.org/zap/.readme.tmpl b/vendor/go.uber.org/zap/.readme.tmpl new file mode 100644 index 0000000..92aa65d --- /dev/null +++ b/vendor/go.uber.org/zap/.readme.tmpl @@ -0,0 +1,109 @@ +# :zap: zap [![GoDoc][doc-img]][doc] [![Build Status][ci-img]][ci] [![Coverage Status][cov-img]][cov] + +Blazing fast, structured, leveled logging in Go. + +## Installation + +`go get -u go.uber.org/zap` + +Note that zap only supports the two most recent minor versions of Go. + +## Quick Start + +In contexts where performance is nice, but not critical, use the +`SugaredLogger`. It's 4-10x faster than other structured logging +packages and includes both structured and `printf`-style APIs. + +```go +logger, _ := zap.NewProduction() +defer logger.Sync() // flushes buffer, if any +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) +``` + +When performance and type safety are critical, use the `Logger`. It's even +faster than the `SugaredLogger` and allocates far less, but it only supports +structured logging. + +```go +logger, _ := zap.NewProduction() +defer logger.Sync() +logger.Info("failed to fetch URL", +  // Structured context as strongly typed Field values. +  zap.String("url", url), +  zap.Int("attempt", 3), +  zap.Duration("backoff", time.Second), +) +``` + +See the [documentation][doc] and [FAQ](FAQ.md) for more details. + +## Performance + +For applications that log in the hot path, reflection-based serialization and +string formatting are prohibitively expensive — they're CPU-intensive +and make many small allocations. Put differently, using `encoding/json` and +`fmt.Fprintf` to log tons of `interface{}`s makes your application slow. + +Zap takes a different approach. It includes a reflection-free, zero-allocation +JSON encoder, and the base `Logger` strives to avoid serialization overhead +and allocations wherever possible. By building the high-level `SugaredLogger` +on that foundation, zap lets users *choose* when they need to count every +allocation and when they'd prefer a more familiar, loosely typed API. + +As measured by its own [benchmarking suite][], not only is zap more performant +than comparable structured logging packages — it's also faster than the +standard library. Like all benchmarks, take these with a grain of salt.<sup +id="anchor-versions">[1](#footnote-versions)</sup> + +Log a message and 10 fields: + +{{.BenchmarkAddingFields}} + +Log a message with a logger that already has 10 fields of context: + +{{.BenchmarkAccumulatedContext}} + +Log a static string, without any context or `printf`-style templating: + +{{.BenchmarkWithoutFields}} + +## Development Status: Stable + +All APIs are finalized, and no breaking changes will be made in the 1.x series +of releases. Users of semver-aware dependency management systems should pin +zap to `^1`. + +## Contributing + +We encourage and support an active, healthy community of contributors — +including you! Details are in the [contribution guide](CONTRIBUTING.md) and +the [code of conduct](CODE_OF_CONDUCT.md). The zap maintainers keep an eye on +issues and pull requests, but you can also report any negative conduct to +oss-conduct@uber.com. That email list is a private, safe space; even the zap +maintainers don't have access, so don't hesitate to hold us to a high +standard. + +<hr> + +Released under the [MIT License](LICENSE.txt). + +<sup id="footnote-versions">1</sup> In particular, keep in mind that we may be +benchmarking against slightly older versions of other packages. Versions are +pinned in the [benchmarks/go.mod][] file. [↩](#anchor-versions) + +[doc-img]: https://pkg.go.dev/badge/go.uber.org/zap +[doc]: https://pkg.go.dev/go.uber.org/zap +[ci-img]: https://github.com/uber-go/zap/actions/workflows/go.yml/badge.svg +[ci]: https://github.com/uber-go/zap/actions/workflows/go.yml +[cov-img]: https://codecov.io/gh/uber-go/zap/branch/master/graph/badge.svg +[cov]: https://codecov.io/gh/uber-go/zap +[benchmarking suite]: https://github.com/uber-go/zap/tree/master/benchmarks +[benchmarks/go.mod]: https://github.com/uber-go/zap/blob/master/benchmarks/go.mod + diff --git a/vendor/go.uber.org/zap/CHANGELOG.md b/vendor/go.uber.org/zap/CHANGELOG.md new file mode 100644 index 0000000..0db1f9f --- /dev/null +++ b/vendor/go.uber.org/zap/CHANGELOG.md @@ -0,0 +1,617 @@ +# Changelog +All notable changes to this project will be documented in this file. + +This project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). + +## 1.24.0 (30 Nov 2022) + +Enhancements: +* [#1148][]: Add `Level` to both `Logger` and `SugaredLogger` that reports the +  current minimum enabled log level. +* [#1185][]: `SugaredLogger` turns errors to zap.Error automatically. + +Thanks to @Abirdcfly, @craigpastro, @nnnkkk7, and @sashamelentyev for their +contributions to this release. + +[#1148]: https://github.coml/uber-go/zap/pull/1148 +[#1185]: https://github.coml/uber-go/zap/pull/1185 + +## 1.23.0 (24 Aug 2022) + +Enhancements: +* [#1147][]: Add a `zapcore.LevelOf` function to determine the level of a +  `LevelEnabler` or `Core`. +* [#1155][]: Add `zap.Stringers` field constructor to log arrays of objects +  that implement `String() string`. + +[#1147]: https://github.com/uber-go/zap/pull/1147 +[#1155]: https://github.com/uber-go/zap/pull/1155 + + +## 1.22.0 (8 Aug 2022) + +Enhancements: +* [#1071][]: Add `zap.Objects` and `zap.ObjectValues` field constructors to log +  arrays of objects. With these two constructors, you don't need to implement +  `zapcore.ArrayMarshaler` for use with `zap.Array` if those objects implement +  `zapcore.ObjectMarshaler`. +* [#1079][]: Add `SugaredLogger.WithOptions` to build a copy of an existing +  `SugaredLogger` with the provided options applied. +* [#1080][]: Add `*ln` variants to `SugaredLogger` for each log level. +  These functions provide a string joining behavior similar to `fmt.Println`. +* [#1088][]: Add `zap.WithFatalHook` option to control the behavior of the +  logger for `Fatal`-level log entries. This defaults to exiting the program. +* [#1108][]: Add a `zap.Must` function that you can use with `NewProduction` or +  `NewDevelopment` to panic if the system was unable to build the logger. +* [#1118][]: Add a `Logger.Log` method that allows specifying the log level for +  a statement dynamically. + +Thanks to @cardil, @craigpastro, @sashamelentyev, @shota3506, and @zhupeijun +for their contributions to this release. + +[#1071]: https://github.com/uber-go/zap/pull/1071 +[#1079]: https://github.com/uber-go/zap/pull/1079 +[#1080]: https://github.com/uber-go/zap/pull/1080 +[#1088]: https://github.com/uber-go/zap/pull/1088 +[#1108]: https://github.com/uber-go/zap/pull/1108 +[#1118]: https://github.com/uber-go/zap/pull/1118 + +## 1.21.0 (7 Feb 2022) + +Enhancements: +*  [#1047][]: Add `zapcore.ParseLevel` to parse a `Level` from a string. +*  [#1048][]: Add `zap.ParseAtomicLevel` to parse an `AtomicLevel` from a +   string. + +Bugfixes: +* [#1058][]: Fix panic in JSON encoder when `EncodeLevel` is unset. + +Other changes: +* [#1052][]: Improve encoding performance when the `AddCaller` and +  `AddStacktrace` options are used together. + +[#1047]: https://github.com/uber-go/zap/pull/1047 +[#1048]: https://github.com/uber-go/zap/pull/1048 +[#1052]: https://github.com/uber-go/zap/pull/1052 +[#1058]: https://github.com/uber-go/zap/pull/1058 + +Thanks to @aerosol and @Techassi for their contributions to this release. + +## 1.20.0 (4 Jan 2022) + +Enhancements: +* [#989][]: Add `EncoderConfig.SkipLineEnding` flag to disable adding newline +  characters between log statements. +* [#1039][]: Add `EncoderConfig.NewReflectedEncoder` field to customize JSON +  encoding of reflected log fields. + +Bugfixes: +* [#1011][]: Fix inaccurate precision when encoding complex64 as JSON. +* [#554][], [#1017][]: Close JSON namespaces opened in `MarshalLogObject` +  methods when the methods return. +* [#1033][]: Avoid panicking in Sampler core if `thereafter` is zero. + +Other changes: +* [#1028][]: Drop support for Go < 1.15. + +[#554]: https://github.com/uber-go/zap/pull/554 +[#989]: https://github.com/uber-go/zap/pull/989 +[#1011]: https://github.com/uber-go/zap/pull/1011 +[#1017]: https://github.com/uber-go/zap/pull/1017 +[#1028]: https://github.com/uber-go/zap/pull/1028 +[#1033]: https://github.com/uber-go/zap/pull/1033 +[#1039]: https://github.com/uber-go/zap/pull/1039 + +Thanks to @psrajat, @lruggieri, @sammyrnycreal for their contributions to this release. + +## 1.19.1 (8 Sep 2021) + +Bugfixes: +* [#1001][]: JSON: Fix complex number encoding with negative imaginary part. Thanks to @hemantjadon. +* [#1003][]: JSON: Fix inaccurate precision when encoding float32. + +[#1001]: https://github.com/uber-go/zap/pull/1001 +[#1003]: https://github.com/uber-go/zap/pull/1003 + +## 1.19.0 (9 Aug 2021) + +Enhancements: +* [#975][]: Avoid panicking in Sampler core if the level is out of bounds. +* [#984][]: Reduce the size of BufferedWriteSyncer by aligning the fields +  better. + +[#975]: https://github.com/uber-go/zap/pull/975 +[#984]: https://github.com/uber-go/zap/pull/984 + +Thanks to @lancoLiu and @thockin for their contributions to this release. + +## 1.18.1 (28 Jun 2021) + +Bugfixes: +* [#974][]: Fix nil dereference in logger constructed by `zap.NewNop`. + +[#974]: https://github.com/uber-go/zap/pull/974 + +## 1.18.0 (28 Jun 2021) + +Enhancements: +* [#961][]: Add `zapcore.BufferedWriteSyncer`, a new `WriteSyncer` that buffers +  messages in-memory and flushes them periodically. +* [#971][]: Add `zapio.Writer` to use a Zap logger as an `io.Writer`. +* [#897][]: Add `zap.WithClock` option to control the source of time via the +  new `zapcore.Clock` interface. +* [#949][]: Avoid panicking in `zap.SugaredLogger` when arguments of `*w` +  methods don't match expectations. +* [#943][]: Add support for filtering by level or arbitrary matcher function to +  `zaptest/observer`. +* [#691][]: Comply with `io.StringWriter` and `io.ByteWriter` in Zap's +  `buffer.Buffer`. + +Thanks to @atrn0, @ernado, @heyanfu, @hnlq715, @zchee +for their contributions to this release. + +[#691]: https://github.com/uber-go/zap/pull/691 +[#897]: https://github.com/uber-go/zap/pull/897 +[#943]: https://github.com/uber-go/zap/pull/943 +[#949]: https://github.com/uber-go/zap/pull/949 +[#961]: https://github.com/uber-go/zap/pull/961 +[#971]: https://github.com/uber-go/zap/pull/971 + +## 1.17.0 (25 May 2021) + +Bugfixes: +* [#867][]: Encode `<nil>` for nil `error` instead of a panic. +* [#931][], [#936][]: Update minimum version constraints to address +  vulnerabilities in dependencies. + +Enhancements: +* [#865][]: Improve alignment of fields of the Logger struct, reducing its +  size from 96 to 80 bytes. +* [#881][]: Support `grpclog.LoggerV2` in zapgrpc. +* [#903][]: Support URL-encoded POST requests to the AtomicLevel HTTP handler +  with the `application/x-www-form-urlencoded` content type. +* [#912][]: Support multi-field encoding with `zap.Inline`. +* [#913][]: Speed up SugaredLogger for calls with a single string. +* [#928][]: Add support for filtering by field name to `zaptest/observer`. + +Thanks to @ash2k, @FMLS, @jimmystewpot, @Oncilla, @tsoslow, @tylitianrui, @withshubh, and @wziww for their contributions to this release. + +## 1.16.0 (1 Sep 2020) + +Bugfixes: +* [#828][]: Fix missing newline in IncreaseLevel error messages. +* [#835][]: Fix panic in JSON encoder when encoding times or durations +  without specifying a time or duration encoder. +* [#843][]: Honor CallerSkip when taking stack traces. +* [#862][]: Fix the default file permissions to use `0666` and rely on the umask instead. +* [#854][]: Encode `<nil>` for nil `Stringer` instead of a panic error log. + +Enhancements: +* [#629][]: Added `zapcore.TimeEncoderOfLayout` to easily create time encoders +  for custom layouts. +* [#697][]: Added support for a configurable delimiter in the console encoder. +* [#852][]: Optimize console encoder by pooling the underlying JSON encoder. +* [#844][]: Add ability to include the calling function as part of logs. +* [#843][]: Add `StackSkip` for including truncated stacks as a field. +* [#861][]: Add options to customize Fatal behaviour for better testability. + +Thanks to @SteelPhase, @tmshn, @lixingwang, @wyxloading, @moul, @segevfiner, @andy-retailnext and @jcorbin for their contributions to this release. + +## 1.15.0 (23 Apr 2020) + +Bugfixes: +* [#804][]: Fix handling of `Time` values out of `UnixNano` range. +* [#812][]: Fix `IncreaseLevel` being reset after a call to `With`. + +Enhancements: +* [#806][]: Add `WithCaller` option to supersede the `AddCaller` option. This +  allows disabling annotation of log entries with caller information if +  previously enabled with `AddCaller`. +* [#813][]: Deprecate `NewSampler` constructor in favor of +  `NewSamplerWithOptions` which supports a `SamplerHook` option. This option +   adds support for monitoring sampling decisions through a hook. + +Thanks to @danielbprice for their contributions to this release. + +## 1.14.1 (14 Mar 2020) + +Bugfixes: +* [#791][]: Fix panic on attempting to build a logger with an invalid Config. +* [#795][]: Vendoring Zap with `go mod vendor` no longer includes Zap's +  development-time dependencies. +* [#799][]: Fix issue introduced in 1.14.0 that caused invalid JSON output to +  be generated for arrays of `time.Time` objects when using string-based time +  formats. + +Thanks to @YashishDua for their contributions to this release. + +## 1.14.0 (20 Feb 2020) + +Enhancements: +* [#771][]: Optimize calls for disabled log levels. +* [#773][]: Add millisecond duration encoder. +* [#775][]: Add option to increase the level of a logger. +* [#786][]: Optimize time formatters using `Time.AppendFormat` where possible. + +Thanks to @caibirdme for their contributions to this release. + +## 1.13.0 (13 Nov 2019) + +Enhancements: +* [#758][]: Add `Intp`, `Stringp`, and other similar `*p` field constructors +  to log pointers to primitives with support for `nil` values. + +Thanks to @jbizzle for their contributions to this release. + +## 1.12.0 (29 Oct 2019) + +Enhancements: +* [#751][]: Migrate to Go modules. + +## 1.11.0 (21 Oct 2019) + +Enhancements: +* [#725][]: Add `zapcore.OmitKey` to omit keys in an `EncoderConfig`. +* [#736][]: Add `RFC3339` and `RFC3339Nano` time encoders. + +Thanks to @juicemia, @uhthomas for their contributions to this release. + +## 1.10.0 (29 Apr 2019) + +Bugfixes: +* [#657][]: Fix `MapObjectEncoder.AppendByteString` not adding value as a +  string. +* [#706][]: Fix incorrect call depth to determine caller in Go 1.12. + +Enhancements: +* [#610][]: Add `zaptest.WrapOptions` to wrap `zap.Option` for creating test +  loggers. +* [#675][]: Don't panic when encoding a String field. +* [#704][]: Disable HTML escaping for JSON objects encoded using the +  reflect-based encoder. + +Thanks to @iaroslav-ciupin, @lelenanam, @joa, @NWilson for their contributions +to this release. + +## v1.9.1 (06 Aug 2018) + +Bugfixes: + +* [#614][]: MapObjectEncoder should not ignore empty slices. + +## v1.9.0 (19 Jul 2018) + +Enhancements: +* [#602][]: Reduce number of allocations when logging with reflection. +* [#572][], [#606][]: Expose a registry for third-party logging sinks. + +Thanks to @nfarah86, @AlekSi, @JeanMertz, @philippgille, @etsangsplk, and +@dimroc for their contributions to this release. + +## v1.8.0 (13 Apr 2018) + +Enhancements: +* [#508][]: Make log level configurable when redirecting the standard +  library's logger. +* [#518][]: Add a logger that writes to a `*testing.TB`. +* [#577][]: Add a top-level alias for `zapcore.Field` to clean up GoDoc. + +Bugfixes: +* [#574][]: Add a missing import comment to `go.uber.org/zap/buffer`. + +Thanks to @DiSiqueira and @djui for their contributions to this release. + +## v1.7.1 (25 Sep 2017) + +Bugfixes: +* [#504][]: Store strings when using AddByteString with the map encoder. + +## v1.7.0 (21 Sep 2017) + +Enhancements: + +* [#487][]: Add `NewStdLogAt`, which extends `NewStdLog` by allowing the user +  to specify the level of the logged messages. + +## v1.6.0 (30 Aug 2017) + +Enhancements: + +* [#491][]: Omit zap stack frames from stacktraces. +* [#490][]: Add a `ContextMap` method to observer logs for simpler +  field validation in tests. + +## v1.5.0 (22 Jul 2017) + +Enhancements: + +* [#460][] and [#470][]: Support errors produced by `go.uber.org/multierr`. +* [#465][]: Support user-supplied encoders for logger names. + +Bugfixes: + +* [#477][]: Fix a bug that incorrectly truncated deep stacktraces. + +Thanks to @richard-tunein and @pavius for their contributions to this release. + +## v1.4.1 (08 Jun 2017) + +This release fixes two bugs. + +Bugfixes: + +* [#435][]: Support a variety of case conventions when unmarshaling levels. +* [#444][]: Fix a panic in the observer. + +## v1.4.0 (12 May 2017) + +This release adds a few small features and is fully backward-compatible. + +Enhancements: + +* [#424][]: Add a `LineEnding` field to `EncoderConfig`, allowing users to +  override the Unix-style default. +* [#425][]: Preserve time zones when logging times. +* [#431][]: Make `zap.AtomicLevel` implement `fmt.Stringer`, which makes a +  variety of operations a bit simpler. + +## v1.3.0 (25 Apr 2017) + +This release adds an enhancement to zap's testing helpers as well as the +ability to marshal an AtomicLevel. It is fully backward-compatible. + +Enhancements: + +* [#415][]: Add a substring-filtering helper to zap's observer. This is +  particularly useful when testing the `SugaredLogger`. +* [#416][]: Make `AtomicLevel` implement `encoding.TextMarshaler`. + +## v1.2.0 (13 Apr 2017) + +This release adds a gRPC compatibility wrapper. It is fully backward-compatible. + +Enhancements: + +* [#402][]: Add a `zapgrpc` package that wraps zap's Logger and implements +  `grpclog.Logger`. + +## v1.1.0 (31 Mar 2017) + +This release fixes two bugs and adds some enhancements to zap's testing helpers. +It is fully backward-compatible. + +Bugfixes: + +* [#385][]: Fix caller path trimming on Windows. +* [#396][]: Fix a panic when attempting to use non-existent directories with +  zap's configuration struct. + +Enhancements: + +* [#386][]: Add filtering helpers to zaptest's observing logger. + +Thanks to @moitias for contributing to this release. + +## v1.0.0 (14 Mar 2017) + +This is zap's first stable release. All exported APIs are now final, and no +further breaking changes will be made in the 1.x release series. Anyone using a +semver-aware dependency manager should now pin to `^1`. + +Breaking changes: + +* [#366][]: Add byte-oriented APIs to encoders to log UTF-8 encoded text without +  casting from `[]byte` to `string`. +* [#364][]: To support buffering outputs, add `Sync` methods to `zapcore.Core`, +  `zap.Logger`, and `zap.SugaredLogger`. +* [#371][]: Rename the `testutils` package to `zaptest`, which is less likely to +  clash with other testing helpers. + +Bugfixes: + +* [#362][]: Make the ISO8601 time formatters fixed-width, which is friendlier +  for tab-separated console output. +* [#369][]: Remove the automatic locks in `zapcore.NewCore`, which allows zap to +  work with concurrency-safe `WriteSyncer` implementations. +* [#347][]: Stop reporting errors when trying to `fsync` standard out on Linux +  systems. +* [#373][]: Report the correct caller from zap's standard library +  interoperability wrappers. + +Enhancements: + +* [#348][]: Add a registry allowing third-party encodings to work with zap's +  built-in `Config`. +* [#327][]: Make the representation of logger callers configurable (like times, +  levels, and durations). +* [#376][]: Allow third-party encoders to use their own buffer pools, which +  removes the last performance advantage that zap's encoders have over plugins. +* [#346][]: Add `CombineWriteSyncers`, a convenience function to tee multiple +  `WriteSyncer`s and lock the result. +* [#365][]: Make zap's stacktraces compatible with mid-stack inlining (coming in +  Go 1.9). +* [#372][]: Export zap's observing logger as `zaptest/observer`. This makes it +  easier for particularly punctilious users to unit test their application's +  logging. + +Thanks to @suyash, @htrendev, @flisky, @Ulexus, and @skipor for their +contributions to this release. + +## v1.0.0-rc.3 (7 Mar 2017) + +This is the third release candidate for zap's stable release. There are no +breaking changes. + +Bugfixes: + +* [#339][]: Byte slices passed to `zap.Any` are now correctly treated as binary blobs +  rather than `[]uint8`. + +Enhancements: + +* [#307][]: Users can opt into colored output for log levels. +* [#353][]: In addition to hijacking the output of the standard library's +  package-global logging functions, users can now construct a zap-backed +  `log.Logger` instance. +* [#311][]: Frames from common runtime functions and some of zap's internal +  machinery are now omitted from stacktraces. + +Thanks to @ansel1 and @suyash for their contributions to this release. + +## v1.0.0-rc.2 (21 Feb 2017) + +This is the second release candidate for zap's stable release. It includes two +breaking changes. + +Breaking changes: + +* [#316][]: Zap's global loggers are now fully concurrency-safe +  (previously, users had to ensure that `ReplaceGlobals` was called before the +  loggers were in use). However, they must now be accessed via the `L()` and +  `S()` functions. Users can update their projects with + +  ``` +  gofmt -r "zap.L -> zap.L()" -w . +  gofmt -r "zap.S -> zap.S()" -w . +  ``` +* [#309][] and [#317][]: RC1 was mistakenly shipped with invalid +  JSON and YAML struct tags on all config structs. This release fixes the tags +  and adds static analysis to prevent similar bugs in the future. + +Bugfixes: + +* [#321][]: Redirecting the standard library's `log` output now +  correctly reports the logger's caller. + +Enhancements: + +* [#325][] and [#333][]: Zap now transparently supports non-standard, rich +  errors like those produced by `github.com/pkg/errors`. +* [#326][]: Though `New(nil)` continues to return a no-op logger, `NewNop()` is +  now preferred. Users can update their projects with `gofmt -r 'zap.New(nil) -> +  zap.NewNop()' -w .`. +* [#300][]: Incorrectly importing zap as `github.com/uber-go/zap` now returns a +  more informative error. + +Thanks to @skipor and @chapsuk for their contributions to this release. + +## v1.0.0-rc.1 (14 Feb 2017) + +This is the first release candidate for zap's stable release. There are multiple +breaking changes and improvements from the pre-release version. Most notably: + +* **Zap's import path is now "go.uber.org/zap"** — all users will +  need to update their code. +* User-facing types and functions remain in the `zap` package. Code relevant +  largely to extension authors is now in the `zapcore` package. +* The `zapcore.Core` type makes it easy for third-party packages to use zap's +  internals but provide a different user-facing API. +* `Logger` is now a concrete type instead of an interface. +* A less verbose (though slower) logging API is included by default. +* Package-global loggers `L` and `S` are included. +* A human-friendly console encoder is included. +* A declarative config struct allows common logger configurations to be managed +  as configuration instead of code. +* Sampling is more accurate, and doesn't depend on the standard library's shared +  timer heap. + +## v0.1.0-beta.1 (6 Feb 2017) + +This is a minor version, tagged to allow users to pin to the pre-1.0 APIs and +upgrade at their leisure. Since this is the first tagged release, there are no +backward compatibility concerns and all functionality is new. + +Early zap adopters should pin to the 0.1.x minor version until they're ready to +upgrade to the upcoming stable release. + +[#316]: https://github.com/uber-go/zap/pull/316 +[#309]: https://github.com/uber-go/zap/pull/309 +[#317]: https://github.com/uber-go/zap/pull/317 +[#321]: https://github.com/uber-go/zap/pull/321 +[#325]: https://github.com/uber-go/zap/pull/325 +[#333]: https://github.com/uber-go/zap/pull/333 +[#326]: https://github.com/uber-go/zap/pull/326 +[#300]: https://github.com/uber-go/zap/pull/300 +[#339]: https://github.com/uber-go/zap/pull/339 +[#307]: https://github.com/uber-go/zap/pull/307 +[#353]: https://github.com/uber-go/zap/pull/353 +[#311]: https://github.com/uber-go/zap/pull/311 +[#366]: https://github.com/uber-go/zap/pull/366 +[#364]: https://github.com/uber-go/zap/pull/364 +[#371]: https://github.com/uber-go/zap/pull/371 +[#362]: https://github.com/uber-go/zap/pull/362 +[#369]: https://github.com/uber-go/zap/pull/369 +[#347]: https://github.com/uber-go/zap/pull/347 +[#373]: https://github.com/uber-go/zap/pull/373 +[#348]: https://github.com/uber-go/zap/pull/348 +[#327]: https://github.com/uber-go/zap/pull/327 +[#376]: https://github.com/uber-go/zap/pull/376 +[#346]: https://github.com/uber-go/zap/pull/346 +[#365]: https://github.com/uber-go/zap/pull/365 +[#372]: https://github.com/uber-go/zap/pull/372 +[#385]: https://github.com/uber-go/zap/pull/385 +[#396]: https://github.com/uber-go/zap/pull/396 +[#386]: https://github.com/uber-go/zap/pull/386 +[#402]: https://github.com/uber-go/zap/pull/402 +[#415]: https://github.com/uber-go/zap/pull/415 +[#416]: https://github.com/uber-go/zap/pull/416 +[#424]: https://github.com/uber-go/zap/pull/424 +[#425]: https://github.com/uber-go/zap/pull/425 +[#431]: https://github.com/uber-go/zap/pull/431 +[#435]: https://github.com/uber-go/zap/pull/435 +[#444]: https://github.com/uber-go/zap/pull/444 +[#477]: https://github.com/uber-go/zap/pull/477 +[#465]: https://github.com/uber-go/zap/pull/465 +[#460]: https://github.com/uber-go/zap/pull/460 +[#470]: https://github.com/uber-go/zap/pull/470 +[#487]: https://github.com/uber-go/zap/pull/487 +[#490]: https://github.com/uber-go/zap/pull/490 +[#491]: https://github.com/uber-go/zap/pull/491 +[#504]: https://github.com/uber-go/zap/pull/504 +[#508]: https://github.com/uber-go/zap/pull/508 +[#518]: https://github.com/uber-go/zap/pull/518 +[#577]: https://github.com/uber-go/zap/pull/577 +[#574]: https://github.com/uber-go/zap/pull/574 +[#602]: https://github.com/uber-go/zap/pull/602 +[#572]: https://github.com/uber-go/zap/pull/572 +[#606]: https://github.com/uber-go/zap/pull/606 +[#614]: https://github.com/uber-go/zap/pull/614 +[#657]: https://github.com/uber-go/zap/pull/657 +[#706]: https://github.com/uber-go/zap/pull/706 +[#610]: https://github.com/uber-go/zap/pull/610 +[#675]: https://github.com/uber-go/zap/pull/675 +[#704]: https://github.com/uber-go/zap/pull/704 +[#725]: https://github.com/uber-go/zap/pull/725 +[#736]: https://github.com/uber-go/zap/pull/736 +[#751]: https://github.com/uber-go/zap/pull/751 +[#758]: https://github.com/uber-go/zap/pull/758 +[#771]: https://github.com/uber-go/zap/pull/771 +[#773]: https://github.com/uber-go/zap/pull/773 +[#775]: https://github.com/uber-go/zap/pull/775 +[#786]: https://github.com/uber-go/zap/pull/786 +[#791]: https://github.com/uber-go/zap/pull/791 +[#795]: https://github.com/uber-go/zap/pull/795 +[#799]: https://github.com/uber-go/zap/pull/799 +[#804]: https://github.com/uber-go/zap/pull/804 +[#812]: https://github.com/uber-go/zap/pull/812 +[#806]: https://github.com/uber-go/zap/pull/806 +[#813]: https://github.com/uber-go/zap/pull/813 +[#629]: https://github.com/uber-go/zap/pull/629 +[#697]: https://github.com/uber-go/zap/pull/697 +[#828]: https://github.com/uber-go/zap/pull/828 +[#835]: https://github.com/uber-go/zap/pull/835 +[#843]: https://github.com/uber-go/zap/pull/843 +[#844]: https://github.com/uber-go/zap/pull/844 +[#852]: https://github.com/uber-go/zap/pull/852 +[#854]: https://github.com/uber-go/zap/pull/854 +[#861]: https://github.com/uber-go/zap/pull/861 +[#862]: https://github.com/uber-go/zap/pull/862 +[#865]: https://github.com/uber-go/zap/pull/865 +[#867]: https://github.com/uber-go/zap/pull/867 +[#881]: https://github.com/uber-go/zap/pull/881 +[#903]: https://github.com/uber-go/zap/pull/903 +[#912]: https://github.com/uber-go/zap/pull/912 +[#913]: https://github.com/uber-go/zap/pull/913 +[#928]: https://github.com/uber-go/zap/pull/928 +[#931]: https://github.com/uber-go/zap/pull/931 +[#936]: https://github.com/uber-go/zap/pull/936 diff --git a/vendor/go.uber.org/zap/CODE_OF_CONDUCT.md b/vendor/go.uber.org/zap/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..e327d9a --- /dev/null +++ b/vendor/go.uber.org/zap/CODE_OF_CONDUCT.md @@ -0,0 +1,75 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as +contributors and maintainers pledge to making participation in our project and +our community a harassment-free experience for everyone, regardless of age, +body size, disability, ethnicity, gender identity and expression, level of +experience, nationality, personal appearance, race, religion, or sexual +identity and orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment +include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or +  advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic +  address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a +  professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable +behavior and are expected to take appropriate and fair corrective action in +response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or +reject comments, commits, code, wiki edits, issues, and other contributions +that are not aligned to this Code of Conduct, or to ban temporarily or +permanently any contributor for other behaviors that they deem inappropriate, +threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces +when an individual is representing the project or its community. Examples of +representing a project or community include using an official project e-mail +address, posting via an official social media account, or acting as an +appointed representative at an online or offline event. Representation of a +project may be further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported by contacting the project team at oss-conduct@uber.com. The project +team will review and investigate all complaints, and will respond in a way +that it deems appropriate to the circumstances. The project team is obligated +to maintain confidentiality with regard to the reporter of an incident. +Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good +faith may face temporary or permanent repercussions as determined by other +members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], +version 1.4, available at +[http://contributor-covenant.org/version/1/4][version]. + +[homepage]: http://contributor-covenant.org +[version]: http://contributor-covenant.org/version/1/4/ diff --git a/vendor/go.uber.org/zap/CONTRIBUTING.md b/vendor/go.uber.org/zap/CONTRIBUTING.md new file mode 100644 index 0000000..ea02f3c --- /dev/null +++ b/vendor/go.uber.org/zap/CONTRIBUTING.md @@ -0,0 +1,70 @@ +# Contributing + +We'd love your help making zap the very best structured logging library in Go! + +If you'd like to add new exported APIs, please [open an issue][open-issue] +describing your proposal — discussing API changes ahead of time makes +pull request review much smoother. In your issue, pull request, and any other +communications, please remember to treat your fellow contributors with +respect! We take our [code of conduct](CODE_OF_CONDUCT.md) seriously. + +Note that you'll need to sign [Uber's Contributor License Agreement][cla] +before we can accept any of your contributions. If necessary, a bot will remind +you to accept the CLA when you open your pull request. + +## Setup + +[Fork][fork], then clone the repository: + +```bash +mkdir -p $GOPATH/src/go.uber.org +cd $GOPATH/src/go.uber.org +git clone git@github.com:your_github_username/zap.git +cd zap +git remote add upstream https://github.com/uber-go/zap.git +git fetch upstream +``` + +Make sure that the tests and the linters pass: + +```bash +make test +make lint +``` + +## Making Changes + +Start by creating a new branch for your changes: + +```bash +cd $GOPATH/src/go.uber.org/zap +git checkout master +git fetch upstream +git rebase upstream/master +git checkout -b cool_new_feature +``` + +Make your changes, then ensure that `make lint` and `make test` still pass. If +you're satisfied with your changes, push them to your fork. + +```bash +git push origin cool_new_feature +``` + +Then use the GitHub UI to open a pull request. + +At this point, you're waiting on us to review your changes. We _try_ to respond +to issues and pull requests within a few business days, and we may suggest some +improvements or alternatives. Once your changes are approved, one of the +project maintainers will merge them. + +We're much more likely to approve your changes if you: + +- Add tests for new functionality. +- Write a [good commit message][commit-message]. +- Maintain backward compatibility. + +[fork]: https://github.com/uber-go/zap/fork +[open-issue]: https://github.com/uber-go/zap/issues/new +[cla]: https://cla-assistant.io/uber-go/zap +[commit-message]: http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html diff --git a/vendor/go.uber.org/zap/FAQ.md b/vendor/go.uber.org/zap/FAQ.md new file mode 100644 index 0000000..b183b20 --- /dev/null +++ b/vendor/go.uber.org/zap/FAQ.md @@ -0,0 +1,164 @@ +# 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 are some of my logs missing? + +Logs are dropped intentionally by zap when sampling is enabled. The production +configuration (as returned by `NewProductionConfig()` enables sampling which will +cause repeated logs within a second to be sampled. See more details on why sampling +is enabled in [Why sample application logs](https://github.com/uber-go/zap/blob/master/FAQ.md#why-sample-application-logs). + +### 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 | +| `github.com/moul/zapgorm` | Gorm | +| `github.com/moul/zapfilter` | Advanced filtering rules | + +[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 diff --git a/vendor/go.uber.org/zap/LICENSE.txt b/vendor/go.uber.org/zap/LICENSE.txt new file mode 100644 index 0000000..6652bed --- /dev/null +++ b/vendor/go.uber.org/zap/LICENSE.txt @@ -0,0 +1,19 @@ +Copyright (c) 2016-2017 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. diff --git a/vendor/go.uber.org/zap/Makefile b/vendor/go.uber.org/zap/Makefile new file mode 100644 index 0000000..9b1bc3b --- /dev/null +++ b/vendor/go.uber.org/zap/Makefile @@ -0,0 +1,73 @@ +export GOBIN ?= $(shell pwd)/bin + +GOLINT = $(GOBIN)/golint +STATICCHECK = $(GOBIN)/staticcheck +BENCH_FLAGS ?= -cpuprofile=cpu.pprof -memprofile=mem.pprof -benchmem + +# Directories containing independent Go modules. +# +# We track coverage only for the main module. +MODULE_DIRS = . ./benchmarks ./zapgrpc/internal/test + +# Many Go tools take file globs or directories as arguments instead of packages. +GO_FILES := $(shell \ +	find . '(' -path '*/.*' -o -path './vendor' ')' -prune \ +	-o -name '*.go' -print | cut -b3-) + +.PHONY: all +all: lint test + +.PHONY: lint +lint: $(GOLINT) $(STATICCHECK) +	@rm -rf lint.log +	@echo "Checking formatting..." +	@gofmt -d -s $(GO_FILES) 2>&1 | tee lint.log +	@echo "Checking vet..." +	@$(foreach dir,$(MODULE_DIRS),(cd $(dir) && go vet ./... 2>&1) &&) true | tee -a lint.log +	@echo "Checking lint..." +	@$(foreach dir,$(MODULE_DIRS),(cd $(dir) && $(GOLINT) ./... 2>&1) &&) true | tee -a lint.log +	@echo "Checking staticcheck..." +	@$(foreach dir,$(MODULE_DIRS),(cd $(dir) && $(STATICCHECK) ./... 2>&1) &&) true | tee -a lint.log +	@echo "Checking for unresolved FIXMEs..." +	@git grep -i fixme | grep -v -e Makefile | tee -a lint.log +	@echo "Checking for license headers..." +	@./checklicense.sh | tee -a lint.log +	@[ ! -s lint.log ] +	@echo "Checking 'go mod tidy'..." +	@make tidy +	@if ! git diff --quiet; then \ +		echo "'go mod tidy' resulted in changes or working tree is dirty:"; \ +		git --no-pager diff; \ +	fi + +$(GOLINT): +	cd tools && go install golang.org/x/lint/golint + +$(STATICCHECK): +	cd tools && go install honnef.co/go/tools/cmd/staticcheck + +.PHONY: test +test: +	@$(foreach dir,$(MODULE_DIRS),(cd $(dir) && go test -race ./...) &&) true + +.PHONY: cover +cover: +	go test -race -coverprofile=cover.out -coverpkg=./... ./... +	go tool cover -html=cover.out -o cover.html + +.PHONY: bench +BENCH ?= . +bench: +	@$(foreach dir,$(MODULE_DIRS), ( \ +		cd $(dir) && \ +		go list ./... | xargs -n1 go test -bench=$(BENCH) -run="^$$" $(BENCH_FLAGS) \ +	) &&) true + +.PHONY: updatereadme +updatereadme: +	rm -f README.md +	cat .readme.tmpl | go run internal/readme/readme.go > README.md + +.PHONY: tidy +tidy: +	@$(foreach dir,$(MODULE_DIRS),(cd $(dir) && go mod tidy) &&) true diff --git a/vendor/go.uber.org/zap/README.md b/vendor/go.uber.org/zap/README.md new file mode 100644 index 0000000..a553a42 --- /dev/null +++ b/vendor/go.uber.org/zap/README.md @@ -0,0 +1,133 @@ +# :zap: zap [![GoDoc][doc-img]][doc] [![Build Status][ci-img]][ci] [![Coverage Status][cov-img]][cov] + +Blazing fast, structured, leveled logging in Go. + +## Installation + +`go get -u go.uber.org/zap` + +Note that zap only supports the two most recent minor versions of Go. + +## Quick Start + +In contexts where performance is nice, but not critical, use the +`SugaredLogger`. It's 4-10x faster than other structured logging +packages and includes both structured and `printf`-style APIs. + +```go +logger, _ := zap.NewProduction() +defer logger.Sync() // flushes buffer, if any +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) +``` + +When performance and type safety are critical, use the `Logger`. It's even +faster than the `SugaredLogger` and allocates far less, but it only supports +structured logging. + +```go +logger, _ := zap.NewProduction() +defer logger.Sync() +logger.Info("failed to fetch URL", +  // Structured context as strongly typed Field values. +  zap.String("url", url), +  zap.Int("attempt", 3), +  zap.Duration("backoff", time.Second), +) +``` + +See the [documentation][doc] and [FAQ](FAQ.md) for more details. + +## Performance + +For applications that log in the hot path, reflection-based serialization and +string formatting are prohibitively expensive — they're CPU-intensive +and make many small allocations. Put differently, using `encoding/json` and +`fmt.Fprintf` to log tons of `interface{}`s makes your application slow. + +Zap takes a different approach. It includes a reflection-free, zero-allocation +JSON encoder, and the base `Logger` strives to avoid serialization overhead +and allocations wherever possible. By building the high-level `SugaredLogger` +on that foundation, zap lets users _choose_ when they need to count every +allocation and when they'd prefer a more familiar, loosely typed API. + +As measured by its own [benchmarking suite][], not only is zap more performant +than comparable structured logging packages — it's also faster than the +standard library. Like all benchmarks, take these with a grain of salt.<sup +id="anchor-versions">[1](#footnote-versions)</sup> + +Log a message and 10 fields: + +| Package             |    Time     | Time % to zap | Objects Allocated | +| :------------------ | :---------: | :-----------: | :---------------: | +| :zap: zap           | 2900 ns/op  |      +0%      |    5 allocs/op    | +| :zap: zap (sugared) | 3475 ns/op  |     +20%      |   10 allocs/op    | +| zerolog             | 10639 ns/op |     +267%     |   32 allocs/op    | +| go-kit              | 14434 ns/op |     +398%     |   59 allocs/op    | +| logrus              | 17104 ns/op |     +490%     |   81 allocs/op    | +| apex/log            | 32424 ns/op |    +1018%     |   66 allocs/op    | +| log15               | 33579 ns/op |    +1058%     |   76 allocs/op    | + +Log a message with a logger that already has 10 fields of context: + +| Package             |    Time     | Time % to zap | Objects Allocated | +| :------------------ | :---------: | :-----------: | :---------------: | +| :zap: zap           |  373 ns/op  |      +0%      |    0 allocs/op    | +| :zap: zap (sugared) |  452 ns/op  |     +21%      |    1 allocs/op    | +| zerolog             |  288 ns/op  |     -23%      |    0 allocs/op    | +| go-kit              | 11785 ns/op |    +3060%     |   58 allocs/op    | +| logrus              | 19629 ns/op |    +5162%     |   70 allocs/op    | +| log15               | 21866 ns/op |    +5762%     |   72 allocs/op    | +| apex/log            | 30890 ns/op |    +8182%     |   55 allocs/op    | + +Log a static string, without any context or `printf`-style templating: + +| Package             |    Time    | Time % to zap | Objects Allocated | +| :------------------ | :--------: | :-----------: | :---------------: | +| :zap: zap           | 381 ns/op  |      +0%      |    0 allocs/op    | +| :zap: zap (sugared) | 410 ns/op  |      +8%      |    1 allocs/op    | +| zerolog             | 369 ns/op  |      -3%      |    0 allocs/op    | +| standard library    | 385 ns/op  |      +1%      |    2 allocs/op    | +| go-kit              | 606 ns/op  |     +59%      |   11 allocs/op    | +| logrus              | 1730 ns/op |     +354%     |   25 allocs/op    | +| apex/log            | 1998 ns/op |     +424%     |    7 allocs/op    | +| log15               | 4546 ns/op |    +1093%     |   22 allocs/op    | + +## Development Status: Stable + +All APIs are finalized, and no breaking changes will be made in the 1.x series +of releases. Users of semver-aware dependency management systems should pin +zap to `^1`. + +## Contributing + +We encourage and support an active, healthy community of contributors — +including you! Details are in the [contribution guide](CONTRIBUTING.md) and +the [code of conduct](CODE_OF_CONDUCT.md). The zap maintainers keep an eye on +issues and pull requests, but you can also report any negative conduct to +oss-conduct@uber.com. That email list is a private, safe space; even the zap +maintainers don't have access, so don't hesitate to hold us to a high +standard. + +<hr> + +Released under the [MIT License](LICENSE.txt). + +<sup id="footnote-versions">1</sup> In particular, keep in mind that we may be +benchmarking against slightly older versions of other packages. Versions are +pinned in the [benchmarks/go.mod][] file. [↩](#anchor-versions) + +[doc-img]: https://pkg.go.dev/badge/go.uber.org/zap +[doc]: https://pkg.go.dev/go.uber.org/zap +[ci-img]: https://github.com/uber-go/zap/actions/workflows/go.yml/badge.svg +[ci]: https://github.com/uber-go/zap/actions/workflows/go.yml +[cov-img]: https://codecov.io/gh/uber-go/zap/branch/master/graph/badge.svg +[cov]: https://codecov.io/gh/uber-go/zap +[benchmarking suite]: https://github.com/uber-go/zap/tree/master/benchmarks +[benchmarks/go.mod]: https://github.com/uber-go/zap/blob/master/benchmarks/go.mod diff --git a/vendor/go.uber.org/zap/array.go b/vendor/go.uber.org/zap/array.go new file mode 100644 index 0000000..5be3704 --- /dev/null +++ b/vendor/go.uber.org/zap/array.go @@ -0,0 +1,320 @@ +// 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 + +import ( +	"time" + +	"go.uber.org/zap/zapcore" +) + +// Array constructs a field with the given key and ArrayMarshaler. It provides +// a flexible, but still type-safe and efficient, way to add array-like types +// to the logging context. The struct's MarshalLogArray method is called lazily. +func Array(key string, val zapcore.ArrayMarshaler) Field { +	return Field{Key: key, Type: zapcore.ArrayMarshalerType, Interface: val} +} + +// Bools constructs a field that carries a slice of bools. +func Bools(key string, bs []bool) Field { +	return Array(key, bools(bs)) +} + +// ByteStrings constructs a field that carries a slice of []byte, each of which +// must be UTF-8 encoded text. +func ByteStrings(key string, bss [][]byte) Field { +	return Array(key, byteStringsArray(bss)) +} + +// Complex128s constructs a field that carries a slice of complex numbers. +func Complex128s(key string, nums []complex128) Field { +	return Array(key, complex128s(nums)) +} + +// Complex64s constructs a field that carries a slice of complex numbers. +func Complex64s(key string, nums []complex64) Field { +	return Array(key, complex64s(nums)) +} + +// Durations constructs a field that carries a slice of time.Durations. +func Durations(key string, ds []time.Duration) Field { +	return Array(key, durations(ds)) +} + +// Float64s constructs a field that carries a slice of floats. +func Float64s(key string, nums []float64) Field { +	return Array(key, float64s(nums)) +} + +// Float32s constructs a field that carries a slice of floats. +func Float32s(key string, nums []float32) Field { +	return Array(key, float32s(nums)) +} + +// Ints constructs a field that carries a slice of integers. +func Ints(key string, nums []int) Field { +	return Array(key, ints(nums)) +} + +// Int64s constructs a field that carries a slice of integers. +func Int64s(key string, nums []int64) Field { +	return Array(key, int64s(nums)) +} + +// Int32s constructs a field that carries a slice of integers. +func Int32s(key string, nums []int32) Field { +	return Array(key, int32s(nums)) +} + +// Int16s constructs a field that carries a slice of integers. +func Int16s(key string, nums []int16) Field { +	return Array(key, int16s(nums)) +} + +// Int8s constructs a field that carries a slice of integers. +func Int8s(key string, nums []int8) Field { +	return Array(key, int8s(nums)) +} + +// Strings constructs a field that carries a slice of strings. +func Strings(key string, ss []string) Field { +	return Array(key, stringArray(ss)) +} + +// Times constructs a field that carries a slice of time.Times. +func Times(key string, ts []time.Time) Field { +	return Array(key, times(ts)) +} + +// Uints constructs a field that carries a slice of unsigned integers. +func Uints(key string, nums []uint) Field { +	return Array(key, uints(nums)) +} + +// Uint64s constructs a field that carries a slice of unsigned integers. +func Uint64s(key string, nums []uint64) Field { +	return Array(key, uint64s(nums)) +} + +// Uint32s constructs a field that carries a slice of unsigned integers. +func Uint32s(key string, nums []uint32) Field { +	return Array(key, uint32s(nums)) +} + +// Uint16s constructs a field that carries a slice of unsigned integers. +func Uint16s(key string, nums []uint16) Field { +	return Array(key, uint16s(nums)) +} + +// Uint8s constructs a field that carries a slice of unsigned integers. +func Uint8s(key string, nums []uint8) Field { +	return Array(key, uint8s(nums)) +} + +// Uintptrs constructs a field that carries a slice of pointer addresses. +func Uintptrs(key string, us []uintptr) Field { +	return Array(key, uintptrs(us)) +} + +// Errors constructs a field that carries a slice of errors. +func Errors(key string, errs []error) Field { +	return Array(key, errArray(errs)) +} + +type bools []bool + +func (bs bools) MarshalLogArray(arr zapcore.ArrayEncoder) error { +	for i := range bs { +		arr.AppendBool(bs[i]) +	} +	return nil +} + +type byteStringsArray [][]byte + +func (bss byteStringsArray) MarshalLogArray(arr zapcore.ArrayEncoder) error { +	for i := range bss { +		arr.AppendByteString(bss[i]) +	} +	return nil +} + +type complex128s []complex128 + +func (nums complex128s) MarshalLogArray(arr zapcore.ArrayEncoder) error { +	for i := range nums { +		arr.AppendComplex128(nums[i]) +	} +	return nil +} + +type complex64s []complex64 + +func (nums complex64s) MarshalLogArray(arr zapcore.ArrayEncoder) error { +	for i := range nums { +		arr.AppendComplex64(nums[i]) +	} +	return nil +} + +type durations []time.Duration + +func (ds durations) MarshalLogArray(arr zapcore.ArrayEncoder) error { +	for i := range ds { +		arr.AppendDuration(ds[i]) +	} +	return nil +} + +type float64s []float64 + +func (nums float64s) MarshalLogArray(arr zapcore.ArrayEncoder) error { +	for i := range nums { +		arr.AppendFloat64(nums[i]) +	} +	return nil +} + +type float32s []float32 + +func (nums float32s) MarshalLogArray(arr zapcore.ArrayEncoder) error { +	for i := range nums { +		arr.AppendFloat32(nums[i]) +	} +	return nil +} + +type ints []int + +func (nums ints) MarshalLogArray(arr zapcore.ArrayEncoder) error { +	for i := range nums { +		arr.AppendInt(nums[i]) +	} +	return nil +} + +type int64s []int64 + +func (nums int64s) MarshalLogArray(arr zapcore.ArrayEncoder) error { +	for i := range nums { +		arr.AppendInt64(nums[i]) +	} +	return nil +} + +type int32s []int32 + +func (nums int32s) MarshalLogArray(arr zapcore.ArrayEncoder) error { +	for i := range nums { +		arr.AppendInt32(nums[i]) +	} +	return nil +} + +type int16s []int16 + +func (nums int16s) MarshalLogArray(arr zapcore.ArrayEncoder) error { +	for i := range nums { +		arr.AppendInt16(nums[i]) +	} +	return nil +} + +type int8s []int8 + +func (nums int8s) MarshalLogArray(arr zapcore.ArrayEncoder) error { +	for i := range nums { +		arr.AppendInt8(nums[i]) +	} +	return nil +} + +type stringArray []string + +func (ss stringArray) MarshalLogArray(arr zapcore.ArrayEncoder) error { +	for i := range ss { +		arr.AppendString(ss[i]) +	} +	return nil +} + +type times []time.Time + +func (ts times) MarshalLogArray(arr zapcore.ArrayEncoder) error { +	for i := range ts { +		arr.AppendTime(ts[i]) +	} +	return nil +} + +type uints []uint + +func (nums uints) MarshalLogArray(arr zapcore.ArrayEncoder) error { +	for i := range nums { +		arr.AppendUint(nums[i]) +	} +	return nil +} + +type uint64s []uint64 + +func (nums uint64s) MarshalLogArray(arr zapcore.ArrayEncoder) error { +	for i := range nums { +		arr.AppendUint64(nums[i]) +	} +	return nil +} + +type uint32s []uint32 + +func (nums uint32s) MarshalLogArray(arr zapcore.ArrayEncoder) error { +	for i := range nums { +		arr.AppendUint32(nums[i]) +	} +	return nil +} + +type uint16s []uint16 + +func (nums uint16s) MarshalLogArray(arr zapcore.ArrayEncoder) error { +	for i := range nums { +		arr.AppendUint16(nums[i]) +	} +	return nil +} + +type uint8s []uint8 + +func (nums uint8s) MarshalLogArray(arr zapcore.ArrayEncoder) error { +	for i := range nums { +		arr.AppendUint8(nums[i]) +	} +	return nil +} + +type uintptrs []uintptr + +func (nums uintptrs) MarshalLogArray(arr zapcore.ArrayEncoder) error { +	for i := range nums { +		arr.AppendUintptr(nums[i]) +	} +	return nil +} diff --git a/vendor/go.uber.org/zap/array_go118.go b/vendor/go.uber.org/zap/array_go118.go new file mode 100644 index 0000000..d0d2c49 --- /dev/null +++ b/vendor/go.uber.org/zap/array_go118.go @@ -0,0 +1,156 @@ +// Copyright (c) 2022 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. + +//go:build go1.18 +// +build go1.18 + +package zap + +import ( +	"fmt" + +	"go.uber.org/zap/zapcore" +) + +// Objects constructs a field with the given key, holding a list of the +// provided objects that can be marshaled by Zap. +// +// Note that these objects must implement zapcore.ObjectMarshaler directly. +// That is, if you're trying to marshal a []Request, the MarshalLogObject +// method must be declared on the Request type, not its pointer (*Request). +// If it's on the pointer, use ObjectValues. +// +// Given an object that implements MarshalLogObject on the value receiver, you +// can log a slice of those objects with Objects like so: +// +//	type Author struct{ ... } +//	func (a Author) MarshalLogObject(enc zapcore.ObjectEncoder) error +// +//	var authors []Author = ... +//	logger.Info("loading article", zap.Objects("authors", authors)) +// +// Similarly, given a type that implements MarshalLogObject on its pointer +// receiver, you can log a slice of pointers to that object with Objects like +// so: +// +//	type Request struct{ ... } +//	func (r *Request) MarshalLogObject(enc zapcore.ObjectEncoder) error +// +//	var requests []*Request = ... +//	logger.Info("sending requests", zap.Objects("requests", requests)) +// +// If instead, you have a slice of values of such an object, use the +// ObjectValues constructor. +// +//	var requests []Request = ... +//	logger.Info("sending requests", zap.ObjectValues("requests", requests)) +func Objects[T zapcore.ObjectMarshaler](key string, values []T) Field { +	return Array(key, objects[T](values)) +} + +type objects[T zapcore.ObjectMarshaler] []T + +func (os objects[T]) MarshalLogArray(arr zapcore.ArrayEncoder) error { +	for _, o := range os { +		if err := arr.AppendObject(o); err != nil { +			return err +		} +	} +	return nil +} + +// ObjectMarshalerPtr is a constraint that specifies that the given type +// implements zapcore.ObjectMarshaler on a pointer receiver. +type ObjectMarshalerPtr[T any] interface { +	*T +	zapcore.ObjectMarshaler +} + +// ObjectValues constructs a field with the given key, holding a list of the +// provided objects, where pointers to these objects can be marshaled by Zap. +// +// Note that pointers to these objects must implement zapcore.ObjectMarshaler. +// That is, if you're trying to marshal a []Request, the MarshalLogObject +// method must be declared on the *Request type, not the value (Request). +// If it's on the value, use Objects. +// +// Given an object that implements MarshalLogObject on the pointer receiver, +// you can log a slice of those objects with ObjectValues like so: +// +//	type Request struct{ ... } +//	func (r *Request) MarshalLogObject(enc zapcore.ObjectEncoder) error +// +//	var requests []Request = ... +//	logger.Info("sending requests", zap.ObjectValues("requests", requests)) +// +// If instead, you have a slice of pointers of such an object, use the Objects +// field constructor. +// +//	var requests []*Request = ... +//	logger.Info("sending requests", zap.Objects("requests", requests)) +func ObjectValues[T any, P ObjectMarshalerPtr[T]](key string, values []T) Field { +	return Array(key, objectValues[T, P](values)) +} + +type objectValues[T any, P ObjectMarshalerPtr[T]] []T + +func (os objectValues[T, P]) MarshalLogArray(arr zapcore.ArrayEncoder) error { +	for i := range os { +		// It is necessary for us to explicitly reference the "P" type. +		// We cannot simply pass "&os[i]" to AppendObject because its type +		// is "*T", which the type system does not consider as +		// implementing ObjectMarshaler. +		// Only the type "P" satisfies ObjectMarshaler, which we have +		// to convert "*T" to explicitly. +		var p P = &os[i] +		if err := arr.AppendObject(p); err != nil { +			return err +		} +	} +	return nil +} + +// Stringers constructs a field with the given key, holding a list of the +// output provided by the value's String method +// +// Given an object that implements String on the value receiver, you +// can log a slice of those objects with Objects like so: +// +//	type Request struct{ ... } +//	func (a Request) String() string +// +//	var requests []Request = ... +//	logger.Info("sending requests", zap.Stringers("requests", requests)) +// +// Note that these objects must implement fmt.Stringer directly. +// That is, if you're trying to marshal a []Request, the String method +// must be declared on the Request type, not its pointer (*Request). +func Stringers[T fmt.Stringer](key string, values []T) Field { +	return Array(key, stringers[T](values)) +} + +type stringers[T fmt.Stringer] []T + +func (os stringers[T]) MarshalLogArray(arr zapcore.ArrayEncoder) error { +	for _, o := range os { +		arr.AppendString(o.String()) +	} +	return nil +} diff --git a/vendor/go.uber.org/zap/buffer/buffer.go b/vendor/go.uber.org/zap/buffer/buffer.go new file mode 100644 index 0000000..9e929cd --- /dev/null +++ b/vendor/go.uber.org/zap/buffer/buffer.go @@ -0,0 +1,141 @@ +// 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 buffer provides a thin wrapper around a byte slice. Unlike the +// standard library's bytes.Buffer, it supports a portion of the strconv +// package's zero-allocation formatters. +package buffer // import "go.uber.org/zap/buffer" + +import ( +	"strconv" +	"time" +) + +const _size = 1024 // by default, create 1 KiB buffers + +// Buffer is a thin wrapper around a byte slice. It's intended to be pooled, so +// the only way to construct one is via a Pool. +type Buffer struct { +	bs   []byte +	pool Pool +} + +// AppendByte writes a single byte to the Buffer. +func (b *Buffer) AppendByte(v byte) { +	b.bs = append(b.bs, v) +} + +// AppendString writes a string to the Buffer. +func (b *Buffer) AppendString(s string) { +	b.bs = append(b.bs, s...) +} + +// AppendInt appends an integer to the underlying buffer (assuming base 10). +func (b *Buffer) AppendInt(i int64) { +	b.bs = strconv.AppendInt(b.bs, i, 10) +} + +// AppendTime appends the time formatted using the specified layout. +func (b *Buffer) AppendTime(t time.Time, layout string) { +	b.bs = t.AppendFormat(b.bs, layout) +} + +// AppendUint appends an unsigned integer to the underlying buffer (assuming +// base 10). +func (b *Buffer) AppendUint(i uint64) { +	b.bs = strconv.AppendUint(b.bs, i, 10) +} + +// AppendBool appends a bool to the underlying buffer. +func (b *Buffer) AppendBool(v bool) { +	b.bs = strconv.AppendBool(b.bs, v) +} + +// AppendFloat appends a float to the underlying buffer. It doesn't quote NaN +// or +/- Inf. +func (b *Buffer) AppendFloat(f float64, bitSize int) { +	b.bs = strconv.AppendFloat(b.bs, f, 'f', -1, bitSize) +} + +// Len returns the length of the underlying byte slice. +func (b *Buffer) Len() int { +	return len(b.bs) +} + +// Cap returns the capacity of the underlying byte slice. +func (b *Buffer) Cap() int { +	return cap(b.bs) +} + +// Bytes returns a mutable reference to the underlying byte slice. +func (b *Buffer) Bytes() []byte { +	return b.bs +} + +// String returns a string copy of the underlying byte slice. +func (b *Buffer) String() string { +	return string(b.bs) +} + +// Reset resets the underlying byte slice. Subsequent writes re-use the slice's +// backing array. +func (b *Buffer) Reset() { +	b.bs = b.bs[:0] +} + +// Write implements io.Writer. +func (b *Buffer) Write(bs []byte) (int, error) { +	b.bs = append(b.bs, bs...) +	return len(bs), nil +} + +// WriteByte writes a single byte to the Buffer. +// +// Error returned is always nil, function signature is compatible +// with bytes.Buffer and bufio.Writer +func (b *Buffer) WriteByte(v byte) error { +	b.AppendByte(v) +	return nil +} + +// WriteString writes a string to the Buffer. +// +// Error returned is always nil, function signature is compatible +// with bytes.Buffer and bufio.Writer +func (b *Buffer) WriteString(s string) (int, error) { +	b.AppendString(s) +	return len(s), nil +} + +// TrimNewline trims any final "\n" byte from the end of the buffer. +func (b *Buffer) TrimNewline() { +	if i := len(b.bs) - 1; i >= 0 { +		if b.bs[i] == '\n' { +			b.bs = b.bs[:i] +		} +	} +} + +// Free returns the Buffer to its Pool. +// +// Callers must not retain references to the Buffer after calling Free. +func (b *Buffer) Free() { +	b.pool.put(b) +} diff --git a/vendor/go.uber.org/zap/buffer/pool.go b/vendor/go.uber.org/zap/buffer/pool.go new file mode 100644 index 0000000..8fb3e20 --- /dev/null +++ b/vendor/go.uber.org/zap/buffer/pool.go @@ -0,0 +1,49 @@ +// 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 buffer + +import "sync" + +// A Pool is a type-safe wrapper around a sync.Pool. +type Pool struct { +	p *sync.Pool +} + +// NewPool constructs a new Pool. +func NewPool() Pool { +	return Pool{p: &sync.Pool{ +		New: func() interface{} { +			return &Buffer{bs: make([]byte, 0, _size)} +		}, +	}} +} + +// Get retrieves a Buffer from the pool, creating one if necessary. +func (p Pool) Get() *Buffer { +	buf := p.p.Get().(*Buffer) +	buf.Reset() +	buf.pool = p +	return buf +} + +func (p Pool) put(buf *Buffer) { +	p.p.Put(buf) +} diff --git a/vendor/go.uber.org/zap/checklicense.sh b/vendor/go.uber.org/zap/checklicense.sh new file mode 100644 index 0000000..345ac8b --- /dev/null +++ b/vendor/go.uber.org/zap/checklicense.sh @@ -0,0 +1,17 @@ +#!/bin/bash -e + +ERROR_COUNT=0 +while read -r file +do +	case "$(head -1 "${file}")" in +		*"Copyright (c) "*" Uber Technologies, Inc.") +			# everything's cool +			;; +		*) +			echo "$file is missing license header." +			(( ERROR_COUNT++ )) +			;; +	esac +done < <(git ls-files "*\.go") + +exit $ERROR_COUNT diff --git a/vendor/go.uber.org/zap/config.go b/vendor/go.uber.org/zap/config.go new file mode 100644 index 0000000..ee60967 --- /dev/null +++ b/vendor/go.uber.org/zap/config.go @@ -0,0 +1,264 @@ +// 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 + +import ( +	"errors" +	"sort" +	"time" + +	"go.uber.org/zap/zapcore" +) + +// SamplingConfig sets a sampling strategy for the logger. Sampling caps the +// global CPU and I/O load that logging puts on your process while attempting +// to preserve a representative subset of your logs. +// +// If specified, the Sampler will invoke the Hook after each decision. +// +// Values configured here are per-second. See zapcore.NewSamplerWithOptions for +// details. +type SamplingConfig struct { +	Initial    int                                           `json:"initial" yaml:"initial"` +	Thereafter int                                           `json:"thereafter" yaml:"thereafter"` +	Hook       func(zapcore.Entry, zapcore.SamplingDecision) `json:"-" yaml:"-"` +} + +// Config offers a declarative way to construct a logger. It doesn't do +// anything that can't be done with New, Options, and the various +// zapcore.WriteSyncer and zapcore.Core wrappers, but it's a simpler way to +// toggle common options. +// +// Note that Config intentionally supports only the most common options. More +// unusual logging setups (logging to network connections or message queues, +// splitting output between multiple files, etc.) are possible, but require +// direct use of the zapcore package. For sample code, see the package-level +// BasicConfiguration and AdvancedConfiguration examples. +// +// For an example showing runtime log level changes, see the documentation for +// AtomicLevel. +type Config struct { +	// Level is the minimum enabled logging level. Note that this is a dynamic +	// level, so calling Config.Level.SetLevel will atomically change the log +	// level of all loggers descended from this config. +	Level AtomicLevel `json:"level" yaml:"level"` +	// Development puts the logger in development mode, which changes the +	// behavior of DPanicLevel and takes stacktraces more liberally. +	Development bool `json:"development" yaml:"development"` +	// DisableCaller stops annotating logs with the calling function's file +	// name and line number. By default, all logs are annotated. +	DisableCaller bool `json:"disableCaller" yaml:"disableCaller"` +	// DisableStacktrace completely disables automatic stacktrace capturing. By +	// default, stacktraces are captured for WarnLevel and above logs in +	// development and ErrorLevel and above in production. +	DisableStacktrace bool `json:"disableStacktrace" yaml:"disableStacktrace"` +	// Sampling sets a sampling policy. A nil SamplingConfig disables sampling. +	Sampling *SamplingConfig `json:"sampling" yaml:"sampling"` +	// Encoding sets the logger's encoding. Valid values are "json" and +	// "console", as well as any third-party encodings registered via +	// RegisterEncoder. +	Encoding string `json:"encoding" yaml:"encoding"` +	// EncoderConfig sets options for the chosen encoder. See +	// zapcore.EncoderConfig for details. +	EncoderConfig zapcore.EncoderConfig `json:"encoderConfig" yaml:"encoderConfig"` +	// OutputPaths is a list of URLs or file paths to write logging output to. +	// See Open for details. +	OutputPaths []string `json:"outputPaths" yaml:"outputPaths"` +	// ErrorOutputPaths is a list of URLs to write internal logger errors to. +	// The default is standard error. +	// +	// Note that this setting only affects internal errors; for sample code that +	// sends error-level logs to a different location from info- and debug-level +	// logs, see the package-level AdvancedConfiguration example. +	ErrorOutputPaths []string `json:"errorOutputPaths" yaml:"errorOutputPaths"` +	// InitialFields is a collection of fields to add to the root logger. +	InitialFields map[string]interface{} `json:"initialFields" yaml:"initialFields"` +} + +// NewProductionEncoderConfig returns an opinionated EncoderConfig for +// production environments. +func NewProductionEncoderConfig() zapcore.EncoderConfig { +	return zapcore.EncoderConfig{ +		TimeKey:        "ts", +		LevelKey:       "level", +		NameKey:        "logger", +		CallerKey:      "caller", +		FunctionKey:    zapcore.OmitKey, +		MessageKey:     "msg", +		StacktraceKey:  "stacktrace", +		LineEnding:     zapcore.DefaultLineEnding, +		EncodeLevel:    zapcore.LowercaseLevelEncoder, +		EncodeTime:     zapcore.EpochTimeEncoder, +		EncodeDuration: zapcore.SecondsDurationEncoder, +		EncodeCaller:   zapcore.ShortCallerEncoder, +	} +} + +// NewProductionConfig is a reasonable production logging configuration. +// Logging is enabled at InfoLevel and above. +// +// It uses a JSON encoder, writes to standard error, and enables sampling. +// Stacktraces are automatically included on logs of ErrorLevel and above. +func NewProductionConfig() Config { +	return Config{ +		Level:       NewAtomicLevelAt(InfoLevel), +		Development: false, +		Sampling: &SamplingConfig{ +			Initial:    100, +			Thereafter: 100, +		}, +		Encoding:         "json", +		EncoderConfig:    NewProductionEncoderConfig(), +		OutputPaths:      []string{"stderr"}, +		ErrorOutputPaths: []string{"stderr"}, +	} +} + +// NewDevelopmentEncoderConfig returns an opinionated EncoderConfig for +// development environments. +func NewDevelopmentEncoderConfig() zapcore.EncoderConfig { +	return zapcore.EncoderConfig{ +		// Keys can be anything except the empty string. +		TimeKey:        "T", +		LevelKey:       "L", +		NameKey:        "N", +		CallerKey:      "C", +		FunctionKey:    zapcore.OmitKey, +		MessageKey:     "M", +		StacktraceKey:  "S", +		LineEnding:     zapcore.DefaultLineEnding, +		EncodeLevel:    zapcore.CapitalLevelEncoder, +		EncodeTime:     zapcore.ISO8601TimeEncoder, +		EncodeDuration: zapcore.StringDurationEncoder, +		EncodeCaller:   zapcore.ShortCallerEncoder, +	} +} + +// NewDevelopmentConfig is a reasonable development logging configuration. +// Logging is enabled at DebugLevel and above. +// +// It enables development mode (which makes DPanicLevel logs panic), uses a +// console encoder, writes to standard error, and disables sampling. +// Stacktraces are automatically included on logs of WarnLevel and above. +func NewDevelopmentConfig() Config { +	return Config{ +		Level:            NewAtomicLevelAt(DebugLevel), +		Development:      true, +		Encoding:         "console", +		EncoderConfig:    NewDevelopmentEncoderConfig(), +		OutputPaths:      []string{"stderr"}, +		ErrorOutputPaths: []string{"stderr"}, +	} +} + +// Build constructs a logger from the Config and Options. +func (cfg Config) Build(opts ...Option) (*Logger, error) { +	enc, err := cfg.buildEncoder() +	if err != nil { +		return nil, err +	} + +	sink, errSink, err := cfg.openSinks() +	if err != nil { +		return nil, err +	} + +	if cfg.Level == (AtomicLevel{}) { +		return nil, errors.New("missing Level") +	} + +	log := New( +		zapcore.NewCore(enc, sink, cfg.Level), +		cfg.buildOptions(errSink)..., +	) +	if len(opts) > 0 { +		log = log.WithOptions(opts...) +	} +	return log, nil +} + +func (cfg Config) buildOptions(errSink zapcore.WriteSyncer) []Option { +	opts := []Option{ErrorOutput(errSink)} + +	if cfg.Development { +		opts = append(opts, Development()) +	} + +	if !cfg.DisableCaller { +		opts = append(opts, AddCaller()) +	} + +	stackLevel := ErrorLevel +	if cfg.Development { +		stackLevel = WarnLevel +	} +	if !cfg.DisableStacktrace { +		opts = append(opts, AddStacktrace(stackLevel)) +	} + +	if scfg := cfg.Sampling; scfg != nil { +		opts = append(opts, WrapCore(func(core zapcore.Core) zapcore.Core { +			var samplerOpts []zapcore.SamplerOption +			if scfg.Hook != nil { +				samplerOpts = append(samplerOpts, zapcore.SamplerHook(scfg.Hook)) +			} +			return zapcore.NewSamplerWithOptions( +				core, +				time.Second, +				cfg.Sampling.Initial, +				cfg.Sampling.Thereafter, +				samplerOpts..., +			) +		})) +	} + +	if len(cfg.InitialFields) > 0 { +		fs := make([]Field, 0, len(cfg.InitialFields)) +		keys := make([]string, 0, len(cfg.InitialFields)) +		for k := range cfg.InitialFields { +			keys = append(keys, k) +		} +		sort.Strings(keys) +		for _, k := range keys { +			fs = append(fs, Any(k, cfg.InitialFields[k])) +		} +		opts = append(opts, Fields(fs...)) +	} + +	return opts +} + +func (cfg Config) openSinks() (zapcore.WriteSyncer, zapcore.WriteSyncer, error) { +	sink, closeOut, err := Open(cfg.OutputPaths...) +	if err != nil { +		return nil, nil, err +	} +	errSink, _, err := Open(cfg.ErrorOutputPaths...) +	if err != nil { +		closeOut() +		return nil, nil, err +	} +	return sink, errSink, nil +} + +func (cfg Config) buildEncoder() (zapcore.Encoder, error) { +	return newEncoder(cfg.Encoding, cfg.EncoderConfig) +} diff --git a/vendor/go.uber.org/zap/doc.go b/vendor/go.uber.org/zap/doc.go new file mode 100644 index 0000000..3c50d7b --- /dev/null +++ b/vendor/go.uber.org/zap/doc.go @@ -0,0 +1,117 @@ +// 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 provides fast, structured, leveled logging. +// +// For applications that log in the hot path, reflection-based serialization +// and string formatting are prohibitively expensive - they're CPU-intensive +// and make many small allocations. Put differently, using json.Marshal and +// fmt.Fprintf to log tons of interface{} makes your application slow. +// +// Zap takes a different approach. It includes a reflection-free, +// zero-allocation JSON encoder, and the base Logger strives to avoid +// serialization overhead and allocations wherever possible. By building the +// high-level SugaredLogger on that foundation, zap lets users choose when +// they need to count every allocation and when they'd prefer a more familiar, +// loosely typed API. +// +// # Choosing a Logger +// +// In contexts where performance is nice, but not critical, use the +// SugaredLogger. It's 4-10x faster than other structured logging packages and +// supports both structured and printf-style logging. Like log15 and go-kit, +// the SugaredLogger's structured logging APIs are loosely typed and accept a +// variadic number of key-value pairs. (For more advanced use cases, they also +// accept strongly typed fields - see the SugaredLogger.With documentation for +// details.) +// +//	sugar := zap.NewExample().Sugar() +//	defer sugar.Sync() +//	sugar.Infow("failed to fetch URL", +//	  "url", "http://example.com", +//	  "attempt", 3, +//	  "backoff", time.Second, +//	) +//	sugar.Infof("failed to fetch URL: %s", "http://example.com") +// +// By default, loggers are unbuffered. However, since zap's low-level APIs +// allow buffering, calling Sync before letting your process exit is a good +// habit. +// +// In the rare contexts where every microsecond and every allocation matter, +// use the Logger. It's even faster than the SugaredLogger and allocates far +// less, but it only supports strongly-typed, structured logging. +// +//	logger := zap.NewExample() +//	defer logger.Sync() +//	logger.Info("failed to fetch URL", +//	  zap.String("url", "http://example.com"), +//	  zap.Int("attempt", 3), +//	  zap.Duration("backoff", time.Second), +//	) +// +// Choosing between the Logger and SugaredLogger doesn't need to be an +// application-wide decision: converting between the two is simple and +// inexpensive. +// +//	logger := zap.NewExample() +//	defer logger.Sync() +//	sugar := logger.Sugar() +//	plain := sugar.Desugar() +// +// # Configuring Zap +// +// The simplest way to build a Logger is to use zap's opinionated presets: +// NewExample, NewProduction, and NewDevelopment. These presets build a logger +// with a single function call: +// +//	logger, err := zap.NewProduction() +//	if err != nil { +//	  log.Fatalf("can't initialize zap logger: %v", err) +//	} +//	defer logger.Sync() +// +// Presets are fine for small projects, but larger projects and organizations +// naturally require a bit more customization. For most users, zap's Config +// struct strikes the right balance between flexibility and convenience. See +// the package-level BasicConfiguration example for sample code. +// +// More unusual configurations (splitting output between files, sending logs +// to a message queue, etc.) are possible, but require direct use of +// go.uber.org/zap/zapcore. See the package-level AdvancedConfiguration +// example for sample code. +// +// # Extending Zap +// +// The zap package itself is a relatively thin wrapper around the interfaces +// in go.uber.org/zap/zapcore. Extending zap to support a new encoding (e.g., +// BSON), a new log sink (e.g., Kafka), or something more exotic (perhaps an +// exception aggregation service, like Sentry or Rollbar) typically requires +// implementing the zapcore.Encoder, zapcore.WriteSyncer, or zapcore.Core +// interfaces. See the zapcore documentation for details. +// +// Similarly, package authors can use the high-performance Encoder and Core +// implementations in the zapcore package to build their own loggers. +// +// # Frequently Asked Questions +// +// An FAQ covering everything from installation errors to design decisions is +// available at https://github.com/uber-go/zap/blob/master/FAQ.md. +package zap // import "go.uber.org/zap" diff --git a/vendor/go.uber.org/zap/encoder.go b/vendor/go.uber.org/zap/encoder.go new file mode 100644 index 0000000..caa04ce --- /dev/null +++ b/vendor/go.uber.org/zap/encoder.go @@ -0,0 +1,79 @@ +// 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 + +import ( +	"errors" +	"fmt" +	"sync" + +	"go.uber.org/zap/zapcore" +) + +var ( +	errNoEncoderNameSpecified = errors.New("no encoder name specified") + +	_encoderNameToConstructor = map[string]func(zapcore.EncoderConfig) (zapcore.Encoder, error){ +		"console": func(encoderConfig zapcore.EncoderConfig) (zapcore.Encoder, error) { +			return zapcore.NewConsoleEncoder(encoderConfig), nil +		}, +		"json": func(encoderConfig zapcore.EncoderConfig) (zapcore.Encoder, error) { +			return zapcore.NewJSONEncoder(encoderConfig), nil +		}, +	} +	_encoderMutex sync.RWMutex +) + +// RegisterEncoder registers an encoder constructor, which the Config struct +// can then reference. By default, the "json" and "console" encoders are +// registered. +// +// Attempting to register an encoder whose name is already taken returns an +// error. +func RegisterEncoder(name string, constructor func(zapcore.EncoderConfig) (zapcore.Encoder, error)) error { +	_encoderMutex.Lock() +	defer _encoderMutex.Unlock() +	if name == "" { +		return errNoEncoderNameSpecified +	} +	if _, ok := _encoderNameToConstructor[name]; ok { +		return fmt.Errorf("encoder already registered for name %q", name) +	} +	_encoderNameToConstructor[name] = constructor +	return nil +} + +func newEncoder(name string, encoderConfig zapcore.EncoderConfig) (zapcore.Encoder, error) { +	if encoderConfig.TimeKey != "" && encoderConfig.EncodeTime == nil { +		return nil, errors.New("missing EncodeTime in EncoderConfig") +	} + +	_encoderMutex.RLock() +	defer _encoderMutex.RUnlock() +	if name == "" { +		return nil, errNoEncoderNameSpecified +	} +	constructor, ok := _encoderNameToConstructor[name] +	if !ok { +		return nil, fmt.Errorf("no encoder registered for name %q", name) +	} +	return constructor(encoderConfig) +} diff --git a/vendor/go.uber.org/zap/error.go b/vendor/go.uber.org/zap/error.go new file mode 100644 index 0000000..65982a5 --- /dev/null +++ b/vendor/go.uber.org/zap/error.go @@ -0,0 +1,80 @@ +// Copyright (c) 2017 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 + +import ( +	"sync" + +	"go.uber.org/zap/zapcore" +) + +var _errArrayElemPool = sync.Pool{New: func() interface{} { +	return &errArrayElem{} +}} + +// Error is shorthand for the common idiom NamedError("error", err). +func Error(err error) Field { +	return NamedError("error", err) +} + +// NamedError constructs a field that lazily stores err.Error() under the +// provided key. Errors which also implement fmt.Formatter (like those produced +// by github.com/pkg/errors) will also have their verbose representation stored +// under key+"Verbose". If passed a nil error, the field is a no-op. +// +// For the common case in which the key is simply "error", the Error function +// is shorter and less repetitive. +func NamedError(key string, err error) Field { +	if err == nil { +		return Skip() +	} +	return Field{Key: key, Type: zapcore.ErrorType, Interface: err} +} + +type errArray []error + +func (errs errArray) MarshalLogArray(arr zapcore.ArrayEncoder) error { +	for i := range errs { +		if errs[i] == nil { +			continue +		} +		// To represent each error as an object with an "error" attribute and +		// potentially an "errorVerbose" attribute, we need to wrap it in a +		// type that implements LogObjectMarshaler. To prevent this from +		// allocating, pool the wrapper type. +		elem := _errArrayElemPool.Get().(*errArrayElem) +		elem.error = errs[i] +		arr.AppendObject(elem) +		elem.error = nil +		_errArrayElemPool.Put(elem) +	} +	return nil +} + +type errArrayElem struct { +	error +} + +func (e *errArrayElem) MarshalLogObject(enc zapcore.ObjectEncoder) error { +	// Re-use the error field's logic, which supports non-standard error types. +	Error(e.error).AddTo(enc) +	return nil +} diff --git a/vendor/go.uber.org/zap/field.go b/vendor/go.uber.org/zap/field.go new file mode 100644 index 0000000..bbb745d --- /dev/null +++ b/vendor/go.uber.org/zap/field.go @@ -0,0 +1,549 @@ +// 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 + +import ( +	"fmt" +	"math" +	"time" + +	"go.uber.org/zap/zapcore" +) + +// Field is an alias for Field. Aliasing this type dramatically +// improves the navigability of this package's API documentation. +type Field = zapcore.Field + +var ( +	_minTimeInt64 = time.Unix(0, math.MinInt64) +	_maxTimeInt64 = time.Unix(0, math.MaxInt64) +) + +// Skip constructs a no-op field, which is often useful when handling invalid +// inputs in other Field constructors. +func Skip() Field { +	return Field{Type: zapcore.SkipType} +} + +// nilField returns a field which will marshal explicitly as nil. See motivation +// in https://github.com/uber-go/zap/issues/753 . If we ever make breaking +// changes and add zapcore.NilType and zapcore.ObjectEncoder.AddNil, the +// implementation here should be changed to reflect that. +func nilField(key string) Field { return Reflect(key, nil) } + +// Binary constructs a field that carries an opaque binary blob. +// +// Binary data is serialized in an encoding-appropriate format. For example, +// zap's JSON encoder base64-encodes binary blobs. To log UTF-8 encoded text, +// use ByteString. +func Binary(key string, val []byte) Field { +	return Field{Key: key, Type: zapcore.BinaryType, Interface: val} +} + +// Bool constructs a field that carries a bool. +func Bool(key string, val bool) Field { +	var ival int64 +	if val { +		ival = 1 +	} +	return Field{Key: key, Type: zapcore.BoolType, Integer: ival} +} + +// Boolp constructs a field that carries a *bool. The returned Field will safely +// and explicitly represent `nil` when appropriate. +func Boolp(key string, val *bool) Field { +	if val == nil { +		return nilField(key) +	} +	return Bool(key, *val) +} + +// ByteString constructs a field that carries UTF-8 encoded text as a []byte. +// To log opaque binary blobs (which aren't necessarily valid UTF-8), use +// Binary. +func ByteString(key string, val []byte) Field { +	return Field{Key: key, Type: zapcore.ByteStringType, Interface: val} +} + +// Complex128 constructs a field that carries a complex number. Unlike most +// numeric fields, this costs an allocation (to convert the complex128 to +// interface{}). +func Complex128(key string, val complex128) Field { +	return Field{Key: key, Type: zapcore.Complex128Type, Interface: val} +} + +// Complex128p constructs a field that carries a *complex128. The returned Field will safely +// and explicitly represent `nil` when appropriate. +func Complex128p(key string, val *complex128) Field { +	if val == nil { +		return nilField(key) +	} +	return Complex128(key, *val) +} + +// Complex64 constructs a field that carries a complex number. Unlike most +// numeric fields, this costs an allocation (to convert the complex64 to +// interface{}). +func Complex64(key string, val complex64) Field { +	return Field{Key: key, Type: zapcore.Complex64Type, Interface: val} +} + +// Complex64p constructs a field that carries a *complex64. The returned Field will safely +// and explicitly represent `nil` when appropriate. +func Complex64p(key string, val *complex64) Field { +	if val == nil { +		return nilField(key) +	} +	return Complex64(key, *val) +} + +// Float64 constructs a field that carries a float64. The way the +// floating-point value is represented is encoder-dependent, so marshaling is +// necessarily lazy. +func Float64(key string, val float64) Field { +	return Field{Key: key, Type: zapcore.Float64Type, Integer: int64(math.Float64bits(val))} +} + +// Float64p constructs a field that carries a *float64. The returned Field will safely +// and explicitly represent `nil` when appropriate. +func Float64p(key string, val *float64) Field { +	if val == nil { +		return nilField(key) +	} +	return Float64(key, *val) +} + +// Float32 constructs a field that carries a float32. The way the +// floating-point value is represented is encoder-dependent, so marshaling is +// necessarily lazy. +func Float32(key string, val float32) Field { +	return Field{Key: key, Type: zapcore.Float32Type, Integer: int64(math.Float32bits(val))} +} + +// Float32p constructs a field that carries a *float32. The returned Field will safely +// and explicitly represent `nil` when appropriate. +func Float32p(key string, val *float32) Field { +	if val == nil { +		return nilField(key) +	} +	return Float32(key, *val) +} + +// Int constructs a field with the given key and value. +func Int(key string, val int) Field { +	return Int64(key, int64(val)) +} + +// Intp constructs a field that carries a *int. The returned Field will safely +// and explicitly represent `nil` when appropriate. +func Intp(key string, val *int) Field { +	if val == nil { +		return nilField(key) +	} +	return Int(key, *val) +} + +// Int64 constructs a field with the given key and value. +func Int64(key string, val int64) Field { +	return Field{Key: key, Type: zapcore.Int64Type, Integer: val} +} + +// Int64p constructs a field that carries a *int64. The returned Field will safely +// and explicitly represent `nil` when appropriate. +func Int64p(key string, val *int64) Field { +	if val == nil { +		return nilField(key) +	} +	return Int64(key, *val) +} + +// Int32 constructs a field with the given key and value. +func Int32(key string, val int32) Field { +	return Field{Key: key, Type: zapcore.Int32Type, Integer: int64(val)} +} + +// Int32p constructs a field that carries a *int32. The returned Field will safely +// and explicitly represent `nil` when appropriate. +func Int32p(key string, val *int32) Field { +	if val == nil { +		return nilField(key) +	} +	return Int32(key, *val) +} + +// Int16 constructs a field with the given key and value. +func Int16(key string, val int16) Field { +	return Field{Key: key, Type: zapcore.Int16Type, Integer: int64(val)} +} + +// Int16p constructs a field that carries a *int16. The returned Field will safely +// and explicitly represent `nil` when appropriate. +func Int16p(key string, val *int16) Field { +	if val == nil { +		return nilField(key) +	} +	return Int16(key, *val) +} + +// Int8 constructs a field with the given key and value. +func Int8(key string, val int8) Field { +	return Field{Key: key, Type: zapcore.Int8Type, Integer: int64(val)} +} + +// Int8p constructs a field that carries a *int8. The returned Field will safely +// and explicitly represent `nil` when appropriate. +func Int8p(key string, val *int8) Field { +	if val == nil { +		return nilField(key) +	} +	return Int8(key, *val) +} + +// String constructs a field with the given key and value. +func String(key string, val string) Field { +	return Field{Key: key, Type: zapcore.StringType, String: val} +} + +// Stringp constructs a field that carries a *string. The returned Field will safely +// and explicitly represent `nil` when appropriate. +func Stringp(key string, val *string) Field { +	if val == nil { +		return nilField(key) +	} +	return String(key, *val) +} + +// Uint constructs a field with the given key and value. +func Uint(key string, val uint) Field { +	return Uint64(key, uint64(val)) +} + +// Uintp constructs a field that carries a *uint. The returned Field will safely +// and explicitly represent `nil` when appropriate. +func Uintp(key string, val *uint) Field { +	if val == nil { +		return nilField(key) +	} +	return Uint(key, *val) +} + +// Uint64 constructs a field with the given key and value. +func Uint64(key string, val uint64) Field { +	return Field{Key: key, Type: zapcore.Uint64Type, Integer: int64(val)} +} + +// Uint64p constructs a field that carries a *uint64. The returned Field will safely +// and explicitly represent `nil` when appropriate. +func Uint64p(key string, val *uint64) Field { +	if val == nil { +		return nilField(key) +	} +	return Uint64(key, *val) +} + +// Uint32 constructs a field with the given key and value. +func Uint32(key string, val uint32) Field { +	return Field{Key: key, Type: zapcore.Uint32Type, Integer: int64(val)} +} + +// Uint32p constructs a field that carries a *uint32. The returned Field will safely +// and explicitly represent `nil` when appropriate. +func Uint32p(key string, val *uint32) Field { +	if val == nil { +		return nilField(key) +	} +	return Uint32(key, *val) +} + +// Uint16 constructs a field with the given key and value. +func Uint16(key string, val uint16) Field { +	return Field{Key: key, Type: zapcore.Uint16Type, Integer: int64(val)} +} + +// Uint16p constructs a field that carries a *uint16. The returned Field will safely +// and explicitly represent `nil` when appropriate. +func Uint16p(key string, val *uint16) Field { +	if val == nil { +		return nilField(key) +	} +	return Uint16(key, *val) +} + +// Uint8 constructs a field with the given key and value. +func Uint8(key string, val uint8) Field { +	return Field{Key: key, Type: zapcore.Uint8Type, Integer: int64(val)} +} + +// Uint8p constructs a field that carries a *uint8. The returned Field will safely +// and explicitly represent `nil` when appropriate. +func Uint8p(key string, val *uint8) Field { +	if val == nil { +		return nilField(key) +	} +	return Uint8(key, *val) +} + +// Uintptr constructs a field with the given key and value. +func Uintptr(key string, val uintptr) Field { +	return Field{Key: key, Type: zapcore.UintptrType, Integer: int64(val)} +} + +// Uintptrp constructs a field that carries a *uintptr. The returned Field will safely +// and explicitly represent `nil` when appropriate. +func Uintptrp(key string, val *uintptr) Field { +	if val == nil { +		return nilField(key) +	} +	return Uintptr(key, *val) +} + +// Reflect constructs a field with the given key and an arbitrary object. It uses +// an encoding-appropriate, reflection-based function to lazily serialize nearly +// any object into the logging context, but it's relatively slow and +// allocation-heavy. Outside tests, Any is always a better choice. +// +// If encoding fails (e.g., trying to serialize a map[int]string to JSON), Reflect +// includes the error message in the final log output. +func Reflect(key string, val interface{}) Field { +	return Field{Key: key, Type: zapcore.ReflectType, Interface: val} +} + +// Namespace creates a named, isolated scope within the logger's context. All +// subsequent fields will be added to the new namespace. +// +// This helps prevent key collisions when injecting loggers into sub-components +// or third-party libraries. +func Namespace(key string) Field { +	return Field{Key: key, Type: zapcore.NamespaceType} +} + +// Stringer constructs a field with the given key and the output of the value's +// String method. The Stringer's String method is called lazily. +func Stringer(key string, val fmt.Stringer) Field { +	return Field{Key: key, Type: zapcore.StringerType, Interface: val} +} + +// Time constructs a Field with the given key and value. The encoder +// controls how the time is serialized. +func Time(key string, val time.Time) Field { +	if val.Before(_minTimeInt64) || val.After(_maxTimeInt64) { +		return Field{Key: key, Type: zapcore.TimeFullType, Interface: val} +	} +	return Field{Key: key, Type: zapcore.TimeType, Integer: val.UnixNano(), Interface: val.Location()} +} + +// Timep constructs a field that carries a *time.Time. The returned Field will safely +// and explicitly represent `nil` when appropriate. +func Timep(key string, val *time.Time) Field { +	if val == nil { +		return nilField(key) +	} +	return Time(key, *val) +} + +// Stack constructs a field that stores a stacktrace of the current goroutine +// under provided key. Keep in mind that taking a stacktrace is eager and +// expensive (relatively speaking); this function both makes an allocation and +// takes about two microseconds. +func Stack(key string) Field { +	return StackSkip(key, 1) // skip Stack +} + +// StackSkip constructs a field similarly to Stack, but also skips the given +// number of frames from the top of the stacktrace. +func StackSkip(key string, skip int) Field { +	// Returning the stacktrace as a string costs an allocation, but saves us +	// from expanding the zapcore.Field union struct to include a byte slice. Since +	// taking a stacktrace is already so expensive (~10us), the extra allocation +	// is okay. +	return String(key, takeStacktrace(skip+1)) // skip StackSkip +} + +// Duration constructs a field with the given key and value. The encoder +// controls how the duration is serialized. +func Duration(key string, val time.Duration) Field { +	return Field{Key: key, Type: zapcore.DurationType, Integer: int64(val)} +} + +// Durationp constructs a field that carries a *time.Duration. The returned Field will safely +// and explicitly represent `nil` when appropriate. +func Durationp(key string, val *time.Duration) Field { +	if val == nil { +		return nilField(key) +	} +	return Duration(key, *val) +} + +// Object constructs a field with the given key and ObjectMarshaler. It +// provides a flexible, but still type-safe and efficient, way to add map- or +// struct-like user-defined types to the logging context. The struct's +// MarshalLogObject method is called lazily. +func Object(key string, val zapcore.ObjectMarshaler) Field { +	return Field{Key: key, Type: zapcore.ObjectMarshalerType, Interface: val} +} + +// Inline constructs a Field that is similar to Object, but it +// will add the elements of the provided ObjectMarshaler to the +// current namespace. +func Inline(val zapcore.ObjectMarshaler) Field { +	return zapcore.Field{ +		Type:      zapcore.InlineMarshalerType, +		Interface: val, +	} +} + +// Any takes a key and an arbitrary value and chooses the best way to represent +// them as a field, falling back to a reflection-based approach only if +// necessary. +// +// Since byte/uint8 and rune/int32 are aliases, Any can't differentiate between +// them. To minimize surprises, []byte values are treated as binary blobs, byte +// values are treated as uint8, and runes are always treated as integers. +func Any(key string, value interface{}) Field { +	switch val := value.(type) { +	case zapcore.ObjectMarshaler: +		return Object(key, val) +	case zapcore.ArrayMarshaler: +		return Array(key, val) +	case bool: +		return Bool(key, val) +	case *bool: +		return Boolp(key, val) +	case []bool: +		return Bools(key, val) +	case complex128: +		return Complex128(key, val) +	case *complex128: +		return Complex128p(key, val) +	case []complex128: +		return Complex128s(key, val) +	case complex64: +		return Complex64(key, val) +	case *complex64: +		return Complex64p(key, val) +	case []complex64: +		return Complex64s(key, val) +	case float64: +		return Float64(key, val) +	case *float64: +		return Float64p(key, val) +	case []float64: +		return Float64s(key, val) +	case float32: +		return Float32(key, val) +	case *float32: +		return Float32p(key, val) +	case []float32: +		return Float32s(key, val) +	case int: +		return Int(key, val) +	case *int: +		return Intp(key, val) +	case []int: +		return Ints(key, val) +	case int64: +		return Int64(key, val) +	case *int64: +		return Int64p(key, val) +	case []int64: +		return Int64s(key, val) +	case int32: +		return Int32(key, val) +	case *int32: +		return Int32p(key, val) +	case []int32: +		return Int32s(key, val) +	case int16: +		return Int16(key, val) +	case *int16: +		return Int16p(key, val) +	case []int16: +		return Int16s(key, val) +	case int8: +		return Int8(key, val) +	case *int8: +		return Int8p(key, val) +	case []int8: +		return Int8s(key, val) +	case string: +		return String(key, val) +	case *string: +		return Stringp(key, val) +	case []string: +		return Strings(key, val) +	case uint: +		return Uint(key, val) +	case *uint: +		return Uintp(key, val) +	case []uint: +		return Uints(key, val) +	case uint64: +		return Uint64(key, val) +	case *uint64: +		return Uint64p(key, val) +	case []uint64: +		return Uint64s(key, val) +	case uint32: +		return Uint32(key, val) +	case *uint32: +		return Uint32p(key, val) +	case []uint32: +		return Uint32s(key, val) +	case uint16: +		return Uint16(key, val) +	case *uint16: +		return Uint16p(key, val) +	case []uint16: +		return Uint16s(key, val) +	case uint8: +		return Uint8(key, val) +	case *uint8: +		return Uint8p(key, val) +	case []byte: +		return Binary(key, val) +	case uintptr: +		return Uintptr(key, val) +	case *uintptr: +		return Uintptrp(key, val) +	case []uintptr: +		return Uintptrs(key, val) +	case time.Time: +		return Time(key, val) +	case *time.Time: +		return Timep(key, val) +	case []time.Time: +		return Times(key, val) +	case time.Duration: +		return Duration(key, val) +	case *time.Duration: +		return Durationp(key, val) +	case []time.Duration: +		return Durations(key, val) +	case error: +		return NamedError(key, val) +	case []error: +		return Errors(key, val) +	case fmt.Stringer: +		return Stringer(key, val) +	default: +		return Reflect(key, val) +	} +} diff --git a/vendor/go.uber.org/zap/flag.go b/vendor/go.uber.org/zap/flag.go new file mode 100644 index 0000000..1312875 --- /dev/null +++ b/vendor/go.uber.org/zap/flag.go @@ -0,0 +1,39 @@ +// 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 + +import ( +	"flag" + +	"go.uber.org/zap/zapcore" +) + +// LevelFlag uses the standard library's flag.Var to declare a global flag +// with the specified name, default, and usage guidance. The returned value is +// a pointer to the value of the flag. +// +// If you don't want to use the flag package's global state, you can use any +// non-nil *Level as a flag.Value with your own *flag.FlagSet. +func LevelFlag(name string, defaultLevel zapcore.Level, usage string) *zapcore.Level { +	lvl := defaultLevel +	flag.Var(&lvl, name, usage) +	return &lvl +} diff --git a/vendor/go.uber.org/zap/glide.yaml b/vendor/go.uber.org/zap/glide.yaml new file mode 100644 index 0000000..8e1d05e --- /dev/null +++ b/vendor/go.uber.org/zap/glide.yaml @@ -0,0 +1,34 @@ +package: go.uber.org/zap +license: MIT +import: +- package: go.uber.org/atomic +  version: ^1 +- package: go.uber.org/multierr +  version: ^1 +testImport: +- package: github.com/satori/go.uuid +- package: github.com/sirupsen/logrus +- package: github.com/apex/log +  subpackages: +  - handlers/json +- package: github.com/go-kit/kit +  subpackages: +  - log +- package: github.com/stretchr/testify +  subpackages: +  - assert +  - require +- package: gopkg.in/inconshreveable/log15.v2 +- package: github.com/mattn/goveralls +- package: github.com/pborman/uuid +- package: github.com/pkg/errors +- package: github.com/rs/zerolog +- package: golang.org/x/tools +  subpackages: +  - cover +- package: golang.org/x/lint +  subpackages: +  - golint +- package: github.com/axw/gocov +  subpackages: +  - gocov diff --git a/vendor/go.uber.org/zap/global.go b/vendor/go.uber.org/zap/global.go new file mode 100644 index 0000000..3cb46c9 --- /dev/null +++ b/vendor/go.uber.org/zap/global.go @@ -0,0 +1,169 @@ +// 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 + +import ( +	"bytes" +	"fmt" +	"log" +	"os" +	"sync" + +	"go.uber.org/zap/zapcore" +) + +const ( +	_stdLogDefaultDepth      = 1 +	_loggerWriterDepth       = 2 +	_programmerErrorTemplate = "You've found a bug in zap! Please file a bug at " + +		"https://github.com/uber-go/zap/issues/new and reference this error: %v" +) + +var ( +	_globalMu sync.RWMutex +	_globalL  = NewNop() +	_globalS  = _globalL.Sugar() +) + +// L returns the global Logger, which can be reconfigured with ReplaceGlobals. +// It's safe for concurrent use. +func L() *Logger { +	_globalMu.RLock() +	l := _globalL +	_globalMu.RUnlock() +	return l +} + +// S returns the global SugaredLogger, which can be reconfigured with +// ReplaceGlobals. It's safe for concurrent use. +func S() *SugaredLogger { +	_globalMu.RLock() +	s := _globalS +	_globalMu.RUnlock() +	return s +} + +// ReplaceGlobals replaces the global Logger and SugaredLogger, and returns a +// function to restore the original values. It's safe for concurrent use. +func ReplaceGlobals(logger *Logger) func() { +	_globalMu.Lock() +	prev := _globalL +	_globalL = logger +	_globalS = logger.Sugar() +	_globalMu.Unlock() +	return func() { ReplaceGlobals(prev) } +} + +// NewStdLog returns a *log.Logger which writes to the supplied zap Logger at +// InfoLevel. To redirect the standard library's package-global logging +// functions, use RedirectStdLog instead. +func NewStdLog(l *Logger) *log.Logger { +	logger := l.WithOptions(AddCallerSkip(_stdLogDefaultDepth + _loggerWriterDepth)) +	f := logger.Info +	return log.New(&loggerWriter{f}, "" /* prefix */, 0 /* flags */) +} + +// NewStdLogAt returns *log.Logger which writes to supplied zap logger at +// required level. +func NewStdLogAt(l *Logger, level zapcore.Level) (*log.Logger, error) { +	logger := l.WithOptions(AddCallerSkip(_stdLogDefaultDepth + _loggerWriterDepth)) +	logFunc, err := levelToFunc(logger, level) +	if err != nil { +		return nil, err +	} +	return log.New(&loggerWriter{logFunc}, "" /* prefix */, 0 /* flags */), nil +} + +// RedirectStdLog redirects output from the standard library's package-global +// logger to the supplied logger at InfoLevel. Since zap already handles caller +// annotations, timestamps, etc., it automatically disables the standard +// library's annotations and prefixing. +// +// It returns a function to restore the original prefix and flags and reset the +// standard library's output to os.Stderr. +func RedirectStdLog(l *Logger) func() { +	f, err := redirectStdLogAt(l, InfoLevel) +	if err != nil { +		// Can't get here, since passing InfoLevel to redirectStdLogAt always +		// works. +		panic(fmt.Sprintf(_programmerErrorTemplate, err)) +	} +	return f +} + +// RedirectStdLogAt redirects output from the standard library's package-global +// logger to the supplied logger at the specified level. Since zap already +// handles caller annotations, timestamps, etc., it automatically disables the +// standard library's annotations and prefixing. +// +// It returns a function to restore the original prefix and flags and reset the +// standard library's output to os.Stderr. +func RedirectStdLogAt(l *Logger, level zapcore.Level) (func(), error) { +	return redirectStdLogAt(l, level) +} + +func redirectStdLogAt(l *Logger, level zapcore.Level) (func(), error) { +	flags := log.Flags() +	prefix := log.Prefix() +	log.SetFlags(0) +	log.SetPrefix("") +	logger := l.WithOptions(AddCallerSkip(_stdLogDefaultDepth + _loggerWriterDepth)) +	logFunc, err := levelToFunc(logger, level) +	if err != nil { +		return nil, err +	} +	log.SetOutput(&loggerWriter{logFunc}) +	return func() { +		log.SetFlags(flags) +		log.SetPrefix(prefix) +		log.SetOutput(os.Stderr) +	}, nil +} + +func levelToFunc(logger *Logger, lvl zapcore.Level) (func(string, ...Field), error) { +	switch lvl { +	case DebugLevel: +		return logger.Debug, nil +	case InfoLevel: +		return logger.Info, nil +	case WarnLevel: +		return logger.Warn, nil +	case ErrorLevel: +		return logger.Error, nil +	case DPanicLevel: +		return logger.DPanic, nil +	case PanicLevel: +		return logger.Panic, nil +	case FatalLevel: +		return logger.Fatal, nil +	} +	return nil, fmt.Errorf("unrecognized level: %q", lvl) +} + +type loggerWriter struct { +	logFunc func(msg string, fields ...Field) +} + +func (l *loggerWriter) Write(p []byte) (int, error) { +	p = bytes.TrimSpace(p) +	l.logFunc(string(p)) +	return len(p), nil +} diff --git a/vendor/go.uber.org/zap/http_handler.go b/vendor/go.uber.org/zap/http_handler.go new file mode 100644 index 0000000..632b683 --- /dev/null +++ b/vendor/go.uber.org/zap/http_handler.go @@ -0,0 +1,133 @@ +// 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 + +import ( +	"encoding/json" +	"errors" +	"fmt" +	"io" +	"net/http" + +	"go.uber.org/zap/zapcore" +) + +// ServeHTTP is a simple JSON endpoint that can report on or change the current +// logging level. +// +// # GET +// +// The GET request returns a JSON description of the current logging level like: +// +//	{"level":"info"} +// +// # PUT +// +// The PUT request changes the logging level. It is perfectly safe to change the +// logging level while a program is running. Two content types are supported: +// +//	Content-Type: application/x-www-form-urlencoded +// +// With this content type, the level can be provided through the request body or +// a query parameter. The log level is URL encoded like: +// +//	level=debug +// +// The request body takes precedence over the query parameter, if both are +// specified. +// +// This content type is the default for a curl PUT request. Following are two +// example curl requests that both set the logging level to debug. +// +//	curl -X PUT localhost:8080/log/level?level=debug +//	curl -X PUT localhost:8080/log/level -d level=debug +// +// For any other content type, the payload is expected to be JSON encoded and +// look like: +// +//	{"level":"info"} +// +// An example curl request could look like this: +// +//	curl -X PUT localhost:8080/log/level -H "Content-Type: application/json" -d '{"level":"debug"}' +func (lvl AtomicLevel) ServeHTTP(w http.ResponseWriter, r *http.Request) { +	type errorResponse struct { +		Error string `json:"error"` +	} +	type payload struct { +		Level zapcore.Level `json:"level"` +	} + +	enc := json.NewEncoder(w) + +	switch r.Method { +	case http.MethodGet: +		enc.Encode(payload{Level: lvl.Level()}) +	case http.MethodPut: +		requestedLvl, err := decodePutRequest(r.Header.Get("Content-Type"), r) +		if err != nil { +			w.WriteHeader(http.StatusBadRequest) +			enc.Encode(errorResponse{Error: err.Error()}) +			return +		} +		lvl.SetLevel(requestedLvl) +		enc.Encode(payload{Level: lvl.Level()}) +	default: +		w.WriteHeader(http.StatusMethodNotAllowed) +		enc.Encode(errorResponse{ +			Error: "Only GET and PUT are supported.", +		}) +	} +} + +// Decodes incoming PUT requests and returns the requested logging level. +func decodePutRequest(contentType string, r *http.Request) (zapcore.Level, error) { +	if contentType == "application/x-www-form-urlencoded" { +		return decodePutURL(r) +	} +	return decodePutJSON(r.Body) +} + +func decodePutURL(r *http.Request) (zapcore.Level, error) { +	lvl := r.FormValue("level") +	if lvl == "" { +		return 0, errors.New("must specify logging level") +	} +	var l zapcore.Level +	if err := l.UnmarshalText([]byte(lvl)); err != nil { +		return 0, err +	} +	return l, nil +} + +func decodePutJSON(body io.Reader) (zapcore.Level, error) { +	var pld struct { +		Level *zapcore.Level `json:"level"` +	} +	if err := json.NewDecoder(body).Decode(&pld); err != nil { +		return 0, fmt.Errorf("malformed request body: %v", err) +	} +	if pld.Level == nil { +		return 0, errors.New("must specify logging level") +	} +	return *pld.Level, nil + +} diff --git a/vendor/go.uber.org/zap/internal/bufferpool/bufferpool.go b/vendor/go.uber.org/zap/internal/bufferpool/bufferpool.go new file mode 100644 index 0000000..dad583a --- /dev/null +++ b/vendor/go.uber.org/zap/internal/bufferpool/bufferpool.go @@ -0,0 +1,31 @@ +// 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 bufferpool houses zap's shared internal buffer pool. Third-party +// packages can recreate the same functionality with buffers.NewPool. +package bufferpool + +import "go.uber.org/zap/buffer" + +var ( +	_pool = buffer.NewPool() +	// Get retrieves a buffer from the pool, creating one if necessary. +	Get = _pool.Get +) diff --git a/vendor/go.uber.org/zap/internal/color/color.go b/vendor/go.uber.org/zap/internal/color/color.go new file mode 100644 index 0000000..c4d5d02 --- /dev/null +++ b/vendor/go.uber.org/zap/internal/color/color.go @@ -0,0 +1,44 @@ +// 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 color adds coloring functionality for TTY output. +package color + +import "fmt" + +// Foreground colors. +const ( +	Black Color = iota + 30 +	Red +	Green +	Yellow +	Blue +	Magenta +	Cyan +	White +) + +// Color represents a text color. +type Color uint8 + +// Add adds the coloring to the given string. +func (c Color) Add(s string) string { +	return fmt.Sprintf("\x1b[%dm%s\x1b[0m", uint8(c), s) +} diff --git a/vendor/go.uber.org/zap/internal/exit/exit.go b/vendor/go.uber.org/zap/internal/exit/exit.go new file mode 100644 index 0000000..f673f99 --- /dev/null +++ b/vendor/go.uber.org/zap/internal/exit/exit.go @@ -0,0 +1,66 @@ +// 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 exit provides stubs so that unit tests can exercise code that calls +// os.Exit(1). +package exit + +import "os" + +var _exit = os.Exit + +// With terminates the process by calling os.Exit(code). If the package is +// stubbed, it instead records a call in the testing spy. +func With(code int) { +	_exit(code) +} + +// A StubbedExit is a testing fake for os.Exit. +type StubbedExit struct { +	Exited bool +	Code   int +	prev   func(code int) +} + +// Stub substitutes a fake for the call to os.Exit(1). +func Stub() *StubbedExit { +	s := &StubbedExit{prev: _exit} +	_exit = s.exit +	return s +} + +// WithStub runs the supplied function with Exit stubbed. It returns the stub +// used, so that users can test whether the process would have crashed. +func WithStub(f func()) *StubbedExit { +	s := Stub() +	defer s.Unstub() +	f() +	return s +} + +// Unstub restores the previous exit function. +func (se *StubbedExit) Unstub() { +	_exit = se.prev +} + +func (se *StubbedExit) exit(code int) { +	se.Exited = true +	se.Code = code +} diff --git a/vendor/go.uber.org/zap/internal/level_enabler.go b/vendor/go.uber.org/zap/internal/level_enabler.go new file mode 100644 index 0000000..5f3e3f1 --- /dev/null +++ b/vendor/go.uber.org/zap/internal/level_enabler.go @@ -0,0 +1,35 @@ +// Copyright (c) 2022 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 internal + +import "go.uber.org/zap/zapcore" + +// LeveledEnabler is an interface satisfied by LevelEnablers that are able to +// report their own level. +// +// This interface is defined to use more conveniently in tests and non-zapcore +// packages. +// This cannot be imported from zapcore because of the cyclic dependency. +type LeveledEnabler interface { +	zapcore.LevelEnabler + +	Level() zapcore.Level +} diff --git a/vendor/go.uber.org/zap/level.go b/vendor/go.uber.org/zap/level.go new file mode 100644 index 0000000..db951e1 --- /dev/null +++ b/vendor/go.uber.org/zap/level.go @@ -0,0 +1,152 @@ +// 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 + +import ( +	"go.uber.org/atomic" +	"go.uber.org/zap/internal" +	"go.uber.org/zap/zapcore" +) + +const ( +	// DebugLevel logs are typically voluminous, and are usually disabled in +	// production. +	DebugLevel = zapcore.DebugLevel +	// InfoLevel is the default logging priority. +	InfoLevel = zapcore.InfoLevel +	// WarnLevel logs are more important than Info, but don't need individual +	// human review. +	WarnLevel = zapcore.WarnLevel +	// ErrorLevel logs are high-priority. If an application is running smoothly, +	// it shouldn't generate any error-level logs. +	ErrorLevel = zapcore.ErrorLevel +	// DPanicLevel logs are particularly important errors. In development the +	// logger panics after writing the message. +	DPanicLevel = zapcore.DPanicLevel +	// PanicLevel logs a message, then panics. +	PanicLevel = zapcore.PanicLevel +	// FatalLevel logs a message, then calls os.Exit(1). +	FatalLevel = zapcore.FatalLevel +) + +// LevelEnablerFunc is a convenient way to implement zapcore.LevelEnabler with +// an anonymous function. +// +// It's particularly useful when splitting log output between different +// outputs (e.g., standard error and standard out). For sample code, see the +// package-level AdvancedConfiguration example. +type LevelEnablerFunc func(zapcore.Level) bool + +// Enabled calls the wrapped function. +func (f LevelEnablerFunc) Enabled(lvl zapcore.Level) bool { return f(lvl) } + +// An AtomicLevel is an atomically changeable, dynamic logging level. It lets +// you safely change the log level of a tree of loggers (the root logger and +// any children created by adding context) at runtime. +// +// The AtomicLevel itself is an http.Handler that serves a JSON endpoint to +// alter its level. +// +// AtomicLevels must be created with the NewAtomicLevel constructor to allocate +// their internal atomic pointer. +type AtomicLevel struct { +	l *atomic.Int32 +} + +var _ internal.LeveledEnabler = AtomicLevel{} + +// NewAtomicLevel creates an AtomicLevel with InfoLevel and above logging +// enabled. +func NewAtomicLevel() AtomicLevel { +	return AtomicLevel{ +		l: atomic.NewInt32(int32(InfoLevel)), +	} +} + +// NewAtomicLevelAt is a convenience function that creates an AtomicLevel +// and then calls SetLevel with the given level. +func NewAtomicLevelAt(l zapcore.Level) AtomicLevel { +	a := NewAtomicLevel() +	a.SetLevel(l) +	return a +} + +// ParseAtomicLevel parses an AtomicLevel based on a lowercase or all-caps ASCII +// representation of the log level. If the provided ASCII representation is +// invalid an error is returned. +// +// This is particularly useful when dealing with text input to configure log +// levels. +func ParseAtomicLevel(text string) (AtomicLevel, error) { +	a := NewAtomicLevel() +	l, err := zapcore.ParseLevel(text) +	if err != nil { +		return a, err +	} + +	a.SetLevel(l) +	return a, nil +} + +// Enabled implements the zapcore.LevelEnabler interface, which allows the +// AtomicLevel to be used in place of traditional static levels. +func (lvl AtomicLevel) Enabled(l zapcore.Level) bool { +	return lvl.Level().Enabled(l) +} + +// Level returns the minimum enabled log level. +func (lvl AtomicLevel) Level() zapcore.Level { +	return zapcore.Level(int8(lvl.l.Load())) +} + +// SetLevel alters the logging level. +func (lvl AtomicLevel) SetLevel(l zapcore.Level) { +	lvl.l.Store(int32(l)) +} + +// String returns the string representation of the underlying Level. +func (lvl AtomicLevel) String() string { +	return lvl.Level().String() +} + +// UnmarshalText unmarshals the text to an AtomicLevel. It uses the same text +// representations as the static zapcore.Levels ("debug", "info", "warn", +// "error", "dpanic", "panic", and "fatal"). +func (lvl *AtomicLevel) UnmarshalText(text []byte) error { +	if lvl.l == nil { +		lvl.l = &atomic.Int32{} +	} + +	var l zapcore.Level +	if err := l.UnmarshalText(text); err != nil { +		return err +	} + +	lvl.SetLevel(l) +	return nil +} + +// MarshalText marshals the AtomicLevel to a byte slice. It uses the same +// text representation as the static zapcore.Levels ("debug", "info", "warn", +// "error", "dpanic", "panic", and "fatal"). +func (lvl AtomicLevel) MarshalText() (text []byte, err error) { +	return lvl.Level().MarshalText() +} diff --git a/vendor/go.uber.org/zap/logger.go b/vendor/go.uber.org/zap/logger.go new file mode 100644 index 0000000..cd44030 --- /dev/null +++ b/vendor/go.uber.org/zap/logger.go @@ -0,0 +1,400 @@ +// 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 + +import ( +	"fmt" +	"io" +	"os" +	"strings" + +	"go.uber.org/zap/internal/bufferpool" +	"go.uber.org/zap/zapcore" +) + +// A Logger provides fast, leveled, structured logging. All methods are safe +// for concurrent use. +// +// The Logger is designed for contexts in which every microsecond and every +// allocation matters, so its API intentionally favors performance and type +// safety over brevity. For most applications, the SugaredLogger strikes a +// better balance between performance and ergonomics. +type Logger struct { +	core zapcore.Core + +	development bool +	addCaller   bool +	onFatal     zapcore.CheckWriteHook // default is WriteThenFatal + +	name        string +	errorOutput zapcore.WriteSyncer + +	addStack zapcore.LevelEnabler + +	callerSkip int + +	clock zapcore.Clock +} + +// New constructs a new Logger from the provided zapcore.Core and Options. If +// the passed zapcore.Core is nil, it falls back to using a no-op +// implementation. +// +// This is the most flexible way to construct a Logger, but also the most +// verbose. For typical use cases, the highly-opinionated presets +// (NewProduction, NewDevelopment, and NewExample) or the Config struct are +// more convenient. +// +// For sample code, see the package-level AdvancedConfiguration example. +func New(core zapcore.Core, options ...Option) *Logger { +	if core == nil { +		return NewNop() +	} +	log := &Logger{ +		core:        core, +		errorOutput: zapcore.Lock(os.Stderr), +		addStack:    zapcore.FatalLevel + 1, +		clock:       zapcore.DefaultClock, +	} +	return log.WithOptions(options...) +} + +// NewNop returns a no-op Logger. It never writes out logs or internal errors, +// and it never runs user-defined hooks. +// +// Using WithOptions to replace the Core or error output of a no-op Logger can +// re-enable logging. +func NewNop() *Logger { +	return &Logger{ +		core:        zapcore.NewNopCore(), +		errorOutput: zapcore.AddSync(io.Discard), +		addStack:    zapcore.FatalLevel + 1, +		clock:       zapcore.DefaultClock, +	} +} + +// NewProduction builds a sensible production Logger that writes InfoLevel and +// above logs to standard error as JSON. +// +// It's a shortcut for NewProductionConfig().Build(...Option). +func NewProduction(options ...Option) (*Logger, error) { +	return NewProductionConfig().Build(options...) +} + +// NewDevelopment builds a development Logger that writes DebugLevel and above +// logs to standard error in a human-friendly format. +// +// It's a shortcut for NewDevelopmentConfig().Build(...Option). +func NewDevelopment(options ...Option) (*Logger, error) { +	return NewDevelopmentConfig().Build(options...) +} + +// Must is a helper that wraps a call to a function returning (*Logger, error) +// and panics if the error is non-nil. It is intended for use in variable +// initialization such as: +// +//	var logger = zap.Must(zap.NewProduction()) +func Must(logger *Logger, err error) *Logger { +	if err != nil { +		panic(err) +	} + +	return logger +} + +// NewExample builds a Logger that's designed for use in zap's testable +// examples. It writes DebugLevel and above logs to standard out as JSON, but +// omits the timestamp and calling function to keep example output +// short and deterministic. +func NewExample(options ...Option) *Logger { +	encoderCfg := zapcore.EncoderConfig{ +		MessageKey:     "msg", +		LevelKey:       "level", +		NameKey:        "logger", +		EncodeLevel:    zapcore.LowercaseLevelEncoder, +		EncodeTime:     zapcore.ISO8601TimeEncoder, +		EncodeDuration: zapcore.StringDurationEncoder, +	} +	core := zapcore.NewCore(zapcore.NewJSONEncoder(encoderCfg), os.Stdout, DebugLevel) +	return New(core).WithOptions(options...) +} + +// Sugar wraps the Logger to provide a more ergonomic, but slightly slower, +// API. Sugaring a Logger is quite inexpensive, so it's reasonable for a +// single application to use both Loggers and SugaredLoggers, converting +// between them on the boundaries of performance-sensitive code. +func (log *Logger) Sugar() *SugaredLogger { +	core := log.clone() +	core.callerSkip += 2 +	return &SugaredLogger{core} +} + +// Named adds a new path segment to the logger's name. Segments are joined by +// periods. By default, Loggers are unnamed. +func (log *Logger) Named(s string) *Logger { +	if s == "" { +		return log +	} +	l := log.clone() +	if log.name == "" { +		l.name = s +	} else { +		l.name = strings.Join([]string{l.name, s}, ".") +	} +	return l +} + +// WithOptions clones the current Logger, applies the supplied Options, and +// returns the resulting Logger. It's safe to use concurrently. +func (log *Logger) WithOptions(opts ...Option) *Logger { +	c := log.clone() +	for _, opt := range opts { +		opt.apply(c) +	} +	return c +} + +// With creates a child logger and adds structured context to it. Fields added +// to the child don't affect the parent, and vice versa. +func (log *Logger) With(fields ...Field) *Logger { +	if len(fields) == 0 { +		return log +	} +	l := log.clone() +	l.core = l.core.With(fields) +	return l +} + +// Level reports the minimum enabled level for this logger. +// +// For NopLoggers, this is [zapcore.InvalidLevel]. +func (log *Logger) Level() zapcore.Level { +	return zapcore.LevelOf(log.core) +} + +// Check returns a CheckedEntry if logging a message at the specified level +// is enabled. It's a completely optional optimization; in high-performance +// applications, Check can help avoid allocating a slice to hold fields. +func (log *Logger) Check(lvl zapcore.Level, msg string) *zapcore.CheckedEntry { +	return log.check(lvl, msg) +} + +// Log logs a message at the specified level. The message includes any fields +// passed at the log site, as well as any fields accumulated on the logger. +func (log *Logger) Log(lvl zapcore.Level, msg string, fields ...Field) { +	if ce := log.check(lvl, msg); ce != nil { +		ce.Write(fields...) +	} +} + +// Debug logs a message at DebugLevel. The message includes any fields passed +// at the log site, as well as any fields accumulated on the logger. +func (log *Logger) Debug(msg string, fields ...Field) { +	if ce := log.check(DebugLevel, msg); ce != nil { +		ce.Write(fields...) +	} +} + +// Info logs a message at InfoLevel. The message includes any fields passed +// at the log site, as well as any fields accumulated on the logger. +func (log *Logger) Info(msg string, fields ...Field) { +	if ce := log.check(InfoLevel, msg); ce != nil { +		ce.Write(fields...) +	} +} + +// Warn logs a message at WarnLevel. The message includes any fields passed +// at the log site, as well as any fields accumulated on the logger. +func (log *Logger) Warn(msg string, fields ...Field) { +	if ce := log.check(WarnLevel, msg); ce != nil { +		ce.Write(fields...) +	} +} + +// Error logs a message at ErrorLevel. The message includes any fields passed +// at the log site, as well as any fields accumulated on the logger. +func (log *Logger) Error(msg string, fields ...Field) { +	if ce := log.check(ErrorLevel, msg); ce != nil { +		ce.Write(fields...) +	} +} + +// DPanic logs a message at DPanicLevel. The message includes any fields +// passed at the log site, as well as any fields accumulated on the logger. +// +// If the logger is in development mode, it then panics (DPanic means +// "development panic"). This is useful for catching errors that are +// recoverable, but shouldn't ever happen. +func (log *Logger) DPanic(msg string, fields ...Field) { +	if ce := log.check(DPanicLevel, msg); ce != nil { +		ce.Write(fields...) +	} +} + +// Panic logs a message at PanicLevel. The message includes any fields passed +// at the log site, as well as any fields accumulated on the logger. +// +// The logger then panics, even if logging at PanicLevel is disabled. +func (log *Logger) Panic(msg string, fields ...Field) { +	if ce := log.check(PanicLevel, msg); ce != nil { +		ce.Write(fields...) +	} +} + +// Fatal logs a message at FatalLevel. The message includes any fields passed +// at the log site, as well as any fields accumulated on the logger. +// +// The logger then calls os.Exit(1), even if logging at FatalLevel is +// disabled. +func (log *Logger) Fatal(msg string, fields ...Field) { +	if ce := log.check(FatalLevel, msg); ce != nil { +		ce.Write(fields...) +	} +} + +// Sync calls the underlying Core's Sync method, flushing any buffered log +// entries. Applications should take care to call Sync before exiting. +func (log *Logger) Sync() error { +	return log.core.Sync() +} + +// Core returns the Logger's underlying zapcore.Core. +func (log *Logger) Core() zapcore.Core { +	return log.core +} + +func (log *Logger) clone() *Logger { +	copy := *log +	return © +} + +func (log *Logger) check(lvl zapcore.Level, msg string) *zapcore.CheckedEntry { +	// Logger.check must always be called directly by a method in the +	// Logger interface (e.g., Check, Info, Fatal). +	// This skips Logger.check and the Info/Fatal/Check/etc. method that +	// called it. +	const callerSkipOffset = 2 + +	// Check the level first to reduce the cost of disabled log calls. +	// Since Panic and higher may exit, we skip the optimization for those levels. +	if lvl < zapcore.DPanicLevel && !log.core.Enabled(lvl) { +		return nil +	} + +	// Create basic checked entry thru the core; this will be non-nil if the +	// log message will actually be written somewhere. +	ent := zapcore.Entry{ +		LoggerName: log.name, +		Time:       log.clock.Now(), +		Level:      lvl, +		Message:    msg, +	} +	ce := log.core.Check(ent, nil) +	willWrite := ce != nil + +	// Set up any required terminal behavior. +	switch ent.Level { +	case zapcore.PanicLevel: +		ce = ce.After(ent, zapcore.WriteThenPanic) +	case zapcore.FatalLevel: +		onFatal := log.onFatal +		// nil or WriteThenNoop will lead to continued execution after +		// a Fatal log entry, which is unexpected. For example, +		// +		//   f, err := os.Open(..) +		//   if err != nil { +		//     log.Fatal("cannot open", zap.Error(err)) +		//   } +		//   fmt.Println(f.Name()) +		// +		// The f.Name() will panic if we continue execution after the +		// log.Fatal. +		if onFatal == nil || onFatal == zapcore.WriteThenNoop { +			onFatal = zapcore.WriteThenFatal +		} +		ce = ce.After(ent, onFatal) +	case zapcore.DPanicLevel: +		if log.development { +			ce = ce.After(ent, zapcore.WriteThenPanic) +		} +	} + +	// Only do further annotation if we're going to write this message; checked +	// entries that exist only for terminal behavior don't benefit from +	// annotation. +	if !willWrite { +		return ce +	} + +	// Thread the error output through to the CheckedEntry. +	ce.ErrorOutput = log.errorOutput + +	addStack := log.addStack.Enabled(ce.Level) +	if !log.addCaller && !addStack { +		return ce +	} + +	// Adding the caller or stack trace requires capturing the callers of +	// this function. We'll share information between these two. +	stackDepth := stacktraceFirst +	if addStack { +		stackDepth = stacktraceFull +	} +	stack := captureStacktrace(log.callerSkip+callerSkipOffset, stackDepth) +	defer stack.Free() + +	if stack.Count() == 0 { +		if log.addCaller { +			fmt.Fprintf(log.errorOutput, "%v Logger.check error: failed to get caller\n", ent.Time.UTC()) +			log.errorOutput.Sync() +		} +		return ce +	} + +	frame, more := stack.Next() + +	if log.addCaller { +		ce.Caller = zapcore.EntryCaller{ +			Defined:  frame.PC != 0, +			PC:       frame.PC, +			File:     frame.File, +			Line:     frame.Line, +			Function: frame.Function, +		} +	} + +	if addStack { +		buffer := bufferpool.Get() +		defer buffer.Free() + +		stackfmt := newStackFormatter(buffer) + +		// We've already extracted the first frame, so format that +		// separately and defer to stackfmt for the rest. +		stackfmt.FormatFrame(frame) +		if more { +			stackfmt.FormatStack(stack) +		} +		ce.Stack = buffer.String() +	} + +	return ce +} diff --git a/vendor/go.uber.org/zap/options.go b/vendor/go.uber.org/zap/options.go new file mode 100644 index 0000000..c4f3bca --- /dev/null +++ b/vendor/go.uber.org/zap/options.go @@ -0,0 +1,167 @@ +// 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 + +import ( +	"fmt" + +	"go.uber.org/zap/zapcore" +) + +// An Option configures a Logger. +type Option interface { +	apply(*Logger) +} + +// optionFunc wraps a func so it satisfies the Option interface. +type optionFunc func(*Logger) + +func (f optionFunc) apply(log *Logger) { +	f(log) +} + +// WrapCore wraps or replaces the Logger's underlying zapcore.Core. +func WrapCore(f func(zapcore.Core) zapcore.Core) Option { +	return optionFunc(func(log *Logger) { +		log.core = f(log.core) +	}) +} + +// Hooks registers functions which will be called each time the Logger writes +// out an Entry. Repeated use of Hooks is additive. +// +// Hooks are useful for simple side effects, like capturing metrics for the +// number of emitted logs. More complex side effects, including anything that +// requires access to the Entry's structured fields, should be implemented as +// a zapcore.Core instead. See zapcore.RegisterHooks for details. +func Hooks(hooks ...func(zapcore.Entry) error) Option { +	return optionFunc(func(log *Logger) { +		log.core = zapcore.RegisterHooks(log.core, hooks...) +	}) +} + +// Fields adds fields to the Logger. +func Fields(fs ...Field) Option { +	return optionFunc(func(log *Logger) { +		log.core = log.core.With(fs) +	}) +} + +// ErrorOutput sets the destination for errors generated by the Logger. Note +// that this option only affects internal errors; for sample code that sends +// error-level logs to a different location from info- and debug-level logs, +// see the package-level AdvancedConfiguration example. +// +// The supplied WriteSyncer must be safe for concurrent use. The Open and +// zapcore.Lock functions are the simplest ways to protect files with a mutex. +func ErrorOutput(w zapcore.WriteSyncer) Option { +	return optionFunc(func(log *Logger) { +		log.errorOutput = w +	}) +} + +// Development puts the logger in development mode, which makes DPanic-level +// logs panic instead of simply logging an error. +func Development() Option { +	return optionFunc(func(log *Logger) { +		log.development = true +	}) +} + +// AddCaller configures the Logger to annotate each message with the filename, +// line number, and function name of zap's caller. See also WithCaller. +func AddCaller() Option { +	return WithCaller(true) +} + +// WithCaller configures the Logger to annotate each message with the filename, +// line number, and function name of zap's caller, or not, depending on the +// value of enabled. This is a generalized form of AddCaller. +func WithCaller(enabled bool) Option { +	return optionFunc(func(log *Logger) { +		log.addCaller = enabled +	}) +} + +// AddCallerSkip increases the number of callers skipped by caller annotation +// (as enabled by the AddCaller option). When building wrappers around the +// Logger and SugaredLogger, supplying this Option prevents zap from always +// reporting the wrapper code as the caller. +func AddCallerSkip(skip int) Option { +	return optionFunc(func(log *Logger) { +		log.callerSkip += skip +	}) +} + +// AddStacktrace configures the Logger to record a stack trace for all messages at +// or above a given level. +func AddStacktrace(lvl zapcore.LevelEnabler) Option { +	return optionFunc(func(log *Logger) { +		log.addStack = lvl +	}) +} + +// IncreaseLevel increase the level of the logger. It has no effect if +// the passed in level tries to decrease the level of the logger. +func IncreaseLevel(lvl zapcore.LevelEnabler) Option { +	return optionFunc(func(log *Logger) { +		core, err := zapcore.NewIncreaseLevelCore(log.core, lvl) +		if err != nil { +			fmt.Fprintf(log.errorOutput, "failed to IncreaseLevel: %v\n", err) +		} else { +			log.core = core +		} +	}) +} + +// OnFatal sets the action to take on fatal logs. +// +// Deprecated: Use [WithFatalHook] instead. +func OnFatal(action zapcore.CheckWriteAction) Option { +	return WithFatalHook(action) +} + +// WithFatalHook sets a CheckWriteHook to run on fatal logs. +// Zap will call this hook after writing a log statement with a Fatal level. +// +// For example, the following builds a logger that will exit the current +// goroutine after writing a fatal log message, but it will not exit the +// program. +// +//	zap.New(core, zap.WithFatalHook(zapcore.WriteThenGoexit)) +// +// It is important that the provided CheckWriteHook stops the control flow at +// the current statement to meet expectations of callers of the logger. +// We recommend calling os.Exit or runtime.Goexit inside custom hooks at +// minimum. +func WithFatalHook(hook zapcore.CheckWriteHook) Option { +	return optionFunc(func(log *Logger) { +		log.onFatal = hook +	}) +} + +// WithClock specifies the clock used by the logger to determine the current +// time for logged entries. Defaults to the system clock with time.Now. +func WithClock(clock zapcore.Clock) Option { +	return optionFunc(func(log *Logger) { +		log.clock = clock +	}) +} diff --git a/vendor/go.uber.org/zap/sink.go b/vendor/go.uber.org/zap/sink.go new file mode 100644 index 0000000..478c9a1 --- /dev/null +++ b/vendor/go.uber.org/zap/sink.go @@ -0,0 +1,179 @@ +// Copyright (c) 2016-2022 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 + +import ( +	"errors" +	"fmt" +	"io" +	"net/url" +	"os" +	"path/filepath" +	"strings" +	"sync" + +	"go.uber.org/zap/zapcore" +) + +const schemeFile = "file" + +var _sinkRegistry = newSinkRegistry() + +// Sink defines the interface to write to and close logger destinations. +type Sink interface { +	zapcore.WriteSyncer +	io.Closer +} + +type errSinkNotFound struct { +	scheme string +} + +func (e *errSinkNotFound) Error() string { +	return fmt.Sprintf("no sink found for scheme %q", e.scheme) +} + +type nopCloserSink struct{ zapcore.WriteSyncer } + +func (nopCloserSink) Close() error { return nil } + +type sinkRegistry struct { +	mu        sync.Mutex +	factories map[string]func(*url.URL) (Sink, error)          // keyed by scheme +	openFile  func(string, int, os.FileMode) (*os.File, error) // type matches os.OpenFile +} + +func newSinkRegistry() *sinkRegistry { +	sr := &sinkRegistry{ +		factories: make(map[string]func(*url.URL) (Sink, error)), +		openFile:  os.OpenFile, +	} +	sr.RegisterSink(schemeFile, sr.newFileSinkFromURL) +	return sr +} + +// RegisterScheme registers the given factory for the specific scheme. +func (sr *sinkRegistry) RegisterSink(scheme string, factory func(*url.URL) (Sink, error)) error { +	sr.mu.Lock() +	defer sr.mu.Unlock() + +	if scheme == "" { +		return errors.New("can't register a sink factory for empty string") +	} +	normalized, err := normalizeScheme(scheme) +	if err != nil { +		return fmt.Errorf("%q is not a valid scheme: %v", scheme, err) +	} +	if _, ok := sr.factories[normalized]; ok { +		return fmt.Errorf("sink factory already registered for scheme %q", normalized) +	} +	sr.factories[normalized] = factory +	return nil +} + +func (sr *sinkRegistry) newSink(rawURL string) (Sink, error) { +	// URL parsing doesn't work well for Windows paths such as `c:\log.txt`, as scheme is set to +	// the drive, and path is unset unless `c:/log.txt` is used. +	// To avoid Windows-specific URL handling, we instead check IsAbs to open as a file. +	// filepath.IsAbs is OS-specific, so IsAbs('c:/log.txt') is false outside of Windows. +	if filepath.IsAbs(rawURL) { +		return sr.newFileSinkFromPath(rawURL) +	} + +	u, err := url.Parse(rawURL) +	if err != nil { +		return nil, fmt.Errorf("can't parse %q as a URL: %v", rawURL, err) +	} +	if u.Scheme == "" { +		u.Scheme = schemeFile +	} + +	sr.mu.Lock() +	factory, ok := sr.factories[u.Scheme] +	sr.mu.Unlock() +	if !ok { +		return nil, &errSinkNotFound{u.Scheme} +	} +	return factory(u) +} + +// RegisterSink registers a user-supplied factory for all sinks with a +// particular scheme. +// +// All schemes must be ASCII, valid under section 0.1 of RFC 3986 +// (https://tools.ietf.org/html/rfc3983#section-3.1), and must not already +// have a factory registered. Zap automatically registers a factory for the +// "file" scheme. +func RegisterSink(scheme string, factory func(*url.URL) (Sink, error)) error { +	return _sinkRegistry.RegisterSink(scheme, factory) +} + +func (sr *sinkRegistry) newFileSinkFromURL(u *url.URL) (Sink, error) { +	if u.User != nil { +		return nil, fmt.Errorf("user and password not allowed with file URLs: got %v", u) +	} +	if u.Fragment != "" { +		return nil, fmt.Errorf("fragments not allowed with file URLs: got %v", u) +	} +	if u.RawQuery != "" { +		return nil, fmt.Errorf("query parameters not allowed with file URLs: got %v", u) +	} +	// Error messages are better if we check hostname and port separately. +	if u.Port() != "" { +		return nil, fmt.Errorf("ports not allowed with file URLs: got %v", u) +	} +	if hn := u.Hostname(); hn != "" && hn != "localhost" { +		return nil, fmt.Errorf("file URLs must leave host empty or use localhost: got %v", u) +	} + +	return sr.newFileSinkFromPath(u.Path) +} + +func (sr *sinkRegistry) newFileSinkFromPath(path string) (Sink, error) { +	switch path { +	case "stdout": +		return nopCloserSink{os.Stdout}, nil +	case "stderr": +		return nopCloserSink{os.Stderr}, nil +	} +	return sr.openFile(path, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0666) +} + +func normalizeScheme(s string) (string, error) { +	// https://tools.ietf.org/html/rfc3986#section-3.1 +	s = strings.ToLower(s) +	if first := s[0]; 'a' > first || 'z' < first { +		return "", errors.New("must start with a letter") +	} +	for i := 1; i < len(s); i++ { // iterate over bytes, not runes +		c := s[i] +		switch { +		case 'a' <= c && c <= 'z': +			continue +		case '0' <= c && c <= '9': +			continue +		case c == '.' || c == '+' || c == '-': +			continue +		} +		return "", fmt.Errorf("may not contain %q", c) +	} +	return s, nil +} diff --git a/vendor/go.uber.org/zap/stacktrace.go b/vendor/go.uber.org/zap/stacktrace.go new file mode 100644 index 0000000..817a3bd --- /dev/null +++ b/vendor/go.uber.org/zap/stacktrace.go @@ -0,0 +1,176 @@ +// 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 + +import ( +	"runtime" +	"sync" + +	"go.uber.org/zap/buffer" +	"go.uber.org/zap/internal/bufferpool" +) + +var _stacktracePool = sync.Pool{ +	New: func() interface{} { +		return &stacktrace{ +			storage: make([]uintptr, 64), +		} +	}, +} + +type stacktrace struct { +	pcs    []uintptr // program counters; always a subslice of storage +	frames *runtime.Frames + +	// The size of pcs varies depending on requirements: +	// it will be one if the only the first frame was requested, +	// and otherwise it will reflect the depth of the call stack. +	// +	// storage decouples the slice we need (pcs) from the slice we pool. +	// We will always allocate a reasonably large storage, but we'll use +	// only as much of it as we need. +	storage []uintptr +} + +// stacktraceDepth specifies how deep of a stack trace should be captured. +type stacktraceDepth int + +const ( +	// stacktraceFirst captures only the first frame. +	stacktraceFirst stacktraceDepth = iota + +	// stacktraceFull captures the entire call stack, allocating more +	// storage for it if needed. +	stacktraceFull +) + +// captureStacktrace captures a stack trace of the specified depth, skipping +// the provided number of frames. skip=0 identifies the caller of +// captureStacktrace. +// +// The caller must call Free on the returned stacktrace after using it. +func captureStacktrace(skip int, depth stacktraceDepth) *stacktrace { +	stack := _stacktracePool.Get().(*stacktrace) + +	switch depth { +	case stacktraceFirst: +		stack.pcs = stack.storage[:1] +	case stacktraceFull: +		stack.pcs = stack.storage +	} + +	// Unlike other "skip"-based APIs, skip=0 identifies runtime.Callers +	// itself. +2 to skip captureStacktrace and runtime.Callers. +	numFrames := runtime.Callers( +		skip+2, +		stack.pcs, +	) + +	// runtime.Callers truncates the recorded stacktrace if there is no +	// room in the provided slice. For the full stack trace, keep expanding +	// storage until there are fewer frames than there is room. +	if depth == stacktraceFull { +		pcs := stack.pcs +		for numFrames == len(pcs) { +			pcs = make([]uintptr, len(pcs)*2) +			numFrames = runtime.Callers(skip+2, pcs) +		} + +		// Discard old storage instead of returning it to the pool. +		// This will adjust the pool size over time if stack traces are +		// consistently very deep. +		stack.storage = pcs +		stack.pcs = pcs[:numFrames] +	} else { +		stack.pcs = stack.pcs[:numFrames] +	} + +	stack.frames = runtime.CallersFrames(stack.pcs) +	return stack +} + +// Free releases resources associated with this stacktrace +// and returns it back to the pool. +func (st *stacktrace) Free() { +	st.frames = nil +	st.pcs = nil +	_stacktracePool.Put(st) +} + +// Count reports the total number of frames in this stacktrace. +// Count DOES NOT change as Next is called. +func (st *stacktrace) Count() int { +	return len(st.pcs) +} + +// Next returns the next frame in the stack trace, +// and a boolean indicating whether there are more after it. +func (st *stacktrace) Next() (_ runtime.Frame, more bool) { +	return st.frames.Next() +} + +func takeStacktrace(skip int) string { +	stack := captureStacktrace(skip+1, stacktraceFull) +	defer stack.Free() + +	buffer := bufferpool.Get() +	defer buffer.Free() + +	stackfmt := newStackFormatter(buffer) +	stackfmt.FormatStack(stack) +	return buffer.String() +} + +// stackFormatter formats a stack trace into a readable string representation. +type stackFormatter struct { +	b        *buffer.Buffer +	nonEmpty bool // whehther we've written at least one frame already +} + +// newStackFormatter builds a new stackFormatter. +func newStackFormatter(b *buffer.Buffer) stackFormatter { +	return stackFormatter{b: b} +} + +// FormatStack formats all remaining frames in the provided stacktrace -- minus +// the final runtime.main/runtime.goexit frame. +func (sf *stackFormatter) FormatStack(stack *stacktrace) { +	// Note: On the last iteration, frames.Next() returns false, with a valid +	// frame, but we ignore this frame. The last frame is a runtime frame which +	// adds noise, since it's only either runtime.main or runtime.goexit. +	for frame, more := stack.Next(); more; frame, more = stack.Next() { +		sf.FormatFrame(frame) +	} +} + +// FormatFrame formats the given frame. +func (sf *stackFormatter) FormatFrame(frame runtime.Frame) { +	if sf.nonEmpty { +		sf.b.AppendByte('\n') +	} +	sf.nonEmpty = true +	sf.b.AppendString(frame.Function) +	sf.b.AppendByte('\n') +	sf.b.AppendByte('\t') +	sf.b.AppendString(frame.File) +	sf.b.AppendByte(':') +	sf.b.AppendInt(int64(frame.Line)) +} diff --git a/vendor/go.uber.org/zap/sugar.go b/vendor/go.uber.org/zap/sugar.go new file mode 100644 index 0000000..ac387b3 --- /dev/null +++ b/vendor/go.uber.org/zap/sugar.go @@ -0,0 +1,416 @@ +// 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 + +import ( +	"fmt" + +	"go.uber.org/zap/zapcore" + +	"go.uber.org/multierr" +) + +const ( +	_oddNumberErrMsg    = "Ignored key without a value." +	_nonStringKeyErrMsg = "Ignored key-value pairs with non-string keys." +	_multipleErrMsg     = "Multiple errors without a key." +) + +// A SugaredLogger wraps the base Logger functionality in a slower, but less +// verbose, API. Any Logger can be converted to a SugaredLogger with its Sugar +// method. +// +// Unlike the Logger, the SugaredLogger doesn't insist on structured logging. +// For each log level, it exposes four methods: +// +//   - methods named after the log level for log.Print-style logging +//   - methods ending in "w" for loosely-typed structured logging +//   - methods ending in "f" for log.Printf-style logging +//   - methods ending in "ln" for log.Println-style logging +// +// For example, the methods for InfoLevel are: +// +//	Info(...any)           Print-style logging +//	Infow(...any)          Structured logging (read as "info with") +//	Infof(string, ...any)  Printf-style logging +//	Infoln(...any)         Println-style logging +type SugaredLogger struct { +	base *Logger +} + +// Desugar unwraps a SugaredLogger, exposing the original Logger. Desugaring +// is quite inexpensive, so it's reasonable for a single application to use +// both Loggers and SugaredLoggers, converting between them on the boundaries +// of performance-sensitive code. +func (s *SugaredLogger) Desugar() *Logger { +	base := s.base.clone() +	base.callerSkip -= 2 +	return base +} + +// Named adds a sub-scope to the logger's name. See Logger.Named for details. +func (s *SugaredLogger) Named(name string) *SugaredLogger { +	return &SugaredLogger{base: s.base.Named(name)} +} + +// WithOptions clones the current SugaredLogger, applies the supplied Options, +// and returns the result. It's safe to use concurrently. +func (s *SugaredLogger) WithOptions(opts ...Option) *SugaredLogger { +	base := s.base.clone() +	for _, opt := range opts { +		opt.apply(base) +	} +	return &SugaredLogger{base: base} +} + +// With adds a variadic number of fields to the logging context. It accepts a +// mix of strongly-typed Field objects and loosely-typed key-value pairs. When +// processing pairs, the first element of the pair is used as the field key +// and the second as the field value. +// +// For example, +// +//	 sugaredLogger.With( +//	   "hello", "world", +//	   "failure", errors.New("oh no"), +//	   Stack(), +//	   "count", 42, +//	   "user", User{Name: "alice"}, +//	) +// +// is the equivalent of +// +//	unsugared.With( +//	  String("hello", "world"), +//	  String("failure", "oh no"), +//	  Stack(), +//	  Int("count", 42), +//	  Object("user", User{Name: "alice"}), +//	) +// +// Note that the keys in key-value pairs should be strings. In development, +// passing a non-string key panics. In production, the logger is more +// forgiving: a separate error is logged, but the key-value pair is skipped +// and execution continues. Passing an orphaned key triggers similar behavior: +// panics in development and errors in production. +func (s *SugaredLogger) With(args ...interface{}) *SugaredLogger { +	return &SugaredLogger{base: s.base.With(s.sweetenFields(args)...)} +} + +// Level reports the minimum enabled level for this logger. +// +// For NopLoggers, this is [zapcore.InvalidLevel]. +func (s *SugaredLogger) Level() zapcore.Level { +	return zapcore.LevelOf(s.base.core) +} + +// Debug uses fmt.Sprint to construct and log a message. +func (s *SugaredLogger) Debug(args ...interface{}) { +	s.log(DebugLevel, "", args, nil) +} + +// Info uses fmt.Sprint to construct and log a message. +func (s *SugaredLogger) Info(args ...interface{}) { +	s.log(InfoLevel, "", args, nil) +} + +// Warn uses fmt.Sprint to construct and log a message. +func (s *SugaredLogger) Warn(args ...interface{}) { +	s.log(WarnLevel, "", args, nil) +} + +// Error uses fmt.Sprint to construct and log a message. +func (s *SugaredLogger) Error(args ...interface{}) { +	s.log(ErrorLevel, "", args, nil) +} + +// DPanic uses fmt.Sprint to construct and log a message. In development, the +// logger then panics. (See DPanicLevel for details.) +func (s *SugaredLogger) DPanic(args ...interface{}) { +	s.log(DPanicLevel, "", args, nil) +} + +// Panic uses fmt.Sprint to construct and log a message, then panics. +func (s *SugaredLogger) Panic(args ...interface{}) { +	s.log(PanicLevel, "", args, nil) +} + +// Fatal uses fmt.Sprint to construct and log a message, then calls os.Exit. +func (s *SugaredLogger) Fatal(args ...interface{}) { +	s.log(FatalLevel, "", args, nil) +} + +// Debugf uses fmt.Sprintf to log a templated message. +func (s *SugaredLogger) Debugf(template string, args ...interface{}) { +	s.log(DebugLevel, template, args, nil) +} + +// Infof uses fmt.Sprintf to log a templated message. +func (s *SugaredLogger) Infof(template string, args ...interface{}) { +	s.log(InfoLevel, template, args, nil) +} + +// Warnf uses fmt.Sprintf to log a templated message. +func (s *SugaredLogger) Warnf(template string, args ...interface{}) { +	s.log(WarnLevel, template, args, nil) +} + +// Errorf uses fmt.Sprintf to log a templated message. +func (s *SugaredLogger) Errorf(template string, args ...interface{}) { +	s.log(ErrorLevel, template, args, nil) +} + +// DPanicf uses fmt.Sprintf to log a templated message. In development, the +// logger then panics. (See DPanicLevel for details.) +func (s *SugaredLogger) DPanicf(template string, args ...interface{}) { +	s.log(DPanicLevel, template, args, nil) +} + +// Panicf uses fmt.Sprintf to log a templated message, then panics. +func (s *SugaredLogger) Panicf(template string, args ...interface{}) { +	s.log(PanicLevel, template, args, nil) +} + +// Fatalf uses fmt.Sprintf to log a templated message, then calls os.Exit. +func (s *SugaredLogger) Fatalf(template string, args ...interface{}) { +	s.log(FatalLevel, template, args, nil) +} + +// Debugw logs a message with some additional context. The variadic key-value +// pairs are treated as they are in With. +// +// When debug-level logging is disabled, this is much faster than +// +//	s.With(keysAndValues).Debug(msg) +func (s *SugaredLogger) Debugw(msg string, keysAndValues ...interface{}) { +	s.log(DebugLevel, msg, nil, keysAndValues) +} + +// Infow logs a message with some additional context. The variadic key-value +// pairs are treated as they are in With. +func (s *SugaredLogger) Infow(msg string, keysAndValues ...interface{}) { +	s.log(InfoLevel, msg, nil, keysAndValues) +} + +// Warnw logs a message with some additional context. The variadic key-value +// pairs are treated as they are in With. +func (s *SugaredLogger) Warnw(msg string, keysAndValues ...interface{}) { +	s.log(WarnLevel, msg, nil, keysAndValues) +} + +// Errorw logs a message with some additional context. The variadic key-value +// pairs are treated as they are in With. +func (s *SugaredLogger) Errorw(msg string, keysAndValues ...interface{}) { +	s.log(ErrorLevel, msg, nil, keysAndValues) +} + +// DPanicw logs a message with some additional context. In development, the +// logger then panics. (See DPanicLevel for details.) The variadic key-value +// pairs are treated as they are in With. +func (s *SugaredLogger) DPanicw(msg string, keysAndValues ...interface{}) { +	s.log(DPanicLevel, msg, nil, keysAndValues) +} + +// Panicw logs a message with some additional context, then panics. The +// variadic key-value pairs are treated as they are in With. +func (s *SugaredLogger) Panicw(msg string, keysAndValues ...interface{}) { +	s.log(PanicLevel, msg, nil, keysAndValues) +} + +// Fatalw logs a message with some additional context, then calls os.Exit. The +// variadic key-value pairs are treated as they are in With. +func (s *SugaredLogger) Fatalw(msg string, keysAndValues ...interface{}) { +	s.log(FatalLevel, msg, nil, keysAndValues) +} + +// Debugln uses fmt.Sprintln to construct and log a message. +func (s *SugaredLogger) Debugln(args ...interface{}) { +	s.logln(DebugLevel, args, nil) +} + +// Infoln uses fmt.Sprintln to construct and log a message. +func (s *SugaredLogger) Infoln(args ...interface{}) { +	s.logln(InfoLevel, args, nil) +} + +// Warnln uses fmt.Sprintln to construct and log a message. +func (s *SugaredLogger) Warnln(args ...interface{}) { +	s.logln(WarnLevel, args, nil) +} + +// Errorln uses fmt.Sprintln to construct and log a message. +func (s *SugaredLogger) Errorln(args ...interface{}) { +	s.logln(ErrorLevel, args, nil) +} + +// DPanicln uses fmt.Sprintln to construct and log a message. In development, the +// logger then panics. (See DPanicLevel for details.) +func (s *SugaredLogger) DPanicln(args ...interface{}) { +	s.logln(DPanicLevel, args, nil) +} + +// Panicln uses fmt.Sprintln to construct and log a message, then panics. +func (s *SugaredLogger) Panicln(args ...interface{}) { +	s.logln(PanicLevel, args, nil) +} + +// Fatalln uses fmt.Sprintln to construct and log a message, then calls os.Exit. +func (s *SugaredLogger) Fatalln(args ...interface{}) { +	s.logln(FatalLevel, args, nil) +} + +// Sync flushes any buffered log entries. +func (s *SugaredLogger) Sync() error { +	return s.base.Sync() +} + +// log message with Sprint, Sprintf, or neither. +func (s *SugaredLogger) log(lvl zapcore.Level, template string, fmtArgs []interface{}, context []interface{}) { +	// If logging at this level is completely disabled, skip the overhead of +	// string formatting. +	if lvl < DPanicLevel && !s.base.Core().Enabled(lvl) { +		return +	} + +	msg := getMessage(template, fmtArgs) +	if ce := s.base.Check(lvl, msg); ce != nil { +		ce.Write(s.sweetenFields(context)...) +	} +} + +// logln message with Sprintln +func (s *SugaredLogger) logln(lvl zapcore.Level, fmtArgs []interface{}, context []interface{}) { +	if lvl < DPanicLevel && !s.base.Core().Enabled(lvl) { +		return +	} + +	msg := getMessageln(fmtArgs) +	if ce := s.base.Check(lvl, msg); ce != nil { +		ce.Write(s.sweetenFields(context)...) +	} +} + +// getMessage format with Sprint, Sprintf, or neither. +func getMessage(template string, fmtArgs []interface{}) string { +	if len(fmtArgs) == 0 { +		return template +	} + +	if template != "" { +		return fmt.Sprintf(template, fmtArgs...) +	} + +	if len(fmtArgs) == 1 { +		if str, ok := fmtArgs[0].(string); ok { +			return str +		} +	} +	return fmt.Sprint(fmtArgs...) +} + +// getMessageln format with Sprintln. +func getMessageln(fmtArgs []interface{}) string { +	msg := fmt.Sprintln(fmtArgs...) +	return msg[:len(msg)-1] +} + +func (s *SugaredLogger) sweetenFields(args []interface{}) []Field { +	if len(args) == 0 { +		return nil +	} + +	var ( +		// Allocate enough space for the worst case; if users pass only structured +		// fields, we shouldn't penalize them with extra allocations. +		fields    = make([]Field, 0, len(args)) +		invalid   invalidPairs +		seenError bool +	) + +	for i := 0; i < len(args); { +		// This is a strongly-typed field. Consume it and move on. +		if f, ok := args[i].(Field); ok { +			fields = append(fields, f) +			i++ +			continue +		} + +		// If it is an error, consume it and move on. +		if err, ok := args[i].(error); ok { +			if !seenError { +				seenError = true +				fields = append(fields, Error(err)) +			} else { +				s.base.Error(_multipleErrMsg, Error(err)) +			} +			i++ +			continue +		} + +		// Make sure this element isn't a dangling key. +		if i == len(args)-1 { +			s.base.Error(_oddNumberErrMsg, Any("ignored", args[i])) +			break +		} + +		// Consume this value and the next, treating them as a key-value pair. If the +		// key isn't a string, add this pair to the slice of invalid pairs. +		key, val := args[i], args[i+1] +		if keyStr, ok := key.(string); !ok { +			// Subsequent errors are likely, so allocate once up front. +			if cap(invalid) == 0 { +				invalid = make(invalidPairs, 0, len(args)/2) +			} +			invalid = append(invalid, invalidPair{i, key, val}) +		} else { +			fields = append(fields, Any(keyStr, val)) +		} +		i += 2 +	} + +	// If we encountered any invalid key-value pairs, log an error. +	if len(invalid) > 0 { +		s.base.Error(_nonStringKeyErrMsg, Array("invalid", invalid)) +	} +	return fields +} + +type invalidPair struct { +	position   int +	key, value interface{} +} + +func (p invalidPair) MarshalLogObject(enc zapcore.ObjectEncoder) error { +	enc.AddInt64("position", int64(p.position)) +	Any("key", p.key).AddTo(enc) +	Any("value", p.value).AddTo(enc) +	return nil +} + +type invalidPairs []invalidPair + +func (ps invalidPairs) MarshalLogArray(enc zapcore.ArrayEncoder) error { +	var err error +	for i := range ps { +		err = multierr.Append(err, enc.AppendObject(ps[i])) +	} +	return err +} diff --git a/vendor/go.uber.org/zap/time.go b/vendor/go.uber.org/zap/time.go new file mode 100644 index 0000000..c5a1f16 --- /dev/null +++ b/vendor/go.uber.org/zap/time.go @@ -0,0 +1,27 @@ +// 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 + +import "time" + +func timeToMillis(t time.Time) int64 { +	return t.UnixNano() / int64(time.Millisecond) +} diff --git a/vendor/go.uber.org/zap/writer.go b/vendor/go.uber.org/zap/writer.go new file mode 100644 index 0000000..f08728e --- /dev/null +++ b/vendor/go.uber.org/zap/writer.go @@ -0,0 +1,98 @@ +// Copyright (c) 2016-2022 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 + +import ( +	"fmt" +	"io" + +	"go.uber.org/zap/zapcore" + +	"go.uber.org/multierr" +) + +// Open is a high-level wrapper that takes a variadic number of URLs, opens or +// creates each of the specified resources, and combines them into a locked +// WriteSyncer. It also returns any error encountered and a function to close +// any opened files. +// +// Passing no URLs returns a no-op WriteSyncer. Zap handles URLs without a +// scheme and URLs with the "file" scheme. Third-party code may register +// factories for other schemes using RegisterSink. +// +// URLs with the "file" scheme must use absolute paths on the local +// filesystem. No user, password, port, fragments, or query parameters are +// allowed, and the hostname must be empty or "localhost". +// +// Since it's common to write logs to the local filesystem, URLs without a +// scheme (e.g., "/var/log/foo.log") are treated as local file paths. Without +// a scheme, the special paths "stdout" and "stderr" are interpreted as +// os.Stdout and os.Stderr. When specified without a scheme, relative file +// paths also work. +func Open(paths ...string) (zapcore.WriteSyncer, func(), error) { +	writers, close, err := open(paths) +	if err != nil { +		return nil, nil, err +	} + +	writer := CombineWriteSyncers(writers...) +	return writer, close, nil +} + +func open(paths []string) ([]zapcore.WriteSyncer, func(), error) { +	writers := make([]zapcore.WriteSyncer, 0, len(paths)) +	closers := make([]io.Closer, 0, len(paths)) +	close := func() { +		for _, c := range closers { +			c.Close() +		} +	} + +	var openErr error +	for _, path := range paths { +		sink, err := _sinkRegistry.newSink(path) +		if err != nil { +			openErr = multierr.Append(openErr, fmt.Errorf("open sink %q: %w", path, err)) +			continue +		} +		writers = append(writers, sink) +		closers = append(closers, sink) +	} +	if openErr != nil { +		close() +		return nil, nil, openErr +	} + +	return writers, close, nil +} + +// CombineWriteSyncers is a utility that combines multiple WriteSyncers into a +// single, locked WriteSyncer. If no inputs are supplied, it returns a no-op +// WriteSyncer. +// +// It's provided purely as a convenience; the result is no different from +// using zapcore.NewMultiWriteSyncer and zapcore.Lock individually. +func CombineWriteSyncers(writers ...zapcore.WriteSyncer) zapcore.WriteSyncer { +	if len(writers) == 0 { +		return zapcore.AddSync(io.Discard) +	} +	return zapcore.Lock(zapcore.NewMultiWriteSyncer(writers...)) +} diff --git a/vendor/go.uber.org/zap/zapcore/buffered_write_syncer.go b/vendor/go.uber.org/zap/zapcore/buffered_write_syncer.go new file mode 100644 index 0000000..a40e93b --- /dev/null +++ b/vendor/go.uber.org/zap/zapcore/buffered_write_syncer.go @@ -0,0 +1,219 @@ +// Copyright (c) 2021 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 zapcore + +import ( +	"bufio" +	"sync" +	"time" + +	"go.uber.org/multierr" +) + +const ( +	// _defaultBufferSize specifies the default size used by Buffer. +	_defaultBufferSize = 256 * 1024 // 256 kB + +	// _defaultFlushInterval specifies the default flush interval for +	// Buffer. +	_defaultFlushInterval = 30 * time.Second +) + +// A BufferedWriteSyncer is a WriteSyncer that buffers writes in-memory before +// flushing them to a wrapped WriteSyncer after reaching some limit, or at some +// fixed interval--whichever comes first. +// +// BufferedWriteSyncer is safe for concurrent use. You don't need to use +// zapcore.Lock for WriteSyncers with BufferedWriteSyncer. +// +// To set up a BufferedWriteSyncer, construct a WriteSyncer for your log +// destination (*os.File is a valid WriteSyncer), wrap it with +// BufferedWriteSyncer, and defer a Stop() call for when you no longer need the +// object. +// +//	 func main() { +//	   ws := ... // your log destination +//	   bws := &zapcore.BufferedWriteSyncer{WS: ws} +//	   defer bws.Stop() +// +//	   // ... +//	   core := zapcore.NewCore(enc, bws, lvl) +//	   logger := zap.New(core) +// +//	   // ... +//	} +// +// By default, a BufferedWriteSyncer will buffer up to 256 kilobytes of logs, +// waiting at most 30 seconds between flushes. +// You can customize these parameters by setting the Size or FlushInterval +// fields. +// For example, the following buffers up to 512 kB of logs before flushing them +// to Stderr, with a maximum of one minute between each flush. +// +//	ws := &BufferedWriteSyncer{ +//	  WS:            os.Stderr, +//	  Size:          512 * 1024, // 512 kB +//	  FlushInterval: time.Minute, +//	} +//	defer ws.Stop() +type BufferedWriteSyncer struct { +	// WS is the WriteSyncer around which BufferedWriteSyncer will buffer +	// writes. +	// +	// This field is required. +	WS WriteSyncer + +	// Size specifies the maximum amount of data the writer will buffered +	// before flushing. +	// +	// Defaults to 256 kB if unspecified. +	Size int + +	// FlushInterval specifies how often the writer should flush data if +	// there have been no writes. +	// +	// Defaults to 30 seconds if unspecified. +	FlushInterval time.Duration + +	// Clock, if specified, provides control of the source of time for the +	// writer. +	// +	// Defaults to the system clock. +	Clock Clock + +	// unexported fields for state +	mu          sync.Mutex +	initialized bool // whether initialize() has run +	stopped     bool // whether Stop() has run +	writer      *bufio.Writer +	ticker      *time.Ticker +	stop        chan struct{} // closed when flushLoop should stop +	done        chan struct{} // closed when flushLoop has stopped +} + +func (s *BufferedWriteSyncer) initialize() { +	size := s.Size +	if size == 0 { +		size = _defaultBufferSize +	} + +	flushInterval := s.FlushInterval +	if flushInterval == 0 { +		flushInterval = _defaultFlushInterval +	} + +	if s.Clock == nil { +		s.Clock = DefaultClock +	} + +	s.ticker = s.Clock.NewTicker(flushInterval) +	s.writer = bufio.NewWriterSize(s.WS, size) +	s.stop = make(chan struct{}) +	s.done = make(chan struct{}) +	s.initialized = true +	go s.flushLoop() +} + +// Write writes log data into buffer syncer directly, multiple Write calls will be batched, +// and log data will be flushed to disk when the buffer is full or periodically. +func (s *BufferedWriteSyncer) Write(bs []byte) (int, error) { +	s.mu.Lock() +	defer s.mu.Unlock() + +	if !s.initialized { +		s.initialize() +	} + +	// To avoid partial writes from being flushed, we manually flush the existing buffer if: +	// * The current write doesn't fit into the buffer fully, and +	// * The buffer is not empty (since bufio will not split large writes when the buffer is empty) +	if len(bs) > s.writer.Available() && s.writer.Buffered() > 0 { +		if err := s.writer.Flush(); err != nil { +			return 0, err +		} +	} + +	return s.writer.Write(bs) +} + +// Sync flushes buffered log data into disk directly. +func (s *BufferedWriteSyncer) Sync() error { +	s.mu.Lock() +	defer s.mu.Unlock() + +	var err error +	if s.initialized { +		err = s.writer.Flush() +	} + +	return multierr.Append(err, s.WS.Sync()) +} + +// flushLoop flushes the buffer at the configured interval until Stop is +// called. +func (s *BufferedWriteSyncer) flushLoop() { +	defer close(s.done) + +	for { +		select { +		case <-s.ticker.C: +			// we just simply ignore error here +			// because the underlying bufio writer stores any errors +			// and we return any error from Sync() as part of the close +			_ = s.Sync() +		case <-s.stop: +			return +		} +	} +} + +// Stop closes the buffer, cleans up background goroutines, and flushes +// remaining unwritten data. +func (s *BufferedWriteSyncer) Stop() (err error) { +	var stopped bool + +	// Critical section. +	func() { +		s.mu.Lock() +		defer s.mu.Unlock() + +		if !s.initialized { +			return +		} + +		stopped = s.stopped +		if stopped { +			return +		} +		s.stopped = true + +		s.ticker.Stop() +		close(s.stop) // tell flushLoop to stop +		<-s.done      // and wait until it has +	}() + +	// Don't call Sync on consecutive Stops. +	if !stopped { +		err = s.Sync() +	} + +	return err +} diff --git a/vendor/go.uber.org/zap/zapcore/clock.go b/vendor/go.uber.org/zap/zapcore/clock.go new file mode 100644 index 0000000..422fd82 --- /dev/null +++ b/vendor/go.uber.org/zap/zapcore/clock.go @@ -0,0 +1,48 @@ +// Copyright (c) 2021 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 zapcore + +import "time" + +// DefaultClock is the default clock used by Zap in operations that require +// time. This clock uses the system clock for all operations. +var DefaultClock = systemClock{} + +// Clock is a source of time for logged entries. +type Clock interface { +	// Now returns the current local time. +	Now() time.Time + +	// NewTicker returns *time.Ticker that holds a channel +	// that delivers "ticks" of a clock. +	NewTicker(time.Duration) *time.Ticker +} + +// systemClock implements default Clock that uses system time. +type systemClock struct{} + +func (systemClock) Now() time.Time { +	return time.Now() +} + +func (systemClock) NewTicker(duration time.Duration) *time.Ticker { +	return time.NewTicker(duration) +} diff --git a/vendor/go.uber.org/zap/zapcore/console_encoder.go b/vendor/go.uber.org/zap/zapcore/console_encoder.go new file mode 100644 index 0000000..1aa5dc3 --- /dev/null +++ b/vendor/go.uber.org/zap/zapcore/console_encoder.go @@ -0,0 +1,157 @@ +// 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 zapcore + +import ( +	"fmt" +	"sync" + +	"go.uber.org/zap/buffer" +	"go.uber.org/zap/internal/bufferpool" +) + +var _sliceEncoderPool = sync.Pool{ +	New: func() interface{} { +		return &sliceArrayEncoder{elems: make([]interface{}, 0, 2)} +	}, +} + +func getSliceEncoder() *sliceArrayEncoder { +	return _sliceEncoderPool.Get().(*sliceArrayEncoder) +} + +func putSliceEncoder(e *sliceArrayEncoder) { +	e.elems = e.elems[:0] +	_sliceEncoderPool.Put(e) +} + +type consoleEncoder struct { +	*jsonEncoder +} + +// NewConsoleEncoder creates an encoder whose output is designed for human - +// rather than machine - consumption. It serializes the core log entry data +// (message, level, timestamp, etc.) in a plain-text format and leaves the +// structured context as JSON. +// +// Note that although the console encoder doesn't use the keys specified in the +// encoder configuration, it will omit any element whose key is set to the empty +// string. +func NewConsoleEncoder(cfg EncoderConfig) Encoder { +	if cfg.ConsoleSeparator == "" { +		// Use a default delimiter of '\t' for backwards compatibility +		cfg.ConsoleSeparator = "\t" +	} +	return consoleEncoder{newJSONEncoder(cfg, true)} +} + +func (c consoleEncoder) Clone() Encoder { +	return consoleEncoder{c.jsonEncoder.Clone().(*jsonEncoder)} +} + +func (c consoleEncoder) EncodeEntry(ent Entry, fields []Field) (*buffer.Buffer, error) { +	line := bufferpool.Get() + +	// We don't want the entry's metadata to be quoted and escaped (if it's +	// encoded as strings), which means that we can't use the JSON encoder. The +	// simplest option is to use the memory encoder and fmt.Fprint. +	// +	// If this ever becomes a performance bottleneck, we can implement +	// ArrayEncoder for our plain-text format. +	arr := getSliceEncoder() +	if c.TimeKey != "" && c.EncodeTime != nil { +		c.EncodeTime(ent.Time, arr) +	} +	if c.LevelKey != "" && c.EncodeLevel != nil { +		c.EncodeLevel(ent.Level, arr) +	} +	if ent.LoggerName != "" && c.NameKey != "" { +		nameEncoder := c.EncodeName + +		if nameEncoder == nil { +			// Fall back to FullNameEncoder for backward compatibility. +			nameEncoder = FullNameEncoder +		} + +		nameEncoder(ent.LoggerName, arr) +	} +	if ent.Caller.Defined { +		if c.CallerKey != "" && c.EncodeCaller != nil { +			c.EncodeCaller(ent.Caller, arr) +		} +		if c.FunctionKey != "" { +			arr.AppendString(ent.Caller.Function) +		} +	} +	for i := range arr.elems { +		if i > 0 { +			line.AppendString(c.ConsoleSeparator) +		} +		fmt.Fprint(line, arr.elems[i]) +	} +	putSliceEncoder(arr) + +	// Add the message itself. +	if c.MessageKey != "" { +		c.addSeparatorIfNecessary(line) +		line.AppendString(ent.Message) +	} + +	// Add any structured context. +	c.writeContext(line, fields) + +	// If there's no stacktrace key, honor that; this allows users to force +	// single-line output. +	if ent.Stack != "" && c.StacktraceKey != "" { +		line.AppendByte('\n') +		line.AppendString(ent.Stack) +	} + +	line.AppendString(c.LineEnding) +	return line, nil +} + +func (c consoleEncoder) writeContext(line *buffer.Buffer, extra []Field) { +	context := c.jsonEncoder.Clone().(*jsonEncoder) +	defer func() { +		// putJSONEncoder assumes the buffer is still used, but we write out the buffer so +		// we can free it. +		context.buf.Free() +		putJSONEncoder(context) +	}() + +	addFields(context, extra) +	context.closeOpenNamespaces() +	if context.buf.Len() == 0 { +		return +	} + +	c.addSeparatorIfNecessary(line) +	line.AppendByte('{') +	line.Write(context.buf.Bytes()) +	line.AppendByte('}') +} + +func (c consoleEncoder) addSeparatorIfNecessary(line *buffer.Buffer) { +	if line.Len() > 0 { +		line.AppendString(c.ConsoleSeparator) +	} +} diff --git a/vendor/go.uber.org/zap/zapcore/core.go b/vendor/go.uber.org/zap/zapcore/core.go new file mode 100644 index 0000000..9dfd640 --- /dev/null +++ b/vendor/go.uber.org/zap/zapcore/core.go @@ -0,0 +1,122 @@ +// 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 zapcore + +// Core is a minimal, fast logger interface. It's designed for library authors +// to wrap in a more user-friendly API. +type Core interface { +	LevelEnabler + +	// With adds structured context to the Core. +	With([]Field) Core +	// Check determines whether the supplied Entry should be logged (using the +	// embedded LevelEnabler and possibly some extra logic). If the entry +	// should be logged, the Core adds itself to the CheckedEntry and returns +	// the result. +	// +	// Callers must use Check before calling Write. +	Check(Entry, *CheckedEntry) *CheckedEntry +	// Write serializes the Entry and any Fields supplied at the log site and +	// writes them to their destination. +	// +	// If called, Write should always log the Entry and Fields; it should not +	// replicate the logic of Check. +	Write(Entry, []Field) error +	// Sync flushes buffered logs (if any). +	Sync() error +} + +type nopCore struct{} + +// NewNopCore returns a no-op Core. +func NewNopCore() Core                                        { return nopCore{} } +func (nopCore) Enabled(Level) bool                            { return false } +func (n nopCore) With([]Field) Core                           { return n } +func (nopCore) Check(_ Entry, ce *CheckedEntry) *CheckedEntry { return ce } +func (nopCore) Write(Entry, []Field) error                    { return nil } +func (nopCore) Sync() error                                   { return nil } + +// NewCore creates a Core that writes logs to a WriteSyncer. +func NewCore(enc Encoder, ws WriteSyncer, enab LevelEnabler) Core { +	return &ioCore{ +		LevelEnabler: enab, +		enc:          enc, +		out:          ws, +	} +} + +type ioCore struct { +	LevelEnabler +	enc Encoder +	out WriteSyncer +} + +var ( +	_ Core           = (*ioCore)(nil) +	_ leveledEnabler = (*ioCore)(nil) +) + +func (c *ioCore) Level() Level { +	return LevelOf(c.LevelEnabler) +} + +func (c *ioCore) With(fields []Field) Core { +	clone := c.clone() +	addFields(clone.enc, fields) +	return clone +} + +func (c *ioCore) Check(ent Entry, ce *CheckedEntry) *CheckedEntry { +	if c.Enabled(ent.Level) { +		return ce.AddCore(ent, c) +	} +	return ce +} + +func (c *ioCore) Write(ent Entry, fields []Field) error { +	buf, err := c.enc.EncodeEntry(ent, fields) +	if err != nil { +		return err +	} +	_, err = c.out.Write(buf.Bytes()) +	buf.Free() +	if err != nil { +		return err +	} +	if ent.Level > ErrorLevel { +		// Since we may be crashing the program, sync the output. Ignore Sync +		// errors, pending a clean solution to issue #370. +		c.Sync() +	} +	return nil +} + +func (c *ioCore) Sync() error { +	return c.out.Sync() +} + +func (c *ioCore) clone() *ioCore { +	return &ioCore{ +		LevelEnabler: c.LevelEnabler, +		enc:          c.enc.Clone(), +		out:          c.out, +	} +} diff --git a/vendor/go.uber.org/zap/zapcore/doc.go b/vendor/go.uber.org/zap/zapcore/doc.go new file mode 100644 index 0000000..31000e9 --- /dev/null +++ b/vendor/go.uber.org/zap/zapcore/doc.go @@ -0,0 +1,24 @@ +// 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 zapcore defines and implements the low-level interfaces upon which +// zap is built. By providing alternate implementations of these interfaces, +// external packages can extend zap's capabilities. +package zapcore // import "go.uber.org/zap/zapcore" diff --git a/vendor/go.uber.org/zap/zapcore/encoder.go b/vendor/go.uber.org/zap/zapcore/encoder.go new file mode 100644 index 0000000..5769ff3 --- /dev/null +++ b/vendor/go.uber.org/zap/zapcore/encoder.go @@ -0,0 +1,451 @@ +// 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 zapcore + +import ( +	"encoding/json" +	"io" +	"time" + +	"go.uber.org/zap/buffer" +) + +// DefaultLineEnding defines the default line ending when writing logs. +// Alternate line endings specified in EncoderConfig can override this +// behavior. +const DefaultLineEnding = "\n" + +// OmitKey defines the key to use when callers want to remove a key from log output. +const OmitKey = "" + +// A LevelEncoder serializes a Level to a primitive type. +type LevelEncoder func(Level, PrimitiveArrayEncoder) + +// LowercaseLevelEncoder serializes a Level to a lowercase string. For example, +// InfoLevel is serialized to "info". +func LowercaseLevelEncoder(l Level, enc PrimitiveArrayEncoder) { +	enc.AppendString(l.String()) +} + +// LowercaseColorLevelEncoder serializes a Level to a lowercase string and adds coloring. +// For example, InfoLevel is serialized to "info" and colored blue. +func LowercaseColorLevelEncoder(l Level, enc PrimitiveArrayEncoder) { +	s, ok := _levelToLowercaseColorString[l] +	if !ok { +		s = _unknownLevelColor.Add(l.String()) +	} +	enc.AppendString(s) +} + +// CapitalLevelEncoder serializes a Level to an all-caps string. For example, +// InfoLevel is serialized to "INFO". +func CapitalLevelEncoder(l Level, enc PrimitiveArrayEncoder) { +	enc.AppendString(l.CapitalString()) +} + +// CapitalColorLevelEncoder serializes a Level to an all-caps string and adds color. +// For example, InfoLevel is serialized to "INFO" and colored blue. +func CapitalColorLevelEncoder(l Level, enc PrimitiveArrayEncoder) { +	s, ok := _levelToCapitalColorString[l] +	if !ok { +		s = _unknownLevelColor.Add(l.CapitalString()) +	} +	enc.AppendString(s) +} + +// UnmarshalText unmarshals text to a LevelEncoder. "capital" is unmarshaled to +// CapitalLevelEncoder, "coloredCapital" is unmarshaled to CapitalColorLevelEncoder, +// "colored" is unmarshaled to LowercaseColorLevelEncoder, and anything else +// is unmarshaled to LowercaseLevelEncoder. +func (e *LevelEncoder) UnmarshalText(text []byte) error { +	switch string(text) { +	case "capital": +		*e = CapitalLevelEncoder +	case "capitalColor": +		*e = CapitalColorLevelEncoder +	case "color": +		*e = LowercaseColorLevelEncoder +	default: +		*e = LowercaseLevelEncoder +	} +	return nil +} + +// A TimeEncoder serializes a time.Time to a primitive type. +type TimeEncoder func(time.Time, PrimitiveArrayEncoder) + +// EpochTimeEncoder serializes a time.Time to a floating-point number of seconds +// since the Unix epoch. +func EpochTimeEncoder(t time.Time, enc PrimitiveArrayEncoder) { +	nanos := t.UnixNano() +	sec := float64(nanos) / float64(time.Second) +	enc.AppendFloat64(sec) +} + +// EpochMillisTimeEncoder serializes a time.Time to a floating-point number of +// milliseconds since the Unix epoch. +func EpochMillisTimeEncoder(t time.Time, enc PrimitiveArrayEncoder) { +	nanos := t.UnixNano() +	millis := float64(nanos) / float64(time.Millisecond) +	enc.AppendFloat64(millis) +} + +// EpochNanosTimeEncoder serializes a time.Time to an integer number of +// nanoseconds since the Unix epoch. +func EpochNanosTimeEncoder(t time.Time, enc PrimitiveArrayEncoder) { +	enc.AppendInt64(t.UnixNano()) +} + +func encodeTimeLayout(t time.Time, layout string, enc PrimitiveArrayEncoder) { +	type appendTimeEncoder interface { +		AppendTimeLayout(time.Time, string) +	} + +	if enc, ok := enc.(appendTimeEncoder); ok { +		enc.AppendTimeLayout(t, layout) +		return +	} + +	enc.AppendString(t.Format(layout)) +} + +// ISO8601TimeEncoder serializes a time.Time to an ISO8601-formatted string +// with millisecond precision. +// +// If enc supports AppendTimeLayout(t time.Time,layout string), it's used +// instead of appending a pre-formatted string value. +func ISO8601TimeEncoder(t time.Time, enc PrimitiveArrayEncoder) { +	encodeTimeLayout(t, "2006-01-02T15:04:05.000Z0700", enc) +} + +// RFC3339TimeEncoder serializes a time.Time to an RFC3339-formatted string. +// +// If enc supports AppendTimeLayout(t time.Time,layout string), it's used +// instead of appending a pre-formatted string value. +func RFC3339TimeEncoder(t time.Time, enc PrimitiveArrayEncoder) { +	encodeTimeLayout(t, time.RFC3339, enc) +} + +// RFC3339NanoTimeEncoder serializes a time.Time to an RFC3339-formatted string +// with nanosecond precision. +// +// If enc supports AppendTimeLayout(t time.Time,layout string), it's used +// instead of appending a pre-formatted string value. +func RFC3339NanoTimeEncoder(t time.Time, enc PrimitiveArrayEncoder) { +	encodeTimeLayout(t, time.RFC3339Nano, enc) +} + +// TimeEncoderOfLayout returns TimeEncoder which serializes a time.Time using +// given layout. +func TimeEncoderOfLayout(layout string) TimeEncoder { +	return func(t time.Time, enc PrimitiveArrayEncoder) { +		encodeTimeLayout(t, layout, enc) +	} +} + +// UnmarshalText unmarshals text to a TimeEncoder. +// "rfc3339nano" and "RFC3339Nano" are unmarshaled to RFC3339NanoTimeEncoder. +// "rfc3339" and "RFC3339" are unmarshaled to RFC3339TimeEncoder. +// "iso8601" and "ISO8601" are unmarshaled to ISO8601TimeEncoder. +// "millis" is unmarshaled to EpochMillisTimeEncoder. +// "nanos" is unmarshaled to EpochNanosEncoder. +// Anything else is unmarshaled to EpochTimeEncoder. +func (e *TimeEncoder) UnmarshalText(text []byte) error { +	switch string(text) { +	case "rfc3339nano", "RFC3339Nano": +		*e = RFC3339NanoTimeEncoder +	case "rfc3339", "RFC3339": +		*e = RFC3339TimeEncoder +	case "iso8601", "ISO8601": +		*e = ISO8601TimeEncoder +	case "millis": +		*e = EpochMillisTimeEncoder +	case "nanos": +		*e = EpochNanosTimeEncoder +	default: +		*e = EpochTimeEncoder +	} +	return nil +} + +// UnmarshalYAML unmarshals YAML to a TimeEncoder. +// If value is an object with a "layout" field, it will be unmarshaled to  TimeEncoder with given layout. +// +//	timeEncoder: +//	  layout: 06/01/02 03:04pm +// +// If value is string, it uses UnmarshalText. +// +//	timeEncoder: iso8601 +func (e *TimeEncoder) UnmarshalYAML(unmarshal func(interface{}) error) error { +	var o struct { +		Layout string `json:"layout" yaml:"layout"` +	} +	if err := unmarshal(&o); err == nil { +		*e = TimeEncoderOfLayout(o.Layout) +		return nil +	} + +	var s string +	if err := unmarshal(&s); err != nil { +		return err +	} +	return e.UnmarshalText([]byte(s)) +} + +// UnmarshalJSON unmarshals JSON to a TimeEncoder as same way UnmarshalYAML does. +func (e *TimeEncoder) UnmarshalJSON(data []byte) error { +	return e.UnmarshalYAML(func(v interface{}) error { +		return json.Unmarshal(data, v) +	}) +} + +// A DurationEncoder serializes a time.Duration to a primitive type. +type DurationEncoder func(time.Duration, PrimitiveArrayEncoder) + +// SecondsDurationEncoder serializes a time.Duration to a floating-point number of seconds elapsed. +func SecondsDurationEncoder(d time.Duration, enc PrimitiveArrayEncoder) { +	enc.AppendFloat64(float64(d) / float64(time.Second)) +} + +// NanosDurationEncoder serializes a time.Duration to an integer number of +// nanoseconds elapsed. +func NanosDurationEncoder(d time.Duration, enc PrimitiveArrayEncoder) { +	enc.AppendInt64(int64(d)) +} + +// MillisDurationEncoder serializes a time.Duration to an integer number of +// milliseconds elapsed. +func MillisDurationEncoder(d time.Duration, enc PrimitiveArrayEncoder) { +	enc.AppendInt64(d.Nanoseconds() / 1e6) +} + +// StringDurationEncoder serializes a time.Duration using its built-in String +// method. +func StringDurationEncoder(d time.Duration, enc PrimitiveArrayEncoder) { +	enc.AppendString(d.String()) +} + +// UnmarshalText unmarshals text to a DurationEncoder. "string" is unmarshaled +// to StringDurationEncoder, and anything else is unmarshaled to +// NanosDurationEncoder. +func (e *DurationEncoder) UnmarshalText(text []byte) error { +	switch string(text) { +	case "string": +		*e = StringDurationEncoder +	case "nanos": +		*e = NanosDurationEncoder +	case "ms": +		*e = MillisDurationEncoder +	default: +		*e = SecondsDurationEncoder +	} +	return nil +} + +// A CallerEncoder serializes an EntryCaller to a primitive type. +type CallerEncoder func(EntryCaller, PrimitiveArrayEncoder) + +// FullCallerEncoder serializes a caller in /full/path/to/package/file:line +// format. +func FullCallerEncoder(caller EntryCaller, enc PrimitiveArrayEncoder) { +	// TODO: consider using a byte-oriented API to save an allocation. +	enc.AppendString(caller.String()) +} + +// ShortCallerEncoder serializes a caller in package/file:line format, trimming +// all but the final directory from the full path. +func ShortCallerEncoder(caller EntryCaller, enc PrimitiveArrayEncoder) { +	// TODO: consider using a byte-oriented API to save an allocation. +	enc.AppendString(caller.TrimmedPath()) +} + +// UnmarshalText unmarshals text to a CallerEncoder. "full" is unmarshaled to +// FullCallerEncoder and anything else is unmarshaled to ShortCallerEncoder. +func (e *CallerEncoder) UnmarshalText(text []byte) error { +	switch string(text) { +	case "full": +		*e = FullCallerEncoder +	default: +		*e = ShortCallerEncoder +	} +	return nil +} + +// A NameEncoder serializes a period-separated logger name to a primitive +// type. +type NameEncoder func(string, PrimitiveArrayEncoder) + +// FullNameEncoder serializes the logger name as-is. +func FullNameEncoder(loggerName string, enc PrimitiveArrayEncoder) { +	enc.AppendString(loggerName) +} + +// UnmarshalText unmarshals text to a NameEncoder. Currently, everything is +// unmarshaled to FullNameEncoder. +func (e *NameEncoder) UnmarshalText(text []byte) error { +	switch string(text) { +	case "full": +		*e = FullNameEncoder +	default: +		*e = FullNameEncoder +	} +	return nil +} + +// An EncoderConfig allows users to configure the concrete encoders supplied by +// zapcore. +type EncoderConfig struct { +	// Set the keys used for each log entry. If any key is empty, that portion +	// of the entry is omitted. +	MessageKey     string `json:"messageKey" yaml:"messageKey"` +	LevelKey       string `json:"levelKey" yaml:"levelKey"` +	TimeKey        string `json:"timeKey" yaml:"timeKey"` +	NameKey        string `json:"nameKey" yaml:"nameKey"` +	CallerKey      string `json:"callerKey" yaml:"callerKey"` +	FunctionKey    string `json:"functionKey" yaml:"functionKey"` +	StacktraceKey  string `json:"stacktraceKey" yaml:"stacktraceKey"` +	SkipLineEnding bool   `json:"skipLineEnding" yaml:"skipLineEnding"` +	LineEnding     string `json:"lineEnding" yaml:"lineEnding"` +	// Configure the primitive representations of common complex types. For +	// example, some users may want all time.Times serialized as floating-point +	// seconds since epoch, while others may prefer ISO8601 strings. +	EncodeLevel    LevelEncoder    `json:"levelEncoder" yaml:"levelEncoder"` +	EncodeTime     TimeEncoder     `json:"timeEncoder" yaml:"timeEncoder"` +	EncodeDuration DurationEncoder `json:"durationEncoder" yaml:"durationEncoder"` +	EncodeCaller   CallerEncoder   `json:"callerEncoder" yaml:"callerEncoder"` +	// Unlike the other primitive type encoders, EncodeName is optional. The +	// zero value falls back to FullNameEncoder. +	EncodeName NameEncoder `json:"nameEncoder" yaml:"nameEncoder"` +	// Configure the encoder for interface{} type objects. +	// If not provided, objects are encoded using json.Encoder +	NewReflectedEncoder func(io.Writer) ReflectedEncoder `json:"-" yaml:"-"` +	// Configures the field separator used by the console encoder. Defaults +	// to tab. +	ConsoleSeparator string `json:"consoleSeparator" yaml:"consoleSeparator"` +} + +// ObjectEncoder is a strongly-typed, encoding-agnostic interface for adding a +// map- or struct-like object to the logging context. Like maps, ObjectEncoders +// aren't safe for concurrent use (though typical use shouldn't require locks). +type ObjectEncoder interface { +	// Logging-specific marshalers. +	AddArray(key string, marshaler ArrayMarshaler) error +	AddObject(key string, marshaler ObjectMarshaler) error + +	// Built-in types. +	AddBinary(key string, value []byte)     // for arbitrary bytes +	AddByteString(key string, value []byte) // for UTF-8 encoded bytes +	AddBool(key string, value bool) +	AddComplex128(key string, value complex128) +	AddComplex64(key string, value complex64) +	AddDuration(key string, value time.Duration) +	AddFloat64(key string, value float64) +	AddFloat32(key string, value float32) +	AddInt(key string, value int) +	AddInt64(key string, value int64) +	AddInt32(key string, value int32) +	AddInt16(key string, value int16) +	AddInt8(key string, value int8) +	AddString(key, value string) +	AddTime(key string, value time.Time) +	AddUint(key string, value uint) +	AddUint64(key string, value uint64) +	AddUint32(key string, value uint32) +	AddUint16(key string, value uint16) +	AddUint8(key string, value uint8) +	AddUintptr(key string, value uintptr) + +	// AddReflected uses reflection to serialize arbitrary objects, so it can be +	// slow and allocation-heavy. +	AddReflected(key string, value interface{}) error +	// OpenNamespace opens an isolated namespace where all subsequent fields will +	// be added. Applications can use namespaces to prevent key collisions when +	// injecting loggers into sub-components or third-party libraries. +	OpenNamespace(key string) +} + +// ArrayEncoder is a strongly-typed, encoding-agnostic interface for adding +// array-like objects to the logging context. Of note, it supports mixed-type +// arrays even though they aren't typical in Go. Like slices, ArrayEncoders +// aren't safe for concurrent use (though typical use shouldn't require locks). +type ArrayEncoder interface { +	// Built-in types. +	PrimitiveArrayEncoder + +	// Time-related types. +	AppendDuration(time.Duration) +	AppendTime(time.Time) + +	// Logging-specific marshalers. +	AppendArray(ArrayMarshaler) error +	AppendObject(ObjectMarshaler) error + +	// AppendReflected uses reflection to serialize arbitrary objects, so it's +	// slow and allocation-heavy. +	AppendReflected(value interface{}) error +} + +// PrimitiveArrayEncoder is the subset of the ArrayEncoder interface that deals +// only in Go's built-in types. It's included only so that Duration- and +// TimeEncoders cannot trigger infinite recursion. +type PrimitiveArrayEncoder interface { +	// Built-in types. +	AppendBool(bool) +	AppendByteString([]byte) // for UTF-8 encoded bytes +	AppendComplex128(complex128) +	AppendComplex64(complex64) +	AppendFloat64(float64) +	AppendFloat32(float32) +	AppendInt(int) +	AppendInt64(int64) +	AppendInt32(int32) +	AppendInt16(int16) +	AppendInt8(int8) +	AppendString(string) +	AppendUint(uint) +	AppendUint64(uint64) +	AppendUint32(uint32) +	AppendUint16(uint16) +	AppendUint8(uint8) +	AppendUintptr(uintptr) +} + +// Encoder is a format-agnostic interface for all log entry marshalers. Since +// log encoders don't need to support the same wide range of use cases as +// general-purpose marshalers, it's possible to make them faster and +// lower-allocation. +// +// Implementations of the ObjectEncoder interface's methods can, of course, +// freely modify the receiver. However, the Clone and EncodeEntry methods will +// be called concurrently and shouldn't modify the receiver. +type Encoder interface { +	ObjectEncoder + +	// Clone copies the encoder, ensuring that adding fields to the copy doesn't +	// affect the original. +	Clone() Encoder + +	// EncodeEntry encodes an entry and fields, along with any accumulated +	// context, into a byte buffer and returns it. Any fields that are empty, +	// including fields on the `Entry` type, should be omitted. +	EncodeEntry(Entry, []Field) (*buffer.Buffer, error) +} diff --git a/vendor/go.uber.org/zap/zapcore/entry.go b/vendor/go.uber.org/zap/zapcore/entry.go new file mode 100644 index 0000000..9d326e9 --- /dev/null +++ b/vendor/go.uber.org/zap/zapcore/entry.go @@ -0,0 +1,300 @@ +// 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 zapcore + +import ( +	"fmt" +	"runtime" +	"strings" +	"sync" +	"time" + +	"go.uber.org/multierr" +	"go.uber.org/zap/internal/bufferpool" +	"go.uber.org/zap/internal/exit" +) + +var ( +	_cePool = sync.Pool{New: func() interface{} { +		// Pre-allocate some space for cores. +		return &CheckedEntry{ +			cores: make([]Core, 4), +		} +	}} +) + +func getCheckedEntry() *CheckedEntry { +	ce := _cePool.Get().(*CheckedEntry) +	ce.reset() +	return ce +} + +func putCheckedEntry(ce *CheckedEntry) { +	if ce == nil { +		return +	} +	_cePool.Put(ce) +} + +// NewEntryCaller makes an EntryCaller from the return signature of +// runtime.Caller. +func NewEntryCaller(pc uintptr, file string, line int, ok bool) EntryCaller { +	if !ok { +		return EntryCaller{} +	} +	return EntryCaller{ +		PC:      pc, +		File:    file, +		Line:    line, +		Defined: true, +	} +} + +// EntryCaller represents the caller of a logging function. +type EntryCaller struct { +	Defined  bool +	PC       uintptr +	File     string +	Line     int +	Function string +} + +// String returns the full path and line number of the caller. +func (ec EntryCaller) String() string { +	return ec.FullPath() +} + +// FullPath returns a /full/path/to/package/file:line description of the +// caller. +func (ec EntryCaller) FullPath() string { +	if !ec.Defined { +		return "undefined" +	} +	buf := bufferpool.Get() +	buf.AppendString(ec.File) +	buf.AppendByte(':') +	buf.AppendInt(int64(ec.Line)) +	caller := buf.String() +	buf.Free() +	return caller +} + +// TrimmedPath returns a package/file:line description of the caller, +// preserving only the leaf directory name and file name. +func (ec EntryCaller) TrimmedPath() string { +	if !ec.Defined { +		return "undefined" +	} +	// nb. To make sure we trim the path correctly on Windows too, we +	// counter-intuitively need to use '/' and *not* os.PathSeparator here, +	// because the path given originates from Go stdlib, specifically +	// runtime.Caller() which (as of Mar/17) returns forward slashes even on +	// Windows. +	// +	// See https://github.com/golang/go/issues/3335 +	// and https://github.com/golang/go/issues/18151 +	// +	// for discussion on the issue on Go side. +	// +	// Find the last separator. +	// +	idx := strings.LastIndexByte(ec.File, '/') +	if idx == -1 { +		return ec.FullPath() +	} +	// Find the penultimate separator. +	idx = strings.LastIndexByte(ec.File[:idx], '/') +	if idx == -1 { +		return ec.FullPath() +	} +	buf := bufferpool.Get() +	// Keep everything after the penultimate separator. +	buf.AppendString(ec.File[idx+1:]) +	buf.AppendByte(':') +	buf.AppendInt(int64(ec.Line)) +	caller := buf.String() +	buf.Free() +	return caller +} + +// An Entry represents a complete log message. The entry's structured context +// is already serialized, but the log level, time, message, and call site +// information are available for inspection and modification. Any fields left +// empty will be omitted when encoding. +// +// Entries are pooled, so any functions that accept them MUST be careful not to +// retain references to them. +type Entry struct { +	Level      Level +	Time       time.Time +	LoggerName string +	Message    string +	Caller     EntryCaller +	Stack      string +} + +// CheckWriteHook is a custom action that may be executed after an entry is +// written. +// +// Register one on a CheckedEntry with the After method. +// +//	if ce := logger.Check(...); ce != nil { +//	  ce = ce.After(hook) +//	  ce.Write(...) +//	} +// +// You can configure the hook for Fatal log statements at the logger level with +// the zap.WithFatalHook option. +type CheckWriteHook interface { +	// OnWrite is invoked with the CheckedEntry that was written and a list +	// of fields added with that entry. +	// +	// The list of fields DOES NOT include fields that were already added +	// to the logger with the With method. +	OnWrite(*CheckedEntry, []Field) +} + +// CheckWriteAction indicates what action to take after a log entry is +// processed. Actions are ordered in increasing severity. +type CheckWriteAction uint8 + +const ( +	// WriteThenNoop indicates that nothing special needs to be done. It's the +	// default behavior. +	WriteThenNoop CheckWriteAction = iota +	// WriteThenGoexit runs runtime.Goexit after Write. +	WriteThenGoexit +	// WriteThenPanic causes a panic after Write. +	WriteThenPanic +	// WriteThenFatal causes an os.Exit(1) after Write. +	WriteThenFatal +) + +// OnWrite implements the OnWrite method to keep CheckWriteAction compatible +// with the new CheckWriteHook interface which deprecates CheckWriteAction. +func (a CheckWriteAction) OnWrite(ce *CheckedEntry, _ []Field) { +	switch a { +	case WriteThenGoexit: +		runtime.Goexit() +	case WriteThenPanic: +		panic(ce.Message) +	case WriteThenFatal: +		exit.With(1) +	} +} + +var _ CheckWriteHook = CheckWriteAction(0) + +// CheckedEntry is an Entry together with a collection of Cores that have +// already agreed to log it. +// +// CheckedEntry references should be created by calling AddCore or After on a +// nil *CheckedEntry. References are returned to a pool after Write, and MUST +// NOT be retained after calling their Write method. +type CheckedEntry struct { +	Entry +	ErrorOutput WriteSyncer +	dirty       bool // best-effort detection of pool misuse +	after       CheckWriteHook +	cores       []Core +} + +func (ce *CheckedEntry) reset() { +	ce.Entry = Entry{} +	ce.ErrorOutput = nil +	ce.dirty = false +	ce.after = nil +	for i := range ce.cores { +		// don't keep references to cores +		ce.cores[i] = nil +	} +	ce.cores = ce.cores[:0] +} + +// Write writes the entry to the stored Cores, returns any errors, and returns +// the CheckedEntry reference to a pool for immediate re-use. Finally, it +// executes any required CheckWriteAction. +func (ce *CheckedEntry) Write(fields ...Field) { +	if ce == nil { +		return +	} + +	if ce.dirty { +		if ce.ErrorOutput != nil { +			// Make a best effort to detect unsafe re-use of this CheckedEntry. +			// If the entry is dirty, log an internal error; because the +			// CheckedEntry is being used after it was returned to the pool, +			// the message may be an amalgamation from multiple call sites. +			fmt.Fprintf(ce.ErrorOutput, "%v Unsafe CheckedEntry re-use near Entry %+v.\n", ce.Time, ce.Entry) +			ce.ErrorOutput.Sync() +		} +		return +	} +	ce.dirty = true + +	var err error +	for i := range ce.cores { +		err = multierr.Append(err, ce.cores[i].Write(ce.Entry, fields)) +	} +	if err != nil && ce.ErrorOutput != nil { +		fmt.Fprintf(ce.ErrorOutput, "%v write error: %v\n", ce.Time, err) +		ce.ErrorOutput.Sync() +	} + +	hook := ce.after +	if hook != nil { +		hook.OnWrite(ce, fields) +	} +	putCheckedEntry(ce) +} + +// AddCore adds a Core that has agreed to log this CheckedEntry. It's intended to be +// used by Core.Check implementations, and is safe to call on nil CheckedEntry +// references. +func (ce *CheckedEntry) AddCore(ent Entry, core Core) *CheckedEntry { +	if ce == nil { +		ce = getCheckedEntry() +		ce.Entry = ent +	} +	ce.cores = append(ce.cores, core) +	return ce +} + +// Should sets this CheckedEntry's CheckWriteAction, which controls whether a +// Core will panic or fatal after writing this log entry. Like AddCore, it's +// safe to call on nil CheckedEntry references. +// +// Deprecated: Use [CheckedEntry.After] instead. +func (ce *CheckedEntry) Should(ent Entry, should CheckWriteAction) *CheckedEntry { +	return ce.After(ent, should) +} + +// After sets this CheckEntry's CheckWriteHook, which will be called after this +// log entry has been written. It's safe to call this on nil CheckedEntry +// references. +func (ce *CheckedEntry) After(ent Entry, hook CheckWriteHook) *CheckedEntry { +	if ce == nil { +		ce = getCheckedEntry() +		ce.Entry = ent +	} +	ce.after = hook +	return ce +} diff --git a/vendor/go.uber.org/zap/zapcore/error.go b/vendor/go.uber.org/zap/zapcore/error.go new file mode 100644 index 0000000..0635990 --- /dev/null +++ b/vendor/go.uber.org/zap/zapcore/error.go @@ -0,0 +1,132 @@ +// Copyright (c) 2017 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 zapcore + +import ( +	"fmt" +	"reflect" +	"sync" +) + +// Encodes the given error into fields of an object. A field with the given +// name is added for the error message. +// +// If the error implements fmt.Formatter, a field with the name ${key}Verbose +// is also added with the full verbose error message. +// +// Finally, if the error implements errorGroup (from go.uber.org/multierr) or +// causer (from github.com/pkg/errors), a ${key}Causes field is added with an +// array of objects containing the errors this error was comprised of. +// +//	{ +//	  "error": err.Error(), +//	  "errorVerbose": fmt.Sprintf("%+v", err), +//	  "errorCauses": [ +//	    ... +//	  ], +//	} +func encodeError(key string, err error, enc ObjectEncoder) (retErr error) { +	// Try to capture panics (from nil references or otherwise) when calling +	// the Error() method +	defer func() { +		if rerr := recover(); rerr != nil { +			// If it's a nil pointer, just say "<nil>". The likeliest causes are a +			// error that fails to guard against nil or a nil pointer for a +			// value receiver, and in either case, "<nil>" is a nice result. +			if v := reflect.ValueOf(err); v.Kind() == reflect.Ptr && v.IsNil() { +				enc.AddString(key, "<nil>") +				return +			} + +			retErr = fmt.Errorf("PANIC=%v", rerr) +		} +	}() + +	basic := err.Error() +	enc.AddString(key, basic) + +	switch e := err.(type) { +	case errorGroup: +		return enc.AddArray(key+"Causes", errArray(e.Errors())) +	case fmt.Formatter: +		verbose := fmt.Sprintf("%+v", e) +		if verbose != basic { +			// This is a rich error type, like those produced by +			// github.com/pkg/errors. +			enc.AddString(key+"Verbose", verbose) +		} +	} +	return nil +} + +type errorGroup interface { +	// Provides read-only access to the underlying list of errors, preferably +	// without causing any allocs. +	Errors() []error +} + +// Note that errArray and errArrayElem are very similar to the version +// implemented in the top-level error.go file. We can't re-use this because +// that would require exporting errArray as part of the zapcore API. + +// Encodes a list of errors using the standard error encoding logic. +type errArray []error + +func (errs errArray) MarshalLogArray(arr ArrayEncoder) error { +	for i := range errs { +		if errs[i] == nil { +			continue +		} + +		el := newErrArrayElem(errs[i]) +		arr.AppendObject(el) +		el.Free() +	} +	return nil +} + +var _errArrayElemPool = sync.Pool{New: func() interface{} { +	return &errArrayElem{} +}} + +// Encodes any error into a {"error": ...} re-using the same errors logic. +// +// May be passed in place of an array to build a single-element array. +type errArrayElem struct{ err error } + +func newErrArrayElem(err error) *errArrayElem { +	e := _errArrayElemPool.Get().(*errArrayElem) +	e.err = err +	return e +} + +func (e *errArrayElem) MarshalLogArray(arr ArrayEncoder) error { +	return arr.AppendObject(e) +} + +func (e *errArrayElem) MarshalLogObject(enc ObjectEncoder) error { +	return encodeError("error", e.err, enc) +} + +func (e *errArrayElem) Free() { +	e.err = nil +	_errArrayElemPool.Put(e) +} diff --git a/vendor/go.uber.org/zap/zapcore/field.go b/vendor/go.uber.org/zap/zapcore/field.go new file mode 100644 index 0000000..95bdb0a --- /dev/null +++ b/vendor/go.uber.org/zap/zapcore/field.go @@ -0,0 +1,233 @@ +// 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 zapcore + +import ( +	"bytes" +	"fmt" +	"math" +	"reflect" +	"time" +) + +// A FieldType indicates which member of the Field union struct should be used +// and how it should be serialized. +type FieldType uint8 + +const ( +	// UnknownType is the default field type. Attempting to add it to an encoder will panic. +	UnknownType FieldType = iota +	// ArrayMarshalerType indicates that the field carries an ArrayMarshaler. +	ArrayMarshalerType +	// ObjectMarshalerType indicates that the field carries an ObjectMarshaler. +	ObjectMarshalerType +	// BinaryType indicates that the field carries an opaque binary blob. +	BinaryType +	// BoolType indicates that the field carries a bool. +	BoolType +	// ByteStringType indicates that the field carries UTF-8 encoded bytes. +	ByteStringType +	// Complex128Type indicates that the field carries a complex128. +	Complex128Type +	// Complex64Type indicates that the field carries a complex128. +	Complex64Type +	// DurationType indicates that the field carries a time.Duration. +	DurationType +	// Float64Type indicates that the field carries a float64. +	Float64Type +	// Float32Type indicates that the field carries a float32. +	Float32Type +	// Int64Type indicates that the field carries an int64. +	Int64Type +	// Int32Type indicates that the field carries an int32. +	Int32Type +	// Int16Type indicates that the field carries an int16. +	Int16Type +	// Int8Type indicates that the field carries an int8. +	Int8Type +	// StringType indicates that the field carries a string. +	StringType +	// TimeType indicates that the field carries a time.Time that is +	// representable by a UnixNano() stored as an int64. +	TimeType +	// TimeFullType indicates that the field carries a time.Time stored as-is. +	TimeFullType +	// Uint64Type indicates that the field carries a uint64. +	Uint64Type +	// Uint32Type indicates that the field carries a uint32. +	Uint32Type +	// Uint16Type indicates that the field carries a uint16. +	Uint16Type +	// Uint8Type indicates that the field carries a uint8. +	Uint8Type +	// UintptrType indicates that the field carries a uintptr. +	UintptrType +	// ReflectType indicates that the field carries an interface{}, which should +	// be serialized using reflection. +	ReflectType +	// NamespaceType signals the beginning of an isolated namespace. All +	// subsequent fields should be added to the new namespace. +	NamespaceType +	// StringerType indicates that the field carries a fmt.Stringer. +	StringerType +	// ErrorType indicates that the field carries an error. +	ErrorType +	// SkipType indicates that the field is a no-op. +	SkipType + +	// InlineMarshalerType indicates that the field carries an ObjectMarshaler +	// that should be inlined. +	InlineMarshalerType +) + +// A Field is a marshaling operation used to add a key-value pair to a logger's +// context. Most fields are lazily marshaled, so it's inexpensive to add fields +// to disabled debug-level log statements. +type Field struct { +	Key       string +	Type      FieldType +	Integer   int64 +	String    string +	Interface interface{} +} + +// AddTo exports a field through the ObjectEncoder interface. It's primarily +// useful to library authors, and shouldn't be necessary in most applications. +func (f Field) AddTo(enc ObjectEncoder) { +	var err error + +	switch f.Type { +	case ArrayMarshalerType: +		err = enc.AddArray(f.Key, f.Interface.(ArrayMarshaler)) +	case ObjectMarshalerType: +		err = enc.AddObject(f.Key, f.Interface.(ObjectMarshaler)) +	case InlineMarshalerType: +		err = f.Interface.(ObjectMarshaler).MarshalLogObject(enc) +	case BinaryType: +		enc.AddBinary(f.Key, f.Interface.([]byte)) +	case BoolType: +		enc.AddBool(f.Key, f.Integer == 1) +	case ByteStringType: +		enc.AddByteString(f.Key, f.Interface.([]byte)) +	case Complex128Type: +		enc.AddComplex128(f.Key, f.Interface.(complex128)) +	case Complex64Type: +		enc.AddComplex64(f.Key, f.Interface.(complex64)) +	case DurationType: +		enc.AddDuration(f.Key, time.Duration(f.Integer)) +	case Float64Type: +		enc.AddFloat64(f.Key, math.Float64frombits(uint64(f.Integer))) +	case Float32Type: +		enc.AddFloat32(f.Key, math.Float32frombits(uint32(f.Integer))) +	case Int64Type: +		enc.AddInt64(f.Key, f.Integer) +	case Int32Type: +		enc.AddInt32(f.Key, int32(f.Integer)) +	case Int16Type: +		enc.AddInt16(f.Key, int16(f.Integer)) +	case Int8Type: +		enc.AddInt8(f.Key, int8(f.Integer)) +	case StringType: +		enc.AddString(f.Key, f.String) +	case TimeType: +		if f.Interface != nil { +			enc.AddTime(f.Key, time.Unix(0, f.Integer).In(f.Interface.(*time.Location))) +		} else { +			// Fall back to UTC if location is nil. +			enc.AddTime(f.Key, time.Unix(0, f.Integer)) +		} +	case TimeFullType: +		enc.AddTime(f.Key, f.Interface.(time.Time)) +	case Uint64Type: +		enc.AddUint64(f.Key, uint64(f.Integer)) +	case Uint32Type: +		enc.AddUint32(f.Key, uint32(f.Integer)) +	case Uint16Type: +		enc.AddUint16(f.Key, uint16(f.Integer)) +	case Uint8Type: +		enc.AddUint8(f.Key, uint8(f.Integer)) +	case UintptrType: +		enc.AddUintptr(f.Key, uintptr(f.Integer)) +	case ReflectType: +		err = enc.AddReflected(f.Key, f.Interface) +	case NamespaceType: +		enc.OpenNamespace(f.Key) +	case StringerType: +		err = encodeStringer(f.Key, f.Interface, enc) +	case ErrorType: +		err = encodeError(f.Key, f.Interface.(error), enc) +	case SkipType: +		break +	default: +		panic(fmt.Sprintf("unknown field type: %v", f)) +	} + +	if err != nil { +		enc.AddString(fmt.Sprintf("%sError", f.Key), err.Error()) +	} +} + +// Equals returns whether two fields are equal. For non-primitive types such as +// errors, marshalers, or reflect types, it uses reflect.DeepEqual. +func (f Field) Equals(other Field) bool { +	if f.Type != other.Type { +		return false +	} +	if f.Key != other.Key { +		return false +	} + +	switch f.Type { +	case BinaryType, ByteStringType: +		return bytes.Equal(f.Interface.([]byte), other.Interface.([]byte)) +	case ArrayMarshalerType, ObjectMarshalerType, ErrorType, ReflectType: +		return reflect.DeepEqual(f.Interface, other.Interface) +	default: +		return f == other +	} +} + +func addFields(enc ObjectEncoder, fields []Field) { +	for i := range fields { +		fields[i].AddTo(enc) +	} +} + +func encodeStringer(key string, stringer interface{}, enc ObjectEncoder) (retErr error) { +	// Try to capture panics (from nil references or otherwise) when calling +	// the String() method, similar to https://golang.org/src/fmt/print.go#L540 +	defer func() { +		if err := recover(); err != nil { +			// If it's a nil pointer, just say "<nil>". The likeliest causes are a +			// Stringer that fails to guard against nil or a nil pointer for a +			// value receiver, and in either case, "<nil>" is a nice result. +			if v := reflect.ValueOf(stringer); v.Kind() == reflect.Ptr && v.IsNil() { +				enc.AddString(key, "<nil>") +				return +			} + +			retErr = fmt.Errorf("PANIC=%v", err) +		} +	}() + +	enc.AddString(key, stringer.(fmt.Stringer).String()) +	return nil +} diff --git a/vendor/go.uber.org/zap/zapcore/hook.go b/vendor/go.uber.org/zap/zapcore/hook.go new file mode 100644 index 0000000..198def9 --- /dev/null +++ b/vendor/go.uber.org/zap/zapcore/hook.go @@ -0,0 +1,77 @@ +// 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 zapcore + +import "go.uber.org/multierr" + +type hooked struct { +	Core +	funcs []func(Entry) error +} + +var ( +	_ Core           = (*hooked)(nil) +	_ leveledEnabler = (*hooked)(nil) +) + +// RegisterHooks wraps a Core and runs a collection of user-defined callback +// hooks each time a message is logged. Execution of the callbacks is blocking. +// +// This offers users an easy way to register simple callbacks (e.g., metrics +// collection) without implementing the full Core interface. +func RegisterHooks(core Core, hooks ...func(Entry) error) Core { +	funcs := append([]func(Entry) error{}, hooks...) +	return &hooked{ +		Core:  core, +		funcs: funcs, +	} +} + +func (h *hooked) Level() Level { +	return LevelOf(h.Core) +} + +func (h *hooked) Check(ent Entry, ce *CheckedEntry) *CheckedEntry { +	// Let the wrapped Core decide whether to log this message or not. This +	// also gives the downstream a chance to register itself directly with the +	// CheckedEntry. +	if downstream := h.Core.Check(ent, ce); downstream != nil { +		return downstream.AddCore(ent, h) +	} +	return ce +} + +func (h *hooked) With(fields []Field) Core { +	return &hooked{ +		Core:  h.Core.With(fields), +		funcs: h.funcs, +	} +} + +func (h *hooked) Write(ent Entry, _ []Field) error { +	// Since our downstream had a chance to register itself directly with the +	// CheckedMessage, we don't need to call it here. +	var err error +	for i := range h.funcs { +		err = multierr.Append(err, h.funcs[i](ent)) +	} +	return err +} diff --git a/vendor/go.uber.org/zap/zapcore/increase_level.go b/vendor/go.uber.org/zap/zapcore/increase_level.go new file mode 100644 index 0000000..7a11237 --- /dev/null +++ b/vendor/go.uber.org/zap/zapcore/increase_level.go @@ -0,0 +1,75 @@ +// Copyright (c) 2020 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 zapcore + +import "fmt" + +type levelFilterCore struct { +	core  Core +	level LevelEnabler +} + +var ( +	_ Core           = (*levelFilterCore)(nil) +	_ leveledEnabler = (*levelFilterCore)(nil) +) + +// NewIncreaseLevelCore creates a core that can be used to increase the level of +// an existing Core. It cannot be used to decrease the logging level, as it acts +// as a filter before calling the underlying core. If level decreases the log level, +// an error is returned. +func NewIncreaseLevelCore(core Core, level LevelEnabler) (Core, error) { +	for l := _maxLevel; l >= _minLevel; l-- { +		if !core.Enabled(l) && level.Enabled(l) { +			return nil, fmt.Errorf("invalid increase level, as level %q is allowed by increased level, but not by existing core", l) +		} +	} + +	return &levelFilterCore{core, level}, nil +} + +func (c *levelFilterCore) Enabled(lvl Level) bool { +	return c.level.Enabled(lvl) +} + +func (c *levelFilterCore) Level() Level { +	return LevelOf(c.level) +} + +func (c *levelFilterCore) With(fields []Field) Core { +	return &levelFilterCore{c.core.With(fields), c.level} +} + +func (c *levelFilterCore) Check(ent Entry, ce *CheckedEntry) *CheckedEntry { +	if !c.Enabled(ent.Level) { +		return ce +	} + +	return c.core.Check(ent, ce) +} + +func (c *levelFilterCore) Write(ent Entry, fields []Field) error { +	return c.core.Write(ent, fields) +} + +func (c *levelFilterCore) Sync() error { +	return c.core.Sync() +} diff --git a/vendor/go.uber.org/zap/zapcore/json_encoder.go b/vendor/go.uber.org/zap/zapcore/json_encoder.go new file mode 100644 index 0000000..3921c5c --- /dev/null +++ b/vendor/go.uber.org/zap/zapcore/json_encoder.go @@ -0,0 +1,562 @@ +// 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 zapcore + +import ( +	"encoding/base64" +	"math" +	"sync" +	"time" +	"unicode/utf8" + +	"go.uber.org/zap/buffer" +	"go.uber.org/zap/internal/bufferpool" +) + +// For JSON-escaping; see jsonEncoder.safeAddString below. +const _hex = "0123456789abcdef" + +var _jsonPool = sync.Pool{New: func() interface{} { +	return &jsonEncoder{} +}} + +func getJSONEncoder() *jsonEncoder { +	return _jsonPool.Get().(*jsonEncoder) +} + +func putJSONEncoder(enc *jsonEncoder) { +	if enc.reflectBuf != nil { +		enc.reflectBuf.Free() +	} +	enc.EncoderConfig = nil +	enc.buf = nil +	enc.spaced = false +	enc.openNamespaces = 0 +	enc.reflectBuf = nil +	enc.reflectEnc = nil +	_jsonPool.Put(enc) +} + +type jsonEncoder struct { +	*EncoderConfig +	buf            *buffer.Buffer +	spaced         bool // include spaces after colons and commas +	openNamespaces int + +	// for encoding generic values by reflection +	reflectBuf *buffer.Buffer +	reflectEnc ReflectedEncoder +} + +// NewJSONEncoder creates a fast, low-allocation JSON encoder. The encoder +// appropriately escapes all field keys and values. +// +// Note that the encoder doesn't deduplicate keys, so it's possible to produce +// a message like +// +//	{"foo":"bar","foo":"baz"} +// +// This is permitted by the JSON specification, but not encouraged. Many +// libraries will ignore duplicate key-value pairs (typically keeping the last +// pair) when unmarshaling, but users should attempt to avoid adding duplicate +// keys. +func NewJSONEncoder(cfg EncoderConfig) Encoder { +	return newJSONEncoder(cfg, false) +} + +func newJSONEncoder(cfg EncoderConfig, spaced bool) *jsonEncoder { +	if cfg.SkipLineEnding { +		cfg.LineEnding = "" +	} else if cfg.LineEnding == "" { +		cfg.LineEnding = DefaultLineEnding +	} + +	// If no EncoderConfig.NewReflectedEncoder is provided by the user, then use default +	if cfg.NewReflectedEncoder == nil { +		cfg.NewReflectedEncoder = defaultReflectedEncoder +	} + +	return &jsonEncoder{ +		EncoderConfig: &cfg, +		buf:           bufferpool.Get(), +		spaced:        spaced, +	} +} + +func (enc *jsonEncoder) AddArray(key string, arr ArrayMarshaler) error { +	enc.addKey(key) +	return enc.AppendArray(arr) +} + +func (enc *jsonEncoder) AddObject(key string, obj ObjectMarshaler) error { +	enc.addKey(key) +	return enc.AppendObject(obj) +} + +func (enc *jsonEncoder) AddBinary(key string, val []byte) { +	enc.AddString(key, base64.StdEncoding.EncodeToString(val)) +} + +func (enc *jsonEncoder) AddByteString(key string, val []byte) { +	enc.addKey(key) +	enc.AppendByteString(val) +} + +func (enc *jsonEncoder) AddBool(key string, val bool) { +	enc.addKey(key) +	enc.AppendBool(val) +} + +func (enc *jsonEncoder) AddComplex128(key string, val complex128) { +	enc.addKey(key) +	enc.AppendComplex128(val) +} + +func (enc *jsonEncoder) AddComplex64(key string, val complex64) { +	enc.addKey(key) +	enc.AppendComplex64(val) +} + +func (enc *jsonEncoder) AddDuration(key string, val time.Duration) { +	enc.addKey(key) +	enc.AppendDuration(val) +} + +func (enc *jsonEncoder) AddFloat64(key string, val float64) { +	enc.addKey(key) +	enc.AppendFloat64(val) +} + +func (enc *jsonEncoder) AddFloat32(key string, val float32) { +	enc.addKey(key) +	enc.AppendFloat32(val) +} + +func (enc *jsonEncoder) AddInt64(key string, val int64) { +	enc.addKey(key) +	enc.AppendInt64(val) +} + +func (enc *jsonEncoder) resetReflectBuf() { +	if enc.reflectBuf == nil { +		enc.reflectBuf = bufferpool.Get() +		enc.reflectEnc = enc.NewReflectedEncoder(enc.reflectBuf) +	} else { +		enc.reflectBuf.Reset() +	} +} + +var nullLiteralBytes = []byte("null") + +// Only invoke the standard JSON encoder if there is actually something to +// encode; otherwise write JSON null literal directly. +func (enc *jsonEncoder) encodeReflected(obj interface{}) ([]byte, error) { +	if obj == nil { +		return nullLiteralBytes, nil +	} +	enc.resetReflectBuf() +	if err := enc.reflectEnc.Encode(obj); err != nil { +		return nil, err +	} +	enc.reflectBuf.TrimNewline() +	return enc.reflectBuf.Bytes(), nil +} + +func (enc *jsonEncoder) AddReflected(key string, obj interface{}) error { +	valueBytes, err := enc.encodeReflected(obj) +	if err != nil { +		return err +	} +	enc.addKey(key) +	_, err = enc.buf.Write(valueBytes) +	return err +} + +func (enc *jsonEncoder) OpenNamespace(key string) { +	enc.addKey(key) +	enc.buf.AppendByte('{') +	enc.openNamespaces++ +} + +func (enc *jsonEncoder) AddString(key, val string) { +	enc.addKey(key) +	enc.AppendString(val) +} + +func (enc *jsonEncoder) AddTime(key string, val time.Time) { +	enc.addKey(key) +	enc.AppendTime(val) +} + +func (enc *jsonEncoder) AddUint64(key string, val uint64) { +	enc.addKey(key) +	enc.AppendUint64(val) +} + +func (enc *jsonEncoder) AppendArray(arr ArrayMarshaler) error { +	enc.addElementSeparator() +	enc.buf.AppendByte('[') +	err := arr.MarshalLogArray(enc) +	enc.buf.AppendByte(']') +	return err +} + +func (enc *jsonEncoder) AppendObject(obj ObjectMarshaler) error { +	// Close ONLY new openNamespaces that are created during +	// AppendObject(). +	old := enc.openNamespaces +	enc.openNamespaces = 0 +	enc.addElementSeparator() +	enc.buf.AppendByte('{') +	err := obj.MarshalLogObject(enc) +	enc.buf.AppendByte('}') +	enc.closeOpenNamespaces() +	enc.openNamespaces = old +	return err +} + +func (enc *jsonEncoder) AppendBool(val bool) { +	enc.addElementSeparator() +	enc.buf.AppendBool(val) +} + +func (enc *jsonEncoder) AppendByteString(val []byte) { +	enc.addElementSeparator() +	enc.buf.AppendByte('"') +	enc.safeAddByteString(val) +	enc.buf.AppendByte('"') +} + +// appendComplex appends the encoded form of the provided complex128 value. +// precision specifies the encoding precision for the real and imaginary +// components of the complex number. +func (enc *jsonEncoder) appendComplex(val complex128, precision int) { +	enc.addElementSeparator() +	// Cast to a platform-independent, fixed-size type. +	r, i := float64(real(val)), float64(imag(val)) +	enc.buf.AppendByte('"') +	// Because we're always in a quoted string, we can use strconv without +	// special-casing NaN and +/-Inf. +	enc.buf.AppendFloat(r, precision) +	// If imaginary part is less than 0, minus (-) sign is added by default +	// by AppendFloat. +	if i >= 0 { +		enc.buf.AppendByte('+') +	} +	enc.buf.AppendFloat(i, precision) +	enc.buf.AppendByte('i') +	enc.buf.AppendByte('"') +} + +func (enc *jsonEncoder) AppendDuration(val time.Duration) { +	cur := enc.buf.Len() +	if e := enc.EncodeDuration; e != nil { +		e(val, enc) +	} +	if cur == enc.buf.Len() { +		// User-supplied EncodeDuration is a no-op. Fall back to nanoseconds to keep +		// JSON valid. +		enc.AppendInt64(int64(val)) +	} +} + +func (enc *jsonEncoder) AppendInt64(val int64) { +	enc.addElementSeparator() +	enc.buf.AppendInt(val) +} + +func (enc *jsonEncoder) AppendReflected(val interface{}) error { +	valueBytes, err := enc.encodeReflected(val) +	if err != nil { +		return err +	} +	enc.addElementSeparator() +	_, err = enc.buf.Write(valueBytes) +	return err +} + +func (enc *jsonEncoder) AppendString(val string) { +	enc.addElementSeparator() +	enc.buf.AppendByte('"') +	enc.safeAddString(val) +	enc.buf.AppendByte('"') +} + +func (enc *jsonEncoder) AppendTimeLayout(time time.Time, layout string) { +	enc.addElementSeparator() +	enc.buf.AppendByte('"') +	enc.buf.AppendTime(time, layout) +	enc.buf.AppendByte('"') +} + +func (enc *jsonEncoder) AppendTime(val time.Time) { +	cur := enc.buf.Len() +	if e := enc.EncodeTime; e != nil { +		e(val, enc) +	} +	if cur == enc.buf.Len() { +		// User-supplied EncodeTime is a no-op. Fall back to nanos since epoch to keep +		// output JSON valid. +		enc.AppendInt64(val.UnixNano()) +	} +} + +func (enc *jsonEncoder) AppendUint64(val uint64) { +	enc.addElementSeparator() +	enc.buf.AppendUint(val) +} + +func (enc *jsonEncoder) AddInt(k string, v int)         { enc.AddInt64(k, int64(v)) } +func (enc *jsonEncoder) AddInt32(k string, v int32)     { enc.AddInt64(k, int64(v)) } +func (enc *jsonEncoder) AddInt16(k string, v int16)     { enc.AddInt64(k, int64(v)) } +func (enc *jsonEncoder) AddInt8(k string, v int8)       { enc.AddInt64(k, int64(v)) } +func (enc *jsonEncoder) AddUint(k string, v uint)       { enc.AddUint64(k, uint64(v)) } +func (enc *jsonEncoder) AddUint32(k string, v uint32)   { enc.AddUint64(k, uint64(v)) } +func (enc *jsonEncoder) AddUint16(k string, v uint16)   { enc.AddUint64(k, uint64(v)) } +func (enc *jsonEncoder) AddUint8(k string, v uint8)     { enc.AddUint64(k, uint64(v)) } +func (enc *jsonEncoder) AddUintptr(k string, v uintptr) { enc.AddUint64(k, uint64(v)) } +func (enc *jsonEncoder) AppendComplex64(v complex64)    { enc.appendComplex(complex128(v), 32) } +func (enc *jsonEncoder) AppendComplex128(v complex128)  { enc.appendComplex(complex128(v), 64) } +func (enc *jsonEncoder) AppendFloat64(v float64)        { enc.appendFloat(v, 64) } +func (enc *jsonEncoder) AppendFloat32(v float32)        { enc.appendFloat(float64(v), 32) } +func (enc *jsonEncoder) AppendInt(v int)                { enc.AppendInt64(int64(v)) } +func (enc *jsonEncoder) AppendInt32(v int32)            { enc.AppendInt64(int64(v)) } +func (enc *jsonEncoder) AppendInt16(v int16)            { enc.AppendInt64(int64(v)) } +func (enc *jsonEncoder) AppendInt8(v int8)              { enc.AppendInt64(int64(v)) } +func (enc *jsonEncoder) AppendUint(v uint)              { enc.AppendUint64(uint64(v)) } +func (enc *jsonEncoder) AppendUint32(v uint32)          { enc.AppendUint64(uint64(v)) } +func (enc *jsonEncoder) AppendUint16(v uint16)          { enc.AppendUint64(uint64(v)) } +func (enc *jsonEncoder) AppendUint8(v uint8)            { enc.AppendUint64(uint64(v)) } +func (enc *jsonEncoder) AppendUintptr(v uintptr)        { enc.AppendUint64(uint64(v)) } + +func (enc *jsonEncoder) Clone() Encoder { +	clone := enc.clone() +	clone.buf.Write(enc.buf.Bytes()) +	return clone +} + +func (enc *jsonEncoder) clone() *jsonEncoder { +	clone := getJSONEncoder() +	clone.EncoderConfig = enc.EncoderConfig +	clone.spaced = enc.spaced +	clone.openNamespaces = enc.openNamespaces +	clone.buf = bufferpool.Get() +	return clone +} + +func (enc *jsonEncoder) EncodeEntry(ent Entry, fields []Field) (*buffer.Buffer, error) { +	final := enc.clone() +	final.buf.AppendByte('{') + +	if final.LevelKey != "" && final.EncodeLevel != nil { +		final.addKey(final.LevelKey) +		cur := final.buf.Len() +		final.EncodeLevel(ent.Level, final) +		if cur == final.buf.Len() { +			// User-supplied EncodeLevel was a no-op. Fall back to strings to keep +			// output JSON valid. +			final.AppendString(ent.Level.String()) +		} +	} +	if final.TimeKey != "" { +		final.AddTime(final.TimeKey, ent.Time) +	} +	if ent.LoggerName != "" && final.NameKey != "" { +		final.addKey(final.NameKey) +		cur := final.buf.Len() +		nameEncoder := final.EncodeName + +		// if no name encoder provided, fall back to FullNameEncoder for backwards +		// compatibility +		if nameEncoder == nil { +			nameEncoder = FullNameEncoder +		} + +		nameEncoder(ent.LoggerName, final) +		if cur == final.buf.Len() { +			// User-supplied EncodeName was a no-op. Fall back to strings to +			// keep output JSON valid. +			final.AppendString(ent.LoggerName) +		} +	} +	if ent.Caller.Defined { +		if final.CallerKey != "" { +			final.addKey(final.CallerKey) +			cur := final.buf.Len() +			final.EncodeCaller(ent.Caller, final) +			if cur == final.buf.Len() { +				// User-supplied EncodeCaller was a no-op. Fall back to strings to +				// keep output JSON valid. +				final.AppendString(ent.Caller.String()) +			} +		} +		if final.FunctionKey != "" { +			final.addKey(final.FunctionKey) +			final.AppendString(ent.Caller.Function) +		} +	} +	if final.MessageKey != "" { +		final.addKey(enc.MessageKey) +		final.AppendString(ent.Message) +	} +	if enc.buf.Len() > 0 { +		final.addElementSeparator() +		final.buf.Write(enc.buf.Bytes()) +	} +	addFields(final, fields) +	final.closeOpenNamespaces() +	if ent.Stack != "" && final.StacktraceKey != "" { +		final.AddString(final.StacktraceKey, ent.Stack) +	} +	final.buf.AppendByte('}') +	final.buf.AppendString(final.LineEnding) + +	ret := final.buf +	putJSONEncoder(final) +	return ret, nil +} + +func (enc *jsonEncoder) truncate() { +	enc.buf.Reset() +} + +func (enc *jsonEncoder) closeOpenNamespaces() { +	for i := 0; i < enc.openNamespaces; i++ { +		enc.buf.AppendByte('}') +	} +	enc.openNamespaces = 0 +} + +func (enc *jsonEncoder) addKey(key string) { +	enc.addElementSeparator() +	enc.buf.AppendByte('"') +	enc.safeAddString(key) +	enc.buf.AppendByte('"') +	enc.buf.AppendByte(':') +	if enc.spaced { +		enc.buf.AppendByte(' ') +	} +} + +func (enc *jsonEncoder) addElementSeparator() { +	last := enc.buf.Len() - 1 +	if last < 0 { +		return +	} +	switch enc.buf.Bytes()[last] { +	case '{', '[', ':', ',', ' ': +		return +	default: +		enc.buf.AppendByte(',') +		if enc.spaced { +			enc.buf.AppendByte(' ') +		} +	} +} + +func (enc *jsonEncoder) appendFloat(val float64, bitSize int) { +	enc.addElementSeparator() +	switch { +	case math.IsNaN(val): +		enc.buf.AppendString(`"NaN"`) +	case math.IsInf(val, 1): +		enc.buf.AppendString(`"+Inf"`) +	case math.IsInf(val, -1): +		enc.buf.AppendString(`"-Inf"`) +	default: +		enc.buf.AppendFloat(val, bitSize) +	} +} + +// safeAddString JSON-escapes a string and appends it to the internal buffer. +// Unlike the standard library's encoder, it doesn't attempt to protect the +// user from browser vulnerabilities or JSONP-related problems. +func (enc *jsonEncoder) safeAddString(s string) { +	for i := 0; i < len(s); { +		if enc.tryAddRuneSelf(s[i]) { +			i++ +			continue +		} +		r, size := utf8.DecodeRuneInString(s[i:]) +		if enc.tryAddRuneError(r, size) { +			i++ +			continue +		} +		enc.buf.AppendString(s[i : i+size]) +		i += size +	} +} + +// safeAddByteString is no-alloc equivalent of safeAddString(string(s)) for s []byte. +func (enc *jsonEncoder) safeAddByteString(s []byte) { +	for i := 0; i < len(s); { +		if enc.tryAddRuneSelf(s[i]) { +			i++ +			continue +		} +		r, size := utf8.DecodeRune(s[i:]) +		if enc.tryAddRuneError(r, size) { +			i++ +			continue +		} +		enc.buf.Write(s[i : i+size]) +		i += size +	} +} + +// tryAddRuneSelf appends b if it is valid UTF-8 character represented in a single byte. +func (enc *jsonEncoder) tryAddRuneSelf(b byte) bool { +	if b >= utf8.RuneSelf { +		return false +	} +	if 0x20 <= b && b != '\\' && b != '"' { +		enc.buf.AppendByte(b) +		return true +	} +	switch b { +	case '\\', '"': +		enc.buf.AppendByte('\\') +		enc.buf.AppendByte(b) +	case '\n': +		enc.buf.AppendByte('\\') +		enc.buf.AppendByte('n') +	case '\r': +		enc.buf.AppendByte('\\') +		enc.buf.AppendByte('r') +	case '\t': +		enc.buf.AppendByte('\\') +		enc.buf.AppendByte('t') +	default: +		// Encode bytes < 0x20, except for the escape sequences above. +		enc.buf.AppendString(`\u00`) +		enc.buf.AppendByte(_hex[b>>4]) +		enc.buf.AppendByte(_hex[b&0xF]) +	} +	return true +} + +func (enc *jsonEncoder) tryAddRuneError(r rune, size int) bool { +	if r == utf8.RuneError && size == 1 { +		enc.buf.AppendString(`\ufffd`) +		return true +	} +	return false +} diff --git a/vendor/go.uber.org/zap/zapcore/level.go b/vendor/go.uber.org/zap/zapcore/level.go new file mode 100644 index 0000000..e01a241 --- /dev/null +++ b/vendor/go.uber.org/zap/zapcore/level.go @@ -0,0 +1,229 @@ +// 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 zapcore + +import ( +	"bytes" +	"errors" +	"fmt" +) + +var errUnmarshalNilLevel = errors.New("can't unmarshal a nil *Level") + +// A Level is a logging priority. Higher levels are more important. +type Level int8 + +const ( +	// DebugLevel logs are typically voluminous, and are usually disabled in +	// production. +	DebugLevel Level = iota - 1 +	// InfoLevel is the default logging priority. +	InfoLevel +	// WarnLevel logs are more important than Info, but don't need individual +	// human review. +	WarnLevel +	// ErrorLevel logs are high-priority. If an application is running smoothly, +	// it shouldn't generate any error-level logs. +	ErrorLevel +	// DPanicLevel logs are particularly important errors. In development the +	// logger panics after writing the message. +	DPanicLevel +	// PanicLevel logs a message, then panics. +	PanicLevel +	// FatalLevel logs a message, then calls os.Exit(1). +	FatalLevel + +	_minLevel = DebugLevel +	_maxLevel = FatalLevel + +	// InvalidLevel is an invalid value for Level. +	// +	// Core implementations may panic if they see messages of this level. +	InvalidLevel = _maxLevel + 1 +) + +// ParseLevel parses a level based on the lower-case or all-caps ASCII +// representation of the log level. If the provided ASCII representation is +// invalid an error is returned. +// +// This is particularly useful when dealing with text input to configure log +// levels. +func ParseLevel(text string) (Level, error) { +	var level Level +	err := level.UnmarshalText([]byte(text)) +	return level, err +} + +type leveledEnabler interface { +	LevelEnabler + +	Level() Level +} + +// LevelOf reports the minimum enabled log level for the given LevelEnabler +// from Zap's supported log levels, or [InvalidLevel] if none of them are +// enabled. +// +// A LevelEnabler may implement a 'Level() Level' method to override the +// behavior of this function. +// +//	func (c *core) Level() Level { +//		return c.currentLevel +//	} +// +// It is recommended that [Core] implementations that wrap other cores use +// LevelOf to retrieve the level of the wrapped core. For example, +// +//	func (c *coreWrapper) Level() Level { +//		return zapcore.LevelOf(c.wrappedCore) +//	} +func LevelOf(enab LevelEnabler) Level { +	if lvler, ok := enab.(leveledEnabler); ok { +		return lvler.Level() +	} + +	for lvl := _minLevel; lvl <= _maxLevel; lvl++ { +		if enab.Enabled(lvl) { +			return lvl +		} +	} + +	return InvalidLevel +} + +// String returns a lower-case ASCII representation of the log level. +func (l Level) String() string { +	switch l { +	case DebugLevel: +		return "debug" +	case InfoLevel: +		return "info" +	case WarnLevel: +		return "warn" +	case ErrorLevel: +		return "error" +	case DPanicLevel: +		return "dpanic" +	case PanicLevel: +		return "panic" +	case FatalLevel: +		return "fatal" +	default: +		return fmt.Sprintf("Level(%d)", l) +	} +} + +// CapitalString returns an all-caps ASCII representation of the log level. +func (l Level) CapitalString() string { +	// Printing levels in all-caps is common enough that we should export this +	// functionality. +	switch l { +	case DebugLevel: +		return "DEBUG" +	case InfoLevel: +		return "INFO" +	case WarnLevel: +		return "WARN" +	case ErrorLevel: +		return "ERROR" +	case DPanicLevel: +		return "DPANIC" +	case PanicLevel: +		return "PANIC" +	case FatalLevel: +		return "FATAL" +	default: +		return fmt.Sprintf("LEVEL(%d)", l) +	} +} + +// MarshalText marshals the Level to text. Note that the text representation +// drops the -Level suffix (see example). +func (l Level) MarshalText() ([]byte, error) { +	return []byte(l.String()), nil +} + +// UnmarshalText unmarshals text to a level. Like MarshalText, UnmarshalText +// expects the text representation of a Level to drop the -Level suffix (see +// example). +// +// In particular, this makes it easy to configure logging levels using YAML, +// TOML, or JSON files. +func (l *Level) UnmarshalText(text []byte) error { +	if l == nil { +		return errUnmarshalNilLevel +	} +	if !l.unmarshalText(text) && !l.unmarshalText(bytes.ToLower(text)) { +		return fmt.Errorf("unrecognized level: %q", text) +	} +	return nil +} + +func (l *Level) unmarshalText(text []byte) bool { +	switch string(text) { +	case "debug", "DEBUG": +		*l = DebugLevel +	case "info", "INFO", "": // make the zero value useful +		*l = InfoLevel +	case "warn", "WARN": +		*l = WarnLevel +	case "error", "ERROR": +		*l = ErrorLevel +	case "dpanic", "DPANIC": +		*l = DPanicLevel +	case "panic", "PANIC": +		*l = PanicLevel +	case "fatal", "FATAL": +		*l = FatalLevel +	default: +		return false +	} +	return true +} + +// Set sets the level for the flag.Value interface. +func (l *Level) Set(s string) error { +	return l.UnmarshalText([]byte(s)) +} + +// Get gets the level for the flag.Getter interface. +func (l *Level) Get() interface{} { +	return *l +} + +// Enabled returns true if the given level is at or above this level. +func (l Level) Enabled(lvl Level) bool { +	return lvl >= l +} + +// LevelEnabler decides whether a given logging level is enabled when logging a +// message. +// +// Enablers are intended to be used to implement deterministic filters; +// concerns like sampling are better implemented as a Core. +// +// Each concrete Level value implements a static LevelEnabler which returns +// true for itself and all higher logging levels. For example WarnLevel.Enabled() +// will return true for WarnLevel, ErrorLevel, DPanicLevel, PanicLevel, and +// FatalLevel, but return false for InfoLevel and DebugLevel. +type LevelEnabler interface { +	Enabled(Level) bool +} diff --git a/vendor/go.uber.org/zap/zapcore/level_strings.go b/vendor/go.uber.org/zap/zapcore/level_strings.go new file mode 100644 index 0000000..7af8dad --- /dev/null +++ b/vendor/go.uber.org/zap/zapcore/level_strings.go @@ -0,0 +1,46 @@ +// 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 zapcore + +import "go.uber.org/zap/internal/color" + +var ( +	_levelToColor = map[Level]color.Color{ +		DebugLevel:  color.Magenta, +		InfoLevel:   color.Blue, +		WarnLevel:   color.Yellow, +		ErrorLevel:  color.Red, +		DPanicLevel: color.Red, +		PanicLevel:  color.Red, +		FatalLevel:  color.Red, +	} +	_unknownLevelColor = color.Red + +	_levelToLowercaseColorString = make(map[Level]string, len(_levelToColor)) +	_levelToCapitalColorString   = make(map[Level]string, len(_levelToColor)) +) + +func init() { +	for level, color := range _levelToColor { +		_levelToLowercaseColorString[level] = color.Add(level.String()) +		_levelToCapitalColorString[level] = color.Add(level.CapitalString()) +	} +} diff --git a/vendor/go.uber.org/zap/zapcore/marshaler.go b/vendor/go.uber.org/zap/zapcore/marshaler.go new file mode 100644 index 0000000..c3c55ba --- /dev/null +++ b/vendor/go.uber.org/zap/zapcore/marshaler.go @@ -0,0 +1,61 @@ +// 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 zapcore + +// ObjectMarshaler allows user-defined types to efficiently add themselves to the +// logging context, and to selectively omit information which shouldn't be +// included in logs (e.g., passwords). +// +// Note: ObjectMarshaler is only used when zap.Object is used or when +// passed directly to zap.Any. It is not used when reflection-based +// encoding is used. +type ObjectMarshaler interface { +	MarshalLogObject(ObjectEncoder) error +} + +// ObjectMarshalerFunc is a type adapter that turns a function into an +// ObjectMarshaler. +type ObjectMarshalerFunc func(ObjectEncoder) error + +// MarshalLogObject calls the underlying function. +func (f ObjectMarshalerFunc) MarshalLogObject(enc ObjectEncoder) error { +	return f(enc) +} + +// ArrayMarshaler allows user-defined types to efficiently add themselves to the +// logging context, and to selectively omit information which shouldn't be +// included in logs (e.g., passwords). +// +// Note: ArrayMarshaler is only used when zap.Array is used or when +// passed directly to zap.Any. It is not used when reflection-based +// encoding is used. +type ArrayMarshaler interface { +	MarshalLogArray(ArrayEncoder) error +} + +// ArrayMarshalerFunc is a type adapter that turns a function into an +// ArrayMarshaler. +type ArrayMarshalerFunc func(ArrayEncoder) error + +// MarshalLogArray calls the underlying function. +func (f ArrayMarshalerFunc) MarshalLogArray(enc ArrayEncoder) error { +	return f(enc) +} diff --git a/vendor/go.uber.org/zap/zapcore/memory_encoder.go b/vendor/go.uber.org/zap/zapcore/memory_encoder.go new file mode 100644 index 0000000..dfead08 --- /dev/null +++ b/vendor/go.uber.org/zap/zapcore/memory_encoder.go @@ -0,0 +1,179 @@ +// 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 zapcore + +import "time" + +// MapObjectEncoder is an ObjectEncoder backed by a simple +// map[string]interface{}. It's not fast enough for production use, but it's +// helpful in tests. +type MapObjectEncoder struct { +	// Fields contains the entire encoded log context. +	Fields map[string]interface{} +	// cur is a pointer to the namespace we're currently writing to. +	cur map[string]interface{} +} + +// NewMapObjectEncoder creates a new map-backed ObjectEncoder. +func NewMapObjectEncoder() *MapObjectEncoder { +	m := make(map[string]interface{}) +	return &MapObjectEncoder{ +		Fields: m, +		cur:    m, +	} +} + +// AddArray implements ObjectEncoder. +func (m *MapObjectEncoder) AddArray(key string, v ArrayMarshaler) error { +	arr := &sliceArrayEncoder{elems: make([]interface{}, 0)} +	err := v.MarshalLogArray(arr) +	m.cur[key] = arr.elems +	return err +} + +// AddObject implements ObjectEncoder. +func (m *MapObjectEncoder) AddObject(k string, v ObjectMarshaler) error { +	newMap := NewMapObjectEncoder() +	m.cur[k] = newMap.Fields +	return v.MarshalLogObject(newMap) +} + +// AddBinary implements ObjectEncoder. +func (m *MapObjectEncoder) AddBinary(k string, v []byte) { m.cur[k] = v } + +// AddByteString implements ObjectEncoder. +func (m *MapObjectEncoder) AddByteString(k string, v []byte) { m.cur[k] = string(v) } + +// AddBool implements ObjectEncoder. +func (m *MapObjectEncoder) AddBool(k string, v bool) { m.cur[k] = v } + +// AddDuration implements ObjectEncoder. +func (m MapObjectEncoder) AddDuration(k string, v time.Duration) { m.cur[k] = v } + +// AddComplex128 implements ObjectEncoder. +func (m *MapObjectEncoder) AddComplex128(k string, v complex128) { m.cur[k] = v } + +// AddComplex64 implements ObjectEncoder. +func (m *MapObjectEncoder) AddComplex64(k string, v complex64) { m.cur[k] = v } + +// AddFloat64 implements ObjectEncoder. +func (m *MapObjectEncoder) AddFloat64(k string, v float64) { m.cur[k] = v } + +// AddFloat32 implements ObjectEncoder. +func (m *MapObjectEncoder) AddFloat32(k string, v float32) { m.cur[k] = v } + +// AddInt implements ObjectEncoder. +func (m *MapObjectEncoder) AddInt(k string, v int) { m.cur[k] = v } + +// AddInt64 implements ObjectEncoder. +func (m *MapObjectEncoder) AddInt64(k string, v int64) { m.cur[k] = v } + +// AddInt32 implements ObjectEncoder. +func (m *MapObjectEncoder) AddInt32(k string, v int32) { m.cur[k] = v } + +// AddInt16 implements ObjectEncoder. +func (m *MapObjectEncoder) AddInt16(k string, v int16) { m.cur[k] = v } + +// AddInt8 implements ObjectEncoder. +func (m *MapObjectEncoder) AddInt8(k string, v int8) { m.cur[k] = v } + +// AddString implements ObjectEncoder. +func (m *MapObjectEncoder) AddString(k string, v string) { m.cur[k] = v } + +// AddTime implements ObjectEncoder. +func (m MapObjectEncoder) AddTime(k string, v time.Time) { m.cur[k] = v } + +// AddUint implements ObjectEncoder. +func (m *MapObjectEncoder) AddUint(k string, v uint) { m.cur[k] = v } + +// AddUint64 implements ObjectEncoder. +func (m *MapObjectEncoder) AddUint64(k string, v uint64) { m.cur[k] = v } + +// AddUint32 implements ObjectEncoder. +func (m *MapObjectEncoder) AddUint32(k string, v uint32) { m.cur[k] = v } + +// AddUint16 implements ObjectEncoder. +func (m *MapObjectEncoder) AddUint16(k string, v uint16) { m.cur[k] = v } + +// AddUint8 implements ObjectEncoder. +func (m *MapObjectEncoder) AddUint8(k string, v uint8) { m.cur[k] = v } + +// AddUintptr implements ObjectEncoder. +func (m *MapObjectEncoder) AddUintptr(k string, v uintptr) { m.cur[k] = v } + +// AddReflected implements ObjectEncoder. +func (m *MapObjectEncoder) AddReflected(k string, v interface{}) error { +	m.cur[k] = v +	return nil +} + +// OpenNamespace implements ObjectEncoder. +func (m *MapObjectEncoder) OpenNamespace(k string) { +	ns := make(map[string]interface{}) +	m.cur[k] = ns +	m.cur = ns +} + +// sliceArrayEncoder is an ArrayEncoder backed by a simple []interface{}. Like +// the MapObjectEncoder, it's not designed for production use. +type sliceArrayEncoder struct { +	elems []interface{} +} + +func (s *sliceArrayEncoder) AppendArray(v ArrayMarshaler) error { +	enc := &sliceArrayEncoder{} +	err := v.MarshalLogArray(enc) +	s.elems = append(s.elems, enc.elems) +	return err +} + +func (s *sliceArrayEncoder) AppendObject(v ObjectMarshaler) error { +	m := NewMapObjectEncoder() +	err := v.MarshalLogObject(m) +	s.elems = append(s.elems, m.Fields) +	return err +} + +func (s *sliceArrayEncoder) AppendReflected(v interface{}) error { +	s.elems = append(s.elems, v) +	return nil +} + +func (s *sliceArrayEncoder) AppendBool(v bool)              { s.elems = append(s.elems, v) } +func (s *sliceArrayEncoder) AppendByteString(v []byte)      { s.elems = append(s.elems, string(v)) } +func (s *sliceArrayEncoder) AppendComplex128(v complex128)  { s.elems = append(s.elems, v) } +func (s *sliceArrayEncoder) AppendComplex64(v complex64)    { s.elems = append(s.elems, v) } +func (s *sliceArrayEncoder) AppendDuration(v time.Duration) { s.elems = append(s.elems, v) } +func (s *sliceArrayEncoder) AppendFloat64(v float64)        { s.elems = append(s.elems, v) } +func (s *sliceArrayEncoder) AppendFloat32(v float32)        { s.elems = append(s.elems, v) } +func (s *sliceArrayEncoder) AppendInt(v int)                { s.elems = append(s.elems, v) } +func (s *sliceArrayEncoder) AppendInt64(v int64)            { s.elems = append(s.elems, v) } +func (s *sliceArrayEncoder) AppendInt32(v int32)            { s.elems = append(s.elems, v) } +func (s *sliceArrayEncoder) AppendInt16(v int16)            { s.elems = append(s.elems, v) } +func (s *sliceArrayEncoder) AppendInt8(v int8)              { s.elems = append(s.elems, v) } +func (s *sliceArrayEncoder) AppendString(v string)          { s.elems = append(s.elems, v) } +func (s *sliceArrayEncoder) AppendTime(v time.Time)         { s.elems = append(s.elems, v) } +func (s *sliceArrayEncoder) AppendUint(v uint)              { s.elems = append(s.elems, v) } +func (s *sliceArrayEncoder) AppendUint64(v uint64)          { s.elems = append(s.elems, v) } +func (s *sliceArrayEncoder) AppendUint32(v uint32)          { s.elems = append(s.elems, v) } +func (s *sliceArrayEncoder) AppendUint16(v uint16)          { s.elems = append(s.elems, v) } +func (s *sliceArrayEncoder) AppendUint8(v uint8)            { s.elems = append(s.elems, v) } +func (s *sliceArrayEncoder) AppendUintptr(v uintptr)        { s.elems = append(s.elems, v) } diff --git a/vendor/go.uber.org/zap/zapcore/reflected_encoder.go b/vendor/go.uber.org/zap/zapcore/reflected_encoder.go new file mode 100644 index 0000000..8746360 --- /dev/null +++ b/vendor/go.uber.org/zap/zapcore/reflected_encoder.go @@ -0,0 +1,41 @@ +// 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 zapcore + +import ( +	"encoding/json" +	"io" +) + +// ReflectedEncoder serializes log fields that can't be serialized with Zap's +// JSON encoder. These have the ReflectType field type. +// Use EncoderConfig.NewReflectedEncoder to set this. +type ReflectedEncoder interface { +	// Encode encodes and writes to the underlying data stream. +	Encode(interface{}) error +} + +func defaultReflectedEncoder(w io.Writer) ReflectedEncoder { +	enc := json.NewEncoder(w) +	// For consistency with our custom JSON encoder. +	enc.SetEscapeHTML(false) +	return enc +} diff --git a/vendor/go.uber.org/zap/zapcore/sampler.go b/vendor/go.uber.org/zap/zapcore/sampler.go new file mode 100644 index 0000000..dc51805 --- /dev/null +++ b/vendor/go.uber.org/zap/zapcore/sampler.go @@ -0,0 +1,230 @@ +// Copyright (c) 2016-2022 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 zapcore + +import ( +	"time" + +	"go.uber.org/atomic" +) + +const ( +	_numLevels        = _maxLevel - _minLevel + 1 +	_countersPerLevel = 4096 +) + +type counter struct { +	resetAt atomic.Int64 +	counter atomic.Uint64 +} + +type counters [_numLevels][_countersPerLevel]counter + +func newCounters() *counters { +	return &counters{} +} + +func (cs *counters) get(lvl Level, key string) *counter { +	i := lvl - _minLevel +	j := fnv32a(key) % _countersPerLevel +	return &cs[i][j] +} + +// fnv32a, adapted from "hash/fnv", but without a []byte(string) alloc +func fnv32a(s string) uint32 { +	const ( +		offset32 = 2166136261 +		prime32  = 16777619 +	) +	hash := uint32(offset32) +	for i := 0; i < len(s); i++ { +		hash ^= uint32(s[i]) +		hash *= prime32 +	} +	return hash +} + +func (c *counter) IncCheckReset(t time.Time, tick time.Duration) uint64 { +	tn := t.UnixNano() +	resetAfter := c.resetAt.Load() +	if resetAfter > tn { +		return c.counter.Inc() +	} + +	c.counter.Store(1) + +	newResetAfter := tn + tick.Nanoseconds() +	if !c.resetAt.CAS(resetAfter, newResetAfter) { +		// We raced with another goroutine trying to reset, and it also reset +		// the counter to 1, so we need to reincrement the counter. +		return c.counter.Inc() +	} + +	return 1 +} + +// SamplingDecision is a decision represented as a bit field made by sampler. +// More decisions may be added in the future. +type SamplingDecision uint32 + +const ( +	// LogDropped indicates that the Sampler dropped a log entry. +	LogDropped SamplingDecision = 1 << iota +	// LogSampled indicates that the Sampler sampled a log entry. +	LogSampled +) + +// optionFunc wraps a func so it satisfies the SamplerOption interface. +type optionFunc func(*sampler) + +func (f optionFunc) apply(s *sampler) { +	f(s) +} + +// SamplerOption configures a Sampler. +type SamplerOption interface { +	apply(*sampler) +} + +// nopSamplingHook is the default hook used by sampler. +func nopSamplingHook(Entry, SamplingDecision) {} + +// SamplerHook registers a function  which will be called when Sampler makes a +// decision. +// +// This hook may be used to get visibility into the performance of the sampler. +// For example, use it to track metrics of dropped versus sampled logs. +// +//	var dropped atomic.Int64 +//	zapcore.SamplerHook(func(ent zapcore.Entry, dec zapcore.SamplingDecision) { +//	  if dec&zapcore.LogDropped > 0 { +//	    dropped.Inc() +//	  } +//	}) +func SamplerHook(hook func(entry Entry, dec SamplingDecision)) SamplerOption { +	return optionFunc(func(s *sampler) { +		s.hook = hook +	}) +} + +// NewSamplerWithOptions creates a Core that samples incoming entries, which +// caps the CPU and I/O load of logging while attempting to preserve a +// representative subset of your logs. +// +// Zap samples by logging the first N entries with a given level and message +// each tick. If more Entries with the same level and message are seen during +// the same interval, every Mth message is logged and the rest are dropped. +// +// For example, +// +//	core = NewSamplerWithOptions(core, time.Second, 10, 5) +// +// This will log the first 10 log entries with the same level and message +// in a one second interval as-is. Following that, it will allow through +// every 5th log entry with the same level and message in that interval. +// +// If thereafter is zero, the Core will drop all log entries after the first N +// in that interval. +// +// Sampler can be configured to report sampling decisions with the SamplerHook +// option. +// +// Keep in mind that Zap's sampling implementation is optimized for speed over +// absolute precision; under load, each tick may be slightly over- or +// under-sampled. +func NewSamplerWithOptions(core Core, tick time.Duration, first, thereafter int, opts ...SamplerOption) Core { +	s := &sampler{ +		Core:       core, +		tick:       tick, +		counts:     newCounters(), +		first:      uint64(first), +		thereafter: uint64(thereafter), +		hook:       nopSamplingHook, +	} +	for _, opt := range opts { +		opt.apply(s) +	} + +	return s +} + +type sampler struct { +	Core + +	counts            *counters +	tick              time.Duration +	first, thereafter uint64 +	hook              func(Entry, SamplingDecision) +} + +var ( +	_ Core           = (*sampler)(nil) +	_ leveledEnabler = (*sampler)(nil) +) + +// NewSampler creates a Core that samples incoming entries, which +// caps the CPU and I/O load of logging while attempting to preserve a +// representative subset of your logs. +// +// Zap samples by logging the first N entries with a given level and message +// each tick. If more Entries with the same level and message are seen during +// the same interval, every Mth message is logged and the rest are dropped. +// +// Keep in mind that zap's sampling implementation is optimized for speed over +// absolute precision; under load, each tick may be slightly over- or +// under-sampled. +// +// Deprecated: use NewSamplerWithOptions. +func NewSampler(core Core, tick time.Duration, first, thereafter int) Core { +	return NewSamplerWithOptions(core, tick, first, thereafter) +} + +func (s *sampler) Level() Level { +	return LevelOf(s.Core) +} + +func (s *sampler) With(fields []Field) Core { +	return &sampler{ +		Core:       s.Core.With(fields), +		tick:       s.tick, +		counts:     s.counts, +		first:      s.first, +		thereafter: s.thereafter, +		hook:       s.hook, +	} +} + +func (s *sampler) Check(ent Entry, ce *CheckedEntry) *CheckedEntry { +	if !s.Enabled(ent.Level) { +		return ce +	} + +	if ent.Level >= _minLevel && ent.Level <= _maxLevel { +		counter := s.counts.get(ent.Level, ent.Message) +		n := counter.IncCheckReset(ent.Time, s.tick) +		if n > s.first && (s.thereafter == 0 || (n-s.first)%s.thereafter != 0) { +			s.hook(ent, LogDropped) +			return ce +		} +		s.hook(ent, LogSampled) +	} +	return s.Core.Check(ent, ce) +} diff --git a/vendor/go.uber.org/zap/zapcore/tee.go b/vendor/go.uber.org/zap/zapcore/tee.go new file mode 100644 index 0000000..9bb32f0 --- /dev/null +++ b/vendor/go.uber.org/zap/zapcore/tee.go @@ -0,0 +1,96 @@ +// Copyright (c) 2016-2022 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 zapcore + +import "go.uber.org/multierr" + +type multiCore []Core + +var ( +	_ leveledEnabler = multiCore(nil) +	_ Core           = multiCore(nil) +) + +// NewTee creates a Core that duplicates log entries into two or more +// underlying Cores. +// +// Calling it with a single Core returns the input unchanged, and calling +// it with no input returns a no-op Core. +func NewTee(cores ...Core) Core { +	switch len(cores) { +	case 0: +		return NewNopCore() +	case 1: +		return cores[0] +	default: +		return multiCore(cores) +	} +} + +func (mc multiCore) With(fields []Field) Core { +	clone := make(multiCore, len(mc)) +	for i := range mc { +		clone[i] = mc[i].With(fields) +	} +	return clone +} + +func (mc multiCore) Level() Level { +	minLvl := _maxLevel // mc is never empty +	for i := range mc { +		if lvl := LevelOf(mc[i]); lvl < minLvl { +			minLvl = lvl +		} +	} +	return minLvl +} + +func (mc multiCore) Enabled(lvl Level) bool { +	for i := range mc { +		if mc[i].Enabled(lvl) { +			return true +		} +	} +	return false +} + +func (mc multiCore) Check(ent Entry, ce *CheckedEntry) *CheckedEntry { +	for i := range mc { +		ce = mc[i].Check(ent, ce) +	} +	return ce +} + +func (mc multiCore) Write(ent Entry, fields []Field) error { +	var err error +	for i := range mc { +		err = multierr.Append(err, mc[i].Write(ent, fields)) +	} +	return err +} + +func (mc multiCore) Sync() error { +	var err error +	for i := range mc { +		err = multierr.Append(err, mc[i].Sync()) +	} +	return err +} diff --git a/vendor/go.uber.org/zap/zapcore/write_syncer.go b/vendor/go.uber.org/zap/zapcore/write_syncer.go new file mode 100644 index 0000000..d4a1af3 --- /dev/null +++ b/vendor/go.uber.org/zap/zapcore/write_syncer.go @@ -0,0 +1,122 @@ +// 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 zapcore + +import ( +	"io" +	"sync" + +	"go.uber.org/multierr" +) + +// A WriteSyncer is an io.Writer that can also flush any buffered data. Note +// that *os.File (and thus, os.Stderr and os.Stdout) implement WriteSyncer. +type WriteSyncer interface { +	io.Writer +	Sync() error +} + +// AddSync converts an io.Writer to a WriteSyncer. It attempts to be +// intelligent: if the concrete type of the io.Writer implements WriteSyncer, +// we'll use the existing Sync method. If it doesn't, we'll add a no-op Sync. +func AddSync(w io.Writer) WriteSyncer { +	switch w := w.(type) { +	case WriteSyncer: +		return w +	default: +		return writerWrapper{w} +	} +} + +type lockedWriteSyncer struct { +	sync.Mutex +	ws WriteSyncer +} + +// Lock wraps a WriteSyncer in a mutex to make it safe for concurrent use. In +// particular, *os.Files must be locked before use. +func Lock(ws WriteSyncer) WriteSyncer { +	if _, ok := ws.(*lockedWriteSyncer); ok { +		// no need to layer on another lock +		return ws +	} +	return &lockedWriteSyncer{ws: ws} +} + +func (s *lockedWriteSyncer) Write(bs []byte) (int, error) { +	s.Lock() +	n, err := s.ws.Write(bs) +	s.Unlock() +	return n, err +} + +func (s *lockedWriteSyncer) Sync() error { +	s.Lock() +	err := s.ws.Sync() +	s.Unlock() +	return err +} + +type writerWrapper struct { +	io.Writer +} + +func (w writerWrapper) Sync() error { +	return nil +} + +type multiWriteSyncer []WriteSyncer + +// NewMultiWriteSyncer creates a WriteSyncer that duplicates its writes +// and sync calls, much like io.MultiWriter. +func NewMultiWriteSyncer(ws ...WriteSyncer) WriteSyncer { +	if len(ws) == 1 { +		return ws[0] +	} +	return multiWriteSyncer(ws) +} + +// See https://golang.org/src/io/multi.go +// When not all underlying syncers write the same number of bytes, +// the smallest number is returned even though Write() is called on +// all of them. +func (ws multiWriteSyncer) Write(p []byte) (int, error) { +	var writeErr error +	nWritten := 0 +	for _, w := range ws { +		n, err := w.Write(p) +		writeErr = multierr.Append(writeErr, err) +		if nWritten == 0 && n != 0 { +			nWritten = n +		} else if n < nWritten { +			nWritten = n +		} +	} +	return nWritten, writeErr +} + +func (ws multiWriteSyncer) Sync() error { +	var err error +	for _, w := range ws { +		err = multierr.Append(err, w.Sync()) +	} +	return err +}  | 
