go mod vendor
+ move k8s.io/apimachinery fork from go.work to go.mod (and include it in vendor)
This commit is contained in:
		
							
								
								
									
										17
									
								
								vendor/go.uber.org/zap/.codecov.yml
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								vendor/go.uber.org/zap/.codecov.yml
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -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 | ||||
|  | ||||
							
								
								
									
										32
									
								
								vendor/go.uber.org/zap/.gitignore
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								vendor/go.uber.org/zap/.gitignore
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -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 | ||||
							
								
								
									
										109
									
								
								vendor/go.uber.org/zap/.readme.tmpl
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										109
									
								
								vendor/go.uber.org/zap/.readme.tmpl
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -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 | ||||
|  | ||||
							
								
								
									
										604
									
								
								vendor/go.uber.org/zap/CHANGELOG.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										604
									
								
								vendor/go.uber.org/zap/CHANGELOG.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,604 @@ | ||||
| # 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.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 | ||||
							
								
								
									
										75
									
								
								vendor/go.uber.org/zap/CODE_OF_CONDUCT.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								vendor/go.uber.org/zap/CODE_OF_CONDUCT.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -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/ | ||||
							
								
								
									
										70
									
								
								vendor/go.uber.org/zap/CONTRIBUTING.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								vendor/go.uber.org/zap/CONTRIBUTING.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -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 | ||||
							
								
								
									
										164
									
								
								vendor/go.uber.org/zap/FAQ.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										164
									
								
								vendor/go.uber.org/zap/FAQ.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -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 | ||||
							
								
								
									
										19
									
								
								vendor/go.uber.org/zap/LICENSE.txt
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								vendor/go.uber.org/zap/LICENSE.txt
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -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. | ||||
							
								
								
									
										73
									
								
								vendor/go.uber.org/zap/Makefile
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										73
									
								
								vendor/go.uber.org/zap/Makefile
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -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 | ||||
							
								
								
									
										133
									
								
								vendor/go.uber.org/zap/README.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										133
									
								
								vendor/go.uber.org/zap/README.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -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 | ||||
							
								
								
									
										320
									
								
								vendor/go.uber.org/zap/array.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										320
									
								
								vendor/go.uber.org/zap/array.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -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 | ||||
| } | ||||
							
								
								
									
										156
									
								
								vendor/go.uber.org/zap/array_go118.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										156
									
								
								vendor/go.uber.org/zap/array_go118.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -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 | ||||
| } | ||||
							
								
								
									
										141
									
								
								vendor/go.uber.org/zap/buffer/buffer.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										141
									
								
								vendor/go.uber.org/zap/buffer/buffer.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -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) | ||||
| } | ||||
							
								
								
									
										49
									
								
								vendor/go.uber.org/zap/buffer/pool.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								vendor/go.uber.org/zap/buffer/pool.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -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) | ||||
| } | ||||
							
								
								
									
										17
									
								
								vendor/go.uber.org/zap/checklicense.sh
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								vendor/go.uber.org/zap/checklicense.sh
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -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 | ||||
							
								
								
									
										264
									
								
								vendor/go.uber.org/zap/config.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										264
									
								
								vendor/go.uber.org/zap/config.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -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) | ||||
| } | ||||
							
								
								
									
										117
									
								
								vendor/go.uber.org/zap/doc.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										117
									
								
								vendor/go.uber.org/zap/doc.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -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" | ||||
							
								
								
									
										79
									
								
								vendor/go.uber.org/zap/encoder.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										79
									
								
								vendor/go.uber.org/zap/encoder.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -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) | ||||
| } | ||||
							
								
								
									
										80
									
								
								vendor/go.uber.org/zap/error.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										80
									
								
								vendor/go.uber.org/zap/error.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -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 | ||||
| } | ||||
							
								
								
									
										549
									
								
								vendor/go.uber.org/zap/field.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										549
									
								
								vendor/go.uber.org/zap/field.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -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) | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										39
									
								
								vendor/go.uber.org/zap/flag.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								vendor/go.uber.org/zap/flag.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -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 | ||||
| } | ||||
							
								
								
									
										34
									
								
								vendor/go.uber.org/zap/glide.yaml
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								vendor/go.uber.org/zap/glide.yaml
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -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 | ||||
							
								
								
									
										169
									
								
								vendor/go.uber.org/zap/global.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										169
									
								
								vendor/go.uber.org/zap/global.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -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 | ||||
| } | ||||
							
								
								
									
										133
									
								
								vendor/go.uber.org/zap/http_handler.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										133
									
								
								vendor/go.uber.org/zap/http_handler.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -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 | ||||
|  | ||||
| } | ||||
							
								
								
									
										31
									
								
								vendor/go.uber.org/zap/internal/bufferpool/bufferpool.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								vendor/go.uber.org/zap/internal/bufferpool/bufferpool.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -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 | ||||
| ) | ||||
							
								
								
									
										44
									
								
								vendor/go.uber.org/zap/internal/color/color.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								vendor/go.uber.org/zap/internal/color/color.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -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) | ||||
| } | ||||
							
								
								
									
										66
									
								
								vendor/go.uber.org/zap/internal/exit/exit.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								vendor/go.uber.org/zap/internal/exit/exit.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -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 | ||||
| } | ||||
							
								
								
									
										35
									
								
								vendor/go.uber.org/zap/internal/level_enabler.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								vendor/go.uber.org/zap/internal/level_enabler.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -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 | ||||
| } | ||||
							
								
								
									
										152
									
								
								vendor/go.uber.org/zap/level.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										152
									
								
								vendor/go.uber.org/zap/level.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -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() | ||||
| } | ||||
							
								
								
									
										393
									
								
								vendor/go.uber.org/zap/logger.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										393
									
								
								vendor/go.uber.org/zap/logger.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,393 @@ | ||||
| // 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 | ||||
| } | ||||
|  | ||||
| // 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 | ||||
| } | ||||
							
								
								
									
										166
									
								
								vendor/go.uber.org/zap/options.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										166
									
								
								vendor/go.uber.org/zap/options.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,166 @@ | ||||
| // 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 | ||||
| 	}) | ||||
| } | ||||
							
								
								
									
										161
									
								
								vendor/go.uber.org/zap/sink.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										161
									
								
								vendor/go.uber.org/zap/sink.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,161 @@ | ||||
| // 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" | ||||
| 	"io" | ||||
| 	"net/url" | ||||
| 	"os" | ||||
| 	"strings" | ||||
| 	"sync" | ||||
|  | ||||
| 	"go.uber.org/zap/zapcore" | ||||
| ) | ||||
|  | ||||
| const schemeFile = "file" | ||||
|  | ||||
| var ( | ||||
| 	_sinkMutex     sync.RWMutex | ||||
| 	_sinkFactories map[string]func(*url.URL) (Sink, error) // keyed by scheme | ||||
| ) | ||||
|  | ||||
| func init() { | ||||
| 	resetSinkRegistry() | ||||
| } | ||||
|  | ||||
| func resetSinkRegistry() { | ||||
| 	_sinkMutex.Lock() | ||||
| 	defer _sinkMutex.Unlock() | ||||
|  | ||||
| 	_sinkFactories = map[string]func(*url.URL) (Sink, error){ | ||||
| 		schemeFile: newFileSink, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // Sink defines the interface to write to and close logger destinations. | ||||
| type Sink interface { | ||||
| 	zapcore.WriteSyncer | ||||
| 	io.Closer | ||||
| } | ||||
|  | ||||
| type nopCloserSink struct{ zapcore.WriteSyncer } | ||||
|  | ||||
| func (nopCloserSink) Close() error { return nil } | ||||
|  | ||||
| type errSinkNotFound struct { | ||||
| 	scheme string | ||||
| } | ||||
|  | ||||
| func (e *errSinkNotFound) Error() string { | ||||
| 	return fmt.Sprintf("no sink found for scheme %q", e.scheme) | ||||
| } | ||||
|  | ||||
| // RegisterSink registers a user-supplied factory for all sinks with a | ||||
| // particular scheme. | ||||
| // | ||||
| // All schemes must be ASCII, valid under section 3.1 of RFC 3986 | ||||
| // (https://tools.ietf.org/html/rfc3986#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 { | ||||
| 	_sinkMutex.Lock() | ||||
| 	defer _sinkMutex.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 := _sinkFactories[normalized]; ok { | ||||
| 		return fmt.Errorf("sink factory already registered for scheme %q", normalized) | ||||
| 	} | ||||
| 	_sinkFactories[normalized] = factory | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func newSink(rawURL string) (Sink, error) { | ||||
| 	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 | ||||
| 	} | ||||
|  | ||||
| 	_sinkMutex.RLock() | ||||
| 	factory, ok := _sinkFactories[u.Scheme] | ||||
| 	_sinkMutex.RUnlock() | ||||
| 	if !ok { | ||||
| 		return nil, &errSinkNotFound{u.Scheme} | ||||
| 	} | ||||
| 	return factory(u) | ||||
| } | ||||
|  | ||||
| func newFileSink(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) | ||||
| 	} | ||||
| 	switch u.Path { | ||||
| 	case "stdout": | ||||
| 		return nopCloserSink{os.Stdout}, nil | ||||
| 	case "stderr": | ||||
| 		return nopCloserSink{os.Stderr}, nil | ||||
| 	} | ||||
| 	return os.OpenFile(u.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 | ||||
| } | ||||
							
								
								
									
										176
									
								
								vendor/go.uber.org/zap/stacktrace.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										176
									
								
								vendor/go.uber.org/zap/stacktrace.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -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 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)) | ||||
| } | ||||
							
								
								
									
										393
									
								
								vendor/go.uber.org/zap/sugar.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										393
									
								
								vendor/go.uber.org/zap/sugar.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,393 @@ | ||||
| // 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." | ||||
| ) | ||||
|  | ||||
| // 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)...)} | ||||
| } | ||||
|  | ||||
| // 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 | ||||
| 	} | ||||
|  | ||||
| 	// 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)) | ||||
| 	var invalid invalidPairs | ||||
|  | ||||
| 	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 | ||||
| 		} | ||||
|  | ||||
| 		// 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 | ||||
| } | ||||
							
								
								
									
										27
									
								
								vendor/go.uber.org/zap/time.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								vendor/go.uber.org/zap/time.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -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) | ||||
| } | ||||
							
								
								
									
										98
									
								
								vendor/go.uber.org/zap/writer.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										98
									
								
								vendor/go.uber.org/zap/writer.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -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 := 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...)) | ||||
| } | ||||
							
								
								
									
										219
									
								
								vendor/go.uber.org/zap/zapcore/buffered_write_syncer.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										219
									
								
								vendor/go.uber.org/zap/zapcore/buffered_write_syncer.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -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 | ||||
| } | ||||
							
								
								
									
										48
									
								
								vendor/go.uber.org/zap/zapcore/clock.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								vendor/go.uber.org/zap/zapcore/clock.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -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) | ||||
| } | ||||
							
								
								
									
										157
									
								
								vendor/go.uber.org/zap/zapcore/console_encoder.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										157
									
								
								vendor/go.uber.org/zap/zapcore/console_encoder.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -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) | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										122
									
								
								vendor/go.uber.org/zap/zapcore/core.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										122
									
								
								vendor/go.uber.org/zap/zapcore/core.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -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, | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										24
									
								
								vendor/go.uber.org/zap/zapcore/doc.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								vendor/go.uber.org/zap/zapcore/doc.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -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" | ||||
							
								
								
									
										451
									
								
								vendor/go.uber.org/zap/zapcore/encoder.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										451
									
								
								vendor/go.uber.org/zap/zapcore/encoder.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -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) | ||||
| } | ||||
							
								
								
									
										299
									
								
								vendor/go.uber.org/zap/zapcore/entry.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										299
									
								
								vendor/go.uber.org/zap/zapcore/entry.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,299 @@ | ||||
| // 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 After(ent Entry, after CheckWriteHook) 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 | ||||
| } | ||||
							
								
								
									
										132
									
								
								vendor/go.uber.org/zap/zapcore/error.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										132
									
								
								vendor/go.uber.org/zap/zapcore/error.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -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) | ||||
| } | ||||
							
								
								
									
										233
									
								
								vendor/go.uber.org/zap/zapcore/field.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										233
									
								
								vendor/go.uber.org/zap/zapcore/field.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -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 | ||||
| } | ||||
							
								
								
									
										77
									
								
								vendor/go.uber.org/zap/zapcore/hook.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								vendor/go.uber.org/zap/zapcore/hook.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -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 | ||||
| } | ||||
							
								
								
									
										75
									
								
								vendor/go.uber.org/zap/zapcore/increase_level.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								vendor/go.uber.org/zap/zapcore/increase_level.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -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() | ||||
| } | ||||
							
								
								
									
										562
									
								
								vendor/go.uber.org/zap/zapcore/json_encoder.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										562
									
								
								vendor/go.uber.org/zap/zapcore/json_encoder.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -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 | ||||
| } | ||||
							
								
								
									
										229
									
								
								vendor/go.uber.org/zap/zapcore/level.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										229
									
								
								vendor/go.uber.org/zap/zapcore/level.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -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 | ||||
| } | ||||
							
								
								
									
										46
									
								
								vendor/go.uber.org/zap/zapcore/level_strings.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								vendor/go.uber.org/zap/zapcore/level_strings.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -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()) | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										61
									
								
								vendor/go.uber.org/zap/zapcore/marshaler.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								vendor/go.uber.org/zap/zapcore/marshaler.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -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) | ||||
| } | ||||
							
								
								
									
										179
									
								
								vendor/go.uber.org/zap/zapcore/memory_encoder.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										179
									
								
								vendor/go.uber.org/zap/zapcore/memory_encoder.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -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) } | ||||
							
								
								
									
										41
									
								
								vendor/go.uber.org/zap/zapcore/reflected_encoder.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								vendor/go.uber.org/zap/zapcore/reflected_encoder.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -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 | ||||
| } | ||||
							
								
								
									
										230
									
								
								vendor/go.uber.org/zap/zapcore/sampler.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										230
									
								
								vendor/go.uber.org/zap/zapcore/sampler.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -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) | ||||
| } | ||||
							
								
								
									
										96
									
								
								vendor/go.uber.org/zap/zapcore/tee.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										96
									
								
								vendor/go.uber.org/zap/zapcore/tee.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -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 | ||||
| } | ||||
							
								
								
									
										122
									
								
								vendor/go.uber.org/zap/zapcore/write_syncer.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										122
									
								
								vendor/go.uber.org/zap/zapcore/write_syncer.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -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 | ||||
| } | ||||
		Reference in New Issue
	
	Block a user