Showing preview only (867K chars total). Download the full file or copy to clipboard to get everything.
Repository: uber-go/zap
Branch: master
Commit: 0ab0d5aae598
Files: 176
Total size: 820.3 KB
Directory structure:
gitextract_vk9f9uhm/
├── .codecov.yml
├── .github/
│ ├── ISSUE_TEMPLATE/
│ │ ├── bug_report.md
│ │ ├── config.yml
│ │ └── feature_request.md
│ ├── dependabot.yml
│ └── workflows/
│ └── go.yml
├── .gitignore
├── .golangci.yml
├── .readme.tmpl
├── CHANGELOG.md
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── FAQ.md
├── LICENSE
├── Makefile
├── README.md
├── array.go
├── array_test.go
├── assets/
│ ├── README.md
│ └── go.mod
├── benchmarks/
│ ├── apex_test.go
│ ├── doc.go
│ ├── go.mod
│ ├── go.sum
│ ├── kit_test.go
│ ├── log15_test.go
│ ├── logrus_test.go
│ ├── scenario_bench_test.go
│ ├── slog_test.go
│ ├── zap_test.go
│ └── zerolog_test.go
├── buffer/
│ ├── buffer.go
│ ├── buffer_test.go
│ ├── pool.go
│ └── pool_test.go
├── checklicense.sh
├── clock_test.go
├── common_test.go
├── config.go
├── config_test.go
├── doc.go
├── encoder.go
├── encoder_test.go
├── error.go
├── error_test.go
├── example_test.go
├── exp/
│ ├── CHANGELOG.md
│ ├── LICENSE
│ ├── go.mod
│ ├── go.sum
│ ├── zapfield/
│ │ ├── zapfield.go
│ │ └── zapfield_test.go
│ └── zapslog/
│ ├── doc.go
│ ├── example_test.go
│ ├── handler.go
│ ├── handler_test.go
│ └── options.go
├── field.go
├── field_test.go
├── flag.go
├── flag_test.go
├── glide.yaml
├── global.go
├── global_test.go
├── go.mod
├── go.sum
├── http_handler.go
├── http_handler_test.go
├── increase_level_test.go
├── internal/
│ ├── bufferpool/
│ │ └── bufferpool.go
│ ├── color/
│ │ ├── color.go
│ │ └── color_test.go
│ ├── exit/
│ │ ├── exit.go
│ │ └── exit_test.go
│ ├── level_enabler.go
│ ├── pool/
│ │ ├── pool.go
│ │ └── pool_test.go
│ ├── readme/
│ │ └── readme.go
│ ├── stacktrace/
│ │ ├── stack.go
│ │ └── stack_test.go
│ └── ztest/
│ ├── clock.go
│ ├── clock_test.go
│ ├── doc.go
│ ├── timeout.go
│ └── writer.go
├── leak_test.go
├── level.go
├── level_test.go
├── logger.go
├── logger_bench_test.go
├── logger_test.go
├── options.go
├── sink.go
├── sink_test.go
├── sink_windows_test.go
├── stacktrace_ext_test.go
├── sugar.go
├── sugar_test.go
├── time.go
├── time_test.go
├── tools/
│ ├── go.mod
│ ├── go.sum
│ └── tools.go
├── writer.go
├── writer_test.go
├── zapcore/
│ ├── buffered_write_syncer.go
│ ├── buffered_write_syncer_bench_test.go
│ ├── buffered_write_syncer_test.go
│ ├── clock.go
│ ├── clock_test.go
│ ├── console_encoder.go
│ ├── console_encoder_bench_test.go
│ ├── console_encoder_test.go
│ ├── core.go
│ ├── core_test.go
│ ├── doc.go
│ ├── encoder.go
│ ├── encoder_test.go
│ ├── entry.go
│ ├── entry_ext_test.go
│ ├── entry_test.go
│ ├── error.go
│ ├── error_test.go
│ ├── field.go
│ ├── field_test.go
│ ├── hook.go
│ ├── hook_test.go
│ ├── increase_level.go
│ ├── increase_level_test.go
│ ├── json_encoder.go
│ ├── json_encoder_bench_test.go
│ ├── json_encoder_impl_test.go
│ ├── json_encoder_test.go
│ ├── lazy_with.go
│ ├── lazy_with_test.go
│ ├── leak_test.go
│ ├── level.go
│ ├── level_strings.go
│ ├── level_strings_test.go
│ ├── level_test.go
│ ├── marshaler.go
│ ├── memory_encoder.go
│ ├── memory_encoder_test.go
│ ├── reflected_encoder.go
│ ├── sampler.go
│ ├── sampler_bench_test.go
│ ├── sampler_test.go
│ ├── tee.go
│ ├── tee_logger_bench_test.go
│ ├── tee_test.go
│ ├── write_syncer.go
│ ├── write_syncer_bench_test.go
│ └── write_syncer_test.go
├── zapgrpc/
│ ├── internal/
│ │ └── test/
│ │ ├── README.md
│ │ ├── go.mod
│ │ ├── go.sum
│ │ ├── grpc.go
│ │ └── grpc_test.go
│ ├── zapgrpc.go
│ └── zapgrpc_test.go
├── zapio/
│ ├── example_test.go
│ ├── writer.go
│ └── writer_test.go
└── zaptest/
├── doc.go
├── logger.go
├── logger_test.go
├── observer/
│ ├── logged_entry.go
│ ├── logged_entry_test.go
│ ├── observer.go
│ └── observer_test.go
├── testingt.go
├── testingt_test.go
├── timeout.go
├── timeout_test.go
├── writer.go
└── writer_test.go
================================================
FILE CONTENTS
================================================
================================================
FILE: .codecov.yml
================================================
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
================================================
FILE: .github/ISSUE_TEMPLATE/bug_report.md
================================================
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior
**Expected behavior**
A clear and concise description of what you expected to happen.
**Additional context**
Add any other context about the problem here.
================================================
FILE: .github/ISSUE_TEMPLATE/config.yml
================================================
contact_links:
- name: Questions
about: Please use our Discussions page
url: https://github.com/uber-go/zap/discussions
================================================
FILE: .github/ISSUE_TEMPLATE/feature_request.md
================================================
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: ''
assignees: ''
---
**Is your feature request related to a problem? Please describe.**
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Is this a breaking change?**
We do not accept breaking changes to the existing API. Please consider if your proposed solution is backwards compatible. If not, we can help you make it backwards compatible, but this must be considered when we consider new features.
**Additional context**
Add any other context or screenshots about the feature request here.
================================================
FILE: .github/dependabot.yml
================================================
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
# Since Zap is a library, we don't want to update its dependency requirements
# regularly--not until we need a newer version of a dependency for a feature
# or specific fix.
# This way, users of Zap aren't forced to upgrade all their transitive
# dependencies every time they upgrade Zap.
#
# However, we do want to regularly update dependencies used inside the tools
# submodule because that holds linters and other development tools.
- package-ecosystem: "gomod"
directory: "/tools"
schedule:
interval: "weekly"
================================================
FILE: .github/workflows/go.yml
================================================
name: Go
on:
push:
branches: [master]
tags: ['v*']
pull_request:
branches: ['*']
permissions:
contents: read
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
go: ["1.25.x", "1.26.x"]
include:
- go: 1.26.x
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: ${{ matrix.go }}
cache-dependency-path: '**/go.sum'
- name: Download Dependencies
run: |
go mod download
(cd tools && go mod download)
(cd benchmarks && go mod download)
(cd zapgrpc/internal/test && go mod download)
- name: Test
run: make cover
- name: Upload coverage to codecov.io
uses: codecov/codecov-action@v5
with:
verbose: true
token: ${{ secrets.CODECOV_TOKEN }}
lint:
name: Lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
name: Check out repository
- uses: actions/setup-go@v5
name: Set up Go
with:
go-version: 1.26.x
cache: false # managed by golangci-lint
- uses: golangci/golangci-lint-action@v6
name: Install golangci-lint
with:
version: latest
# Hack: Use the official action to download, but not run.
# make lint below will handle actually running the linter.
args: --help
- run: make lint
name: Lint
- name: vulncheck
run: make vulncheck
================================================
FILE: .gitignore
================================================
# 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
================================================
FILE: .golangci.yml
================================================
output:
# Make output more digestible with quickfix in vim/emacs/etc.
sort-results: true
print-issued-lines: false
linters:
# We'll track the golangci-lint default linters manually
# instead of letting them change without our control.
disable-all: true
enable:
# golangci-lint defaults:
- errcheck
- gosimple
- govet
- ineffassign
- staticcheck
- unused
# Our own extras:
- gofumpt
- nolintlint # lints nolint directives
- revive
linters-settings:
govet:
# These govet checks are disabled by default, but they're useful.
enable:
- nilness
- reflectvaluecompare
- sortslice
- unusedwrite
errcheck:
exclude-functions:
# These methods can not fail.
# They operate on an in-memory buffer.
- (*go.uber.org/zap/buffer.Buffer).Write
- (*go.uber.org/zap/buffer.Buffer).WriteByte
- (*go.uber.org/zap/buffer.Buffer).WriteString
- (*go.uber.org/zap/zapio.Writer).Close
- (*go.uber.org/zap/zapio.Writer).Sync
- (*go.uber.org/zap/zapio.Writer).Write
# Write to zapio.Writer cannot fail,
# so io.WriteString on it cannot fail.
- io.WriteString(*go.uber.org/zap/zapio.Writer)
# Writing a plain string to a fmt.State cannot fail.
- io.WriteString(fmt.State)
issues:
# Print all issues reported by all linters.
max-issues-per-linter: 0
max-same-issues: 0
# Don't ignore some of the issues that golangci-lint considers okay.
# This includes documenting all exported entities.
exclude-use-default: false
exclude-rules:
# Don't warn on unused parameters.
# Parameter names are useful; replacing them with '_' is undesirable.
- linters: [revive]
text: 'unused-parameter: parameter \S+ seems to be unused, consider removing or renaming it as _'
# staticcheck already has smarter checks for empty blocks.
# revive's empty-block linter has false positives.
# For example, as of writing this, the following is not allowed.
# for foo() { }
- linters: [revive]
text: 'empty-block: this block is empty, you can remove it'
# Ignore logger.Sync() errcheck failures in example_test.go
# since those are intended to be uncomplicated examples.
- linters: [errcheck]
path: example_test.go
text: 'Error return value of `logger.Sync` is not checked'
================================================
FILE: .readme.tmpl
================================================
# :zap: zap [![GoDoc][doc-img]][doc] [![Build Status][ci-img]][ci] [![Coverage Status][cov-img]][cov]
<div align="center">
Blazing fast, structured, leveled logging in Go.

[![GoDoc][doc-img]][doc] [![Build Status][ci-img]][ci] [![Coverage Status][cov-img]][cov]
</div>
## 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).
<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
================================================
FILE: CHANGELOG.md
================================================
# Changelog
All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## 1.27.1 (19 Nov 2025)
Enhancements:
* [#1501][]: prevent `Object` from panicking on nils
* [#1511][]: Fix a race condition in `WithLazy`.
Thanks to @rabbbit, @alshopov, @jquirke, @arukiidou for their contributions to this release.
[#1501]: https://github.com/uber-go/zap/pull/1501
[#1511]: https://github.com/uber-go/zap/pull/1511
## 1.27.0 (20 Feb 2024)
Enhancements:
* [#1378][]: Add `WithLazy` method for `SugaredLogger`.
* [#1399][]: zaptest: Add `NewTestingWriter` for customizing TestingWriter with more flexibility than `NewLogger`.
* [#1406][]: Add `Log`, `Logw`, `Logln` methods for `SugaredLogger`.
* [#1416][]: Add `WithPanicHook` option for testing panic logs.
Thanks to @defval, @dimmo, @arxeiss, and @MKrupauskas for their contributions to this release.
[#1378]: https://github.com/uber-go/zap/pull/1378
[#1399]: https://github.com/uber-go/zap/pull/1399
[#1406]: https://github.com/uber-go/zap/pull/1406
[#1416]: https://github.com/uber-go/zap/pull/1416
## 1.26.0 (14 Sep 2023)
Enhancements:
* [#1297][]: Add Dict as a Field.
* [#1319][]: Add `WithLazy` method to `Logger` which lazily evaluates the structured
context.
* [#1350][]: String encoding is much (~50%) faster now.
Thanks to @hhk7734, @jquirke, and @cdvr1993 for their contributions to this release.
[#1297]: https://github.com/uber-go/zap/pull/1297
[#1319]: https://github.com/uber-go/zap/pull/1319
[#1350]: https://github.com/uber-go/zap/pull/1350
## 1.25.0 (1 Aug 2023)
This release contains several improvements including performance, API additions,
and two new experimental packages whose APIs are unstable and may change in the
future.
Enhancements:
* [#1246][]: Add `zap/exp/zapslog` package for integration with slog.
* [#1273][]: Add `Name` to `Logger` which returns the Logger's name if one is set.
* [#1281][]: Add `zap/exp/expfield` package which contains helper methods
`Str` and `Strs` for constructing String-like zap.Fields.
* [#1310][]: Reduce stack size on `Any`.
Thanks to @knight42, @dzakaammar, @bcspragu, and @rexywork for their contributions
to this release.
[#1246]: https://github.com/uber-go/zap/pull/1246
[#1273]: https://github.com/uber-go/zap/pull/1273
[#1281]: https://github.com/uber-go/zap/pull/1281
[#1310]: https://github.com/uber-go/zap/pull/1310
## 1.24.0 (30 Nov 2022)
Enhancements:
* [#1148][]: Add `Level` to both `Logger` and `SugaredLogger` that reports the
current minimum enabled log level.
* [#1185][]: `SugaredLogger` turns errors to zap.Error automatically.
Thanks to @Abirdcfly, @craigpastro, @nnnkkk7, and @sashamelentyev for their
contributions to this release.
[#1148]: https://github.coml/uber-go/zap/pull/1148
[#1185]: https://github.coml/uber-go/zap/pull/1185
## 1.23.0 (24 Aug 2022)
Enhancements:
* [#1147][]: Add a `zapcore.LevelOf` function to determine the level of a
`LevelEnabler` or `Core`.
* [#1155][]: Add `zap.Stringers` field constructor to log arrays of objects
that implement `String() string`.
[#1147]: https://github.com/uber-go/zap/pull/1147
[#1155]: https://github.com/uber-go/zap/pull/1155
## 1.22.0 (8 Aug 2022)
Enhancements:
* [#1071][]: Add `zap.Objects` and `zap.ObjectValues` field constructors to log
arrays of objects. With these two constructors, you don't need to implement
`zapcore.ArrayMarshaler` for use with `zap.Array` if those objects implement
`zapcore.ObjectMarshaler`.
* [#1079][]: Add `SugaredLogger.WithOptions` to build a copy of an existing
`SugaredLogger` with the provided options applied.
* [#1080][]: Add `*ln` variants to `SugaredLogger` for each log level.
These functions provide a string joining behavior similar to `fmt.Println`.
* [#1088][]: Add `zap.WithFatalHook` option to control the behavior of the
logger for `Fatal`-level log entries. This defaults to exiting the program.
* [#1108][]: Add a `zap.Must` function that you can use with `NewProduction` or
`NewDevelopment` to panic if the system was unable to build the logger.
* [#1118][]: Add a `Logger.Log` method that allows specifying the log level for
a statement dynamically.
Thanks to @cardil, @craigpastro, @sashamelentyev, @shota3506, and @zhupeijun
for their contributions to this release.
[#1071]: https://github.com/uber-go/zap/pull/1071
[#1079]: https://github.com/uber-go/zap/pull/1079
[#1080]: https://github.com/uber-go/zap/pull/1080
[#1088]: https://github.com/uber-go/zap/pull/1088
[#1108]: https://github.com/uber-go/zap/pull/1108
[#1118]: https://github.com/uber-go/zap/pull/1118
## 1.21.0 (7 Feb 2022)
Enhancements:
* [#1047][]: Add `zapcore.ParseLevel` to parse a `Level` from a string.
* [#1048][]: Add `zap.ParseAtomicLevel` to parse an `AtomicLevel` from a
string.
Bugfixes:
* [#1058][]: Fix panic in JSON encoder when `EncodeLevel` is unset.
Other changes:
* [#1052][]: Improve encoding performance when the `AddCaller` and
`AddStacktrace` options are used together.
[#1047]: https://github.com/uber-go/zap/pull/1047
[#1048]: https://github.com/uber-go/zap/pull/1048
[#1052]: https://github.com/uber-go/zap/pull/1052
[#1058]: https://github.com/uber-go/zap/pull/1058
Thanks to @aerosol and @Techassi for their contributions to this release.
## 1.20.0 (4 Jan 2022)
Enhancements:
* [#989][]: Add `EncoderConfig.SkipLineEnding` flag to disable adding newline
characters between log statements.
* [#1039][]: Add `EncoderConfig.NewReflectedEncoder` field to customize JSON
encoding of reflected log fields.
Bugfixes:
* [#1011][]: Fix inaccurate precision when encoding complex64 as JSON.
* [#554][], [#1017][]: Close JSON namespaces opened in `MarshalLogObject`
methods when the methods return.
* [#1033][]: Avoid panicking in Sampler core if `thereafter` is zero.
Other changes:
* [#1028][]: Drop support for Go < 1.15.
[#554]: https://github.com/uber-go/zap/pull/554
[#989]: https://github.com/uber-go/zap/pull/989
[#1011]: https://github.com/uber-go/zap/pull/1011
[#1017]: https://github.com/uber-go/zap/pull/1017
[#1028]: https://github.com/uber-go/zap/pull/1028
[#1033]: https://github.com/uber-go/zap/pull/1033
[#1039]: https://github.com/uber-go/zap/pull/1039
Thanks to @psrajat, @lruggieri, @sammyrnycreal for their contributions to this release.
## 1.19.1 (8 Sep 2021)
Bugfixes:
* [#1001][]: JSON: Fix complex number encoding with negative imaginary part. Thanks to @hemantjadon.
* [#1003][]: JSON: Fix inaccurate precision when encoding float32.
[#1001]: https://github.com/uber-go/zap/pull/1001
[#1003]: https://github.com/uber-go/zap/pull/1003
## 1.19.0 (9 Aug 2021)
Enhancements:
* [#975][]: Avoid panicking in Sampler core if the level is out of bounds.
* [#984][]: Reduce the size of BufferedWriteSyncer by aligning the fields
better.
[#975]: https://github.com/uber-go/zap/pull/975
[#984]: https://github.com/uber-go/zap/pull/984
Thanks to @lancoLiu and @thockin for their contributions to this release.
## 1.18.1 (28 Jun 2021)
Bugfixes:
* [#974][]: Fix nil dereference in logger constructed by `zap.NewNop`.
[#974]: https://github.com/uber-go/zap/pull/974
## 1.18.0 (28 Jun 2021)
Enhancements:
* [#961][]: Add `zapcore.BufferedWriteSyncer`, a new `WriteSyncer` that buffers
messages in-memory and flushes them periodically.
* [#971][]: Add `zapio.Writer` to use a Zap logger as an `io.Writer`.
* [#897][]: Add `zap.WithClock` option to control the source of time via the
new `zapcore.Clock` interface.
* [#949][]: Avoid panicking in `zap.SugaredLogger` when arguments of `*w`
methods don't match expectations.
* [#943][]: Add support for filtering by level or arbitrary matcher function to
`zaptest/observer`.
* [#691][]: Comply with `io.StringWriter` and `io.ByteWriter` in Zap's
`buffer.Buffer`.
Thanks to @atrn0, @ernado, @heyanfu, @hnlq715, @zchee
for their contributions to this release.
[#691]: https://github.com/uber-go/zap/pull/691
[#897]: https://github.com/uber-go/zap/pull/897
[#943]: https://github.com/uber-go/zap/pull/943
[#949]: https://github.com/uber-go/zap/pull/949
[#961]: https://github.com/uber-go/zap/pull/961
[#971]: https://github.com/uber-go/zap/pull/971
## 1.17.0 (25 May 2021)
Bugfixes:
* [#867][]: Encode `<nil>` for nil `error` instead of a panic.
* [#931][], [#936][]: Update minimum version constraints to address
vulnerabilities in dependencies.
Enhancements:
* [#865][]: Improve alignment of fields of the Logger struct, reducing its
size from 96 to 80 bytes.
* [#881][]: Support `grpclog.LoggerV2` in zapgrpc.
* [#903][]: Support URL-encoded POST requests to the AtomicLevel HTTP handler
with the `application/x-www-form-urlencoded` content type.
* [#912][]: Support multi-field encoding with `zap.Inline`.
* [#913][]: Speed up SugaredLogger for calls with a single string.
* [#928][]: Add support for filtering by field name to `zaptest/observer`.
Thanks to @ash2k, @FMLS, @jimmystewpot, @Oncilla, @tsoslow, @tylitianrui, @withshubh, and @wziww for their contributions to this release.
[#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
## 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.
[#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
## 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.
[#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
## 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.
[#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
## 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.
[#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
## 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.
[#758]: https://github.com/uber-go/zap/pull/758
## 1.12.0 (29 Oct 2019)
Enhancements:
* [#751][]: Migrate to Go modules.
[#751]: https://github.com/uber-go/zap/pull/751
## 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.
[#725]: https://github.com/uber-go/zap/pull/725
[#736]: https://github.com/uber-go/zap/pull/736
## 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.
[#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
## 1.9.1 (06 Aug 2018)
Bugfixes:
* [#614][]: MapObjectEncoder should not ignore empty slices.
[#614]: https://github.com/uber-go/zap/pull/614
## 1.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.
[#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
## 1.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.
[#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
## 1.7.1 (25 Sep 2017)
Bugfixes:
* [#504][]: Store strings when using AddByteString with the map encoder.
[#504]: https://github.com/uber-go/zap/pull/504
## 1.7.0 (21 Sep 2017)
Enhancements:
* [#487][]: Add `NewStdLogAt`, which extends `NewStdLog` by allowing the user
to specify the level of the logged messages.
[#487]: https://github.com/uber-go/zap/pull/487
## 1.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.
[#490]: https://github.com/uber-go/zap/pull/490
[#491]: https://github.com/uber-go/zap/pull/491
## 1.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.
[#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
## 1.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.
[#435]: https://github.com/uber-go/zap/pull/435
[#444]: https://github.com/uber-go/zap/pull/444
## 1.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.
[#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
## 1.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`.
[#415]: https://github.com/uber-go/zap/pull/415
[#416]: https://github.com/uber-go/zap/pull/416
## 1.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`.
[#402]: https://github.com/uber-go/zap/pull/402
## 1.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.
[#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
## 1.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.
[#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
## 1.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.
[#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
## 1.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.
[#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
## 1.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.
## 0.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.
================================================
FILE: CODE_OF_CONDUCT.md
================================================
# 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]: https://contributor-covenant.org
[version]: https://contributor-covenant.org/version/1/4/
================================================
FILE: CONTRIBUTING.md
================================================
# 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
================================================
FILE: FAQ.md
================================================
# 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
================================================
FILE: LICENSE
================================================
Copyright (c) 2016-2024 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.
================================================
FILE: Makefile
================================================
# Directory containing the Makefile.
PROJECT_ROOT = $(dir $(abspath $(lastword $(MAKEFILE_LIST))))
export GOBIN ?= $(PROJECT_ROOT)/bin
export PATH := $(GOBIN):$(PATH)
GOVULNCHECK = $(GOBIN)/govulncheck
BENCH_FLAGS ?= -cpuprofile=cpu.pprof -memprofile=mem.pprof -benchmem
# Directories containing independent Go modules.
MODULE_DIRS = . ./exp ./benchmarks ./zapgrpc/internal/test
# Directories that we want to track coverage for.
COVER_DIRS = . ./exp
.PHONY: all
all: lint test
.PHONY: lint
lint: golangci-lint tidy-lint license-lint
.PHONY: golangci-lint
golangci-lint:
@$(foreach mod,$(MODULE_DIRS), \
(cd $(mod) && \
echo "[lint] golangci-lint: $(mod)" && \
golangci-lint run --path-prefix $(mod) ./...) &&) true
.PHONY: tidy
tidy:
@$(foreach dir,$(MODULE_DIRS), \
(cd $(dir) && go mod tidy) &&) true
.PHONY: tidy-lint
tidy-lint:
@$(foreach mod,$(MODULE_DIRS), \
(cd $(mod) && \
echo "[lint] tidy: $(mod)" && \
go mod tidy && \
git diff --exit-code -- go.mod go.sum) &&) true
.PHONY: license-lint
license-lint:
./checklicense.sh
$(GOVULNCHECK):
cd tools && go install golang.org/x/vuln/cmd/govulncheck
.PHONY: test
test:
@$(foreach dir,$(MODULE_DIRS),(cd $(dir) && go test -race ./...) &&) true
.PHONY: cover
cover:
@$(foreach dir,$(COVER_DIRS), ( \
cd $(dir) && \
go test -race -coverprofile=cover.out -coverpkg=./... ./... \
&& go tool cover -html=cover.out -o cover.html) &&) true
.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: vulncheck
vulncheck: $(GOVULNCHECK)
$(GOVULNCHECK) ./...
================================================
FILE: README.md
================================================
# :zap: zap
<div align="center">
Blazing fast, structured, leveled logging in Go.

[![GoDoc][doc-img]][doc] [![Build Status][ci-img]][ci] [![Coverage Status][cov-img]][cov]
</div>
## 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 | 656 ns/op | +0% | 5 allocs/op
| :zap: zap (sugared) | 935 ns/op | +43% | 10 allocs/op
| zerolog | 380 ns/op | -42% | 1 allocs/op
| go-kit | 2249 ns/op | +243% | 57 allocs/op
| slog (LogAttrs) | 2479 ns/op | +278% | 40 allocs/op
| slog | 2481 ns/op | +278% | 42 allocs/op
| apex/log | 9591 ns/op | +1362% | 63 allocs/op
| log15 | 11393 ns/op | +1637% | 75 allocs/op
| logrus | 11654 ns/op | +1677% | 79 allocs/op
Log a message with a logger that already has 10 fields of context:
| Package | Time | Time % to zap | Objects Allocated |
| :------ | :--: | :-----------: | :---------------: |
| :zap: zap | 67 ns/op | +0% | 0 allocs/op
| :zap: zap (sugared) | 84 ns/op | +25% | 1 allocs/op
| zerolog | 35 ns/op | -48% | 0 allocs/op
| slog | 193 ns/op | +188% | 0 allocs/op
| slog (LogAttrs) | 200 ns/op | +199% | 0 allocs/op
| go-kit | 2460 ns/op | +3572% | 56 allocs/op
| log15 | 9038 ns/op | +13390% | 70 allocs/op
| apex/log | 9068 ns/op | +13434% | 53 allocs/op
| logrus | 10521 ns/op | +15603% | 68 allocs/op
Log a static string, without any context or `printf`-style templating:
| Package | Time | Time % to zap | Objects Allocated |
| :------ | :--: | :-----------: | :---------------: |
| :zap: zap | 63 ns/op | +0% | 0 allocs/op
| :zap: zap (sugared) | 81 ns/op | +29% | 1 allocs/op
| zerolog | 32 ns/op | -49% | 0 allocs/op
| standard library | 124 ns/op | +97% | 1 allocs/op
| slog | 196 ns/op | +211% | 0 allocs/op
| slog (LogAttrs) | 200 ns/op | +217% | 0 allocs/op
| go-kit | 213 ns/op | +238% | 9 allocs/op
| apex/log | 771 ns/op | +1124% | 5 allocs/op
| logrus | 1439 ns/op | +2184% | 23 allocs/op
| log15 | 2069 ns/op | +3184% | 20 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).
<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
================================================
FILE: array.go
================================================
// 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"
"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))
}
// 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
}
// Strings constructs a field that carries a slice of strings.
func Strings(key string, ss []string) Field {
return Array(key, stringArray(ss))
}
// 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
}
// 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
}
================================================
FILE: array_test.go
================================================
// 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"
"testing"
"time"
"go.uber.org/zap/zapcore"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func BenchmarkBoolsArrayMarshaler(b *testing.B) {
// Keep this benchmark here to capture the overhead of the ArrayMarshaler
// wrapper.
bs := make([]bool, 50)
enc := zapcore.NewJSONEncoder(zapcore.EncoderConfig{})
b.ResetTimer()
for i := 0; i < b.N; i++ {
Bools("array", bs).AddTo(enc.Clone())
}
}
func BenchmarkBoolsReflect(b *testing.B) {
bs := make([]bool, 50)
enc := zapcore.NewJSONEncoder(zapcore.EncoderConfig{})
b.ResetTimer()
for i := 0; i < b.N; i++ {
Reflect("array", bs).AddTo(enc.Clone())
}
}
func TestArrayWrappers(t *testing.T) {
tests := []struct {
desc string
field Field
expected []interface{}
}{
{"empty bools", Bools("", []bool{}), []interface{}{}},
{"empty byte strings", ByteStrings("", [][]byte{}), []interface{}{}},
{"empty complex128s", Complex128s("", []complex128{}), []interface{}{}},
{"empty complex64s", Complex64s("", []complex64{}), []interface{}{}},
{"empty durations", Durations("", []time.Duration{}), []interface{}{}},
{"empty float64s", Float64s("", []float64{}), []interface{}{}},
{"empty float32s", Float32s("", []float32{}), []interface{}{}},
{"empty ints", Ints("", []int{}), []interface{}{}},
{"empty int64s", Int64s("", []int64{}), []interface{}{}},
{"empty int32s", Int32s("", []int32{}), []interface{}{}},
{"empty int16s", Int16s("", []int16{}), []interface{}{}},
{"empty int8s", Int8s("", []int8{}), []interface{}{}},
{"empty strings", Strings("", []string{}), []interface{}{}},
{"empty times", Times("", []time.Time{}), []interface{}{}},
{"empty uints", Uints("", []uint{}), []interface{}{}},
{"empty uint64s", Uint64s("", []uint64{}), []interface{}{}},
{"empty uint32s", Uint32s("", []uint32{}), []interface{}{}},
{"empty uint16s", Uint16s("", []uint16{}), []interface{}{}},
{"empty uint8s", Uint8s("", []uint8{}), []interface{}{}},
{"empty uintptrs", Uintptrs("", []uintptr{}), []interface{}{}},
{"bools", Bools("", []bool{true, false}), []interface{}{true, false}},
{"byte strings", ByteStrings("", [][]byte{{1, 2}, {3, 4}}), []interface{}{"\x01\x02", "\x03\x04"}},
{"complex128s", Complex128s("", []complex128{1 + 2i, 3 + 4i}), []interface{}{1 + 2i, 3 + 4i}},
{"complex64s", Complex64s("", []complex64{1 + 2i, 3 + 4i}), []interface{}{complex64(1 + 2i), complex64(3 + 4i)}},
{"durations", Durations("", []time.Duration{1, 2}), []interface{}{time.Nanosecond, 2 * time.Nanosecond}},
{"float64s", Float64s("", []float64{1.2, 3.4}), []interface{}{1.2, 3.4}},
{"float32s", Float32s("", []float32{1.2, 3.4}), []interface{}{float32(1.2), float32(3.4)}},
{"ints", Ints("", []int{1, 2}), []interface{}{1, 2}},
{"int64s", Int64s("", []int64{1, 2}), []interface{}{int64(1), int64(2)}},
{"int32s", Int32s("", []int32{1, 2}), []interface{}{int32(1), int32(2)}},
{"int16s", Int16s("", []int16{1, 2}), []interface{}{int16(1), int16(2)}},
{"int8s", Int8s("", []int8{1, 2}), []interface{}{int8(1), int8(2)}},
{"strings", Strings("", []string{"foo", "bar"}), []interface{}{"foo", "bar"}},
{"times", Times("", []time.Time{time.Unix(0, 0), time.Unix(0, 0)}), []interface{}{time.Unix(0, 0), time.Unix(0, 0)}},
{"uints", Uints("", []uint{1, 2}), []interface{}{uint(1), uint(2)}},
{"uint64s", Uint64s("", []uint64{1, 2}), []interface{}{uint64(1), uint64(2)}},
{"uint32s", Uint32s("", []uint32{1, 2}), []interface{}{uint32(1), uint32(2)}},
{"uint16s", Uint16s("", []uint16{1, 2}), []interface{}{uint16(1), uint16(2)}},
{"uint8s", Uint8s("", []uint8{1, 2}), []interface{}{uint8(1), uint8(2)}},
{"uintptrs", Uintptrs("", []uintptr{1, 2}), []interface{}{uintptr(1), uintptr(2)}},
}
for _, tt := range tests {
enc := zapcore.NewMapObjectEncoder()
tt.field.Key = "k"
tt.field.AddTo(enc)
assert.Equal(t, tt.expected, enc.Fields["k"], "%s: unexpected map contents.", tt.desc)
assert.Equal(t, 1, len(enc.Fields), "%s: found extra keys in map: %v", tt.desc, enc.Fields)
}
}
func TestObjectsAndObjectValues(t *testing.T) {
t.Parallel()
tests := []struct {
desc string
give Field
want []any
}{
{
desc: "Objects/nil slice",
give: Objects[*emptyObject]("", nil),
want: []any{},
},
{
desc: "ObjectValues/nil slice",
give: ObjectValues[emptyObject]("", nil),
want: []any{},
},
{
desc: "ObjectValues/empty slice",
give: ObjectValues("", []emptyObject{}),
want: []any{},
},
{
desc: "ObjectValues/single item",
give: ObjectValues("", []emptyObject{
{},
}),
want: []any{
map[string]any{},
},
},
{
desc: "Objects/multiple different objects",
give: Objects("", []*fakeObject{
{value: "foo"},
{value: "bar"},
{value: "baz"},
}),
want: []any{
map[string]any{"value": "foo"},
map[string]any{"value": "bar"},
map[string]any{"value": "baz"},
},
},
{
desc: "ObjectValues/multiple different objects",
give: ObjectValues("", []fakeObject{
{value: "foo"},
{value: "bar"},
{value: "baz"},
}),
want: []any{
map[string]any{"value": "foo"},
map[string]any{"value": "bar"},
map[string]any{"value": "baz"},
},
},
}
for _, tt := range tests {
tt := tt
t.Run(tt.desc, func(t *testing.T) {
t.Parallel()
tt.give.Key = "k"
enc := zapcore.NewMapObjectEncoder()
tt.give.AddTo(enc)
assert.Equal(t, tt.want, enc.Fields["k"])
})
}
}
type emptyObject struct{}
func (*emptyObject) MarshalLogObject(zapcore.ObjectEncoder) error {
return nil
}
type fakeObject struct {
value string
err error // marshaling error, if any
}
func (o *fakeObject) MarshalLogObject(enc zapcore.ObjectEncoder) error {
enc.AddString("value", o.value)
return o.err
}
func TestObjectsAndObjectValues_marshalError(t *testing.T) {
t.Parallel()
tests := []struct {
desc string
give Field
want []any
wantErr string
}{
{
desc: "Objects",
give: Objects("", []*fakeObject{
{value: "foo"},
{value: "bar", err: errors.New("great sadness")},
{value: "baz"}, // does not get marshaled
}),
want: []any{
map[string]any{"value": "foo"},
map[string]any{"value": "bar"},
},
wantErr: "great sadness",
},
{
desc: "ObjectValues",
give: ObjectValues("", []fakeObject{
{value: "foo"},
{value: "bar", err: errors.New("stuff failed")},
{value: "baz"}, // does not get marshaled
}),
want: []any{
map[string]any{"value": "foo"},
map[string]any{"value": "bar"},
},
wantErr: "stuff failed",
},
}
for _, tt := range tests {
tt := tt
t.Run(tt.desc, func(t *testing.T) {
t.Parallel()
tt.give.Key = "k"
enc := zapcore.NewMapObjectEncoder()
tt.give.AddTo(enc)
require.Contains(t, enc.Fields, "k")
assert.Equal(t, tt.want, enc.Fields["k"])
// AddTo puts the error in a "%vError" field based on the name of the
// original field.
require.Contains(t, enc.Fields, "kError")
assert.Equal(t, tt.wantErr, enc.Fields["kError"])
})
}
}
type stringerObject struct {
value string
}
func (s stringerObject) String() string {
return s.value
}
func TestStringers(t *testing.T) {
t.Parallel()
tests := []struct {
desc string
give Field
want []any
}{
{
desc: "Stringers",
give: Stringers("", []stringerObject{
{value: "foo"},
{value: "bar"},
{value: "baz"},
}),
want: []any{
"foo",
"bar",
"baz",
},
},
{
desc: "Stringers with []fmt.Stringer",
give: Stringers("", []fmt.Stringer{
stringerObject{value: "foo"},
stringerObject{value: "bar"},
stringerObject{value: "baz"},
}),
want: []any{
"foo",
"bar",
"baz",
},
},
}
for _, tt := range tests {
tt := tt
t.Run(tt.desc, func(t *testing.T) {
t.Parallel()
tt.give.Key = "k"
enc := zapcore.NewMapObjectEncoder()
tt.give.AddTo(enc)
assert.Equal(t, tt.want, enc.Fields["k"])
})
}
}
================================================
FILE: assets/README.md
================================================
The logo for Zap was designed by [Abhinav Gupta](https://abhinavg.net/)
and is made available under the Creative Commons 4.0 Attribution License.
It is based on the Go Gopher mascot originally created by Renee French,
which is also licensed under the Creative Commons 4.0 Attribution License.
================================================
FILE: assets/go.mod
================================================
module go.uber.org/zap/assets
go 1.21.5
================================================
FILE: benchmarks/apex_test.go
================================================
// 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 benchmarks
import (
"io"
"github.com/apex/log"
"github.com/apex/log/handlers/json"
)
func newDisabledApexLog() *log.Logger {
return &log.Logger{
Handler: json.New(io.Discard),
Level: log.ErrorLevel,
}
}
func newApexLog() *log.Logger {
return &log.Logger{
Handler: json.New(io.Discard),
Level: log.DebugLevel,
}
}
func fakeApexFields() log.Fields {
return log.Fields{
"int": _tenInts[0],
"ints": _tenInts,
"string": _tenStrings[0],
"strings": _tenStrings,
"time": _tenTimes[0],
"times": _tenTimes,
"user1": _oneUser,
"user2": _oneUser,
"users": _tenUsers,
"error": errExample,
}
}
================================================
FILE: benchmarks/doc.go
================================================
// 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 benchmarks contains only benchmarks comparing zap to other
// structured logging libraries.
package benchmarks
================================================
FILE: benchmarks/go.mod
================================================
module go.uber.org/zap/benchmarks
go 1.21
replace go.uber.org/zap => ../
require (
github.com/apex/log v1.9.0
github.com/go-kit/log v0.2.1
github.com/rs/zerolog v1.30.0
github.com/sirupsen/logrus v1.9.3
go.uber.org/multierr v1.11.0
go.uber.org/zap v1.23.0
gopkg.in/inconshreveable/log15.v2 v2.16.0
)
require (
github.com/go-logfmt/logfmt v0.6.0 // indirect
github.com/go-stack/stack v1.8.1 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.19 // indirect
github.com/pkg/errors v0.9.1 // indirect
golang.org/x/sys v0.12.0 // indirect
golang.org/x/term v0.12.0 // indirect
)
================================================
FILE: benchmarks/go.sum
================================================
github.com/apex/log v1.9.0 h1:FHtw/xuaM8AgmvDDTI9fiwoAL25Sq2cxojnZICUU8l0=
github.com/apex/log v1.9.0/go.mod h1:m82fZlWIuiWzWP04XCTXmnX0xRkYYbCdYn8jbJeLBEA=
github.com/apex/logs v1.0.0/go.mod h1:XzxuLZ5myVHDy9SAmYpamKKRNApGj54PfYLcFrXqDwo=
github.com/aphistic/golf v0.0.0-20180712155816-02c07f170c5a/go.mod h1:3NqKYiepwy8kCu4PNA+aP7WUV72eXWJeP9/r3/K9aLE=
github.com/aphistic/sweet v0.2.0/go.mod h1:fWDlIh/isSE9n6EPsRmC0det+whmX6dJid3stzu0Xys=
github.com/aws/aws-sdk-go v1.20.6/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59/go.mod h1:q/89r3U2H7sSsE2t6Kca0lfwTK8JdoNGS/yzM/4iH5I=
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/go-kit/log v0.2.1 h1:MRVx0/zhvdseW+Gza6N9rVzU/IVzaeE1SFI4raAhmBU=
github.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-logfmt/logfmt v0.6.0 h1:wGYYu3uicYdqXVgoYbvnkrPVXkuLM1p1ifugDMEdRi4=
github.com/go-logfmt/logfmt v0.6.0/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
github.com/go-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw=
github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
github.com/jpillora/backoff v0.0.0-20180909062703-3050d21c67d7/go.mod h1:2iMrUgbbvHEiQClaW2NsSzMyGHqN+rDFqY705q49KG0=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ=
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rogpeppe/fastuuid v1.1.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
github.com/rs/zerolog v1.30.0 h1:SymVODrcRsaRaSInD9yQtKbtWqwsfoPcRff/oRXLj4c=
github.com/rs/zerolog v1.30.0/go.mod h1:/tk+P47gFdPXq4QYjvCmT5/Gsug2nagsFWBWhAiSi1w=
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/smartystreets/assertions v1.0.0/go.mod h1:kHHU4qYBaI3q23Pp3VPrmWhuIUrLW/7eUrw0BU5VaoM=
github.com/smartystreets/go-aws-auth v0.0.0-20180515143844-0c1422d1fdb9/go.mod h1:SnhjPscd9TpLiy1LpzGSKh3bXCfxxXuqd9xmQJy3slM=
github.com/smartystreets/gunit v1.0.0/go.mod h1:qwPWnhz6pn0NnRBP++URONOVyNkPyr4SauJk4cUOwJs=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/tj/assert v0.0.0-20171129193455-018094318fb0/go.mod h1:mZ9/Rh9oLWpLLDRpvE+3b7gP/C2YyLFYxNmcLnPTMe0=
github.com/tj/assert v0.0.3 h1:Df/BlaZ20mq6kuai7f5z2TvPFiwC3xaWJSDQNiIS3Rk=
github.com/tj/assert v0.0.3/go.mod h1:Ne6X72Q+TB1AteidzQncjw9PabbMp4PBMZ1k+vd1Pvk=
github.com/tj/go-buffer v1.1.0/go.mod h1:iyiJpfFcR2B9sXu7KvjbT9fpM4mOelRSDTbntVj52Uc=
github.com/tj/go-elastic v0.0.0-20171221160941-36157cbbebc2/go.mod h1:WjeM0Oo1eNAjXGDx2yma7uG2XoyRZTq1uv3M/o7imD0=
github.com/tj/go-kinesis v0.0.0-20171128231115-08b17f58cb1b/go.mod h1:/yhzCV0xPfx6jb1bBgRFjl5lytqVqZXEaeqWP8lTEao=
github.com/tj/go-spin v1.1.0/go.mod h1:Mg1mzmePZm4dva8Qz60H2lHwmJ2loum4VIrLgVnKwh4=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o=
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.12.0 h1:/ZfYdc3zq+q02Rv9vGqTeSItdzZTSNDmfTi0mBAuidU=
golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/inconshreveable/log15.v2 v2.16.0 h1:LWHLVX8KbBMkQFSqfno4901Z4Wg8L3B7Cu0n4K/Q7MA=
gopkg.in/inconshreveable/log15.v2 v2.16.0/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
================================================
FILE: benchmarks/kit_test.go
================================================
// 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 benchmarks
import (
"io"
"github.com/go-kit/log"
)
func newKitLog(fields ...interface{}) log.Logger {
return log.With(log.NewJSONLogger(io.Discard), fields...)
}
================================================
FILE: benchmarks/log15_test.go
================================================
// 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 benchmarks
import (
"io"
"gopkg.in/inconshreveable/log15.v2"
)
func newLog15() log15.Logger {
logger := log15.New()
logger.SetHandler(log15.StreamHandler(io.Discard, log15.JsonFormat()))
return logger
}
================================================
FILE: benchmarks/logrus_test.go
================================================
// 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 benchmarks
import (
"io"
"github.com/sirupsen/logrus"
)
func newDisabledLogrus() *logrus.Logger {
logger := newLogrus()
logger.Level = logrus.ErrorLevel
return logger
}
func newLogrus() *logrus.Logger {
return &logrus.Logger{
Out: io.Discard,
Formatter: new(logrus.JSONFormatter),
Hooks: make(logrus.LevelHooks),
Level: logrus.DebugLevel,
}
}
func fakeLogrusFields() logrus.Fields {
return logrus.Fields{
"int": _tenInts[0],
"ints": _tenInts,
"string": _tenStrings[0],
"strings": _tenStrings,
"time": _tenTimes[0],
"times": _tenTimes,
"user1": _oneUser,
"user2": _oneUser,
"users": _tenUsers,
"error": errExample,
}
}
================================================
FILE: benchmarks/scenario_bench_test.go
================================================
// 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 benchmarks
import (
"context"
"log"
"log/slog"
"testing"
"go.uber.org/zap"
"go.uber.org/zap/internal/ztest"
)
func BenchmarkDisabledWithoutFields(b *testing.B) {
b.Logf("Logging at a disabled level without any structured context.")
b.Run("Zap", func(b *testing.B) {
logger := newZapLogger(zap.ErrorLevel)
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
logger.Info(getMessage(0))
}
})
})
b.Run("Zap.Check", func(b *testing.B) {
logger := newZapLogger(zap.ErrorLevel)
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
if m := logger.Check(zap.InfoLevel, getMessage(0)); m != nil {
m.Write()
}
}
})
})
b.Run("Zap.Sugar", func(b *testing.B) {
logger := newZapLogger(zap.ErrorLevel).Sugar()
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
logger.Info(getMessage(0))
}
})
})
b.Run("Zap.SugarFormatting", func(b *testing.B) {
logger := newZapLogger(zap.ErrorLevel).Sugar()
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
logger.Infof("%v %v %v %s %v %v %v %v %v %s\n", fakeFmtArgs()...)
}
})
})
b.Run("apex/log", func(b *testing.B) {
logger := newDisabledApexLog()
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
logger.Info(getMessage(0))
}
})
})
b.Run("sirupsen/logrus", func(b *testing.B) {
logger := newDisabledLogrus()
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
logger.Info(getMessage(0))
}
})
})
b.Run("rs/zerolog", func(b *testing.B) {
logger := newDisabledZerolog()
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
logger.Info().Msg(getMessage(0))
}
})
})
b.Run("slog", func(b *testing.B) {
logger := newDisabledSlog()
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
logger.Info(getMessage(0))
}
})
})
b.Run("slog.LogAttrs", func(b *testing.B) {
logger := newDisabledSlog()
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
logger.LogAttrs(context.Background(), slog.LevelInfo, getMessage(0))
}
})
})
}
func BenchmarkDisabledAccumulatedContext(b *testing.B) {
b.Logf("Logging at a disabled level with some accumulated context.")
b.Run("Zap", func(b *testing.B) {
logger := newZapLogger(zap.ErrorLevel).With(fakeFields()...)
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
logger.Info(getMessage(0))
}
})
})
b.Run("Zap.Check", func(b *testing.B) {
logger := newZapLogger(zap.ErrorLevel).With(fakeFields()...)
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
if m := logger.Check(zap.InfoLevel, getMessage(0)); m != nil {
m.Write()
}
}
})
})
b.Run("Zap.Sugar", func(b *testing.B) {
logger := newZapLogger(zap.ErrorLevel).With(fakeFields()...).Sugar()
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
logger.Info(getMessage(0))
}
})
})
b.Run("Zap.SugarFormatting", func(b *testing.B) {
logger := newZapLogger(zap.ErrorLevel).With(fakeFields()...).Sugar()
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
logger.Infof("%v %v %v %s %v %v %v %v %v %s\n", fakeFmtArgs()...)
}
})
})
b.Run("apex/log", func(b *testing.B) {
logger := newDisabledApexLog().WithFields(fakeApexFields())
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
logger.Info(getMessage(0))
}
})
})
b.Run("sirupsen/logrus", func(b *testing.B) {
logger := newDisabledLogrus().WithFields(fakeLogrusFields())
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
logger.Info(getMessage(0))
}
})
})
b.Run("rs/zerolog", func(b *testing.B) {
logger := fakeZerologContext(newDisabledZerolog().With()).Logger()
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
logger.Info().Msg(getMessage(0))
}
})
})
b.Run("slog", func(b *testing.B) {
logger := newDisabledSlog(fakeSlogFields()...)
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
logger.Info(getMessage(0))
}
})
})
b.Run("slog.LogAttrs", func(b *testing.B) {
logger := newDisabledSlog(fakeSlogFields()...)
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
logger.LogAttrs(context.Background(), slog.LevelInfo, getMessage(0))
}
})
})
}
func BenchmarkDisabledAddingFields(b *testing.B) {
b.Logf("Logging at a disabled level, adding context at each log site.")
b.Run("Zap", func(b *testing.B) {
logger := newZapLogger(zap.ErrorLevel)
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
logger.Info(getMessage(0), fakeFields()...)
}
})
})
b.Run("Zap.Check", func(b *testing.B) {
logger := newZapLogger(zap.ErrorLevel)
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
if m := logger.Check(zap.InfoLevel, getMessage(0)); m != nil {
m.Write(fakeFields()...)
}
}
})
})
b.Run("Zap.Sugar", func(b *testing.B) {
logger := newZapLogger(zap.ErrorLevel).Sugar()
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
logger.Infow(getMessage(0), fakeSugarFields()...)
}
})
})
b.Run("apex/log", func(b *testing.B) {
logger := newDisabledApexLog()
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
logger.WithFields(fakeApexFields()).Info(getMessage(0))
}
})
})
b.Run("sirupsen/logrus", func(b *testing.B) {
logger := newDisabledLogrus()
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
logger.WithFields(fakeLogrusFields()).Info(getMessage(0))
}
})
})
b.Run("rs/zerolog", func(b *testing.B) {
logger := newDisabledZerolog()
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
fakeZerologFields(logger.Info()).Msg(getMessage(0))
}
})
})
b.Run("slog", func(b *testing.B) {
logger := newDisabledSlog()
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
logger.Info(getMessage(0), fakeSlogArgs()...)
}
})
})
b.Run("slog.LogAttrs", func(b *testing.B) {
logger := newDisabledSlog()
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
logger.LogAttrs(context.Background(), slog.LevelInfo, getMessage(0), fakeSlogFields()...)
}
})
})
}
func BenchmarkWithoutFields(b *testing.B) {
b.Logf("Logging without any structured context.")
b.Run("Zap", func(b *testing.B) {
logger := newZapLogger(zap.DebugLevel)
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
logger.Info(getMessage(0))
}
})
})
b.Run("Zap.Check", func(b *testing.B) {
logger := newZapLogger(zap.DebugLevel)
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
if ce := logger.Check(zap.InfoLevel, getMessage(0)); ce != nil {
ce.Write()
}
}
})
})
b.Run("Zap.CheckSampled", func(b *testing.B) {
logger := newSampledLogger(zap.DebugLevel)
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
i := 0
for pb.Next() {
i++
if ce := logger.Check(zap.InfoLevel, getMessage(i)); ce != nil {
ce.Write()
}
}
})
})
b.Run("Zap.Sugar", func(b *testing.B) {
logger := newZapLogger(zap.DebugLevel).Sugar()
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
logger.Info(getMessage(0))
}
})
})
b.Run("Zap.SugarFormatting", func(b *testing.B) {
logger := newZapLogger(zap.DebugLevel).Sugar()
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
logger.Infof("%v %v %v %s %v %v %v %v %v %s\n", fakeFmtArgs()...)
}
})
})
b.Run("apex/log", func(b *testing.B) {
logger := newApexLog()
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
logger.Info(getMessage(0))
}
})
})
b.Run("go-kit/kit/log", func(b *testing.B) {
logger := newKitLog()
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
if err := logger.Log(getMessage(0), getMessage(1)); err != nil {
b.Fatal(err)
}
}
})
})
b.Run("inconshreveable/log15", func(b *testing.B) {
logger := newLog15()
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
logger.Info(getMessage(0))
}
})
})
b.Run("sirupsen/logrus", func(b *testing.B) {
logger := newLogrus()
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
logger.Info(getMessage(0))
}
})
})
b.Run("stdlib.Println", func(b *testing.B) {
logger := log.New(&ztest.Discarder{}, "", log.LstdFlags)
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
logger.Println(getMessage(0))
}
})
})
b.Run("stdlib.Printf", func(b *testing.B) {
logger := log.New(&ztest.Discarder{}, "", log.LstdFlags)
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
logger.Printf("%v %v %v %s %v %v %v %v %v %s\n", fakeFmtArgs()...)
}
})
})
b.Run("rs/zerolog", func(b *testing.B) {
logger := newZerolog()
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
logger.Info().Msg(getMessage(0))
}
})
})
b.Run("rs/zerolog.Formatting", func(b *testing.B) {
logger := newZerolog()
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
logger.Info().Msgf("%v %v %v %s %v %v %v %v %v %s\n", fakeFmtArgs()...)
}
})
})
b.Run("rs/zerolog.Check", func(b *testing.B) {
logger := newZerolog()
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
if e := logger.Info(); e.Enabled() {
e.Msg(getMessage(0))
}
}
})
})
b.Run("slog", func(b *testing.B) {
logger := newSlog()
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
logger.Info(getMessage(0))
}
})
})
b.Run("slog.LogAttrs", func(b *testing.B) {
logger := newSlog()
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
logger.LogAttrs(context.Background(), slog.LevelInfo, getMessage(0))
}
})
})
}
func BenchmarkAccumulatedContext(b *testing.B) {
b.Logf("Logging with some accumulated context.")
b.Run("Zap", func(b *testing.B) {
logger := newZapLogger(zap.DebugLevel).With(fakeFields()...)
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
logger.Info(getMessage(0))
}
})
})
b.Run("Zap.Check", func(b *testing.B) {
logger := newZapLogger(zap.DebugLevel).With(fakeFields()...)
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
if ce := logger.Check(zap.InfoLevel, getMessage(0)); ce != nil {
ce.Write()
}
}
})
})
b.Run("Zap.CheckSampled", func(b *testing.B) {
logger := newSampledLogger(zap.DebugLevel).With(fakeFields()...)
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
i := 0
for pb.Next() {
i++
if ce := logger.Check(zap.InfoLevel, getMessage(i)); ce != nil {
ce.Write()
}
}
})
})
b.Run("Zap.Sugar", func(b *testing.B) {
logger := newZapLogger(zap.DebugLevel).With(fakeFields()...).Sugar()
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
logger.Info(getMessage(0))
}
})
})
b.Run("Zap.SugarFormatting", func(b *testing.B) {
logger := newZapLogger(zap.DebugLevel).With(fakeFields()...).Sugar()
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
logger.Infof("%v %v %v %s %v %v %v %v %v %s\n", fakeFmtArgs()...)
}
})
})
b.Run("apex/log", func(b *testing.B) {
logger := newApexLog().WithFields(fakeApexFields())
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
logger.Info(getMessage(0))
}
})
})
b.Run("go-kit/kit/log", func(b *testing.B) {
logger := newKitLog(fakeSugarFields()...)
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
if err := logger.Log(getMessage(0), getMessage(1)); err != nil {
b.Fatal(err)
}
}
})
})
b.Run("inconshreveable/log15", func(b *testing.B) {
logger := newLog15().New(fakeSugarFields())
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
logger.Info(getMessage(0))
}
})
})
b.Run("sirupsen/logrus", func(b *testing.B) {
logger := newLogrus().WithFields(fakeLogrusFields())
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
logger.Info(getMessage(0))
}
})
})
b.Run("rs/zerolog", func(b *testing.B) {
logger := fakeZerologContext(newZerolog().With()).Logger()
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
logger.Info().Msg(getMessage(0))
}
})
})
b.Run("rs/zerolog.Check", func(b *testing.B) {
logger := fakeZerologContext(newZerolog().With()).Logger()
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
if e := logger.Info(); e.Enabled() {
e.Msg(getMessage(0))
}
}
})
})
b.Run("rs/zerolog.Formatting", func(b *testing.B) {
logger := fakeZerologContext(newZerolog().With()).Logger()
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
logger.Info().Msgf("%v %v %v %s %v %v %v %v %v %s\n", fakeFmtArgs()...)
}
})
})
b.Run("slog", func(b *testing.B) {
logger := newSlog(fakeSlogFields()...)
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
logger.Info(getMessage(0))
}
})
})
b.Run("slog.LogAttrs", func(b *testing.B) {
logger := newSlog(fakeSlogFields()...)
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
logger.LogAttrs(context.Background(), slog.LevelInfo, getMessage(0))
}
})
})
}
func BenchmarkAddingFields(b *testing.B) {
b.Logf("Logging with additional context at each log site.")
b.Run("Zap", func(b *testing.B) {
logger := newZapLogger(zap.DebugLevel)
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
logger.Info(getMessage(0), fakeFields()...)
}
})
})
b.Run("Zap.Check", func(b *testing.B) {
logger := newZapLogger(zap.DebugLevel)
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
if ce := logger.Check(zap.InfoLevel, getMessage(0)); ce != nil {
ce.Write(fakeFields()...)
}
}
})
})
b.Run("Zap.CheckSampled", func(b *testing.B) {
logger := newSampledLogger(zap.DebugLevel)
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
i := 0
for pb.Next() {
i++
if ce := logger.Check(zap.InfoLevel, getMessage(i)); ce != nil {
ce.Write(fakeFields()...)
}
}
})
})
b.Run("Zap.Sugar", func(b *testing.B) {
logger := newZapLogger(zap.DebugLevel).Sugar()
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
logger.Infow(getMessage(0), fakeSugarFields()...)
}
})
})
b.Run("apex/log", func(b *testing.B) {
logger := newApexLog()
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
logger.WithFields(fakeApexFields()).Info(getMessage(0))
}
})
})
b.Run("go-kit/kit/log", func(b *testing.B) {
logger := newKitLog()
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
if err := logger.Log(fakeSugarFields()...); err != nil {
b.Fatal(err)
}
}
})
})
b.Run("inconshreveable/log15", func(b *testing.B) {
logger := newLog15()
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
logger.Info(getMessage(0), fakeSugarFields()...)
}
})
})
b.Run("sirupsen/logrus", func(b *testing.B) {
logger := newLogrus()
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
logger.WithFields(fakeLogrusFields()).Info(getMessage(0))
}
})
})
b.Run("rs/zerolog", func(b *testing.B) {
logger := newZerolog()
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
fakeZerologFields(logger.Info()).Msg(getMessage(0))
}
})
})
b.Run("rs/zerolog.Check", func(b *testing.B) {
logger := newZerolog()
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
if e := logger.Info(); e.Enabled() {
fakeZerologFields(e).Msg(getMessage(0))
}
}
})
})
b.Run("slog", func(b *testing.B) {
logger := newSlog()
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
logger.Info(getMessage(0), fakeSlogArgs()...)
}
})
})
b.Run("slog.LogAttrs", func(b *testing.B) {
logger := newSlog()
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
logger.LogAttrs(context.Background(), slog.LevelInfo, getMessage(0), fakeSlogFields()...)
}
})
})
}
================================================
FILE: benchmarks/slog_test.go
================================================
// 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 benchmarks
import (
"io"
"log/slog"
)
func newSlog(fields ...slog.Attr) *slog.Logger {
return slog.New(slog.NewJSONHandler(io.Discard, nil).WithAttrs(fields))
}
func newDisabledSlog(fields ...slog.Attr) *slog.Logger {
return slog.New(slog.NewJSONHandler(io.Discard, &slog.HandlerOptions{Level: slog.LevelError}).WithAttrs(fields))
}
func fakeSlogFields() []slog.Attr {
return []slog.Attr{
slog.Int("int", _tenInts[0]),
slog.Any("ints", _tenInts),
slog.String("string", _tenStrings[0]),
slog.Any("strings", _tenStrings),
slog.Time("time", _tenTimes[0]),
slog.Any("times", _tenTimes),
slog.Any("user1", _oneUser),
slog.Any("user2", _oneUser),
slog.Any("users", _tenUsers),
slog.Any("error", errExample),
}
}
func fakeSlogArgs() []any {
return []any{
"int", _tenInts[0],
"ints", _tenInts,
"string", _tenStrings[0],
"strings", _tenStrings,
"time", _tenTimes[0],
"times", _tenTimes,
"user1", _oneUser,
"user2", _oneUser,
"users", _tenUsers,
"error", errExample,
}
}
================================================
FILE: benchmarks/zap_test.go
================================================
// 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 benchmarks
import (
"errors"
"fmt"
"time"
"go.uber.org/multierr"
"go.uber.org/zap"
"go.uber.org/zap/internal/ztest"
"go.uber.org/zap/zapcore"
)
var (
errExample = errors.New("fail")
_messages = fakeMessages(1000)
_tenInts = []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 0}
_tenStrings = []string{"a", "b", "c", "d", "e", "f", "g", "h", "i", "j"}
_tenTimes = []time.Time{
time.Unix(0, 0),
time.Unix(1, 0),
time.Unix(2, 0),
time.Unix(3, 0),
time.Unix(4, 0),
time.Unix(5, 0),
time.Unix(6, 0),
time.Unix(7, 0),
time.Unix(8, 0),
time.Unix(9, 0),
}
_oneUser = &user{
Name: "Jane Doe",
Email: "jane@test.com",
CreatedAt: time.Date(1980, 1, 1, 12, 0, 0, 0, time.UTC),
}
_tenUsers = users{
_oneUser,
_oneUser,
_oneUser,
_oneUser,
_oneUser,
_oneUser,
_oneUser,
_oneUser,
_oneUser,
_oneUser,
}
)
func fakeMessages(n int) []string {
messages := make([]string, n)
for i := range messages {
messages[i] = fmt.Sprintf("Test logging, but use a somewhat realistic message length. (#%v)", i)
}
return messages
}
func getMessage(iter int) string {
return _messages[iter%1000]
}
type users []*user
func (uu users) MarshalLogArray(arr zapcore.ArrayEncoder) error {
var err error
for i := range uu {
err = multierr.Append(err, arr.AppendObject(uu[i]))
}
return err
}
type user struct {
Name string `json:"name"`
Email string `json:"email"`
CreatedAt time.Time `json:"created_at"`
}
func (u *user) MarshalLogObject(enc zapcore.ObjectEncoder) error {
enc.AddString("name", u.Name)
enc.AddString("email", u.Email)
enc.AddInt64("createdAt", u.CreatedAt.UnixNano())
return nil
}
func newZapLogger(lvl zapcore.Level) *zap.Logger {
ec := zap.NewProductionEncoderConfig()
ec.EncodeDuration = zapcore.NanosDurationEncoder
ec.EncodeTime = zapcore.EpochNanosTimeEncoder
enc := zapcore.NewJSONEncoder(ec)
return zap.New(zapcore.NewCore(
enc,
&ztest.Discarder{},
lvl,
))
}
func newSampledLogger(lvl zapcore.Level) *zap.Logger {
return zap.New(zapcore.NewSamplerWithOptions(
newZapLogger(zap.DebugLevel).Core(),
100*time.Millisecond,
10, // first
10, // thereafter
))
}
func fakeFields() []zap.Field {
return []zap.Field{
zap.Int("int", _tenInts[0]),
zap.Ints("ints", _tenInts),
zap.String("string", _tenStrings[0]),
zap.Strings("strings", _tenStrings),
zap.Time("time", _tenTimes[0]),
zap.Times("times", _tenTimes),
zap.Object("user1", _oneUser),
zap.Object("user2", _oneUser),
zap.Object("user3", nil),
zap.Array("users", _tenUsers),
zap.Error(errExample),
}
}
func fakeSugarFields() []interface{} {
return []interface{}{
"int", _tenInts[0],
"ints", _tenInts,
"string", _tenStrings[0],
"strings", _tenStrings,
"time", _tenTimes[0],
"times", _tenTimes,
"user1", _oneUser,
"user2", _oneUser,
"users", _tenUsers,
"error", errExample,
}
}
func fakeFmtArgs() []interface{} {
// Need to keep this a function instead of a package-global var so that we
// pay the cast-to-interface{} penalty on each call.
return []interface{}{
_tenInts[0],
_tenInts,
_tenStrings[0],
_tenStrings,
_tenTimes[0],
_tenTimes,
_oneUser,
_oneUser,
_tenUsers,
errExample,
}
}
================================================
FILE: benchmarks/zerolog_test.go
================================================
// 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 benchmarks
import (
"io"
"github.com/rs/zerolog"
)
func newZerolog() zerolog.Logger {
return zerolog.New(io.Discard).With().Timestamp().Logger()
}
func newDisabledZerolog() zerolog.Logger {
return newZerolog().Level(zerolog.Disabled)
}
func (u *user) MarshalZerologObject(e *zerolog.Event) {
e.Str("name", u.Name).
Str("email", u.Email).
Int64("createdAt", u.CreatedAt.UnixNano())
}
func (uu users) MarshalZerologArray(a *zerolog.Array) {
for _, u := range uu {
a.Object(u)
}
}
func fakeZerologFields(e *zerolog.Event) *zerolog.Event {
return e.
Int("int", _tenInts[0]).
Ints("ints", _tenInts).
Str("string", _tenStrings[0]).
Strs("strings", _tenStrings).
Time("time", _tenTimes[0]).
Times("times", _tenTimes).
Object("user1", _oneUser).
Object("user2", _oneUser).
Array("users", _tenUsers).
Err(errExample)
}
func fakeZerologContext(c zerolog.Context) zerolog.Context {
return c.
Int("int", _tenInts[0]).
Ints("ints", _tenInts).
Str("string", _tenStrings[0]).
Strs("strings", _tenStrings).
Time("time", _tenTimes[0]).
Times("times", _tenTimes).
Object("user1", _oneUser).
Object("user2", _oneUser).
Array("users", _tenUsers).
Err(errExample)
}
================================================
FILE: buffer/buffer.go
================================================
// 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)
}
// AppendBytes writes the given slice of bytes to the Buffer.
func (b *Buffer) AppendBytes(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)
}
================================================
FILE: buffer/buffer_test.go
================================================
// 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 (
"bytes"
"strings"
"testing"
"time"
"github.com/stretchr/testify/assert"
)
func TestBufferWrites(t *testing.T) {
buf := NewPool().Get()
tests := []struct {
desc string
f func()
want string
}{
{"AppendByte", func() { buf.AppendByte('v') }, "v"},
{"AppendString", func() { buf.AppendString("foo") }, "foo"},
{"AppendIntPositive", func() { buf.AppendInt(42) }, "42"},
{"AppendIntNegative", func() { buf.AppendInt(-42) }, "-42"},
{"AppendUint", func() { buf.AppendUint(42) }, "42"},
{"AppendBool", func() { buf.AppendBool(true) }, "true"},
{"AppendFloat64", func() { buf.AppendFloat(3.14, 64) }, "3.14"},
// Intentionally introduce some floating-point error.
{"AppendFloat32", func() { buf.AppendFloat(float64(float32(3.14)), 32) }, "3.14"},
{"AppendWrite", func() { buf.Write([]byte("foo")) }, "foo"},
{"AppendTime", func() { buf.AppendTime(time.Date(2000, 1, 2, 3, 4, 5, 6, time.UTC), time.RFC3339) }, "2000-01-02T03:04:05Z"},
{"WriteByte", func() { buf.WriteByte('v') }, "v"},
{"WriteString", func() { buf.WriteString("foo") }, "foo"},
}
for _, tt := range tests {
t.Run(tt.desc, func(t *testing.T) {
buf.Reset()
tt.f()
assert.Equal(t, tt.want, buf.String(), "Unexpected buffer.String().")
assert.Equal(t, tt.want, string(buf.Bytes()), "Unexpected string(buffer.Bytes()).")
assert.Equal(t, len(tt.want), buf.Len(), "Unexpected buffer length.")
// We're not writing more than a kibibyte in tests.
assert.Equal(t, _size, buf.Cap(), "Expected buffer capacity to remain constant.")
})
}
}
func BenchmarkBuffers(b *testing.B) {
// Because we use the strconv.AppendFoo functions so liberally, we can't
// use the standard library's bytes.Buffer anyways (without incurring a
// bunch of extra allocations). Nevertheless, let's make sure that we're
// not losing any precious nanoseconds.
str := strings.Repeat("a", 1024)
slice := make([]byte, 0, 1024)
buf := bytes.NewBuffer(slice)
custom := NewPool().Get()
b.Run("ByteSlice", func(b *testing.B) {
for i := 0; i < b.N; i++ {
slice = append(slice, str...)
slice = slice[:0]
}
})
b.Run("BytesBuffer", func(b *testing.B) {
for i := 0; i < b.N; i++ {
buf.WriteString(str)
buf.Reset()
}
})
b.Run("CustomBuffer", func(b *testing.B) {
for i := 0; i < b.N; i++ {
custom.AppendString(str)
custom.Reset()
}
})
}
================================================
FILE: buffer/pool.go
================================================
// 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 (
"go.uber.org/zap/internal/pool"
)
// A Pool is a type-safe wrapper around a sync.Pool.
type Pool struct {
p *pool.Pool[*Buffer]
}
// NewPool constructs a new Pool.
func NewPool() Pool {
return Pool{
p: pool.New(func() *Buffer {
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()
buf.Reset()
buf.pool = p
return buf
}
func (p Pool) put(buf *Buffer) {
p.p.Put(buf)
}
================================================
FILE: buffer/pool_test.go
================================================
// 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"
"testing"
"github.com/stretchr/testify/assert"
)
func TestBuffers(t *testing.T) {
const dummyData = "dummy data"
p := NewPool()
var wg sync.WaitGroup
for g := 0; g < 10; g++ {
wg.Add(1)
go func() {
for i := 0; i < 100; i++ {
buf := p.Get()
assert.Zero(t, buf.Len(), "Expected truncated buffer")
assert.NotZero(t, buf.Cap(), "Expected non-zero capacity")
buf.AppendString(dummyData)
assert.Equal(t, buf.Len(), len(dummyData), "Expected buffer to contain dummy data")
buf.Free()
}
wg.Done()
}()
}
wg.Wait()
}
================================================
FILE: checklicense.sh
================================================
#!/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
================================================
FILE: clock_test.go
================================================
// 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 zap
import (
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.uber.org/zap/zaptest/observer"
)
type constantClock time.Time
func (c constantClock) Now() time.Time { return time.Time(c) }
func (c constantClock) NewTicker(d time.Duration) *time.Ticker {
return &time.Ticker{}
}
func TestWithClock(t *testing.T) {
date := time.Date(2077, 1, 23, 10, 15, 13, 441, time.UTC)
clock := constantClock(date)
withLogger(t, DebugLevel, []Option{WithClock(clock)}, func(log *Logger, logs *observer.ObservedLogs) {
log.Info("")
require.Equal(t, 1, logs.Len(), "Expected only one log entry to be written.")
assert.Equal(t, date, logs.All()[0].Time, "Unexpected entry time.")
})
}
================================================
FILE: common_test.go
================================================
// 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 (
"sync"
"testing"
"go.uber.org/zap/zapcore"
"go.uber.org/zap/zaptest/observer"
)
func opts(opts ...Option) []Option {
return opts
}
// Here specifically to introduce an easily-identifiable filename for testing
// stacktraces and caller skips.
func withLogger(t testing.TB, e zapcore.LevelEnabler, opts []Option, f func(*Logger, *observer.ObservedLogs)) {
fac, logs := observer.New(e)
log := New(fac, opts...)
f(log, logs)
}
func withSugar(t testing.TB, e zapcore.LevelEnabler, opts []Option, f func(*SugaredLogger, *observer.ObservedLogs)) {
withLogger(t, e, opts, func(logger *Logger, logs *observer.ObservedLogs) { f(logger.Sugar(), logs) })
}
func runConcurrently(goroutines, iterations int, wg *sync.WaitGroup, f func()) {
wg.Add(goroutines)
for g := 0; g < goroutines; g++ {
go func() {
defer wg.Done()
for i := 0; i < iterations; i++ {
f()
}
}()
}
}
================================================
FILE: config.go
================================================
// 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.
//
// Messages encoded with this configuration will be JSON-formatted
// and will have the following keys by default:
//
// - "level": The logging level (e.g. "info", "error").
// - "ts": The current time in number of seconds since the Unix epoch.
// - "msg": The message passed to the log statement.
// - "caller": If available, a short path to the file and line number
// where the log statement was issued.
// The logger configuration determines whether this field is captured.
// - "stacktrace": If available, a stack trace from the line
// where the log statement was issued.
// The logger configuration determines whether this field is captured.
//
// By default, the following formats are used for different types:
//
// - Time is formatted as floating-point number of seconds since the Unix
// epoch.
// - Duration is formatted as floating-point number of seconds.
//
// You may change these by setting the appropriate fields in the returned
// object.
// For example, use the following to change the time encoding format:
//
// cfg := zap.NewProductionEncoderConfig()
// cfg.EncodeTime = zapcore.ISO8601TimeEncoder
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 builds a reasonable default production logging
// configuration.
// Logging is enabled at InfoLevel and above, and uses a JSON encoder.
// Logs are written to standard error.
// Stacktraces are included on logs of ErrorLevel and above.
// DPanicLevel logs will not panic, but will write a stacktrace.
//
// Sampling is enabled at 100:100 by default,
// meaning that after the first 100 log entries
// with the same level and message in the same second,
// it will log every 100th entry
// with the same level and message in the same second.
// You may disable this behavior by setting Sampling to nil.
//
// See [NewProductionEncoderConfig] for information
// on the default encoder configuration.
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.
//
// Messages encoded with this configuration will use Zap's console encoder
// intended to print human-readable output.
// It will print log messages with the following information:
//
// - The log level (e.g. "INFO", "ERROR").
// - The time in ISO8601 format (e.g. "2017-01-01T12:00:00Z").
// - The message passed to the log statement.
// - If available, a short path to the file and line number
// where the log statement was issued.
// The logger configuration determines whether this field is captured.
// - If available, a stacktrace from the line
// where the log statement was issued.
// The logger configuration determines whether this field is captured.
//
// By default, the following formats are used for different types:
//
// - Time is formatted in ISO8601 format (e.g. "2017-01-01T12:00:00Z").
// - Duration is formatted as a string (e.g. "1.234s").
//
// You may change these by setting the appropriate fields in the returned
// object.
// For example, use the following to change the time encoding format:
//
// cfg := zap.NewDevelopmentEncoderConfig()
// cfg.EncodeTime = zapcore.ISO8601TimeEncoder
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 builds a reasonable default development logging
// configuration.
// Logging is enabled at DebugLevel and above, and uses a console encoder.
// Logs are written to standard error.
// Stacktraces are included on logs of WarnLevel and above.
// DPanicLevel logs will panic.
//
// See [NewDevelopmentEncoderConfig] for information
// on the default encoder configuration.
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)
}
================================================
FILE: config_test.go
================================================
// 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 (
"os"
"path/filepath"
"sync/atomic"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.uber.org/zap/zapcore"
)
func TestConfig(t *testing.T) {
tests := []struct {
desc string
cfg Config
expectN int64
expectRe string
}{
{
desc: "production",
cfg: NewProductionConfig(),
expectN: 2 + 100 + 1, // 2 from initial logs, 100 initial sampled logs, 1 from off-by-one in sampler
expectRe: `{"level":"info","caller":"[a-z0-9_-]+/config_test.go:\d+","msg":"info","k":"v","z":"zz"}` + "\n" +
`{"level":"warn","caller":"[a-z0-9_-]+/config_test.go:\d+","msg":"warn","k":"v","z":"zz"}` + "\n",
},
{
desc: "development",
cfg: NewDevelopmentConfig(),
expectN: 3 + 200, // 3 initial logs, all 200 subsequent logs
expectRe: "DEBUG\t[a-z0-9_-]+/config_test.go:" + `\d+` + "\tdebug\t" + `{"k": "v", "z": "zz"}` + "\n" +
"INFO\t[a-z0-9_-]+/config_test.go:" + `\d+` + "\tinfo\t" + `{"k": "v", "z": "zz"}` + "\n" +
"WARN\t[a-z0-9_-]+/config_test.go:" + `\d+` + "\twarn\t" + `{"k": "v", "z": "zz"}` + "\n" +
`go.uber.org/zap.TestConfig.\w+`,
},
}
for _, tt := range tests {
t.Run(tt.desc, func(t *testing.T) {
logOut := filepath.Join(t.TempDir(), "test.log")
tt.cfg.OutputPaths = []string{logOut}
tt.cfg.EncoderConfig.TimeKey = "" // no timestamps in tests
tt.cfg.InitialFields = map[string]interface{}{"z": "zz", "k": "v"}
hook, count := makeCountingHook()
logger, err := tt.cfg.Build(Hooks(hook))
require.NoError(t, err, "Unexpected error constructing logger.")
logger.Debug("debug")
logger.Info("info")
logger.Warn("warn")
byteContents, err := os.ReadFile(logOut)
require.NoError(t, err, "Couldn't read log contents from temp file.")
logs := string(byteContents)
assert.Regexp(t, tt.expectRe, logs, "Unexpected log output.")
for i := 0; i < 200; i++ {
logger.Info("sampling")
}
assert.Equal(t, tt.expectN, count.Load(), "Hook called an unexpected number of times.")
})
}
}
func TestConfigWithInvalidPaths(t *testing.T) {
tests := []struct {
desc string
output string
errOutput string
}{
{"output directory doesn't exist", "/tmp/not-there/foo.log", "stderr"},
{"error output directory doesn't exist", "stdout", "/tmp/not-there/foo-errors.log"},
{"neither output directory exists", "/tmp/not-there/foo.log", "/tmp/not-there/foo-errors.log"},
}
for _, tt := range tests {
t.Run(tt.desc, func(t *testing.T) {
cfg := NewProductionConfig()
cfg.OutputPaths = []string{tt.output}
cfg.ErrorOutputPaths = []string{tt.errOutput}
_, err := cfg.Build()
assert.Error(t, err, "Expected an error opening a non-existent directory.")
})
}
}
func TestConfigWithMissingAttributes(t *testing.T) {
tests := []struct {
desc string
cfg Config
expectErr string
}{
{
desc: "missing level",
cfg: Config{
Encoding: "json",
},
expectErr: "missing Level",
},
{
desc: "missing encoder time in encoder config",
cfg: Config{
Level: NewAtomicLevelAt(zapcore.InfoLevel),
Encoding: "json",
EncoderConfig: zapcore.EncoderConfig{
MessageKey: "msg",
TimeKey: "ts",
},
},
expectErr: "missing EncodeTime in EncoderConfig",
},
}
for _, tt := range tests {
t.Run(tt.desc, func(t *testing.T) {
cfg := tt.cfg
_, err := cfg.Build()
assert.EqualError(t, err, tt.expectErr)
})
}
}
func makeSamplerCountingHook() (h func(zapcore.Entry, zapcore.SamplingDecision),
dropped, sampled *atomic.Int64,
) {
dropped = new(atomic.Int64)
sampled = new(atomic.Int64)
h = func(_ zapcore.Entry, dec zapcore.SamplingDecision) {
if dec&zapcore.LogDropped > 0 {
dropped.Add(1)
} else if dec&zapcore.LogSampled > 0 {
sampled.Add(1)
}
}
return h, dropped, sampled
}
func TestConfigWithSamplingHook(t *testing.T) {
shook, dcount, scount := makeSamplerCountingHook()
cfg := Config{
Level: NewAtomicLevelAt(InfoLevel),
Development: false,
Sampling: &SamplingConfig{
Initial: 100,
Thereafter: 100,
Hook: shook,
},
Encoding: "json",
EncoderConfig: NewProductionEncoderConfig(),
OutputPaths: []string{"stderr"},
ErrorOutputPaths: []string{"stderr"},
}
expectRe := `{"level":"info","caller":"[a-z0-9_-]+/config_test.go:\d+","msg":"info","k":"v","z":"zz"}` + "\n" +
`{"level":"warn","caller":"[a-z0-9_-]+/config_test.go:\d+","msg":"warn","k":"v","z":"zz"}` + "\n"
expectDropped := 99 // 200 - 100 initial - 1 thereafter
expectSampled := 103 // 2 from initial + 100 + 1 thereafter
logOut := filepath.Join(t.TempDir(), "test.log")
cfg.OutputPaths = []string{logOut}
cfg.EncoderConfig.TimeKey = "" // no timestamps in tests
cfg.InitialFields = map[string]interface{}{"z": "zz", "k": "v"}
logger, err := cfg.Build()
require.NoError(t, err, "Unexpected error constructing logger.")
logger.Debug("debug")
logger.Info("info")
logger.Warn("warn")
byteContents, err := os.ReadFile(logOut)
require.NoError(t, err, "Couldn't read log contents from temp file.")
logs := string(byteContents)
assert.Regexp(t, expectRe, logs, "Unexpected log output.")
for i := 0; i < 200; i++ {
logger.Info("sampling")
}
assert.Equal(t, int64(expectDropped), dcount.Load())
assert.Equal(t, int64(expectSampled), scount.Load())
}
================================================
FILE: doc.go
================================================
// 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"
================================================
FILE: encoder.go
================================================
// 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)
}
================================================
FILE: encoder_test.go
================================================
// 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 (
"testing"
"go.uber.org/zap/zapcore"
"github.com/stretchr/testify/assert"
)
func TestRegisterDefaultEncoders(t *testing.T) {
testEncodersRegistered(t, "console", "json")
}
func TestRegisterEncoder(t *testing.T) {
testEncoders(func() {
assert.NoError(t, RegisterEncoder("foo", newNilEncoder), "expected to be able to register the encoder foo")
testEncodersRegistered(t, "foo")
})
}
func TestDuplicateRegisterEncoder(t *testing.T) {
testEncoders(func() {
assert.NoError(t, RegisterEncoder("foo", newNilEncoder), "expected to be able to register the encoder foo")
assert.Error(t, RegisterEncoder("foo", newNilEncoder), "expected an error when registering an encoder with the same name twice")
})
}
func TestRegisterEncoderNoName(t *testing.T) {
assert.Equal(t, errNoEncoderNameSpecified, RegisterEncoder("", newNilEncoder), "expected an error when registering an encoder with no name")
}
func TestNewEncoder(t *testing.T) {
testEncoders(func() {
assert.NoError(t, RegisterEncoder("foo", newNilEncoder), "expected to be able to register the encoder foo")
encoder, err := newEncoder("foo", zapcore.EncoderConfig{})
assert.NoError(t, err, "could not create an encoder for the registered name foo")
assert.Nil(t, encoder, "the encoder from newNilEncoder is not nil")
})
}
func TestNewEncoderNotRegistered(t *testing.T) {
_, err := newEncoder("foo", zapcore.EncoderConfig{})
assert.Error(t, err, "expected an error when trying to create an encoder of an unregistered name")
}
func TestNewEncoderNoName(t *testing.T) {
_, err := newEncoder("", zapcore.EncoderConfig{})
assert.Equal(t, errNoEncoderNameSpecified, err, "expected an error when creating an encoder with no name")
}
func testEncoders(f func()) {
existing := _encoderNameToConstructor
_encoderNameToConstructor = make(map[string]func(zapcore.EncoderConfig) (zapcore.Encoder, error))
defer func() { _encoderNameToConstructor = existing }()
f()
}
func testEncodersRegistered(t *testing.T, names ...string) {
assert.Len(t, _encoderNameToConstructor, len(names), "the expected number of registered encoders does not match the actual number")
for _, name := range names {
assert.NotNil(t, _encoderNameToConstructor[name], "no encoder is registered for name %s", name)
}
}
func newNilEncoder(_ zapcore.EncoderConfig) (zapcore.Encoder, error) {
return nil, nil
}
================================================
FILE: error.go
================================================
// 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 (
"go.uber.org/zap/internal/pool"
"go.uber.org/zap/zapcore"
)
var _errArrayElemPool = pool.New(func() *errArrayElem {
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()
elem.error = errs[i]
err := arr.AppendObject(elem)
elem.error = nil
_errArrayElemPool.Put(elem)
if err != nil {
return err
}
}
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
}
================================================
FILE: error_test.go
================================================
// 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 (
"errors"
"fmt"
"testing"
"go.uber.org/zap/zapcore"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestErrorConstructors(t *testing.T) {
fail := errors.New("fail")
tests := []struct {
name string
field Field
expect Field
}{
{"Error", Skip(), Error(nil)},
{"Error", Field{Key: "error", Type: zapcore.ErrorType, Interface: fail}, Error(fail)},
{"NamedError", Skip(), NamedError("foo", nil)},
{"NamedError", Field{Key: "foo", Type: zapcore.ErrorType, Interface: fail}, NamedError("foo", fail)},
{"Any:Error", Any("k", errors.New("v")), NamedError("k", errors.New("v"))},
{"Any:Errors", Any("k", []error{errors.New("v")}), Errors("k", []error{errors.New("v")})},
}
for _, tt := range tests {
if !assert.Equal(t, tt.expect, tt.field, "Unexpected output from convenience field constructor %s.", tt.name) {
t.Logf("type expected: %T\nGot: %T", tt.expect.Interface, tt.field.Interface)
}
assertCanBeReused(t, tt.field)
}
}
func TestErrorArrayConstructor(t *testing.T) {
tests := []struct {
desc string
field Field
expected []interface{}
}{
{"empty errors", Errors("", []error{}), []interface{}{}},
{
"errors",
Errors("", []error{nil, errors.New("foo"), nil, errors.New("bar")}),
[]interface{}{map[string]interface{}{"error": "foo"}, map[string]interface{}{"error": "bar"}},
},
}
for _, tt := range tests {
enc := zapcore.NewMapObjectEncoder()
tt.field.Key = "k"
tt.field.AddTo(enc)
assert.Equal(t, tt.expected, enc.Fields["k"], "%s: unexpected map contents.", tt.desc)
assert.Equal(t, 1, len(enc.Fields), "%s: found extra keys in map: %v", tt.desc, enc.Fields)
}
}
func TestErrorsArraysHandleRichErrors(t *testing.T) {
errs := []error{fmt.Errorf("egad")}
enc := zapcore.NewMapObjectEncoder()
Errors("k", errs).AddTo(enc)
assert.Equal(t, 1, len(enc.Fields), "Expected only top-level field.")
val := enc.Fields["k"]
arr, ok := val.([]interface{})
require.True(t, ok, "Expected top-level field to be an array.")
require.Equal(t, 1, len(arr), "Expected only one error object in array.")
serialized := arr[0]
errMap, ok := serialized.(map[string]interface{})
require.True(t, ok, "Expected serialized error to be a map, got %T.", serialized)
assert.Equal(t, "egad", errMap["error"], "Unexpected standard error string.")
}
func TestErrArrayBrokenEncoder(t *testing.T) {
t.Parallel()
failWith := errors.New("great sadness")
err := (brokenArrayObjectEncoder{
Err: failWith,
ObjectEncoder: zapcore.NewMapObjectEncoder(),
}).AddArray("errors", errArray{
errors.New("foo"),
errors.New("bar"),
})
require.Error(t, err, "Expected error from broken encoder.")
assert.ErrorIs(t, err, failWith, "Unexpected error.")
}
// brokenArrayObjectEncoder is an ObjectEncoder
// that builds a broken ArrayEncoder.
type brokenArrayObjectEncoder struct {
zapcore.ObjectEncoder
zapcore.ArrayEncoder
Err error // error to return
}
func (enc brokenArrayObjectEncoder) AddArray(key string, marshaler zapcore.ArrayMarshaler) error {
return enc.ObjectEncoder.AddArray(key,
zapcore.ArrayMarshalerFunc(func(ae zapcore.ArrayEncoder) error {
enc.ArrayEncoder = ae
return marshaler.MarshalLogArray(enc)
}))
}
func (enc brokenArrayObjectEncoder) AppendObject(zapcore.ObjectMarshaler) error {
return enc.Err
}
================================================
FILE: example_test.go
================================================
// 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_test
import (
"encoding/json"
"io"
"log"
"os"
"time"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
)
func Example_presets() {
// Using zap's preset constructors is the simplest way to get a feel for the
// package, but they don't allow much customization.
logger := zap.NewExample() // or NewProduction, or NewDevelopment
defer logger.Sync()
const url = "http://example.com"
// In most circumstances, use the SugaredLogger. It's 4-10x faster than most
// other structured logging packages and has a familiar, loosely-typed API.
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)
// In the unusual situations where every microsecond matters, use the
// Logger. It's even faster than the SugaredLogger, but only supports
// structured logging.
logger.Info("Failed to fetch URL.",
// Structured context as strongly typed fields.
zap.String("url", url),
zap.Int("attempt", 3),
zap.Duration("backoff", time.Second),
)
// Output:
// {"level":"info","msg":"Failed to fetch URL.","url":"http://example.com","attempt":3,"backoff":"1s"}
// {"level":"info","msg":"Failed to fetch URL: http://example.com"}
// {"level":"info","msg":"Failed to fetch URL.","url":"http://example.com","attempt":3,"backoff":"1s"}
}
func Example_basicConfiguration() {
// For some users, the presets offered by the NewProduction, NewDevelopment,
// and NewExample constructors won't be appropriate. For most of those
// users, the bundled Config struct offers the right balance of flexibility
// and convenience. (For more complex needs, see the AdvancedConfiguration
// example.)
//
// See the documentation for Config and zapcore.EncoderConfig for all the
// available options.
rawJSON := []byte(`{
"level": "debug",
"encoding": "json",
"outputPaths": ["stdout", "/tmp/logs"],
"errorOutputPaths": ["stderr"],
"initialFields": {"foo": "bar"},
"encoderConfig": {
"messageKey": "message",
"levelKey": "level",
"levelEncoder": "lowercase"
}
}`)
var cfg zap.Config
if err := json.Unmarshal(rawJSON, &cfg); err != nil {
panic(err)
}
logger := zap.Must(cfg.Build())
defer logger.Sync()
logger.Info("logger construction succeeded")
// Output:
// {"level":"info","message":"logger construction succeeded","foo":"bar"}
}
func Example_advancedConfiguration() {
// The bundled Config struct only supports the most common configuration
// options. More complex needs, like splitting logs between multiple files
// or writing to non-file outputs, require use of the zapcore package.
//
// In this example, imagine we're both sending our logs to Kafka and writing
// them to the console. We'd like to encode the console output and the Kafka
// topics differently, and we'd also like special treatment for
// high-priority logs.
// First, define our level-handling logic.
highPriority := zap.LevelEnablerFunc(func(lvl zapcore.Level) bool {
return lvl >= zapcore.ErrorLevel
})
lowPriority := zap.LevelEnablerFunc(func(lvl zapcore.Level) bool {
return lvl < zapcore.ErrorLevel
})
// Assume that we have clients for two Kafka topics. The clients implement
// zapcore.WriteSyncer and are safe for concurrent use. (If they only
// implement io.Writer, we can use zapcore.AddSync to add a no-op Sync
// method. If they're not safe for concurrent use, we can add a protecting
// mutex with zapcore.Lock.)
topicDebugging := zapcore.AddSync(io.Discard)
topicErrors := zapcore.AddSync(io.Discard)
// High-priority output should also go to standard error, and low-priority
// output should also go to standard out.
consoleDebugging := zapcore.Lock(os.Stdout)
consoleErrors := zapcore.Lock(os.Stderr)
// Optimize the Kafka output for machine consumption and the console output
// for human operators.
kafkaEncoder := zapcore.NewJSONEncoder(zap.NewProductionEncoderConfig())
consoleEncoder := zapcore.NewConsoleEncoder(zap.NewDevelopmentEncoderConfig())
// Join the outputs, encoders, and level-handling functions into
// zapcore.Cores, then tee the four cores together.
core := zapcore.NewTee(
zapcore.NewCore(kafkaEncoder, topicErrors, highPriority),
zapcore.NewCore(consoleEncoder, consoleErrors, highPriority),
zapcore.NewCore(kafkaEncoder, topicDebugging, lowPriority),
zapcore.NewCore(consoleEncoder, consoleDebugging, lowPriority),
)
// From a zapcore.Core, it's easy to construct a Logger.
logger := zap.New(core)
defer logger.Sync()
logger.Info("constructed a logger")
}
func ExampleNamespace() {
logger := zap.NewExample()
defer logger.Sync()
logger.With(
zap.Namespace("metrics"),
zap.Int("counter", 1),
).Info("tracked some metrics")
// Output:
// {"level":"info","msg":"tracked some metrics","metrics":{"counter":1}}
}
type addr struct {
IP string
Port int
}
type request struct {
URL string
Listen addr
Remote addr
}
func (a addr) MarshalLogObject(enc zapcore.ObjectEncoder) error {
enc.AddString("ip", a.IP)
enc.AddInt("port", a.Port)
return nil
}
func (r *request) MarshalLogObject(enc zapcore.ObjectEncoder) error {
enc.AddString("url", r.URL)
zap.Inline(r.Listen).AddTo(enc)
return enc.AddObject("remote", r.Remote)
}
func ExampleObject() {
logger := zap.NewExample()
defer logger.Sync()
req := &request{
URL: "/test",
Listen: addr{"127.0.0.1", 8080},
Remote: addr{"127.0.0.1", 31200},
}
logger.Info("new request, in nested object", zap.Object("req", req))
logger.Info("new request, inline", zap.Inline(req))
// Output:
// {"level":"info","msg":"new request, in nested object","req":{"url":"/test","ip":"127.0.0.1","port":8080,"remote":{"ip":"127.0.0.1","port":31200}}}
// {"level":"info","msg":"new request, inline","url":"/test","ip":"127.0.0.1","port":8080,"remote":{"ip":"127.0.0.1","port":31200}}
}
func ExampleNewStdLog() {
logger := zap.NewExample()
defer logger.Sync()
std := zap.NewStdLog(logger)
std.Print("standard logger wrapper")
// Output:
// {"level":"info","msg":"standard logger wrapper"}
}
func ExampleRedirectStdLog() {
logger := zap.NewExample()
defer logger.Sync()
undo := zap.RedirectStdLog(logger)
defer undo()
log.Print("redirected standard library")
// Output:
// {"level":"info","msg":"redirected standard library"}
}
func ExampleReplaceGlobals() {
logger := zap.NewExample()
defer logger.Sync()
undo := zap.ReplaceGlobals(logger)
defer undo()
zap.L().Info("replaced zap's global loggers")
// Output:
// {"level":"info","msg":"replaced zap's global loggers"}
}
func ExampleAtomicLevel() {
atom := zap.NewAtomicLevel()
// To keep the example deterministic, disable timestamps in the output.
encoderCfg := zap.NewProductionEncoderConfig()
encoderCfg.TimeKey = ""
logger := zap.New(zapcore.NewCore(
zapcore.NewJSONEncoder(encoderCfg),
zapcore.Lock(os.Stdout),
atom,
))
defer logger.Sync()
logger.Info("info logging enabled")
atom.SetLevel(zap.ErrorLevel)
logger.Info("info logging disabled")
// Output:
// {"level":"info","msg":"info logging enabled"}
}
func ExampleAtomicLevel_config() {
// The zap.Config struct includes an AtomicLevel. To use it, keep a
// reference to the Config.
rawJSON := []byte(`{
"level": "info",
"outputPaths": ["stdout"],
"errorOutputPaths": ["stderr"],
"encoding": "json",
"encoderConfig": {
"messageKey": "message",
"levelKey": "level",
"levelEncoder": "lowercase"
}
}`)
var cfg zap.Config
if err := json.Unmarshal(rawJSON, &cfg); err != nil {
panic(err)
}
logger := zap.Must(cfg.Build())
defer logger.Sync()
logger.Info("info logging enabled")
cfg.Level.SetLevel(zap.ErrorLevel)
logger.Info("info logging disabled")
// Output:
// {"level":"info","message":"info logging enabled"}
}
func ExampleLogger_Check() {
logger := zap.NewExample()
defer logger.Sync()
if ce := logger.Check(zap.DebugLevel, "debugging"); ce != nil {
// If debug-level log output isn't enabled or if zap's sampling would have
// dropped this log entry, we don't allocate the slice that holds these
// fields.
ce.Write(
zap.String("foo", "bar"),
zap.String("baz", "quux"),
)
}
// Output:
// {"level":"debug","msg":"debugging","foo":"bar","baz":"quux"}
}
func ExampleLogger_Named() {
logger := zap.NewExample()
defer logger.Sync()
// By default, Loggers are unnamed.
logger.Info("no name")
// The first call to Named sets the Logger name.
main := logger.Named("main")
main.Info("main logger")
// Additional calls to Named create a period-separated path.
main.Named("subpackage").Info("sub-logger")
// Output:
// {"level":"info","msg":"no name"}
// {"level":"info","logger":"main","msg":"main logger"}
// {"level":"info","logger":"main.subpackage","msg":"sub-logger"}
}
func ExampleWrapCore_replace() {
// Replacing a Logger's core can alter fundamental behaviors.
// For example, it can convert a Logger to a no-op.
nop := zap.WrapCore(func(zapcore.Core) zapcore.Core {
return zapcore.NewNopCore()
})
logger := zap.NewExample()
defer logger.Sync()
logger.Info("working")
logger.WithOptions(nop).Info("no-op")
logger.Info("original logger still works")
// Output:
// {"level":"info","msg":"working"}
// {"level":"info","msg":"original logger still works"}
}
func ExampleWrapCore_wrap() {
// Wrapping a Logger's core can extend its functionality. As a trivial
// example, it can double-write all logs.
doubled := zap.WrapCore(func(c zapcore.Core) zapcore.Core {
return zapcore.NewTee(c, c)
})
logger := zap.NewExample()
defer logger.Sync()
logger.Info("single")
logger.WithOptions(doubled).Info("doubled")
// Output:
// {"level":"info","msg":"single"}
// {"level":"info","msg":"doubled"}
// {"level":"info","msg":"doubled"}
}
func ExampleDict() {
logger := zap.NewExample()
defer logger.Sync()
logger.Info("login event",
zap.Dict("event",
zap.Int("id", 123),
zap.String("name", "jane"),
zap.String("status", "pending")))
// Output:
// {"level":"info","msg":"login event","event":{"id":123,"name":"jane","status":"pending"}}
}
func ExampleObjects() {
logger := zap.NewExample()
defer logger.Sync()
// Use the Objects field constructor when you have a list of objects,
// all of which implement zapcore.ObjectMarshaler.
logger.Debug("opening connections",
zap.Objects("addrs", []addr{
{IP: "123.45.67.89", Port: 4040},
{IP: "127.0.0.1", Port: 4041},
{IP: "192.168.0.1", Port: 4042},
}))
// Output:
// {"level":"debug","msg":"opening connections","addrs":[{"ip":"123.45.67.89","port":4040},{"ip":"127.0.0.1","port":4041},{"ip":"192.168.0.1","port":4042}]}
}
func ExampleDictObject() {
logger := zap.NewExample()
defer logger.Sync()
// Use DictObject to create zapcore.ObjectMarshaler implementations from Field arrays,
// then use the Object and Objects field constructors to turn them back into a Field.
logger.Debug("worker received job",
zap.Object("w1",
zap.DictObject(
zap.Int("id", 402000),
zap.String("description", "compress image data"),
zap.Int("priority", 3),
),
))
d1 := 68 * time.Millisecond
d2 := 79 * time.Millisecond
d3 := 57 * time.Millisecond
logger.Info("worker status checks",
zap.Objects("job batch enqueued",
[]zapcore.ObjectMarshaler{
zap.DictObject(
zap.String("worker", "w1"),
zap.Int("load", 419),
zap.Duration("latency", d1),
),
zap.DictObject(
zap.String("worker", "w2"),
zap.Int("load", 520),
zap.Duration("latency", d2),
),
zap.DictObject(
zap.String("worker", "w3"),
zap.Int("load", 310),
zap.Duration("latency", d3),
),
},
))
// Output:
// {"level":"debug","msg":"worker received job","w1":{"id":402000,"description":"compress image data","priority":3}}
// {"level":"info","msg":"worker status checks","job batch enqueued":[{"worker":"w1","load":419,"latency":"68ms"},{"worker":"w2","load":520,"latency":"79ms"},{"worker":"w3","load":310,"latency":"57ms"}]}
}
func ExampleObjectValues() {
logger := zap.NewExample()
defer logger.Sync()
// Use the ObjectValues field constructor when you have a list of
// objects that do not implement zapcore.ObjectMarshaler directly,
// but on their pointer receivers.
logger.Debug("starting tunnels",
zap.ObjectValues("addrs", []request{
{
URL: "/foo",
Listen: addr{"127.0.0.1", 8080},
Remote: addr{"123.45.67.89", 4040},
},
{
URL: "/bar",
Listen: addr{"127.0.0.1", 8080},
Remote: addr{"127.0.0.1", 31200},
},
}))
// Output:
// {"level":"debug","msg":"starting tunnels","addrs":[{"url":"/foo","ip":"127.0.0.1","port":8080,"remote":{"ip":"123.45.67.89","port":4040}},{"url":"/bar","ip":"127.0.0.1","port":8080,"remote":{"ip":"127.0.0.1","port":31200}}]}
}
================================================
FILE: exp/CHANGELOG.md
================================================
# Changelog
All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## 0.3.0 - 22 Oct 2024
Breaking changes:
* [#1339][]: zapslog: Drop `HandlerOptions` in favor of `HandlerOption`,
which uses the functional options pattern.
* [#1339][]: zapslog: Rename `AddSource` option to `WithCaller`.
Enhancements:
* [#1339][]: zapslog: Record stack traces for error logs or higher.
The new `AddStackAt` option changes this level.
Bug fixes:
* [#1344][], [#1408][]: zapslog: Comply fully with `slog.Handler` contract.
This includes ignoring empty `Attr`s, inlining `Group`s with empty names,
and omitting groups with no attributes.
[#1344]: https://github.com/uber-go/zap/pull/1344
[#1339]: https://github.com/uber-go/zap/pull/1339
[#1408]: https://github.com/uber-go/zap/pull/1408
Thanks to @zekth and @arukiidou for their contributions to this release.
## 0.2.0 - 9 Sep 2023
Breaking changes:
* [#1315][]: zapslog: Drop HandlerOptions.New in favor of just the NewHandler constructor.
* [#1320][], [#1338][]: zapslog: Drop support for golang.org/x/exp/slog in favor of log/slog released in Go 1.21.
[#1315]: https://github.com/uber-go/zap/pull/1315
[#1320]: https://github.com/uber-go/zap/pull/1320
[#1338]: https://github.com/uber-go/zap/pull/1338
## 0.1.0 - 1 Aug 2023
Initial release of go.uber.org/zap/exp.
This submodule contains experimental features for Zap.
Features incubated here may be promoted to the root Zap module,
but it's not guaranteed.
================================================
FILE: exp/LICENSE
================================================
Copyright (c) 2016-2024 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.
=============================
gitextract_vk9f9uhm/
├── .codecov.yml
├── .github/
│ ├── ISSUE_TEMPLATE/
│ │ ├── bug_report.md
│ │ ├── config.yml
│ │ └── feature_request.md
│ ├── dependabot.yml
│ └── workflows/
│ └── go.yml
├── .gitignore
├── .golangci.yml
├── .readme.tmpl
├── CHANGELOG.md
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── FAQ.md
├── LICENSE
├── Makefile
├── README.md
├── array.go
├── array_test.go
├── assets/
│ ├── README.md
│ └── go.mod
├── benchmarks/
│ ├── apex_test.go
│ ├── doc.go
│ ├── go.mod
│ ├── go.sum
│ ├── kit_test.go
│ ├── log15_test.go
│ ├── logrus_test.go
│ ├── scenario_bench_test.go
│ ├── slog_test.go
│ ├── zap_test.go
│ └── zerolog_test.go
├── buffer/
│ ├── buffer.go
│ ├── buffer_test.go
│ ├── pool.go
│ └── pool_test.go
├── checklicense.sh
├── clock_test.go
├── common_test.go
├── config.go
├── config_test.go
├── doc.go
├── encoder.go
├── encoder_test.go
├── error.go
├── error_test.go
├── example_test.go
├── exp/
│ ├── CHANGELOG.md
│ ├── LICENSE
│ ├── go.mod
│ ├── go.sum
│ ├── zapfield/
│ │ ├── zapfield.go
│ │ └── zapfield_test.go
│ └── zapslog/
│ ├── doc.go
│ ├── example_test.go
│ ├── handler.go
│ ├── handler_test.go
│ └── options.go
├── field.go
├── field_test.go
├── flag.go
├── flag_test.go
├── glide.yaml
├── global.go
├── global_test.go
├── go.mod
├── go.sum
├── http_handler.go
├── http_handler_test.go
├── increase_level_test.go
├── internal/
│ ├── bufferpool/
│ │ └── bufferpool.go
│ ├── color/
│ │ ├── color.go
│ │ └── color_test.go
│ ├── exit/
│ │ ├── exit.go
│ │ └── exit_test.go
│ ├── level_enabler.go
│ ├── pool/
│ │ ├── pool.go
│ │ └── pool_test.go
│ ├── readme/
│ │ └── readme.go
│ ├── stacktrace/
│ │ ├── stack.go
│ │ └── stack_test.go
│ └── ztest/
│ ├── clock.go
│ ├── clock_test.go
│ ├── doc.go
│ ├── timeout.go
│ └── writer.go
├── leak_test.go
├── level.go
├── level_test.go
├── logger.go
├── logger_bench_test.go
├── logger_test.go
├── options.go
├── sink.go
├── sink_test.go
├── sink_windows_test.go
├── stacktrace_ext_test.go
├── sugar.go
├── sugar_test.go
├── time.go
├── time_test.go
├── tools/
│ ├── go.mod
│ ├── go.sum
│ └── tools.go
├── writer.go
├── writer_test.go
├── zapcore/
│ ├── buffered_write_syncer.go
│ ├── buffered_write_syncer_bench_test.go
│ ├── buffered_write_syncer_test.go
│ ├── clock.go
│ ├── clock_test.go
│ ├── console_encoder.go
│ ├── console_encoder_bench_test.go
│ ├── console_encoder_test.go
│ ├── core.go
│ ├── core_test.go
│ ├── doc.go
│ ├── encoder.go
│ ├── encoder_test.go
│ ├── entry.go
│ ├── entry_ext_test.go
│ ├── entry_test.go
│ ├── error.go
│ ├── error_test.go
│ ├── field.go
│ ├── field_test.go
│ ├── hook.go
│ ├── hook_test.go
│ ├── increase_level.go
│ ├── increase_level_test.go
│ ├── json_encoder.go
│ ├── json_encoder_bench_test.go
│ ├── json_encoder_impl_test.go
│ ├── json_encoder_test.go
│ ├── lazy_with.go
│ ├── lazy_with_test.go
│ ├── leak_test.go
│ ├── level.go
│ ├── level_strings.go
│ ├── level_strings_test.go
│ ├── level_test.go
│ ├── marshaler.go
│ ├── memory_encoder.go
│ ├── memory_encoder_test.go
│ ├── reflected_encoder.go
│ ├── sampler.go
│ ├── sampler_bench_test.go
│ ├── sampler_test.go
│ ├── tee.go
│ ├── tee_logger_bench_test.go
│ ├── tee_test.go
│ ├── write_syncer.go
│ ├── write_syncer_bench_test.go
│ └── write_syncer_test.go
├── zapgrpc/
│ ├── internal/
│ │ └── test/
│ │ ├── README.md
│ │ ├── go.mod
│ │ ├── go.sum
│ │ ├── grpc.go
│ │ └── grpc_test.go
│ ├── zapgrpc.go
│ └── zapgrpc_test.go
├── zapio/
│ ├── example_test.go
│ ├── writer.go
│ └── writer_test.go
└── zaptest/
├── doc.go
├── logger.go
├── logger_test.go
├── observer/
│ ├── logged_entry.go
│ ├── logged_entry_test.go
│ ├── observer.go
│ └── observer_test.go
├── testingt.go
├── testingt_test.go
├── timeout.go
├── timeout_test.go
├── writer.go
└── writer_test.go
SYMBOL INDEX (1372 symbols across 132 files)
FILE: array.go
function Array (line 33) | func Array(key string, val zapcore.ArrayMarshaler) Field {
function Bools (line 38) | func Bools(key string, bs []bool) Field {
function ByteStrings (line 44) | func ByteStrings(key string, bss [][]byte) Field {
function Complex128s (line 49) | func Complex128s(key string, nums []complex128) Field {
function Complex64s (line 54) | func Complex64s(key string, nums []complex64) Field {
function Durations (line 59) | func Durations(key string, ds []time.Duration) Field {
function Float64s (line 64) | func Float64s(key string, nums []float64) Field {
function Float32s (line 69) | func Float32s(key string, nums []float32) Field {
function Ints (line 74) | func Ints(key string, nums []int) Field {
function Int64s (line 79) | func Int64s(key string, nums []int64) Field {
function Int32s (line 84) | func Int32s(key string, nums []int32) Field {
function Int16s (line 89) | func Int16s(key string, nums []int16) Field {
function Int8s (line 94) | func Int8s(key string, nums []int8) Field {
function Objects (line 130) | func Objects[T zapcore.ObjectMarshaler](key string, values []T) Field {
type objects (line 134) | type objects
method MarshalLogArray (line 136) | func (os objects[T]) MarshalLogArray(arr zapcore.ArrayEncoder) error {
type ObjectMarshalerPtr (line 147) | type ObjectMarshalerPtr interface
function ObjectValues (line 174) | func ObjectValues[T any, P ObjectMarshalerPtr[T]](key string, values []T...
type objectValues (line 178) | type objectValues
method MarshalLogArray (line 180) | func (os objectValues[T, P]) MarshalLogArray(arr zapcore.ArrayEncoder) e...
function Strings (line 197) | func Strings(key string, ss []string) Field {
function Stringers (line 216) | func Stringers[T fmt.Stringer](key string, values []T) Field {
type stringers (line 220) | type stringers
method MarshalLogArray (line 222) | func (os stringers[T]) MarshalLogArray(arr zapcore.ArrayEncoder) error {
function Times (line 230) | func Times(key string, ts []time.Time) Field {
function Uints (line 235) | func Uints(key string, nums []uint) Field {
function Uint64s (line 240) | func Uint64s(key string, nums []uint64) Field {
function Uint32s (line 245) | func Uint32s(key string, nums []uint32) Field {
function Uint16s (line 250) | func Uint16s(key string, nums []uint16) Field {
function Uint8s (line 255) | func Uint8s(key string, nums []uint8) Field {
function Uintptrs (line 260) | func Uintptrs(key string, us []uintptr) Field {
function Errors (line 265) | func Errors(key string, errs []error) Field {
type bools (line 269) | type bools
method MarshalLogArray (line 271) | func (bs bools) MarshalLogArray(arr zapcore.ArrayEncoder) error {
type byteStringsArray (line 278) | type byteStringsArray
method MarshalLogArray (line 280) | func (bss byteStringsArray) MarshalLogArray(arr zapcore.ArrayEncoder) ...
type complex128s (line 287) | type complex128s
method MarshalLogArray (line 289) | func (nums complex128s) MarshalLogArray(arr zapcore.ArrayEncoder) error {
type complex64s (line 296) | type complex64s
method MarshalLogArray (line 298) | func (nums complex64s) MarshalLogArray(arr zapcore.ArrayEncoder) error {
type durations (line 305) | type durations
method MarshalLogArray (line 307) | func (ds durations) MarshalLogArray(arr zapcore.ArrayEncoder) error {
type float64s (line 314) | type float64s
method MarshalLogArray (line 316) | func (nums float64s) MarshalLogArray(arr zapcore.ArrayEncoder) error {
type float32s (line 323) | type float32s
method MarshalLogArray (line 325) | func (nums float32s) MarshalLogArray(arr zapcore.ArrayEncoder) error {
type ints (line 332) | type ints
method MarshalLogArray (line 334) | func (nums ints) MarshalLogArray(arr zapcore.ArrayEncoder) error {
type int64s (line 341) | type int64s
method MarshalLogArray (line 343) | func (nums int64s) MarshalLogArray(arr zapcore.ArrayEncoder) error {
type int32s (line 350) | type int32s
method MarshalLogArray (line 352) | func (nums int32s) MarshalLogArray(arr zapcore.ArrayEncoder) error {
type int16s (line 359) | type int16s
method MarshalLogArray (line 361) | func (nums int16s) MarshalLogArray(arr zapcore.ArrayEncoder) error {
type int8s (line 368) | type int8s
method MarshalLogArray (line 370) | func (nums int8s) MarshalLogArray(arr zapcore.ArrayEncoder) error {
type stringArray (line 377) | type stringArray
method MarshalLogArray (line 379) | func (ss stringArray) MarshalLogArray(arr zapcore.ArrayEncoder) error {
type times (line 386) | type times
method MarshalLogArray (line 388) | func (ts times) MarshalLogArray(arr zapcore.ArrayEncoder) error {
type uints (line 395) | type uints
method MarshalLogArray (line 397) | func (nums uints) MarshalLogArray(arr zapcore.ArrayEncoder) error {
type uint64s (line 404) | type uint64s
method MarshalLogArray (line 406) | func (nums uint64s) MarshalLogArray(arr zapcore.ArrayEncoder) error {
type uint32s (line 413) | type uint32s
method MarshalLogArray (line 415) | func (nums uint32s) MarshalLogArray(arr zapcore.ArrayEncoder) error {
type uint16s (line 422) | type uint16s
method MarshalLogArray (line 424) | func (nums uint16s) MarshalLogArray(arr zapcore.ArrayEncoder) error {
type uint8s (line 431) | type uint8s
method MarshalLogArray (line 433) | func (nums uint8s) MarshalLogArray(arr zapcore.ArrayEncoder) error {
type uintptrs (line 440) | type uintptrs
method MarshalLogArray (line 442) | func (nums uintptrs) MarshalLogArray(arr zapcore.ArrayEncoder) error {
FILE: array_test.go
function BenchmarkBoolsArrayMarshaler (line 35) | func BenchmarkBoolsArrayMarshaler(b *testing.B) {
function BenchmarkBoolsReflect (line 46) | func BenchmarkBoolsReflect(b *testing.B) {
function TestArrayWrappers (line 55) | func TestArrayWrappers(t *testing.T) {
function TestObjectsAndObjectValues (line 112) | func TestObjectsAndObjectValues(t *testing.T) {
type emptyObject (line 186) | type emptyObject struct
method MarshalLogObject (line 188) | func (*emptyObject) MarshalLogObject(zapcore.ObjectEncoder) error {
type fakeObject (line 192) | type fakeObject struct
method MarshalLogObject (line 197) | func (o *fakeObject) MarshalLogObject(enc zapcore.ObjectEncoder) error {
function TestObjectsAndObjectValues_marshalError (line 202) | func TestObjectsAndObjectValues_marshalError(t *testing.T) {
type stringerObject (line 260) | type stringerObject struct
method String (line 264) | func (s stringerObject) String() string {
function TestStringers (line 268) | func TestStringers(t *testing.T) {
FILE: benchmarks/apex_test.go
function newDisabledApexLog (line 30) | func newDisabledApexLog() *log.Logger {
function newApexLog (line 37) | func newApexLog() *log.Logger {
function fakeApexFields (line 44) | func fakeApexFields() log.Fields {
FILE: benchmarks/kit_test.go
function newKitLog (line 29) | func newKitLog(fields ...interface{}) log.Logger {
FILE: benchmarks/log15_test.go
function newLog15 (line 29) | func newLog15() log15.Logger {
FILE: benchmarks/logrus_test.go
function newDisabledLogrus (line 29) | func newDisabledLogrus() *logrus.Logger {
function newLogrus (line 35) | func newLogrus() *logrus.Logger {
function fakeLogrusFields (line 44) | func fakeLogrusFields() logrus.Fields {
FILE: benchmarks/scenario_bench_test.go
function BenchmarkDisabledWithoutFields (line 33) | func BenchmarkDisabledWithoutFields(b *testing.B) {
function BenchmarkDisabledAccumulatedContext (line 120) | func BenchmarkDisabledAccumulatedContext(b *testing.B) {
function BenchmarkDisabledAddingFields (line 207) | func BenchmarkDisabledAddingFields(b *testing.B) {
function BenchmarkWithoutFields (line 285) | func BenchmarkWithoutFields(b *testing.B) {
function BenchmarkAccumulatedContext (line 443) | func BenchmarkAccumulatedContext(b *testing.B) {
function BenchmarkAddingFields (line 583) | func BenchmarkAddingFields(b *testing.B) {
FILE: benchmarks/slog_test.go
function newSlog (line 28) | func newSlog(fields ...slog.Attr) *slog.Logger {
function newDisabledSlog (line 32) | func newDisabledSlog(fields ...slog.Attr) *slog.Logger {
function fakeSlogFields (line 36) | func fakeSlogFields() []slog.Attr {
function fakeSlogArgs (line 51) | func fakeSlogArgs() []any {
FILE: benchmarks/zap_test.go
function fakeMessages (line 71) | func fakeMessages(n int) []string {
function getMessage (line 79) | func getMessage(iter int) string {
type users (line 83) | type users
method MarshalLogArray (line 85) | func (uu users) MarshalLogArray(arr zapcore.ArrayEncoder) error {
type user (line 93) | type user struct
method MarshalLogObject (line 99) | func (u *user) MarshalLogObject(enc zapcore.ObjectEncoder) error {
function newZapLogger (line 106) | func newZapLogger(lvl zapcore.Level) *zap.Logger {
function newSampledLogger (line 118) | func newSampledLogger(lvl zapcore.Level) *zap.Logger {
function fakeFields (line 127) | func fakeFields() []zap.Field {
function fakeSugarFields (line 143) | func fakeSugarFields() []interface{} {
function fakeFmtArgs (line 158) | func fakeFmtArgs() []interface{} {
FILE: benchmarks/zerolog_test.go
function newZerolog (line 29) | func newZerolog() zerolog.Logger {
function newDisabledZerolog (line 33) | func newDisabledZerolog() zerolog.Logger {
method MarshalZerologObject (line 37) | func (u *user) MarshalZerologObject(e *zerolog.Event) {
method MarshalZerologArray (line 43) | func (uu users) MarshalZerologArray(a *zerolog.Array) {
function fakeZerologFields (line 49) | func fakeZerologFields(e *zerolog.Event) *zerolog.Event {
function fakeZerologContext (line 63) | func fakeZerologContext(c zerolog.Context) zerolog.Context {
FILE: buffer/buffer.go
constant _size (line 31) | _size = 1024
type Buffer (line 35) | type Buffer struct
method AppendByte (line 41) | func (b *Buffer) AppendByte(v byte) {
method AppendBytes (line 46) | func (b *Buffer) AppendBytes(v []byte) {
method AppendString (line 51) | func (b *Buffer) AppendString(s string) {
method AppendInt (line 56) | func (b *Buffer) AppendInt(i int64) {
method AppendTime (line 61) | func (b *Buffer) AppendTime(t time.Time, layout string) {
method AppendUint (line 67) | func (b *Buffer) AppendUint(i uint64) {
method AppendBool (line 72) | func (b *Buffer) AppendBool(v bool) {
method AppendFloat (line 78) | func (b *Buffer) AppendFloat(f float64, bitSize int) {
method Len (line 83) | func (b *Buffer) Len() int {
method Cap (line 88) | func (b *Buffer) Cap() int {
method Bytes (line 93) | func (b *Buffer) Bytes() []byte {
method String (line 98) | func (b *Buffer) String() string {
method Reset (line 104) | func (b *Buffer) Reset() {
method Write (line 109) | func (b *Buffer) Write(bs []byte) (int, error) {
method WriteByte (line 118) | func (b *Buffer) WriteByte(v byte) error {
method WriteString (line 127) | func (b *Buffer) WriteString(s string) (int, error) {
method TrimNewline (line 133) | func (b *Buffer) TrimNewline() {
method Free (line 144) | func (b *Buffer) Free() {
FILE: buffer/buffer_test.go
function TestBufferWrites (line 32) | func TestBufferWrites(t *testing.T) {
function BenchmarkBuffers (line 68) | func BenchmarkBuffers(b *testing.B) {
FILE: buffer/pool.go
type Pool (line 28) | type Pool struct
method Get (line 44) | func (p Pool) Get() *Buffer {
method put (line 51) | func (p Pool) put(buf *Buffer) {
function NewPool (line 33) | func NewPool() Pool {
FILE: buffer/pool_test.go
function TestBuffers (line 30) | func TestBuffers(t *testing.T) {
FILE: clock_test.go
type constantClock (line 32) | type constantClock
method Now (line 34) | func (c constantClock) Now() time.Time { return time.Time(c) }
method NewTicker (line 35) | func (c constantClock) NewTicker(d time.Duration) *time.Ticker {
function TestWithClock (line 39) | func TestWithClock(t *testing.T) {
FILE: common_test.go
function opts (line 31) | func opts(opts ...Option) []Option {
function withLogger (line 37) | func withLogger(t testing.TB, e zapcore.LevelEnabler, opts []Option, f f...
function withSugar (line 43) | func withSugar(t testing.TB, e zapcore.LevelEnabler, opts []Option, f fu...
function runConcurrently (line 47) | func runConcurrently(goroutines, iterations int, wg *sync.WaitGroup, f f...
FILE: config.go
type SamplingConfig (line 39) | type SamplingConfig struct
type Config (line 58) | type Config struct
method Build (line 239) | func (cfg Config) Build(opts ...Option) (*Logger, error) {
method buildOptions (line 264) | func (cfg Config) buildOptions(errSink zapcore.WriteSyncer) []Option {
method openSinks (line 315) | func (cfg Config) openSinks() (zapcore.WriteSyncer, zapcore.WriteSynce...
method buildEncoder (line 328) | func (cfg Config) buildEncoder() (zapcore.Encoder, error) {
function NewProductionEncoderConfig (line 124) | func NewProductionEncoderConfig() zapcore.EncoderConfig {
function NewProductionConfig (line 157) | func NewProductionConfig() Config {
function NewDevelopmentEncoderConfig (line 200) | func NewDevelopmentEncoderConfig() zapcore.EncoderConfig {
function NewDevelopmentConfig (line 227) | func NewDevelopmentConfig() Config {
FILE: config_test.go
function TestConfig (line 34) | func TestConfig(t *testing.T) {
function TestConfigWithInvalidPaths (line 88) | func TestConfigWithInvalidPaths(t *testing.T) {
function TestConfigWithMissingAttributes (line 110) | func TestConfigWithMissingAttributes(t *testing.T) {
function makeSamplerCountingHook (line 146) | func makeSamplerCountingHook() (h func(zapcore.Entry, zapcore.SamplingDe...
function TestConfigWithSamplingHook (line 161) | func TestConfigWithSamplingHook(t *testing.T) {
FILE: encoder.go
function RegisterEncoder (line 51) | func RegisterEncoder(name string, constructor func(zapcore.EncoderConfig...
function newEncoder (line 64) | func newEncoder(name string, encoderConfig zapcore.EncoderConfig) (zapco...
FILE: encoder_test.go
function TestRegisterDefaultEncoders (line 31) | func TestRegisterDefaultEncoders(t *testing.T) {
function TestRegisterEncoder (line 35) | func TestRegisterEncoder(t *testing.T) {
function TestDuplicateRegisterEncoder (line 42) | func TestDuplicateRegisterEncoder(t *testing.T) {
function TestRegisterEncoderNoName (line 49) | func TestRegisterEncoderNoName(t *testing.T) {
function TestNewEncoder (line 53) | func TestNewEncoder(t *testing.T) {
function TestNewEncoderNotRegistered (line 62) | func TestNewEncoderNotRegistered(t *testing.T) {
function TestNewEncoderNoName (line 67) | func TestNewEncoderNoName(t *testing.T) {
function testEncoders (line 72) | func testEncoders(f func()) {
function testEncodersRegistered (line 79) | func testEncodersRegistered(t *testing.T, names ...string) {
function newNilEncoder (line 86) | func newNilEncoder(_ zapcore.EncoderConfig) (zapcore.Encoder, error) {
FILE: error.go
function Error (line 33) | func Error(err error) Field {
function NamedError (line 44) | func NamedError(key string, err error) Field {
type errArray (line 51) | type errArray
method MarshalLogArray (line 53) | func (errs errArray) MarshalLogArray(arr zapcore.ArrayEncoder) error {
type errArrayElem (line 74) | type errArrayElem struct
method MarshalLogObject (line 78) | func (e *errArrayElem) MarshalLogObject(enc zapcore.ObjectEncoder) err...
FILE: error_test.go
function TestErrorConstructors (line 34) | func TestErrorConstructors(t *testing.T) {
function TestErrorArrayConstructor (line 58) | func TestErrorArrayConstructor(t *testing.T) {
function TestErrorsArraysHandleRichErrors (line 81) | func TestErrorsArraysHandleRichErrors(t *testing.T) {
function TestErrArrayBrokenEncoder (line 99) | func TestErrArrayBrokenEncoder(t *testing.T) {
type brokenArrayObjectEncoder (line 116) | type brokenArrayObjectEncoder struct
method AddArray (line 123) | func (enc brokenArrayObjectEncoder) AddArray(key string, marshaler zap...
method AppendObject (line 131) | func (enc brokenArrayObjectEncoder) AppendObject(zapcore.ObjectMarshal...
FILE: example_test.go
function Example_presets (line 34) | func Example_presets() {
function Example_basicConfiguration (line 68) | func Example_basicConfiguration() {
function Example_advancedConfiguration (line 102) | func Example_advancedConfiguration() {
function ExampleNamespace (line 153) | func ExampleNamespace() {
type addr (line 165) | type addr struct
method MarshalLogObject (line 176) | func (a addr) MarshalLogObject(enc zapcore.ObjectEncoder) error {
type request (line 170) | type request struct
method MarshalLogObject (line 182) | func (r *request) MarshalLogObject(enc zapcore.ObjectEncoder) error {
function ExampleObject (line 188) | func ExampleObject() {
function ExampleNewStdLog (line 204) | func ExampleNewStdLog() {
function ExampleRedirectStdLog (line 214) | func ExampleRedirectStdLog() {
function ExampleReplaceGlobals (line 226) | func ExampleReplaceGlobals() {
function ExampleAtomicLevel (line 238) | func ExampleAtomicLevel() {
function ExampleAtomicLevel_config (line 260) | func ExampleAtomicLevel_config() {
function ExampleLogger_Check (line 289) | func ExampleLogger_Check() {
function ExampleLogger_Named (line 307) | func ExampleLogger_Named() {
function ExampleWrapCore_replace (line 326) | func ExampleWrapCore_replace() {
function ExampleWrapCore_wrap (line 344) | func ExampleWrapCore_wrap() {
function ExampleDict (line 362) | func ExampleDict() {
function ExampleObjects (line 375) | func ExampleObjects() {
function ExampleDictObject (line 391) | func ExampleDictObject() {
function ExampleObjectValues (line 436) | func ExampleObjectValues() {
FILE: exp/zapfield/zapfield.go
function Str (line 30) | func Str[K ~string, V ~string](k K, v V) zap.Field {
type stringArray (line 34) | type stringArray
method MarshalLogArray (line 36) | func (a stringArray[T]) MarshalLogArray(enc zapcore.ArrayEncoder) error {
function Strs (line 44) | func Strs[K ~string, V ~[]S, S ~string](k K, v V) zap.Field {
FILE: exp/zapfield/zapfield_test.go
type MyKey (line 33) | type MyKey
type MyValue (line 34) | type MyValue
type MyValues (line 35) | type MyValues
function TestFieldConstructors (line 38) | func TestFieldConstructors(t *testing.T) {
function assertCanBeReused (line 65) | func assertCanBeReused(t testing.TB, field zap.Field) {
FILE: exp/zapslog/example_test.go
type Password (line 35) | type Password
method LogValue (line 37) | func (p Password) LogValue() slog.Value {
function Example_slog (line 41) | func Example_slog() {
FILE: exp/zapslog/handler.go
type Handler (line 36) | type Handler struct
method Enabled (line 133) | func (h *Handler) Enabled(ctx context.Context, level slog.Level) bool {
method Handle (line 138) | func (h *Handler) Handle(ctx context.Context, record slog.Record) error {
method appendGroups (line 190) | func (h *Handler) appendGroups(fields []zapcore.Field) []zapcore.Field {
method WithAttrs (line 199) | func (h *Handler) WithAttrs(attrs []slog.Attr) slog.Handler {
method WithGroup (line 224) | func (h *Handler) WithGroup(group string) slog.Handler {
function NewHandler (line 53) | func NewHandler(core zapcore.Core, opts ...HandlerOption) *Handler {
type groupObject (line 67) | type groupObject
method MarshalLogObject (line 69) | func (gs groupObject) MarshalLogObject(enc zapcore.ObjectEncoder) error {
function convertAttrToField (line 76) | func convertAttrToField(attr slog.Attr) zapcore.Field {
function convertSlogLevel (line 119) | func convertSlogLevel(l slog.Level) zapcore.Level {
FILE: exp/zapslog/handler_test.go
function TestAddCaller (line 41) | func TestAddCaller(t *testing.T) {
function TestAddStack (line 58) | func TestAddStack(t *testing.T) {
function TestAddStackSkip (line 78) | func TestAddStackSkip(t *testing.T) {
function TestEmptyAttr (line 92) | func TestEmptyAttr(t *testing.T) {
function TestWithName (line 135) | func TestWithName(t *testing.T) {
function TestInlineGroup (line 158) | func TestInlineGroup(t *testing.T) {
function TestWithGroup (line 188) | func TestWithGroup(t *testing.T) {
function TestConcurrentLogs (line 271) | func TestConcurrentLogs(t *testing.T) {
type Token (line 343) | type Token
method LogValue (line 345) | func (Token) LogValue() slog.Value {
function TestAttrKinds (line 349) | func TestAttrKinds(t *testing.T) {
function TestSlogtest (line 383) | func TestSlogtest(t *testing.T) {
FILE: exp/zapslog/options.go
type HandlerOption (line 28) | type HandlerOption interface
type handlerOptionFunc (line 33) | type handlerOptionFunc
method apply (line 35) | func (f handlerOptionFunc) apply(handler *Handler) {
function WithName (line 40) | func WithName(name string) HandlerOption {
function WithCaller (line 48) | func WithCaller(enabled bool) HandlerOption {
function WithCallerSkip (line 60) | func WithCallerSkip(skip int) HandlerOption {
function AddStacktraceAt (line 68) | func AddStacktraceAt(lvl slog.Level) HandlerOption {
FILE: field.go
function Skip (line 43) | func Skip() Field {
function nilField (line 51) | func nilField(key string) Field { return Reflect(key, nil) }
function Binary (line 58) | func Binary(key string, val []byte) Field {
function Bool (line 63) | func Bool(key string, val bool) Field {
function Boolp (line 73) | func Boolp(key string, val *bool) Field {
function ByteString (line 83) | func ByteString(key string, val []byte) Field {
function Complex128 (line 90) | func Complex128(key string, val complex128) Field {
function Complex128p (line 96) | func Complex128p(key string, val *complex128) Field {
function Complex64 (line 106) | func Complex64(key string, val complex64) Field {
function Complex64p (line 112) | func Complex64p(key string, val *complex64) Field {
function Float64 (line 122) | func Float64(key string, val float64) Field {
function Float64p (line 128) | func Float64p(key string, val *float64) Field {
function Float32 (line 138) | func Float32(key string, val float32) Field {
function Float32p (line 144) | func Float32p(key string, val *float32) Field {
function Int (line 152) | func Int(key string, val int) Field {
function Intp (line 158) | func Intp(key string, val *int) Field {
function Int64 (line 166) | func Int64(key string, val int64) Field {
function Int64p (line 172) | func Int64p(key string, val *int64) Field {
function Int32 (line 180) | func Int32(key string, val int32) Field {
function Int32p (line 186) | func Int32p(key string, val *int32) Field {
function Int16 (line 194) | func Int16(key string, val int16) Field {
function Int16p (line 200) | func Int16p(key string, val *int16) Field {
function Int8 (line 208) | func Int8(key string, val int8) Field {
function Int8p (line 214) | func Int8p(key string, val *int8) Field {
function String (line 222) | func String(key string, val string) Field {
function Stringp (line 228) | func Stringp(key string, val *string) Field {
function Uint (line 236) | func Uint(key string, val uint) Field {
function Uintp (line 242) | func Uintp(key string, val *uint) Field {
function Uint64 (line 250) | func Uint64(key string, val uint64) Field {
function Uint64p (line 256) | func Uint64p(key string, val *uint64) Field {
function Uint32 (line 264) | func Uint32(key string, val uint32) Field {
function Uint32p (line 270) | func Uint32p(key string, val *uint32) Field {
function Uint16 (line 278) | func Uint16(key string, val uint16) Field {
function Uint16p (line 284) | func Uint16p(key string, val *uint16) Field {
function Uint8 (line 292) | func Uint8(key string, val uint8) Field {
function Uint8p (line 298) | func Uint8p(key string, val *uint8) Field {
function Uintptr (line 306) | func Uintptr(key string, val uintptr) Field {
function Uintptrp (line 312) | func Uintptrp(key string, val *uintptr) Field {
function Reflect (line 326) | func Reflect(key string, val interface{}) Field {
function Namespace (line 335) | func Namespace(key string) Field {
function Stringer (line 341) | func Stringer(key string, val fmt.Stringer) Field {
function Time (line 347) | func Time(key string, val time.Time) Field {
function Timep (line 356) | func Timep(key string, val *time.Time) Field {
function Stack (line 367) | func Stack(key string) Field {
function StackSkip (line 373) | func StackSkip(key string, skip int) Field {
function Duration (line 383) | func Duration(key string, val time.Duration) Field {
function Durationp (line 389) | func Durationp(key string, val *time.Duration) Field {
function Object (line 400) | func Object(key string, val zapcore.ObjectMarshaler) Field {
function Inline (line 410) | func Inline(val zapcore.ObjectMarshaler) Field {
function Dict (line 419) | func Dict(key string, val ...Field) Field {
function dictField (line 424) | func dictField(key string, val []Field) Field {
type dictObject (line 428) | type dictObject
method MarshalLogObject (line 430) | func (d dictObject) MarshalLogObject(enc zapcore.ObjectEncoder) error {
function DictObject (line 440) | func DictObject(val ...Field) zapcore.ObjectMarshaler {
type anyFieldC (line 475) | type anyFieldC
method Any (line 477) | func (f anyFieldC[T]) Any(key string, val any) Field {
function Any (line 490) | func Any(key string, value interface{}) Field {
FILE: field_test.go
type username (line 36) | type username
method MarshalLogObject (line 38) | func (n username) MarshalLogObject(enc zapcore.ObjectEncoder) error {
function assertCanBeReused (line 43) | func assertCanBeReused(t testing.TB, field Field) {
function TestFieldConstructors (line 63) | func TestFieldConstructors(t *testing.T) {
function TestStackField (line 269) | func TestStackField(t *testing.T) {
function TestStackSkipField (line 278) | func TestStackSkipField(t *testing.T) {
function TestStackSkipFieldWithSkip (line 287) | func TestStackSkipFieldWithSkip(t *testing.T) {
function TestDict (line 295) | func TestDict(t *testing.T) {
function TestDictObject (line 319) | func TestDictObject(t *testing.T) {
FILE: flag.go
function LevelFlag (line 35) | func LevelFlag(name string, defaultLevel zapcore.Level, usage string) *z...
FILE: flag_test.go
type flagTestCase (line 33) | type flagTestCase struct
method runImplicitSet (line 39) | func (tc flagTestCase) runImplicitSet(t testing.TB) {
method runExplicitSet (line 49) | func (tc flagTestCase) runExplicitSet(t testing.TB) {
method run (line 57) | func (tc flagTestCase) run(t testing.TB, set *flag.FlagSet, actual *za...
function TestLevelFlag (line 68) | func TestLevelFlag(t *testing.T) {
function TestLevelFlagsAreIndependent (line 90) | func TestLevelFlagsAreIndependent(t *testing.T) {
FILE: global.go
constant _stdLogDefaultDepth (line 34) | _stdLogDefaultDepth = 1
constant _loggerWriterDepth (line 35) | _loggerWriterDepth = 2
constant _programmerErrorTemplate (line 36) | _programmerErrorTemplate = "You've found a bug in zap! Please file a bug...
function L (line 48) | func L() *Logger {
function S (line 57) | func S() *SugaredLogger {
function ReplaceGlobals (line 66) | func ReplaceGlobals(logger *Logger) func() {
function NewStdLog (line 78) | func NewStdLog(l *Logger) *log.Logger {
function NewStdLogAt (line 86) | func NewStdLogAt(l *Logger, level zapcore.Level) (*log.Logger, error) {
function RedirectStdLog (line 102) | func RedirectStdLog(l *Logger) func() {
function RedirectStdLogAt (line 119) | func RedirectStdLogAt(l *Logger, level zapcore.Level) (func(), error) {
function redirectStdLogAt (line 123) | func redirectStdLogAt(l *Logger, level zapcore.Level) (func(), error) {
function levelToFunc (line 141) | func levelToFunc(logger *Logger, lvl zapcore.Level) (func(string, ...Fie...
type loggerWriter (line 161) | type loggerWriter struct
method Write (line 165) | func (l *loggerWriter) Write(p []byte) (int, error) {
FILE: global_test.go
function TestReplaceGlobals (line 40) | func TestReplaceGlobals(t *testing.T) {
function TestGlobalsConcurrentUse (line 69) | func TestGlobalsConcurrentUse(t *testing.T) {
function TestNewStdLog (line 100) | func TestNewStdLog(t *testing.T) {
function TestNewStdLogAt (line 108) | func TestNewStdLogAt(t *testing.T) {
function TestNewStdLogAtPanics (line 121) | func TestNewStdLogAtPanics(t *testing.T) {
function TestNewStdLogAtFatal (line 134) | func TestNewStdLogAtFatal(t *testing.T) {
function TestNewStdLogAtInvalid (line 147) | func TestNewStdLogAtInvalid(t *testing.T) {
function TestRedirectStdLog (line 152) | func TestRedirectStdLog(t *testing.T) {
function TestRedirectStdLogCaller (line 170) | func TestRedirectStdLogCaller(t *testing.T) {
function TestRedirectStdLogAt (line 180) | func TestRedirectStdLogAt(t *testing.T) {
function TestRedirectStdLogAtCaller (line 204) | func TestRedirectStdLogAtCaller(t *testing.T) {
function TestRedirectStdLogAtPanics (line 220) | func TestRedirectStdLogAtPanics(t *testing.T) {
function TestRedirectStdLogAtFatal (line 240) | func TestRedirectStdLogAtFatal(t *testing.T) {
function TestRedirectStdLogAtInvalid (line 260) | func TestRedirectStdLogAtInvalid(t *testing.T) {
function checkStdLogMessage (line 270) | func checkStdLogMessage(t *testing.T, msg string, logs *observer.Observe...
FILE: http_handler.go
method ServeHTTP (line 71) | func (lvl AtomicLevel) ServeHTTP(w http.ResponseWriter, r *http.Request) {
method serveHTTP (line 78) | func (lvl AtomicLevel) serveHTTP(w http.ResponseWriter, r *http.Request)...
function decodePutRequest (line 110) | func decodePutRequest(contentType string, r *http.Request) (zapcore.Leve...
function decodePutURL (line 117) | func decodePutURL(r *http.Request) (zapcore.Level, error) {
function decodePutJSON (line 129) | func decodePutJSON(body io.Reader) (zapcore.Level, error) {
FILE: http_handler_test.go
function TestAtomicLevelServeHTTP (line 39) | func TestAtomicLevelServeHTTP(t *testing.T) {
function TestAtomicLevelServeHTTPBrokenWriter (line 196) | func TestAtomicLevelServeHTTPBrokenWriter(t *testing.T) {
type brokenHTTPResponseWriter (line 212) | type brokenHTTPResponseWriter struct
method Write (line 216) | func (w *brokenHTTPResponseWriter) Write([]byte) (int, error) {
function TestAtomicLevelServeHTTPBadLevel (line 220) | func TestAtomicLevelServeHTTPBadLevel(t *testing.T) {
function FuzzAtomicLevelServeHTTP (line 241) | func FuzzAtomicLevelServeHTTP(f *testing.F) {
FILE: increase_level_test.go
function newLoggedEntry (line 32) | func newLoggedEntry(level zapcore.Level, msg string, fields ...zapcore.F...
function TestIncreaseLevelTryDecrease (line 42) | func TestIncreaseLevelTryDecrease(t *testing.T) {
function TestIncreaseLevel (line 68) | func TestIncreaseLevel(t *testing.T) {
FILE: internal/color/color.go
constant Black (line 28) | Black Color = iota + 30
constant Red (line 29) | Red
constant Green (line 30) | Green
constant Yellow (line 31) | Yellow
constant Blue (line 32) | Blue
constant Magenta (line 33) | Magenta
constant Cyan (line 34) | Cyan
constant White (line 35) | White
type Color (line 39) | type Color
method Add (line 42) | func (c Color) Add(s string) string {
FILE: internal/color/color_test.go
function TestColorFormatting (line 29) | func TestColorFormatting(t *testing.T) {
FILE: internal/exit/exit.go
function With (line 31) | func With(code int) {
type StubbedExit (line 36) | type StubbedExit struct
method Unstub (line 59) | func (se *StubbedExit) Unstub() {
method exit (line 63) | func (se *StubbedExit) exit(code int) {
function Stub (line 43) | func Stub() *StubbedExit {
function WithStub (line 51) | func WithStub(f func()) *StubbedExit {
FILE: internal/exit/exit_test.go
function TestStub (line 30) | func TestStub(t *testing.T) {
FILE: internal/level_enabler.go
type LeveledEnabler (line 33) | type LeveledEnabler interface
FILE: internal/pool/pool.go
type Pool (line 34) | type Pool struct
function New (line 40) | func New[T any](fn func() T) *Pool[T] {
method Get (line 51) | func (p *Pool[T]) Get() T {
method Put (line 56) | func (p *Pool[T]) Put(x T) {
FILE: internal/pool/pool_test.go
type pooledValue (line 32) | type pooledValue struct
function TestNew (line 36) | func TestNew(t *testing.T) {
function TestNew_Race (line 78) | func TestNew_Race(t *testing.T) {
FILE: internal/readme/readme.go
function main (line 51) | func main() {
function do (line 58) | func do() error {
function getTmplData (line 74) | func getTmplData() (*tmplData, error) {
function getBenchmarkRows (line 94) | func getBenchmarkRows(benchmarkName string) (string, error) {
function getBenchmarkRow (line 130) | func getBenchmarkRow(
function findUniqueSubstring (line 172) | func findUniqueSubstring(input []string, substring string) (string, erro...
function getBenchmarkOutput (line 185) | func getBenchmarkOutput(benchmarkName string) ([]string, error) {
type tmplData (line 195) | type tmplData struct
type benchmarkRow (line 201) | type benchmarkRow struct
method String (line 213) | func (b *benchmarkRow) String() string {
type benchmarkRowsByTime (line 229) | type benchmarkRowsByTime
method Len (line 231) | func (b benchmarkRowsByTime) Len() int { return len(b) }
method Swap (line 232) | func (b benchmarkRowsByTime) Swap(i, j int) { b[i], b[j] = b[j], b[i] }
method Less (line 233) | func (b benchmarkRowsByTime) Less(i, j int) bool {
FILE: internal/stacktrace/stack.go
type Stack (line 40) | type Stack struct
method Free (line 113) | func (st *Stack) Free() {
method Count (line 121) | func (st *Stack) Count() int {
method Next (line 127) | func (st *Stack) Next() (_ runtime.Frame, more bool) {
type Depth (line 55) | type Depth
constant First (line 59) | First Depth = iota
constant Full (line 63) | Full
function Capture (line 71) | func Capture(skip int, depth Depth) *Stack {
function Take (line 135) | func Take(skip int) string {
type Formatter (line 148) | type Formatter struct
method FormatStack (line 160) | func (sf *Formatter) FormatStack(stack *Stack) {
method FormatFrame (line 170) | func (sf *Formatter) FormatFrame(frame runtime.Frame) {
function NewFormatter (line 154) | func NewFormatter(b *buffer.Buffer) Formatter {
FILE: internal/stacktrace/stack_test.go
function TestTake (line 32) | func TestTake(t *testing.T) {
function TestTakeWithSkip (line 44) | func TestTakeWithSkip(t *testing.T) {
function TestTakeWithSkipInnerFunc (line 56) | func TestTakeWithSkipInnerFunc(t *testing.T) {
function TestTakeDeepStack (line 71) | func TestTakeDeepStack(t *testing.T) {
function BenchmarkTake (line 89) | func BenchmarkTake(b *testing.B) {
function withStackDepth (line 95) | func withStackDepth(depth int, f func()) {
FILE: internal/ztest/clock.go
type MockClock (line 34) | type MockClock struct
method Now (line 54) | func (c *MockClock) Now() time.Time {
method NewTicker (line 68) | func (c *MockClock) NewTicker(d time.Duration) *time.Ticker {
method runAt (line 93) | func (c *MockClock) runAt(t time.Time, fn func()) {
method Add (line 113) | func (c *MockClock) Add(d time.Duration) {
function NewMockClock (line 47) | func NewMockClock() *MockClock {
type waiter (line 99) | type waiter struct
FILE: internal/ztest/clock_test.go
function TestMockClock_NewTicker (line 31) | func TestMockClock_NewTicker(t *testing.T) {
function TestMockClock_NewTicker_slowConsumer (line 59) | func TestMockClock_NewTicker_slowConsumer(t *testing.T) {
function TestMockClock_Add_negative (line 77) | func TestMockClock_Add_negative(t *testing.T) {
FILE: internal/ztest/timeout.go
function Timeout (line 33) | func Timeout(base time.Duration) time.Duration {
function Sleep (line 38) | func Sleep(base time.Duration) {
function Initialize (line 44) | func Initialize(factor string) func() {
function init (line 54) | func init() {
FILE: internal/ztest/writer.go
type Syncer (line 31) | type Syncer struct
method SetError (line 37) | func (s *Syncer) SetError(err error) {
method Sync (line 43) | func (s *Syncer) Sync() error {
method Called (line 49) | func (s *Syncer) Called() bool {
type Discarder (line 54) | type Discarder struct
method Write (line 57) | func (d *Discarder) Write(b []byte) (int, error) {
type FailWriter (line 62) | type FailWriter struct
method Write (line 65) | func (w FailWriter) Write(b []byte) (int, error) {
type ShortWriter (line 71) | type ShortWriter struct
method Write (line 74) | func (w ShortWriter) Write(b []byte) (int, error) {
type Buffer (line 81) | type Buffer struct
method Lines (line 87) | func (b *Buffer) Lines() []string {
method Stripped (line 94) | func (b *Buffer) Stripped() string {
FILE: leak_test.go
function TestMain (line 29) | func TestMain(m *testing.M) {
FILE: level.go
constant DebugLevel (line 33) | DebugLevel = zapcore.DebugLevel
constant InfoLevel (line 35) | InfoLevel = zapcore.InfoLevel
constant WarnLevel (line 38) | WarnLevel = zapcore.WarnLevel
constant ErrorLevel (line 41) | ErrorLevel = zapcore.ErrorLevel
constant DPanicLevel (line 44) | DPanicLevel = zapcore.DPanicLevel
constant PanicLevel (line 46) | PanicLevel = zapcore.PanicLevel
constant FatalLevel (line 48) | FatalLevel = zapcore.FatalLevel
type LevelEnablerFunc (line 57) | type LevelEnablerFunc
method Enabled (line 60) | func (f LevelEnablerFunc) Enabled(lvl zapcore.Level) bool { return f(l...
type AtomicLevel (line 71) | type AtomicLevel struct
method Enabled (line 112) | func (lvl AtomicLevel) Enabled(l zapcore.Level) bool {
method Level (line 117) | func (lvl AtomicLevel) Level() zapcore.Level {
method SetLevel (line 122) | func (lvl AtomicLevel) SetLevel(l zapcore.Level) {
method String (line 127) | func (lvl AtomicLevel) String() string {
method UnmarshalText (line 134) | func (lvl *AtomicLevel) UnmarshalText(text []byte) error {
method MarshalText (line 151) | func (lvl AtomicLevel) MarshalText() (text []byte, err error) {
function NewAtomicLevel (line 79) | func NewAtomicLevel() AtomicLevel {
function NewAtomicLevelAt (line 87) | func NewAtomicLevelAt(l zapcore.Level) AtomicLevel {
function ParseAtomicLevel (line 99) | func ParseAtomicLevel(text string) (AtomicLevel, error) {
FILE: level_test.go
function TestLevelEnablerFunc (line 33) | func TestLevelEnablerFunc(t *testing.T) {
function TestNewAtomicLevel (line 52) | func TestNewAtomicLevel(t *testing.T) {
function TestParseAtomicLevel (line 61) | func TestParseAtomicLevel(t *testing.T) {
function TestAtomicLevelMutation (line 83) | func TestAtomicLevelMutation(t *testing.T) {
function TestAtomicLevelText (line 101) | func TestAtomicLevelText(t *testing.T) {
FILE: logger.go
type Logger (line 41) | type Logger struct
method Sugar (line 146) | func (log *Logger) Sugar() *SugaredLogger {
method Named (line 154) | func (log *Logger) Named(s string) *Logger {
method WithOptions (line 169) | func (log *Logger) WithOptions(opts ...Option) *Logger {
method With (line 180) | func (log *Logger) With(fields ...Field) *Logger {
method WithLazy (line 202) | func (log *Logger) WithLazy(fields ...Field) *Logger {
method Level (line 214) | func (log *Logger) Level() zapcore.Level {
method Check (line 221) | func (log *Logger) Check(lvl zapcore.Level, msg string) *zapcore.Check...
method Log (line 229) | func (log *Logger) Log(lvl zapcore.Level, msg string, fields ...Field) {
method Debug (line 237) | func (log *Logger) Debug(msg string, fields ...Field) {
method Info (line 245) | func (log *Logger) Info(msg string, fields ...Field) {
method Warn (line 253) | func (log *Logger) Warn(msg string, fields ...Field) {
method Error (line 261) | func (log *Logger) Error(msg string, fields ...Field) {
method DPanic (line 273) | func (log *Logger) DPanic(msg string, fields ...Field) {
method Panic (line 283) | func (log *Logger) Panic(msg string, fields ...Field) {
method Fatal (line 294) | func (log *Logger) Fatal(msg string, fields ...Field) {
method Sync (line 302) | func (log *Logger) Sync() error {
method Core (line 307) | func (log *Logger) Core() zapcore.Core {
method Name (line 313) | func (log *Logger) Name() string {
method clone (line 317) | func (log *Logger) clone() *Logger {
method check (line 322) | func (log *Logger) check(lvl zapcore.Level, msg string) *zapcore.Check...
function New (line 69) | func New(core zapcore.Core, options ...Option) *Logger {
function NewNop (line 87) | func NewNop() *Logger {
function NewProduction (line 100) | func NewProduction(options ...Option) (*Logger, error) {
function NewDevelopment (line 108) | func NewDevelopment(options ...Option) (*Logger, error) {
function Must (line 117) | func Must(logger *Logger, err error) *Logger {
function NewExample (line 129) | func NewExample(options ...Option) *Logger {
function terminalHookOverride (line 424) | func terminalHookOverride(defaultHook, override zapcore.CheckWriteHook) ...
FILE: logger_bench_test.go
type user (line 35) | type user struct
method MarshalLogObject (line 41) | func (u *user) MarshalLogObject(enc zapcore.ObjectEncoder) error {
function withBenchedLogger (line 54) | func withBenchedLogger(b *testing.B, f func(*Logger)) {
function BenchmarkNoContext (line 69) | func BenchmarkNoContext(b *testing.B) {
function BenchmarkBoolField (line 75) | func BenchmarkBoolField(b *testing.B) {
function BenchmarkByteStringField (line 81) | func BenchmarkByteStringField(b *testing.B) {
function BenchmarkFloat64Field (line 88) | func BenchmarkFloat64Field(b *testing.B) {
function BenchmarkIntField (line 94) | func BenchmarkIntField(b *testing.B) {
function BenchmarkInt64Field (line 100) | func BenchmarkInt64Field(b *testing.B) {
function BenchmarkStringField (line 106) | func BenchmarkStringField(b *testing.B) {
function BenchmarkStringerField (line 112) | func BenchmarkStringerField(b *testing.B) {
function BenchmarkTimeField (line 118) | func BenchmarkTimeField(b *testing.B) {
function BenchmarkDurationField (line 125) | func BenchmarkDurationField(b *testing.B) {
function BenchmarkErrorField (line 131) | func BenchmarkErrorField(b *testing.B) {
function BenchmarkErrorsField (line 138) | func BenchmarkErrorsField(b *testing.B) {
function BenchmarkStackField (line 150) | func BenchmarkStackField(b *testing.B) {
function BenchmarkObjectField (line 156) | func BenchmarkObjectField(b *testing.B) {
function BenchmarkReflectField (line 162) | func BenchmarkReflectField(b *testing.B) {
function BenchmarkAddCallerHook (line 168) | func BenchmarkAddCallerHook(b *testing.B) {
function BenchmarkAddCallerAndStacktrace (line 185) | func BenchmarkAddCallerAndStacktrace(b *testing.B) {
function Benchmark5WithsUsed (line 203) | func Benchmark5WithsUsed(b *testing.B) {
function Benchmark5WithsNotUsed (line 209) | func Benchmark5WithsNotUsed(b *testing.B) {
function Benchmark5WithLazysUsed (line 213) | func Benchmark5WithLazysUsed(b *testing.B) {
function Benchmark5WithLazysNotUsed (line 219) | func Benchmark5WithLazysNotUsed(b *testing.B) {
function benchmarkWithUsed (line 223) | func benchmarkWithUsed(b *testing.B, withMethod func(*Logger, ...zapcore...
function Benchmark10Fields (line 245) | func Benchmark10Fields(b *testing.B) {
function Benchmark100Fields (line 262) | func Benchmark100Fields(b *testing.B) {
function BenchmarkAny (line 287) | func BenchmarkAny(b *testing.B) {
FILE: logger_test.go
function makeCountingHook (line 40) | func makeCountingHook() (func(zapcore.Entry) error, *atomic.Int64) {
function TestLoggerAtomicLevel (line 49) | func TestLoggerAtomicLevel(t *testing.T) {
function TestLoggerLevel (line 88) | func TestLoggerLevel(t *testing.T) {
function TestLoggerInitialFields (line 115) | func TestLoggerInitialFields(t *testing.T) {
function TestLoggerWith (line 128) | func TestLoggerWith(t *testing.T) {
function TestLoggerWithCaptures (line 178) | func TestLoggerWithCaptures(t *testing.T) {
function TestLoggerLogPanic (line 375) | func TestLoggerLogPanic(t *testing.T) {
function TestLoggerLogFatal (line 405) | func TestLoggerLogFatal(t *testing.T) {
function TestLoggerLeveledMethods (line 432) | func TestLoggerLeveledMethods(t *testing.T) {
function TestLoggerLogLevels (line 458) | func TestLoggerLogLevels(t *testing.T) {
function TestLoggerAlwaysPanics (line 481) | func TestLoggerAlwaysPanics(t *testing.T) {
function TestLoggerAlwaysFatals (line 497) | func TestLoggerAlwaysFatals(t *testing.T) {
function TestLoggerDPanic (line 518) | func TestLoggerDPanic(t *testing.T) {
function TestLoggerNoOpsDisabledLevels (line 539) | func TestLoggerNoOpsDisabledLevels(t *testing.T) {
function TestLoggerNames (line 551) | func TestLoggerNames(t *testing.T) {
function TestLoggerWriteFailure (line 590) | func TestLoggerWriteFailure(t *testing.T) {
function TestLoggerSync (line 607) | func TestLoggerSync(t *testing.T) {
function TestLoggerSyncFail (line 614) | func TestLoggerSyncFail(t *testing.T) {
function TestLoggerAddCaller (line 627) | func TestLoggerAddCaller(t *testing.T) {
function TestLoggerAddCallerFunction (line 659) | func TestLoggerAddCallerFunction(t *testing.T) {
function TestLoggerAddCallerFail (line 739) | func TestLoggerAddCallerFail(t *testing.T) {
function TestLoggerReplaceCore (line 762) | func TestLoggerReplaceCore(t *testing.T) {
function TestLoggerIncreaseLevel (line 774) | func TestLoggerIncreaseLevel(t *testing.T) {
function TestLoggerHooks (line 789) | func TestLoggerHooks(t *testing.T) {
function TestLoggerConcurrent (line 798) | func TestLoggerConcurrent(t *testing.T) {
function TestLoggerFatalOnNoop (line 828) | func TestLoggerFatalOnNoop(t *testing.T) {
function TestLoggerCustomOnPanic (line 839) | func TestLoggerCustomOnPanic(t *testing.T) {
function TestLoggerCustomOnFatal (line 963) | func TestLoggerCustomOnFatal(t *testing.T) {
type customWriteHook (line 1007) | type customWriteHook struct
method OnWrite (line 1011) | func (h *customWriteHook) OnWrite(_ *zapcore.CheckedEntry, _ []Field) {
function TestLoggerWithFatalHook (line 1015) | func TestLoggerWithFatalHook(t *testing.T) {
function TestNopLogger (line 1024) | func TestNopLogger(t *testing.T) {
function TestMust (line 1045) | func TestMust(t *testing.T) {
function infoLog (line 1055) | func infoLog(logger *Logger, msg string, fields ...Field) {
function infoLogSugared (line 1059) | func infoLogSugared(logger *SugaredLogger, args ...interface{}) {
FILE: options.go
type Option (line 30) | type Option interface
type optionFunc (line 35) | type optionFunc
method apply (line 37) | func (f optionFunc) apply(log *Logger) {
function WrapCore (line 42) | func WrapCore(f func(zapcore.Core) zapcore.Core) Option {
function Hooks (line 55) | func Hooks(hooks ...func(zapcore.Entry) error) Option {
function Fields (line 62) | func Fields(fs ...Field) Option {
function ErrorOutput (line 75) | func ErrorOutput(w zapcore.WriteSyncer) Option {
function Development (line 83) | func Development() Option {
function AddCaller (line 91) | func AddCaller() Option {
function WithCaller (line 98) | func WithCaller(enabled bool) Option {
function AddCallerSkip (line 108) | func AddCallerSkip(skip int) Option {
function AddStacktrace (line 116) | func AddStacktrace(lvl zapcore.LevelEnabler) Option {
function IncreaseLevel (line 124) | func IncreaseLevel(lvl zapcore.LevelEnabler) Option {
function WithPanicHook (line 148) | func WithPanicHook(hook zapcore.CheckWriteHook) Option {
function OnFatal (line 157) | func OnFatal(action zapcore.CheckWriteAction) Option {
function WithFatalHook (line 174) | func WithFatalHook(hook zapcore.CheckWriteHook) Option {
function WithClock (line 182) | func WithClock(clock zapcore.Clock) Option {
FILE: sink.go
constant schemeFile (line 36) | schemeFile = "file"
type Sink (line 41) | type Sink interface
type errSinkNotFound (line 46) | type errSinkNotFound struct
method Error (line 50) | func (e *errSinkNotFound) Error() string {
type nopCloserSink (line 54) | type nopCloserSink struct
method Close (line 56) | func (nopCloserSink) Close() error { return nil }
type sinkRegistry (line 58) | type sinkRegistry struct
method RegisterSink (line 75) | func (sr *sinkRegistry) RegisterSink(scheme string, factory func(*url....
method newSink (line 93) | func (sr *sinkRegistry) newSink(rawURL string) (Sink, error) {
method newFileSinkFromURL (line 130) | func (sr *sinkRegistry) newFileSinkFromURL(u *url.URL) (Sink, error) {
method newFileSinkFromPath (line 151) | func (sr *sinkRegistry) newFileSinkFromPath(path string) (Sink, error) {
function newSinkRegistry (line 64) | func newSinkRegistry() *sinkRegistry {
function RegisterSink (line 126) | func RegisterSink(scheme string, factory func(*url.URL) (Sink, error)) e...
function normalizeScheme (line 161) | func normalizeScheme(s string) (string, error) {
FILE: sink_test.go
function stubSinkRegistry (line 36) | func stubSinkRegistry(t testing.TB) *sinkRegistry {
function TestRegisterSink (line 47) | func TestRegisterSink(t *testing.T) {
function TestRegisterSinkErrors (line 86) | func TestRegisterSinkErrors(t *testing.T) {
FILE: sink_windows_test.go
function TestWindowsPaths (line 32) | func TestWindowsPaths(t *testing.T) {
FILE: stacktrace_ext_test.go
function TestStacktraceFiltersZapLog (line 49) | func TestStacktraceFiltersZapLog(t *testing.T) {
function TestStacktraceFiltersZapMarshal (line 59) | func TestStacktraceFiltersZapMarshal(t *testing.T) {
function TestStacktraceFiltersVendorZap (line 86) | func TestStacktraceFiltersVendorZap(t *testing.T) {
function TestStacktraceWithoutCallerSkip (line 122) | func TestStacktraceWithoutCallerSkip(t *testing.T) {
function TestStacktraceWithCallerSkip (line 133) | func TestStacktraceWithCallerSkip(t *testing.T) {
function withLogger (line 148) | func withLogger(t *testing.T, fn func(logger *zap.Logger, out *bytes.Buf...
function verifyNoZap (line 156) | func verifyNoZap(t *testing.T, logs string) {
function withGoPath (line 162) | func withGoPath(t *testing.T, f func(goPath string)) {
function getSelfFilename (line 169) | func getSelfFilename(t *testing.T) string {
function setupSymlink (line 176) | func setupSymlink(t *testing.T, src, dst string) {
type dependency (line 188) | type dependency struct
function downloadDependencies (line 195) | func downloadDependencies(t *testing.T) []dependency {
FILE: sugar.go
constant _oddNumberErrMsg (line 32) | _oddNumberErrMsg = "Ignored key without a value."
constant _nonStringKeyErrMsg (line 33) | _nonStringKeyErrMsg = "Ignored key-value pairs with non-string keys."
constant _multipleErrMsg (line 34) | _multipleErrMsg = "Multiple errors without a key."
type SugaredLogger (line 55) | type SugaredLogger struct
method Desugar (line 63) | func (s *SugaredLogger) Desugar() *Logger {
method Named (line 70) | func (s *SugaredLogger) Named(name string) *SugaredLogger {
method WithOptions (line 76) | func (s *SugaredLogger) WithOptions(opts ...Option) *SugaredLogger {
method With (line 114) | func (s *SugaredLogger) With(args ...interface{}) *SugaredLogger {
method WithLazy (line 129) | func (s *SugaredLogger) WithLazy(args ...interface{}) *SugaredLogger {
method Level (line 136) | func (s *SugaredLogger) Level() zapcore.Level {
method Log (line 142) | func (s *SugaredLogger) Log(lvl zapcore.Level, args ...interface{}) {
method Debug (line 148) | func (s *SugaredLogger) Debug(args ...interface{}) {
method Info (line 154) | func (s *SugaredLogger) Info(args ...interface{}) {
method Warn (line 160) | func (s *SugaredLogger) Warn(args ...interface{}) {
method Error (line 166) | func (s *SugaredLogger) Error(args ...interface{}) {
method DPanic (line 173) | func (s *SugaredLogger) DPanic(args ...interface{}) {
method Panic (line 179) | func (s *SugaredLogger) Panic(args ...interface{}) {
method Fatal (line 185) | func (s *SugaredLogger) Fatal(args ...interface{}) {
method Logf (line 191) | func (s *SugaredLogger) Logf(lvl zapcore.Level, template string, args ...
method Debugf (line 197) | func (s *SugaredLogger) Debugf(template string, args ...interface{}) {
method Infof (line 203) | func (s *SugaredLogger) Infof(template string, args ...interface{}) {
method Warnf (line 209) | func (s *SugaredLogger) Warnf(template string, args ...interface{}) {
method Errorf (line 215) | func (s *SugaredLogger) Errorf(template string, args ...interface{}) {
method DPanicf (line 222) | func (s *SugaredLogger) DPanicf(template string, args ...interface{}) {
method Panicf (line 228) | func (s *SugaredLogger) Panicf(template string, args ...interface{}) {
method Fatalf (line 234) | func (s *SugaredLogger) Fatalf(template string, args ...interface{}) {
method Logw (line 240) | func (s *SugaredLogger) Logw(lvl zapcore.Level, msg string, keysAndVal...
method Debugw (line 250) | func (s *SugaredLogger) Debugw(msg string, keysAndValues ...interface{...
method Infow (line 256) | func (s *SugaredLogger) Infow(msg string, keysAndValues ...interface{}) {
method Warnw (line 262) | func (s *SugaredLogger) Warnw(msg string, keysAndValues ...interface{}) {
method Errorw (line 268) | func (s *SugaredLogger) Errorw(msg string, keysAndValues ...interface{...
method DPanicw (line 275) | func (s *SugaredLogger) DPanicw(msg string, keysAndValues ...interface...
method Panicw (line 281) | func (s *SugaredLogger) Panicw(msg string, keysAndValues ...interface{...
method Fatalw (line 287) | func (s *SugaredLogger) Fatalw(msg string, keysAndValues ...interface{...
method Logln (line 293) | func (s *SugaredLogger) Logln(lvl zapcore.Level, args ...interface{}) {
method Debugln (line 299) | func (s *SugaredLogger) Debugln(args ...interface{}) {
method Infoln (line 305) | func (s *SugaredLogger) Infoln(args ...interface{}) {
method Warnln (line 311) | func (s *SugaredLogger) Warnln(args ...interface{}) {
method Errorln (line 317) | func (s *SugaredLogger) Errorln(args ...interface{}) {
method DPanicln (line 324) | func (s *SugaredLogger) DPanicln(args ...interface{}) {
method Panicln (line 330) | func (s *SugaredLogger) Panicln(args ...interface{}) {
method Fatalln (line 336) | func (s *SugaredLogger) Fatalln(args ...interface{}) {
method Sync (line 341) | func (s *SugaredLogger) Sync() error {
method log (line 346) | func (s *SugaredLogger) log(lvl zapcore.Level, template string, fmtArg...
method logln (line 360) | func (s *SugaredLogger) logln(lvl zapcore.Level, fmtArgs []interface{}...
method sweetenFields (line 395) | func (s *SugaredLogger) sweetenFields(args []interface{}) []Field {
function getMessage (line 372) | func getMessage(template string, fmtArgs []interface{}) string {
function getMessageln (line 390) | func getMessageln(fmtArgs []interface{}) string {
type invalidPair (line 456) | type invalidPair struct
method MarshalLogObject (line 461) | func (p invalidPair) MarshalLogObject(enc zapcore.ObjectEncoder) error {
type invalidPairs (line 468) | type invalidPairs
method MarshalLogArray (line 470) | func (ps invalidPairs) MarshalLogArray(enc zapcore.ArrayEncoder) error {
FILE: sugar_test.go
function TestSugarWith (line 38) | func TestSugarWith(t *testing.T) {
function TestSugarWithCaptures (line 165) | func TestSugarWithCaptures(t *testing.T) {
function TestSugaredLoggerLevel (line 241) | func TestSugaredLoggerLevel(t *testing.T) {
function TestSugarFieldsInvalidPairs (line 270) | func TestSugarFieldsInvalidPairs(t *testing.T) {
function TestSugarStructuredLogging (line 290) | func TestSugarStructuredLogging(t *testing.T) {
function TestSugarConcatenatingLogging (line 328) | func TestSugarConcatenatingLogging(t *testing.T) {
function TestSugarTemplatedLogging (line 361) | func TestSugarTemplatedLogging(t *testing.T) {
function TestSugarLnLogging (line 398) | func TestSugarLnLogging(t *testing.T) {
function TestSugarLnLoggingIgnored (line 435) | func TestSugarLnLoggingIgnored(t *testing.T) {
function TestSugarPanicLogging (line 442) | func TestSugarPanicLogging(t *testing.T) {
function TestSugarFatalLogging (line 477) | func TestSugarFatalLogging(t *testing.T) {
function TestSugarAddCaller (line 513) | func TestSugarAddCaller(t *testing.T) {
function TestSugarAddCallerFail (line 538) | func TestSugarAddCallerFail(t *testing.T) {
function TestSugarWithOptionsIncreaseLevel (line 556) | func TestSugarWithOptionsIncreaseLevel(t *testing.T) {
function TestSugarLnWithOptionsIncreaseLevel (line 572) | func TestSugarLnWithOptionsIncreaseLevel(t *testing.T) {
function BenchmarkSugarSingleStrArg (line 588) | func BenchmarkSugarSingleStrArg(b *testing.B) {
function BenchmarkLnSugarSingleStrArg (line 596) | func BenchmarkLnSugarSingleStrArg(b *testing.B) {
FILE: time.go
function timeToMillis (line 25) | func timeToMillis(t time.Time) int64 {
FILE: time_test.go
function TestTimeToMillis (line 30) | func TestTimeToMillis(t *testing.T) {
FILE: writer.go
function Open (line 50) | func Open(paths ...string) (zapcore.WriteSyncer, func(), error) {
function open (line 60) | func open(paths []string) ([]zapcore.WriteSyncer, func(), error) {
function CombineWriteSyncers (line 93) | func CombineWriteSyncers(writers ...zapcore.WriteSyncer) zapcore.WriteSy...
FILE: writer_test.go
function TestOpenNoPaths (line 38) | func TestOpenNoPaths(t *testing.T) {
function TestOpen (line 51) | func TestOpen(t *testing.T) {
function TestOpenPathsNotFound (line 96) | func TestOpenPathsNotFound(t *testing.T) {
function TestOpenRelativePath (line 142) | func TestOpenRelativePath(t *testing.T) {
function TestOpenFails (line 162) | func TestOpenFails(t *testing.T) {
function TestOpenOtherErrors (line 179) | func TestOpenOtherErrors(t *testing.T) {
type testWriter (line 227) | type testWriter struct
method Write (line 232) | func (w *testWriter) Write(actual []byte) (int, error) {
method Sync (line 237) | func (w *testWriter) Sync() error {
function TestOpenWithErroringSinkFactory (line 241) | func TestOpenWithErroringSinkFactory(t *testing.T) {
function TestCombineWriteSyncers (line 254) | func TestCombineWriteSyncers(t *testing.T) {
function fileExists (line 261) | func fileExists(name string) bool {
FILE: zapcore/buffered_write_syncer.go
constant _defaultBufferSize (line 33) | _defaultBufferSize = 256 * 1024
constant _defaultFlushInterval (line 37) | _defaultFlushInterval = 30 * time.Second
type BufferedWriteSyncer (line 77) | type BufferedWriteSyncer struct
method initialize (line 112) | func (s *BufferedWriteSyncer) initialize() {
method Write (line 137) | func (s *BufferedWriteSyncer) Write(bs []byte) (int, error) {
method Sync (line 158) | func (s *BufferedWriteSyncer) Sync() error {
method flushLoop (line 172) | func (s *BufferedWriteSyncer) flushLoop() {
method Stop (line 190) | func (s *BufferedWriteSyncer) Stop() (err error) {
FILE: zapcore/buffered_write_syncer_bench_test.go
function BenchmarkBufferedWriteSyncer (line 31) | func BenchmarkBufferedWriteSyncer(b *testing.B) {
FILE: zapcore/buffered_write_syncer_test.go
function TestBufferWriter (line 33) | func TestBufferWriter(t *testing.T) {
function TestBufferWriterWithoutStart (line 138) | func TestBufferWriterWithoutStart(t *testing.T) {
FILE: zapcore/clock.go
type Clock (line 30) | type Clock interface
type systemClock (line 40) | type systemClock struct
method Now (line 42) | func (systemClock) Now() time.Time {
method NewTicker (line 46) | func (systemClock) NewTicker(duration time.Duration) *time.Ticker {
FILE: zapcore/clock_test.go
function TestSystemClock_NewTicker (line 33) | func TestSystemClock_NewTicker(t *testing.T) {
FILE: zapcore/console_encoder.go
function getSliceEncoder (line 37) | func getSliceEncoder() *sliceArrayEncoder {
function putSliceEncoder (line 41) | func putSliceEncoder(e *sliceArrayEncoder) {
type consoleEncoder (line 46) | type consoleEncoder struct
method Clone (line 66) | func (c consoleEncoder) Clone() Encoder {
method EncodeEntry (line 70) | func (c consoleEncoder) EncodeEntry(ent Entry, fields []Field) (*buffe...
method writeContext (line 132) | func (c consoleEncoder) writeContext(line *buffer.Buffer, extra []Fiel...
method addSeparatorIfNecessary (line 153) | func (c consoleEncoder) addSeparatorIfNecessary(line *buffer.Buffer) {
function NewConsoleEncoder (line 58) | func NewConsoleEncoder(cfg EncoderConfig) Encoder {
FILE: zapcore/console_encoder_bench_test.go
function BenchmarkZapConsole (line 30) | func BenchmarkZapConsole(b *testing.B) {
FILE: zapcore/console_encoder_test.go
function TestConsoleEncodeEntry (line 40) | func TestConsoleEncodeEntry(t *testing.T) {
function TestConsoleSeparator (line 84) | func TestConsoleSeparator(t *testing.T) {
function encoderTestEncoderConfig (line 131) | func encoderTestEncoderConfig(separator string) EncoderConfig {
FILE: zapcore/core.go
type Core (line 25) | type Core interface
type nopCore (line 47) | type nopCore struct
method Enabled (line 51) | func (nopCore) Enabled(Level) bool { return...
method With (line 52) | func (n nopCore) With([]Field) Core { return...
method Check (line 53) | func (nopCore) Check(_ Entry, ce *CheckedEntry) *CheckedEntry { return...
method Write (line 54) | func (nopCore) Write(Entry, []Field) error { return...
method Sync (line 55) | func (nopCore) Sync() error { return...
function NewNopCore (line 50) | func NewNopCore() Core { return n...
function NewCore (line 58) | func NewCore(enc Encoder, ws WriteSyncer, enab LevelEnabler) Core {
type ioCore (line 66) | type ioCore struct
method Level (line 77) | func (c *ioCore) Level() Level {
method With (line 81) | func (c *ioCore) With(fields []Field) Core {
method Check (line 87) | func (c *ioCore) Check(ent Entry, ce *CheckedEntry) *CheckedEntry {
method Write (line 94) | func (c *ioCore) Write(ent Entry, fields []Field) error {
method Sync (line 112) | func (c *ioCore) Sync() error {
method clone (line 116) | func (c *ioCore) clone() *ioCore {
FILE: zapcore/core_test.go
function makeInt64Field (line 37) | func makeInt64Field(key string, val int) Field {
function TestNopCore (line 41) | func TestNopCore(t *testing.T) {
function TestIOCore (line 70) | func TestIOCore(t *testing.T) {
function TestIOCoreSyncFail (line 111) | func TestIOCoreSyncFail(t *testing.T) {
function TestIOCoreSyncsOutput (line 130) | func TestIOCoreSyncsOutput(t *testing.T) {
function TestIOCoreWriteFailure (line 157) | func TestIOCoreWriteFailure(t *testing.T) {
FILE: zapcore/encoder.go
constant DefaultLineEnding (line 34) | DefaultLineEnding = "\n"
constant OmitKey (line 37) | OmitKey = ""
type LevelEncoder (line 43) | type LevelEncoder
method UnmarshalText (line 81) | func (e *LevelEncoder) UnmarshalText(text []byte) error {
function LowercaseLevelEncoder (line 47) | func LowercaseLevelEncoder(l Level, enc PrimitiveArrayEncoder) {
function LowercaseColorLevelEncoder (line 53) | func LowercaseColorLevelEncoder(l Level, enc PrimitiveArrayEncoder) {
function CapitalLevelEncoder (line 63) | func CapitalLevelEncoder(l Level, enc PrimitiveArrayEncoder) {
function CapitalColorLevelEncoder (line 69) | func CapitalColorLevelEncoder(l Level, enc PrimitiveArrayEncoder) {
type TimeEncoder (line 99) | type TimeEncoder
method UnmarshalText (line 177) | func (e *TimeEncoder) UnmarshalText(text []byte) error {
method UnmarshalYAML (line 204) | func (e *TimeEncoder) UnmarshalYAML(unmarshal func(interface{}) error)...
method UnmarshalJSON (line 221) | func (e *TimeEncoder) UnmarshalJSON(data []byte) error {
function EpochTimeEncoder (line 103) | func EpochTimeEncoder(t time.Time, enc PrimitiveArrayEncoder) {
function EpochMillisTimeEncoder (line 111) | func EpochMillisTimeEncoder(t time.Time, enc PrimitiveArrayEncoder) {
function EpochNanosTimeEncoder (line 119) | func EpochNanosTimeEncoder(t time.Time, enc PrimitiveArrayEncoder) {
function encodeTimeLayout (line 123) | func encodeTimeLayout(t time.Time, layout string, enc PrimitiveArrayEnco...
function ISO8601TimeEncoder (line 141) | func ISO8601TimeEncoder(t time.Time, enc PrimitiveArrayEncoder) {
function RFC3339TimeEncoder (line 149) | func RFC3339TimeEncoder(t time.Time, enc PrimitiveArrayEncoder) {
function RFC3339NanoTimeEncoder (line 158) | func RFC3339NanoTimeEncoder(t time.Time, enc PrimitiveArrayEncoder) {
function TimeEncoderOfLayout (line 164) | func TimeEncoderOfLayout(layout string) TimeEncoder {
type DurationEncoder (line 231) | type DurationEncoder
method UnmarshalText (line 259) | func (e *DurationEncoder) UnmarshalText(text []byte) error {
function SecondsDurationEncoder (line 234) | func SecondsDurationEncoder(d time.Duration, enc PrimitiveArrayEncoder) {
function NanosDurationEncoder (line 240) | func NanosDurationEncoder(d time.Duration, enc PrimitiveArrayEncoder) {
function MillisDurationEncoder (line 246) | func MillisDurationEncoder(d time.Duration, enc PrimitiveArrayEncoder) {
function StringDurationEncoder (line 252) | func StringDurationEncoder(d time.Duration, enc PrimitiveArrayEncoder) {
type CallerEncoder (line 277) | type CallerEncoder
method UnmarshalText (line 295) | func (e *CallerEncoder) UnmarshalText(text []byte) error {
function FullCallerEncoder (line 281) | func FullCallerEncoder(caller EntryCaller, enc PrimitiveArrayEncoder) {
function ShortCallerEncoder (line 288) | func ShortCallerEncoder(caller EntryCaller, enc PrimitiveArrayEncoder) {
type NameEncoder (line 310) | type NameEncoder
method UnmarshalText (line 319) | func (e *NameEncoder) UnmarshalText(text []byte) error {
function FullNameEncoder (line 313) | func FullNameEncoder(loggerName string, enc PrimitiveArrayEncoder) {
type EncoderConfig (line 331) | type EncoderConfig struct
type ObjectEncoder (line 364) | type ObjectEncoder interface
type ArrayEncoder (line 405) | type ArrayEncoder interface
type PrimitiveArrayEncoder (line 425) | type PrimitiveArrayEncoder interface
type Encoder (line 455) | type Encoder interface
FILE: zapcore/encoder_test.go
function testEncoderConfig (line 49) | func testEncoderConfig() EncoderConfig {
function humanEncoderConfig (line 66) | func humanEncoderConfig() EncoderConfig {
function capitalNameEncoder (line 74) | func capitalNameEncoder(loggerName string, enc PrimitiveArrayEncoder) {
function TestEncoderConfiguration (line 78) | func TestEncoderConfiguration(t *testing.T) {
function TestLevelEncoders (line 564) | func TestLevelEncoders(t *testing.T) {
function TestTimeEncoders (line 587) | func TestTimeEncoders(t *testing.T) {
function TestTimeEncodersWrongYAML (line 619) | func TestTimeEncodersWrongYAML(t *testing.T) {
function TestTimeEncodersParseFromJSON (line 630) | func TestTimeEncodersParseFromJSON(t *testing.T) {
function TestDurationEncoders (line 653) | func TestDurationEncoders(t *testing.T) {
function TestCallerEncoders (line 678) | func TestCallerEncoders(t *testing.T) {
function TestNameEncoders (line 702) | func TestNameEncoders(t *testing.T) {
function assertAppended (line 724) | func assertAppended(t testing.TB, expected interface{}, f func(ArrayEnco...
FILE: zapcore/entry.go
function getCheckedEntry (line 42) | func getCheckedEntry() *CheckedEntry {
function putCheckedEntry (line 48) | func putCheckedEntry(ce *CheckedEntry) {
function NewEntryCaller (line 57) | func NewEntryCaller(pc uintptr, file string, line int, ok bool) EntryCal...
type EntryCaller (line 70) | type EntryCaller struct
method String (line 79) | func (ec EntryCaller) String() string {
method FullPath (line 85) | func (ec EntryCaller) FullPath() string {
method TrimmedPath (line 100) | func (ec EntryCaller) TrimmedPath() string {
type Entry (line 143) | type Entry struct
type CheckWriteHook (line 164) | type CheckWriteHook interface
type CheckWriteAction (line 175) | type CheckWriteAction
method OnWrite (line 191) | func (a CheckWriteAction) OnWrite(ce *CheckedEntry, _ []Field) {
constant WriteThenNoop (line 180) | WriteThenNoop CheckWriteAction = iota
constant WriteThenGoexit (line 182) | WriteThenGoexit
constant WriteThenPanic (line 184) | WriteThenPanic
constant WriteThenFatal (line 186) | WriteThenFatal
type CheckPreWriteHook (line 210) | type CheckPreWriteHook
type CheckedEntry (line 218) | type CheckedEntry struct
method reset (line 227) | func (ce *CheckedEntry) reset() {
method Write (line 246) | func (ce *CheckedEntry) Write(fields ...Field) {
method AddCore (line 298) | func (ce *CheckedEntry) AddCore(ent Entry, core Core) *CheckedEntry {
method Should (line 312) | func (ce *CheckedEntry) Should(ent Entry, should CheckWriteAction) *Ch...
method Before (line 319) | func (ce *CheckedEntry) Before(ent Entry, hook CheckPreWriteHook) *Che...
method After (line 331) | func (ce *CheckedEntry) After(ent Entry, hook CheckWriteHook) *Checked...
FILE: zapcore/entry_ext_test.go
function TestCheckedEntryIllegalReuse (line 34) | func TestCheckedEntryIllegalReuse(t *testing.T) {
FILE: zapcore/entry_test.go
function assertGoexit (line 32) | func assertGoexit(t *testing.T, f func()) {
function TestPutNilEntry (line 48) | func TestPutNilEntry(t *testing.T) {
function TestEntryCaller (line 76) | func TestEntryCaller(t *testing.T) {
function TestCheckedEntryWrite (line 106) | func TestCheckedEntryWrite(t *testing.T) {
type customHook (line 143) | type customHook struct
method OnWrite (line 147) | func (c *customHook) OnWrite(_ *CheckedEntry, _ []Field) {
function TestCheckedEntryBefore (line 151) | func TestCheckedEntryBefore(t *testing.T) {
type recordingCore (line 215) | type recordingCore struct
method Enabled (line 220) | func (c *recordingCore) Enabled(Level) bool ...
method With (line 221) | func (c *recordingCore) With([]Field) Core ...
method Check (line 222) | func (c *recordingCore) Check(ent Entry, ce *CheckedEntry) *CheckedEnt...
method Sync (line 223) | func (c *recordingCore) Sync() error ...
method Write (line 224) | func (c *recordingCore) Write(ent Entry, fields []Field) error {
FILE: zapcore/error.go
function encodeError (line 47) | func encodeError(key string, err error, enc ObjectEncoder) (retErr error) {
type errorGroup (line 81) | type errorGroup interface
type errArray (line 92) | type errArray
method MarshalLogArray (line 94) | func (errs errArray) MarshalLogArray(arr ArrayEncoder) error {
type errArrayElem (line 117) | type errArrayElem struct
method MarshalLogArray (line 125) | func (e *errArrayElem) MarshalLogArray(arr ArrayEncoder) error {
method MarshalLogObject (line 129) | func (e *errArrayElem) MarshalLogObject(enc ObjectEncoder) error {
method Free (line 133) | func (e *errArrayElem) Free() {
function newErrArrayElem (line 119) | func newErrArrayElem(err error) *errArrayElem {
FILE: zapcore/error_test.go
type errTooManyUsers (line 36) | type errTooManyUsers
method Error (line 38) | func (e errTooManyUsers) Error() string {
method Format (line 42) | func (e errTooManyUsers) Format(s fmt.State, verb rune) {
type errTooFewUsers (line 50) | type errTooFewUsers
method Error (line 52) | func (e errTooFewUsers) Error() string {
method Format (line 56) | func (e errTooFewUsers) Format(s fmt.State, verb rune) {
type customMultierr (line 63) | type customMultierr struct
method Error (line 65) | func (e customMultierr) Error() string {
method Errors (line 69) | func (e customMultierr) Errors() []error {
function TestErrorEncoding (line 80) | func TestErrorEncoding(t *testing.T) {
function TestRichErrorSupport (line 171) | func TestRichErrorSupport(t *testing.T) {
function TestErrArrayBrokenEncoder (line 182) | func TestErrArrayBrokenEncoder(t *testing.T) {
type brokenArrayObjectEncoder (line 209) | type brokenArrayObjectEncoder struct
method AddArray (line 216) | func (enc brokenArrayObjectEncoder) AddArray(key string, marshaler Arr...
method AppendObject (line 224) | func (enc brokenArrayObjectEncoder) AppendObject(ObjectMarshaler) error {
FILE: zapcore/field.go
type FieldType (line 33) | type FieldType
constant UnknownType (line 37) | UnknownType FieldType = iota
constant ArrayMarshalerType (line 39) | ArrayMarshalerType
constant ObjectMarshalerType (line 41) | ObjectMarshalerType
constant BinaryType (line 43) | BinaryType
constant BoolType (line 45) | BoolType
constant ByteStringType (line 47) | ByteStringType
constant Complex128Type (line 49) | Complex128Type
constant Complex64Type (line 51) | Complex64Type
constant DurationType (line 53) | DurationType
constant Float64Type (line 55) | Float64Type
constant Float32Type (line 57) | Float32Type
constant Int64Type (line 59) | Int64Type
constant Int32Type (line 61) | Int32Type
constant Int16Type (line 63) | Int16Type
constant Int8Type (line 65) | Int8Type
constant StringType (line 67) | StringType
constant TimeType (line 70) | TimeType
constant TimeFullType (line 72) | TimeFullType
constant Uint64Type (line 74) | Uint64Type
constant Uint32Type (line 76) | Uint32Type
constant Uint16Type (line 78) | Uint16Type
constant Uint8Type (line 80) | Uint8Type
constant UintptrType (line 82) | UintptrType
constant ReflectType (line 85) | ReflectType
constant NamespaceType (line 88) | NamespaceType
constant StringerType (line 90) | StringerType
constant ErrorType (line 92) | ErrorType
constant SkipType (line 94) | SkipType
constant InlineMarshalerType (line 98) | InlineMarshalerType
type Field (line 104) | type Field struct
method AddTo (line 114) | func (f Field) AddTo(enc ObjectEncoder) {
method Equals (line 190) | func (f Field) Equals(other Field) bool {
function addFields (line 208) | func addFields(enc ObjectEncoder, fields []Field) {
function encodeStringer (line 214) | func encodeStringer(key string, stringer interface{}, enc ObjectEncoder)...
FILE: zapcore/field_test.go
type users (line 39) | type users
method String (line 41) | func (u users) String() string {
method MarshalLogObject (line 45) | func (u users) MarshalLogObject(enc ObjectEncoder) error {
method MarshalLogArray (line 53) | func (u users) MarshalLogArray(enc ArrayEncoder) error {
type obj (line 63) | type obj struct
method String (line 67) | func (o *obj) String() string {
type errObj (line 85) | type errObj struct
method Error (line 90) | func (eobj *errObj) Error() string {
function TestUnknownFieldType (line 97) | func TestUnknownFieldType(t *testing.T) {
function TestFieldAddingError (line 105) | func TestFieldAddingError(t *testing.T) {
function TestFields (line 131) | func TestFields(t *testing.T) {
function TestInlineMarshaler (line 185) | func TestInlineMarshaler(t *testing.T) {
function TestEquals (line 206) | func TestEquals(t *testing.T) {
FILE: zapcore/hook.go
type hooked (line 25) | type hooked struct
method Level (line 48) | func (h *hooked) Level() Level {
method Check (line 52) | func (h *hooked) Check(ent Entry, ce *CheckedEntry) *CheckedEntry {
method With (line 62) | func (h *hooked) With(fields []Field) Core {
method Write (line 69) | func (h *hooked) Write(ent Entry, _ []Field) error {
function RegisterHooks (line 40) | func RegisterHooks(core Core, hooks ...func(Entry) error) Core {
FILE: zapcore/hook_test.go
function TestHooks (line 34) | func TestHooks(t *testing.T) {
FILE: zapcore/increase_level.go
type levelFilterCore (line 25) | type levelFilterCore struct
method Enabled (line 49) | func (c *levelFilterCore) Enabled(lvl Level) bool {
method Level (line 53) | func (c *levelFilterCore) Level() Level {
method With (line 57) | func (c *levelFilterCore) With(fields []Field) Core {
method Check (line 61) | func (c *levelFilterCore) Check(ent Entry, ce *CheckedEntry) *CheckedE...
method Write (line 69) | func (c *levelFilterCore) Write(ent Entry, fields []Field) error {
method Sync (line 73) | func (c *levelFilterCore) Sync() error {
function NewIncreaseLevelCore (line 39) | func NewIncreaseLevelCore(core Core, level LevelEnabler) (Core, error) {
FILE: zapcore/increase_level_test.go
function TestIncreaseLevel (line 36) | func TestIncreaseLevel(t *testing.T) {
FILE: zapcore/json_encoder.go
constant _hex (line 35) | _hex = "0123456789abcdef"
function putJSONEncoder (line 41) | func putJSONEncoder(enc *jsonEncoder) {
type jsonEncoder (line 54) | type jsonEncoder struct
method AddArray (line 100) | func (enc *jsonEncoder) AddArray(key string, arr ArrayMarshaler) error {
method AddObject (line 105) | func (enc *jsonEncoder) AddObject(key string, obj ObjectMarshaler) err...
method AddBinary (line 110) | func (enc *jsonEncoder) AddBinary(key string, val []byte) {
method AddByteString (line 114) | func (enc *jsonEncoder) AddByteString(key string, val []byte) {
method AddBool (line 119) | func (enc *jsonEncoder) AddBool(key string, val bool) {
method AddComplex128 (line 124) | func (enc *jsonEncoder) AddComplex128(key string, val complex128) {
method AddComplex64 (line 129) | func (enc *jsonEncoder) AddComplex64(key string, val complex64) {
method AddDuration (line 134) | func (enc *jsonEncoder) AddDuration(key string, val time.Duration) {
method AddFloat64 (line 139) | func (enc *jsonEncoder) AddFloat64(key string, val float64) {
method AddFloat32 (line 144) | func (enc *jsonEncoder) AddFloat32(key string, val float32) {
method AddInt64 (line 149) | func (enc *jsonEncoder) AddInt64(key string, val int64) {
method resetReflectBuf (line 154) | func (enc *jsonEncoder) resetReflectBuf() {
method encodeReflected (line 167) | func (enc *jsonEncoder) encodeReflected(obj interface{}) ([]byte, erro...
method AddReflected (line 179) | func (enc *jsonEncoder) AddReflected(key string, obj interface{}) error {
method OpenNamespace (line 189) | func (enc *jsonEncoder) OpenNamespace(key string) {
method AddString (line 195) | func (enc *jsonEncoder) AddString(key, val string) {
method AddTime (line 200) | func (enc *jsonEncoder) AddTime(key string, val time.Time) {
method AddUint64 (line 205) | func (enc *jsonEncoder) AddUint64(key string, val uint64) {
method AppendArray (line 210) | func (enc *jsonEncoder) AppendArray(arr ArrayMarshaler) error {
method AppendObject (line 218) | func (enc *jsonEncoder) AppendObject(obj ObjectMarshaler) error {
method AppendBool (line 232) | func (enc *jsonEncoder) AppendBool(val bool) {
method AppendByteString (line 237) | func (enc *jsonEncoder) AppendByteString(val []byte) {
method appendComplex (line 247) | func (enc *jsonEncoder) appendComplex(val complex128, precision int) {
method AppendDuration (line 265) | func (enc *jsonEncoder) AppendDuration(val time.Duration) {
method AppendInt64 (line 277) | func (enc *jsonEncoder) AppendInt64(val int64) {
method AppendReflected (line 282) | func (enc *jsonEncoder) AppendReflected(val interface{}) error {
method AppendString (line 292) | func (enc *jsonEncoder) AppendString(val string) {
method AppendTimeLayout (line 299) | func (enc *jsonEncoder) AppendTimeLayout(time time.Time, layout string) {
method AppendTime (line 306) | func (enc *jsonEncoder) AppendTime(val time.Time) {
method AppendUint64 (line 318) | func (enc *jsonEncoder) AppendUint64(val uint64) {
method AddInt (line 323) | func (enc *jsonEncoder) AddInt(k string, v int) { enc.AddInt64...
method AddInt32 (line 324) | func (enc *jsonEncoder) AddInt32(k string, v int32) { enc.AddInt64...
method AddInt16 (line 325) | func (enc *jsonEncoder) AddInt16(k string, v int16) { enc.AddInt64...
method AddInt8 (line 326) | func (enc *jsonEncoder) AddInt8(k string, v int8) { enc.AddInt64...
method AddUint (line 327) | func (enc *jsonEncoder) AddUint(k string, v uint) { enc.AddUint6...
method AddUint32 (line 328) | func (enc *jsonEncoder) AddUint32(k string, v uint32) { enc.AddUint6...
method AddUint16 (line 329) | func (enc *jsonEncoder) AddUint16(k string, v uint16) { enc.AddUint6...
method AddUint8 (line 330) | func (enc *jsonEncoder) AddUint8(k string, v uint8) { enc.AddUint6...
method AddUintptr (line 331) | func (enc *jsonEncoder) AddUintptr(k string, v uintptr) { enc.AddUint6...
method AppendComplex64 (line 332) | func (enc *jsonEncoder) AppendComplex64(v complex64) { enc.appendCo...
method AppendComplex128 (line 333) | func (enc *jsonEncoder) AppendComplex128(v complex128) { enc.appendCo...
method AppendFloat64 (line 334) | func (enc *jsonEncoder) AppendFloat64(v float64) { enc.appendFl...
method AppendFloat32 (line 335) | func (enc *jsonEncoder) AppendFloat32(v float32) { enc.appendFl...
method AppendInt (line 336) | func (enc *jsonEncoder) AppendInt(v int) { enc.AppendIn...
method AppendInt32 (line 337) | func (enc *jsonEncoder) AppendInt32(v int32) { enc.AppendIn...
method AppendInt16 (line 338) | func (enc *jsonEncoder) AppendInt16(v int16) { enc.AppendIn...
method AppendInt8 (line 339) | func (enc *jsonEncoder) AppendInt8(v int8) { enc.AppendIn...
method AppendUint (line 340) | func (enc *jsonEncoder) AppendUint(v uint) { enc.AppendUi...
method AppendUint32 (line 341) | func (enc *jsonEncoder) AppendUint32(v uint32) { enc.AppendUi...
method AppendUint16 (line 342) | func (enc *jsonEncoder) AppendUint16(v uint16) { enc.AppendUi...
method AppendUint8 (line 343) | func (enc *jsonEncoder) AppendUint8(v uint8) { enc.AppendUi...
method AppendUintptr (line 344) | func (enc *jsonEncoder) AppendUintptr(v uintptr) { enc.AppendUi...
method Clone (line 346) | func (enc *jsonEncoder) Clone() Encoder {
method clone (line 352) | func (enc *jsonEncoder) clone() *jsonEncoder {
method EncodeEntry (line 361) | func (enc *jsonEncoder) EncodeEntry(ent Entry, fields []Field) (*buffe...
method truncate (line 433) | func (enc *jsonEncoder) truncate() {
method closeOpenNamespaces (line 437) | func (enc *jsonEncoder) closeOpenNamespaces() {
method addKey (line 444) | func (enc *jsonEncoder) addKey(key string) {
method addElementSeparator (line 455) | func (enc *jsonEncoder) addElementSeparator() {
method appendFloat (line 471) | func (enc *jsonEncoder) appendFloat(val float64, bitSize int) {
method safeAddString (line 488) | func (enc *jsonEncoder) safeAddString(s string) {
method safeAddByteString (line 498) | func (enc *jsonEncoder) safeAddByteString(s []byte) {
function NewJSONEncoder (line 77) | func NewJSONEncoder(cfg EncoderConfig) Encoder {
function newJSONEncoder (line 81) | func newJSONEncoder(cfg EncoderConfig, spaced bool) *jsonEncoder {
function safeAppendStringLike (line 509) | func safeAppendStringLike[S []byte | string](
FILE: zapcore/json_encoder_bench_test.go
function BenchmarkJSONLogMarshalerFunc (line 33) | func BenchmarkJSONLogMarshalerFunc(b *testing.B) {
function BenchmarkZapJSONFloat32AndComplex64 (line 46) | func BenchmarkZapJSONFloat32AndComplex64(b *testing.B) {
constant _sliceSize (line 56) | _sliceSize = 5000
type StringSlice (line 58) | type StringSlice
method MarshalLogArray (line 60) | func (s StringSlice) MarshalLogArray(encoder ArrayEncoder) error {
function generateStringSlice (line 67) | func generateStringSlice(n int) StringSlice {
function BenchmarkZapJSON (line 75) | func BenchmarkZapJSON(b *testing.B) {
function BenchmarkStandardJSON (line 100) | func BenchmarkStandardJSON(b *testing.B) {
FILE: zapcore/json_encoder_impl_test.go
function TestJSONClone (line 47) | func TestJSONClone(t *testing.T) {
function TestJSONEscaping (line 60) | func TestJSONEscaping(t *testing.T) {
function TestJSONEncoderObjectFields (line 112) | func TestJSONEncoderObjectFields(t *testing.T) {
function TestJSONEncoderTimeFormats (line 291) | func TestJSONEncoderTimeFormats(t *testing.T) {
function TestJSONEncoderArrays (line 340) | func TestJSONEncoderArrays(t *testing.T) {
function TestJSONEncoderTimeArrays (line 459) | func TestJSONEncoderTimeArrays(t *testing.T) {
function assertJSON (line 511) | func assertJSON(t *testing.T, expected string, enc *jsonEncoder) {
function assertOutput (line 515) | func assertOutput(t testing.TB, cfg EncoderConfig, expected string, f fu...
type turducken (line 533) | type turducken struct
method MarshalLogObject (line 535) | func (t turducken) MarshalLogObject(enc ObjectEncoder) error {
type turduckens (line 550) | type turduckens
method MarshalLogArray (line 552) | func (t turduckens) MarshalLogArray(enc ArrayEncoder) error {
type loggable (line 561) | type loggable struct
method MarshalLogObject (line 563) | func (l loggable) MarshalLogObject(enc ObjectEncoder) error {
method MarshalLogArray (line 571) | func (l loggable) MarshalLogArray(enc ArrayEncoder) error {
type maybeNamespace (line 580) | type maybeNamespace struct
method MarshalLogObject (line 582) | func (m maybeNamespace) MarshalLogObject(enc ObjectEncoder) error {
type noJSON (line 591) | type noJSON struct
method MarshalJSON (line 593) | func (nj noJSON) MarshalJSON() ([]byte, error) {
function zapEncode (line 597) | func zapEncode(encode func(*jsonEncoder, string)) func(s string) []byte {
function roundTripsCorrectly (line 611) | func roundTripsCorrectly(encode func(string) []byte, original string) bo...
function roundTripsCorrectlyString (line 624) | func roundTripsCorrectlyString(original string) bool {
function roundTripsCorrectlyByteString (line 628) | func roundTripsCorrectlyByteString(original string) bool {
type ASCII (line 636) | type ASCII
method Generate (line 638) | func (s ASCII) Generate(r *rand.Rand, size int) reflect.Value {
function asciiRoundTripsCorrectlyString (line 647) | func asciiRoundTripsCorrectlyString(s ASCII) bool {
function asciiRoundTripsCorrectlyByteString (line 651) | func asciiRoundTripsCorrectlyByteString(s ASCII) bool {
function TestJSONQuick (line 655) | func TestJSONQuick(t *testing.T) {
function FuzzSafeAppendStringLike_bytes (line 679) | func FuzzSafeAppendStringLike_bytes(f *testing.F) {
function FuzzSafeAppendStringLike_string (line 699) | func FuzzSafeAppendStringLike_string(f *testing.F) {
function fuzzSafeAppendStringLike (line 719) | func fuzzSafeAppendStringLike(
FILE: zapcore/json_encoder_test.go
function TestJSONEncodeEntry (line 39) | func TestJSONEncodeEntry(t *testing.T) {
function TestNoEncodeLevelSupplied (line 153) | func TestNoEncodeLevelSupplied(t *testing.T) {
function TestJSONEmptyConfig (line 182) | func TestJSONEmptyConfig(t *testing.T) {
type emptyReflectedEncoder (line 220) | type emptyReflectedEncoder struct
method Encode (line 224) | func (enc *emptyReflectedEncoder) Encode(obj interface{}) error {
function TestJSONCustomReflectedEncoder (line 229) | func TestJSONCustomReflectedEncoder(t *testing.T) {
FILE: zapcore/lazy_with.go
type lazyWithCore (line 25) | type lazyWithCore struct
method initOnce (line 42) | func (d *lazyWithCore) initOnce() {
method With (line 48) | func (d *lazyWithCore) With(fields []Field) Core {
method Check (line 53) | func (d *lazyWithCore) Check(e Entry, ce *CheckedEntry) *CheckedEntry {
method Enabled (line 64) | func (d *lazyWithCore) Enabled(level Level) bool {
method Write (line 69) | func (d *lazyWithCore) Write(e Entry, fields []Field) error {
method Sync (line 74) | func (d *lazyWithCore) Sync() error {
function NewLazyWith (line 34) | func NewLazyWith(core Core, fields []Field) Core {
FILE: zapcore/lazy_with_test.go
type proxyCore (line 33) | type proxyCore struct
method With (line 44) | func (p *proxyCore) With(fields []zapcore.Field) zapcore.Core {
method Check (line 49) | func (p *proxyCore) Check(e zapcore.Entry, ce *zapcore.CheckedEntry) *...
function newProxyCore (line 40) | func newProxyCore(inner zapcore.Core) *proxyCore {
function withLazyCore (line 54) | func withLazyCore(f func(zapcore.Core, *proxyCore, *observer.ObservedLog...
function TestLazyCore (line 61) | func TestLazyCore(t *testing.T) {
function TestLazyCoreRace (line 192) | func TestLazyCoreRace(t *testing.T) {
FILE: zapcore/leak_test.go
function TestMain (line 29) | func TestMain(m *testing.M) {
FILE: zapcore/level.go
type Level (line 32) | type Level
method String (line 113) | func (l Level) String() string {
method CapitalString (line 135) | func (l Level) CapitalString() string {
method MarshalText (line 160) | func (l Level) MarshalText() ([]byte, error) {
method UnmarshalText (line 170) | func (l *Level) UnmarshalText(text []byte) error {
method unmarshalText (line 180) | func (l *Level) unmarshalText(text []byte) bool {
method Set (line 203) | func (l *Level) Set(s string) error {
method Get (line 208) | func (l *Level) Get() interface{} {
method Enabled (line 213) | func (l Level) Enabled(lvl Level) bool {
constant DebugLevel (line 37) | DebugLevel Level = iota - 1
constant InfoLevel (line 39) | InfoLevel
constant WarnLevel (line 42) | WarnLevel
constant ErrorLevel (line 45) | ErrorLevel
constant DPanicLevel (line 48) | DPanicLevel
constant PanicLevel (line 50) | PanicLevel
constant FatalLevel (line 52) | FatalLevel
constant _minLevel (line 54) | _minLevel = DebugLevel
constant _maxLevel (line 55) | _maxLevel = FatalLevel
constant InvalidLevel (line 60) | InvalidLevel = _maxLevel + 1
function ParseLevel (line 69) | func ParseLevel(text string) (Level, error) {
type leveledEnabler (line 75) | type leveledEnabler interface
function LevelOf (line 98) | func LevelOf(enab LevelEnabler) Level {
type LevelEnabler (line 227) | type LevelEnabler interface
FILE: zapcore/level_strings.go
function init (line 41) | func init() {
FILE: zapcore/level_strings_test.go
function TestAllLevelsCoveredByLevelString (line 29) | func TestAllLevelsCoveredByLevelString(t *testing.T) {
FILE: zapcore/level_test.go
function TestLevelString (line 32) | func TestLevelString(t *testing.T) {
function TestLevelText (line 51) | func TestLevelText(t *testing.T) {
function TestParseLevel (line 90) | func TestParseLevel(t *testing.T) {
function TestCapitalLevelsParse (line 112) | func TestCapitalLevelsParse(t *testing.T) {
function TestWeirdLevelsParse (line 133) | func TestWeirdLevelsParse(t *testing.T) {
function TestLevelNils (line 164) | func TestLevelNils(t *testing.T) {
function TestLevelUnmarshalUnknownText (line 180) | func TestLevelUnmarshalUnknownText(t *testing.T) {
function TestLevelAsFlagValue (line 186) | func TestLevelAsFlagValue(t *testing.T) {
type enablerWithCustomLevel (line 214) | type enablerWithCustomLevel struct
method Enabled (line 218) | func (l *enablerWithCustomLevel) Enabled(lvl Level) bool {
method Level (line 222) | func (l *enablerWithCustomLevel) Level() Level {
function TestLevelOf (line 226) | func TestLevelOf(t *testing.T) {
FILE: zapcore/marshaler.go
type ObjectMarshaler (line 30) | type ObjectMarshaler interface
type ObjectMarshalerFunc (line 36) | type ObjectMarshalerFunc
method MarshalLogObject (line 39) | func (f ObjectMarshalerFunc) MarshalLogObject(enc ObjectEncoder) error {
type ArrayMarshaler (line 50) | type ArrayMarshaler interface
type ArrayMarshalerFunc (line 56) | type ArrayMarshalerFunc
method MarshalLogArray (line 59) | func (f ArrayMarshalerFunc) MarshalLogArray(enc ArrayEncoder) error {
FILE: zapcore/memory_encoder.go
type MapObjectEncoder (line 28) | type MapObjectEncoder struct
method AddArray (line 45) | func (m *MapObjectEncoder) AddArray(key string, v ArrayMarshaler) error {
method AddObject (line 53) | func (m *MapObjectEncoder) AddObject(k string, v ObjectMarshaler) error {
method AddBinary (line 60) | func (m *MapObjectEncoder) AddBinary(k string, v []byte) { m.cur[k] = v }
method AddByteString (line 63) | func (m *MapObjectEncoder) AddByteString(k string, v []byte) { m.cur[k...
method AddBool (line 66) | func (m *MapObjectEncoder) AddBool(k string, v bool) { m.cur[k] = v }
method AddDuration (line 69) | func (m MapObjectEncoder) AddDuration(k string, v time.Duration) { m.c...
method AddComplex128 (line 72) | func (m *MapObjectEncoder) AddComplex128(k string, v complex128) { m.c...
method AddComplex64 (line 75) | func (m *MapObjectEncoder) AddComplex64(k string, v complex64) { m.cur...
method AddFloat64 (line 78) | func (m *MapObjectEncoder) AddFloat64(k string, v float64) { m.cur[k] ...
method AddFloat32 (line 81) | func (m *MapObjectEncoder) AddFloat32(k string, v float32) { m.cur[k] ...
method AddInt (line 84) | func (m *MapObjectEncoder) AddInt(k string, v int) { m.cur[k] = v }
method AddInt64 (line 87) | func (m *MapObjectEncoder) AddInt64(k string, v int64) { m.cur[k] = v }
method AddInt32 (line 90) | func (m *MapObjectEncoder) AddInt32(k string, v int32) { m.cur[k] = v }
method AddInt16 (line 93) | func (m *MapObjectEncoder) AddInt16(k string, v int16) { m.cur[k] = v }
method AddInt8 (line 96) | func (m *MapObjectEncoder) AddInt8(k string, v int8) { m.cur[k] = v }
method AddString (line 99) | func (m *MapObjectEncoder) AddString(k string, v string) { m.cur[k] = v }
method AddTime (line 102) | func (m MapObjectEncoder) AddTime(k string, v time.Time) { m.cur[k] = v }
method AddUint (line 105) | func (m *MapObjectEncoder) AddUint(k string, v uint) { m.cur[k] = v }
method AddUint64 (line 108) | func (m *MapObjectEncoder) AddUint64(k string, v uint64) { m.cur[k] = v }
method AddUint32 (line 111) | func (m *MapObjectEncoder) AddUint32(k string, v uint32) { m.cur[k] = v }
method AddUint16 (line 114) | func (m *MapObjectEncoder) AddUint16(k string, v uint16) { m.cur[k] = v }
method AddUint8 (line 117) | func (m *MapObjectEncoder) AddUint8(k string, v uint8) { m.cur[k] = v }
method AddUintptr (line 120) | func (m *MapObjectEncoder) AddUintptr(k string, v uintptr) { m.cur[k] ...
method AddReflected (line 123) | func (m *MapObjectEncoder) AddReflected(k string, v interface{}) error {
method OpenNamespace (line 129) | func (m *MapObjectEncoder) OpenNamespace(k string) {
function NewMapObjectEncoder (line 36) | func NewMapObjectEncoder() *MapObjectEncoder {
type sliceArrayEncoder (line 137) | type sliceArrayEncoder struct
method AppendArray (line 141) | func (s *sliceArrayEncoder) AppendArray(v ArrayMarshaler) error {
method AppendObject (line 148) | func (s *sliceArrayEncoder) AppendObject(v ObjectMarshaler) error {
method AppendReflected (line 155) | func (s *sliceArrayEncoder) AppendReflected(v interface{}) error {
method AppendBool (line 160) | func (s *sliceArrayEncoder) AppendBool(v bool) { s.elems ...
method AppendByteString (line 161) | func (s *sliceArrayEncoder) AppendByteString(v []byte) { s.elems ...
method AppendComplex128 (line 162) | func (s *sliceArrayEncoder) AppendComplex128(v complex128) { s.elems ...
method AppendComplex64 (line 163) | func (s *sliceArrayEncoder) AppendComplex64(v complex64) { s.elems ...
method AppendDuration (line 164) | func (s *sliceArrayEncoder) AppendDuration(v time.Duration) { s.elems ...
method AppendFloat64 (line 165) | func (s *sliceArrayEncoder) AppendFloat64(v float64) { s.elems ...
method AppendFloat32 (line 166) | func (s *sliceArrayEncoder) AppendFloat32(v float32) { s.elems ...
method AppendInt (line 167) | func (s *sliceArrayEncoder) AppendInt(v int) { s.elems ...
method AppendInt64 (line 168) | func (s *sliceArrayEncoder) AppendInt64(v int64) { s.elems ...
method AppendInt32 (line 169) | func (s *sliceArrayEncoder) AppendInt32(v int32) { s.elems ...
method AppendInt16 (line 170) | func (s *sliceArrayEncoder) AppendInt16(v int16) { s.elems ...
method AppendInt8 (line 171) | func (s *sliceArrayEncoder) AppendInt8(v int8) { s.elems ...
method AppendString (line 172) | func (s *sliceArrayEncoder) AppendString(v string) { s.elems ...
method AppendTime (line 173) | func (s *sliceArrayEncoder) AppendTime(v time.Time) { s.elems ...
method AppendUint (line 174) | func (s *sliceArrayEncoder) AppendUint(v uint) { s.elems ...
method AppendUint64 (line 175) | func (s *sliceArrayEncoder) AppendUint64(v uint64) { s.elems ...
method AppendUint32 (line 176) | func (s *sliceArrayEncoder) AppendUint32(v uint32) { s.elems ...
method AppendUint16 (line 177) | func (s *sliceArrayEncoder) AppendUint16(v uint16) { s.elems ...
method AppendUint8 (line 178) | func (s *sliceArrayEncoder) AppendUint8(v uint8) { s.elems ...
method AppendUintptr (line 179) | func (s *sliceArrayEncoder) AppendUintptr(v uintptr) { s.elems ...
FILE: zapcore/memory_encoder_test.go
function TestMapObjectEncoderAdd (line 31) | func TestMapObjectEncoderAdd(t *testing.T) {
function TestSliceArrayEncoderAppend (line 259) | func TestSliceArrayEncoderAppend(t *testing.T) {
function TestMapObjectEncoderReflectionFailures (line 361) | func TestMapObjectEncoderReflectionFailures(t *testing.T) {
FILE: zapcore/reflected_encoder.go
type ReflectedEncoder (line 31) | type ReflectedEncoder interface
function defaultReflectedEncoder (line 36) | func defaultReflectedEncoder(w io.Writer) ReflectedEncoder {
FILE: zapcore/sampler.go
constant _numLevels (line 29) | _numLevels = _maxLevel - _minLevel + 1
constant _countersPerLevel (line 30) | _countersPerLevel = 4096
type counter (line 33) | type counter struct
method IncCheckReset (line 64) | func (c *counter) IncCheckReset(t time.Time, tick time.Duration) uint64 {
type counters (line 38) | type counters
method get (line 44) | func (cs *counters) get(lvl Level, key string) *counter {
function newCounters (line 40) | func newCounters() *counters {
function fnv32a (line 51) | func fnv32a(s string) uint32 {
type SamplingDecision (line 85) | type SamplingDecision
constant LogDropped (line 89) | LogDropped SamplingDecision = 1 << iota
constant LogSampled (line 91) | LogSampled
type optionFunc (line 95) | type optionFunc
method apply (line 97) | func (f optionFunc) apply(s *sampler) {
type SamplerOption (line 102) | type SamplerOption interface
function nopSamplingHook (line 107) | func nopSamplingHook(Entry, SamplingDecision) {}
function SamplerHook (line 121) | func SamplerHook(hook func(entry Entry, dec SamplingDecision)) SamplerOp...
function NewSamplerWithOptions (line 152) | func NewSamplerWithOptions(core Core, tick time.Duration, first, thereaf...
type sampler (line 168) | type sampler struct
method Level (line 199) | func (s *sampler) Level() Level {
method With (line 203) | func (s *sampler) With(fields []Field) Core {
method Check (line 214) | func (s *sampler) Check(ent Entry, ce *CheckedEntry) *CheckedEntry {
function NewSampler (line 195) | func NewSampler(core Core, tick time.Duration, first, thereafter int) Co...
FILE: zapcore/sampler_bench_test.go
function BenchmarkSampler_Check (line 207) | func BenchmarkSampler_Check(b *testing.B) {
function makeSamplerCountingHook (line 236) | func makeSamplerCountingHook() (func(_ Entry, dec SamplingDecision), *at...
function BenchmarkSampler_CheckWithHook (line 249) | func BenchmarkSampler_CheckWithHook(b *testing.B) {
FILE: zapcore/sampler_test.go
function fakeSampler (line 40) | func fakeSampler(lvl LevelEnabler, tick time.Duration, first, thereafter...
function assertSequence (line 47) | func assertSequence(t testing.TB, logs []observer.LoggedEntry, lvl Level...
function writeSequence (line 61) | func writeSequence(core Core, n int, lvl Level) {
function TestSampler (line 70) | func TestSampler(t *testing.T) {
function TestLevelOfSampler (line 92) | func TestLevelOfSampler(t *testing.T) {
function TestSamplerDisabledLevels (line 105) | func TestSamplerDisabledLevels(t *testing.T) {
function TestSamplerTicking (line 114) | func TestSamplerTicking(t *testing.T) {
type countingCore (line 153) | type countingCore struct
method Check (line 157) | func (c *countingCore) Check(ent Entry, ce *CheckedEntry) *CheckedEntry {
method Write (line 161) | func (c *countingCore) Write(Entry, []Field) error {
method With (line 166) | func (c *countingCore) With([]Field) Core { return c }
method Enabled (line 167) | func (*countingCore) Enabled(Level) bool { return true }
method Sync (line 168) | func (*countingCore) Sync() error { return nil }
function TestSamplerConcurrent (line 170) | func TestSamplerConcurrent(t *testing.T) {
function TestSamplerRaces (line 251) | func TestSamplerRaces(t *testing.T) {
function TestSamplerUnknownLevels (line 272) | func TestSamplerUnknownLevels(t *testing.T) {
function TestSamplerWithZeroThereafter (line 292) | func TestSamplerWithZeroThereafter(t *testing.T) {
FILE: zapcore/tee.go
type multiCore (line 25) | type multiCore
method With (line 48) | func (mc multiCore) With(fields []Field) Core {
method Level (line 56) | func (mc multiCore) Level() Level {
method Enabled (line 66) | func (mc multiCore) Enabled(lvl Level) bool {
method Check (line 75) | func (mc multiCore) Check(ent Entry, ce *CheckedEntry) *CheckedEntry {
method Write (line 82) | func (mc multiCore) Write(ent Entry, fields []Field) error {
method Sync (line 90) | func (mc multiCore) Sync() error {
function NewTee (line 37) | func NewTee(cores ...Core) Core {
FILE: zapcore/tee_logger_bench_test.go
function withBenchedTee (line 31) | func withBenchedTee(b *testing.B, f func(Core)) {
function BenchmarkTeeCheck (line 40) | func BenchmarkTeeCheck(b *testing.B) {
FILE: zapcore/tee_test.go
function withTee (line 35) | func withTee(f func(core Core, debugLogs, warnLogs *observer.ObservedLog...
function TestTeeUnusualInput (line 42) | func TestTeeUnusualInput(t *testing.T) {
function TestLevelOfTee (line 53) | func TestLevelOfTee(t *testing.T) {
function TestTeeCheck (line 91) | func TestTeeCheck(t *testing.T) {
function TestTeeWrite (line 117) | func TestTeeWrite(t *testing.T) {
function TestTeeWith (line 136) | func TestTeeWith(t *testing.T) {
function TestTeeEnabled (line 153) | func TestTeeEnabled(t *testing.T) {
function TestTeeSync (line 175) | func TestTeeSync(t *testing.T) {
FILE: zapcore/write_syncer.go
type WriteSyncer (line 32) | type WriteSyncer interface
function AddSync (line 40) | func AddSync(w io.Writer) WriteSyncer {
type lockedWriteSyncer (line 49) | type lockedWriteSyncer struct
method Write (line 64) | func (s *lockedWriteSyncer) Write(bs []byte) (int, error) {
method Sync (line 71) | func (s *lockedWriteSyncer) Sync() error {
function Lock (line 56) | func Lock(ws WriteSyncer) WriteSyncer {
type writerWrapper (line 78) | type writerWrapper struct
method Sync (line 82) | func (w writerWrapper) Sync() error {
type multiWriteSyncer (line 86) | type multiWriteSyncer
method Write (line 101) | func (ws multiWriteSyncer) Write(p []byte) (int, error) {
method Sync (line 116) | func (ws multiWriteSyncer) Sync() error {
function NewMultiWriteSyncer (line 90) | func NewMultiWriteSyncer(ws ...WriteSyncer) WriteSyncer {
FILE: zapcore/write_syncer_bench_test.go
function BenchmarkMultiWriteSyncer (line 32) | func BenchmarkMultiWriteSyncer(b *testing.B) {
function BenchmarkWriteSyncer (line 86) | func BenchmarkWriteSyncer(b *testing.B) {
FILE: zapcore/write_syncer_test.go
type writeSyncSpy (line 34) | type writeSyncSpy struct
function requireWriteWorks (line 39) | func requireWriteWorks(t testing.TB, ws WriteSyncer) {
function TestAddSyncWriteSyncer (line 45) | func TestAddSyncWriteSyncer(t *testing.T) {
function TestAddSyncWriter (line 58) | func TestAddSyncWriter(t *testing.T) {
function TestNewMultiWriteSyncerWorksForSingleWriter (line 67) | func TestNewMultiWriteSyncerWorksForSingleWriter(t *testing.T) {
function TestMultiWriteSyncerWritesBoth (line 77) | func TestMultiWriteSyncerWritesBoth(t *testing.T) {
function TestMultiWriteSyncerFailsWrite (line 91) | func TestMultiWriteSyncerFailsWrite(t *testing.T) {
function TestMultiWriteSyncerFailsShortWrite (line 97) | func TestMultiWriteSyncerFailsShortWrite(t *testing.T) {
function TestWritestoAllSyncs_EvenIfFirstErrors (line 104) | func TestWritestoAllSyncs_EvenIfFirstErrors(t *testing.T) {
function TestMultiWriteSyncerSync_PropagatesErrors (line 114) | func TestMultiWriteSyncerSync_PropagatesErrors(t *testing.T) {
function TestMultiWriteSyncerSync_NoErrorsOnDiscard (line 122) | func TestMultiWriteSyncerSync_NoErrorsOnDiscard(t *testing.T) {
function TestMultiWriteSyncerSync_AllCalled (line 127) | func TestMultiWriteSyncerSync_AllCalled(t *testing.T) {
FILE: zapgrpc/internal/test/grpc_test.go
function TestLoggerV2 (line 35) | func TestLoggerV2(t *testing.T) {
FILE: zapgrpc/zapgrpc.go
constant grpcLvlInfo (line 33) | grpcLvlInfo int = iota
constant grpcLvlWarn (line 34) | grpcLvlWarn
constant grpcLvlError (line 35) | grpcLvlError
constant grpcLvlFatal (line 36) | grpcLvlFatal
type Option (line 49) | type Option interface
type optionFunc (line 53) | type optionFunc
method apply (line 55) | func (f optionFunc) apply(log *Logger) {
function WithDebug (line 64) | func WithDebug() Option {
function withWarn (line 77) | func withWarn() Option {
function NewLogger (line 89) | func NewLogger(l *zap.Logger, options ...Option) *Logger {
type printer (line 116) | type printer struct
method Print (line 123) | func (v *printer) Print(args ...interface{}) {
method Printf (line 127) | func (v *printer) Printf(format string, args ...interface{}) {
method Println (line 131) | func (v *printer) Println(args ...interface{}) {
type Logger (line 138) | type Logger struct
method Print (line 150) | func (l *Logger) Print(args ...interface{}) {
method Printf (line 157) | func (l *Logger) Printf(format string, args ...interface{}) {
method Println (line 164) | func (l *Logger) Println(args ...interface{}) {
method Info (line 169) | func (l *Logger) Info(args ...interface{}) {
method Infoln (line 174) | func (l *Logger) Infoln(args ...interface{}) {
method Infof (line 181) | func (l *Logger) Infof(format string, args ...interface{}) {
method Warning (line 186) | func (l *Logger) Warning(args ...interface{}) {
method Warningln (line 191) | func (l *Logger) Warningln(args ...interface{}) {
method Warningf (line 198) | func (l *Logger) Warningf(format string, args ...interface{}) {
method Error (line 203) | func (l *Logger) Error(args ...interface{}) {
method Errorln (line 208) | func (l *Logger) Errorln(args ...interface{}) {
method Errorf (line 215) | func (l *Logger) Errorf(format string, args ...interface{}) {
method Fatal (line 220) | func (l *Logger) Fatal(args ...interface{}) {
method Fatalln (line 225) | func (l *Logger) Fatalln(args ...interface{}) {
method Fatalf (line 230) | func (l *Logger) Fatalf(format string, args ...interface{}) {
method V (line 235) | func (l *Logger) V(level int) bool {
function sprintln (line 239) | func sprintln(args []interface{}) string {
FILE: zapgrpc/zapgrpc_test.go
function TestLoggerInfoExpected (line 34) | func TestLoggerInfoExpected(t *testing.T) {
function TestLoggerDebugExpected (line 68) | func TestLoggerDebugExpected(t *testing.T) {
function TestLoggerDebugSuppressed (line 88) | func TestLoggerDebugSuppressed(t *testing.T) {
function TestLoggerWarningExpected (line 98) | func TestLoggerWarningExpected(t *testing.T) {
function TestLoggerErrorExpected (line 118) | func TestLoggerErrorExpected(t *testing.T) {
function TestLoggerFatalExpected (line 138) | func TestLoggerFatalExpected(t *testing.T) {
function TestLoggerV (line 158) | func TestLoggerV(t *testing.T) {
function checkLevel (line 218) | func checkLevel(
function checkMessages (line 234) | func checkMessages(
function withLogger (line 256) | func withLogger(
FILE: zapio/example_test.go
function ExampleWriter (line 31) | func ExampleWriter() {
FILE: zapio/writer.go
type Writer (line 51) | type Writer struct
method Write (line 75) | func (w *Writer) Write(bs []byte) (n int, err error) {
method writeLine (line 91) | func (w *Writer) writeLine(line []byte) (remaining []byte) {
method Close (line 122) | func (w *Writer) Close() error {
method Sync (line 128) | func (w *Writer) Sync() error {
method flush (line 138) | func (w *Writer) flush(allowEmpty bool) {
method log (line 145) | func (w *Writer) log(b []byte) {
FILE: zapio/writer_test.go
function TestWriter (line 34) | func TestWriter(t *testing.T) {
function TestWrite_Sync (line 160) | func TestWrite_Sync(t *testing.T) {
function BenchmarkWriter (line 193) | func BenchmarkWriter(b *testing.B) {
type partiallyNopCore (line 238) | type partiallyNopCore struct
method Enabled (line 240) | func (*partiallyNopCore) Enabled(zapcore.Level) bool { return true }
method Check (line 242) | func (c *partiallyNopCore) Check(ent zapcore.Entry, ce *zapcore.Checke...
method With (line 246) | func (c *partiallyNopCore) With([]zapcore.Field) zapcore.Core {...
method Write (line 247) | func (*partiallyNopCore) Write(zapcore.Entry, []zapcore.Field) error {...
method Sync (line 248) | func (*partiallyNopCore) Sync() error {...
FILE: zaptest/logger.go
type LoggerOption (line 31) | type LoggerOption interface
type loggerOptions (line 35) | type loggerOptions struct
type loggerOptionFunc (line 40) | type loggerOptionFunc
method applyLoggerOption (line 42) | func (f loggerOptionFunc) applyLoggerOption(opts *loggerOptions) {
function Level (line 48) | func Level(enab zapcore.LevelEnabler) LoggerOption {
function WrapOptions (line 55) | func WrapOptions(zapOpts ...zap.Option) LoggerOption {
function NewLogger (line 77) | func NewLogger(t TestingT, opts ...LoggerOption) *zap.Logger {
type TestingWriter (line 104) | type TestingWriter struct
method WithMarkFailed (line 133) | func (w TestingWriter) WithMarkFailed(v bool) TestingWriter {
method Write (line 139) | func (w TestingWriter) Write(p []byte) (n int, err error) {
method Sync (line 155) | func (w TestingWriter) Sync() error {
function NewTestingWriter (line 127) | func NewTestingWriter(t TestingT) TestingWriter {
FILE: zaptest/logger_test.go
function TestTestLogger (line 37) | func TestTestLogger(t *testing.T) {
function TestTestLoggerSupportsLevels (line 61) | func TestTestLoggerSupportsLevels(t *testing.T) {
function TestTestLoggerSupportsWrappedZapOptions (line 83) | func TestTestLoggerSupportsWrappedZapOptions(t *testing.T) {
function TestTestingWriter (line 107) | func TestTestingWriter(t *testing.T) {
function TestTestLoggerErrorOutput (line 116) | func TestTestLoggerErrorOutput(t *testing.T) {
type testLogSpy (line 142) | type testLogSpy struct
method Fail (line 153) | func (t *testLogSpy) Fail() {
method Failed (line 157) | func (t *testLogSpy) Failed() bool {
method FailNow (line 161) | func (t *testLogSpy) FailNow() {
method Logf (line 166) | func (t *testLogSpy) Logf(format string, args ...interface{}) {
method AssertMessages (line 179) | func (t *testLogSpy) AssertMessages(msgs ...string) {
method AssertPassed (line 183) | func (t *testLogSpy) AssertPassed() {
method AssertFailed (line 187) | func (t *testLogSpy) AssertFailed() {
method assertFailed (line 191) | func (t *testLogSpy) assertFailed(v bool, msg string) {
function newTestLogSpy (line 149) | func newTestLogSpy(t testing.TB) *testLogSpy {
FILE: zaptest/observer/logged_entry.go
type LoggedEntry (line 27) | type LoggedEntry struct
method ContextMap (line 33) | func (e LoggedEntry) ContextMap() map[string]interface{} {
FILE: zaptest/observer/logged_entry_test.go
function TestLoggedEntryContextMap (line 32) | func TestLoggedEntryContextMap(t *testing.T) {
FILE: zaptest/observer/observer.go
type ObservedLogs (line 37) | type ObservedLogs struct
method Len (line 43) | func (o *ObservedLogs) Len() int {
method All (line 51) | func (o *ObservedLogs) All() []LoggedEntry {
method TakeAll (line 61) | func (o *ObservedLogs) TakeAll() []LoggedEntry {
method AllUntimed (line 72) | func (o *ObservedLogs) AllUntimed() []LoggedEntry {
method FilterLevelExact (line 81) | func (o *ObservedLogs) FilterLevelExact(level zapcore.Level) *Observed...
method FilterMessage (line 88) | func (o *ObservedLogs) FilterMessage(msg string) *ObservedLogs {
method FilterLoggerName (line 95) | func (o *ObservedLogs) FilterLoggerName(name string) *ObservedLogs {
method FilterMessageSnippet (line 102) | func (o *ObservedLogs) FilterMessageSnippet(snippet string) *ObservedL...
method FilterField (line 109) | func (o *ObservedLogs) FilterField(field zapcore.Field) *ObservedLogs {
method FilterFieldKey (line 121) | func (o *ObservedLogs) FilterFieldKey(key string) *ObservedLogs {
method Filter (line 134) | func (o *ObservedLogs) Filter(keep func(LoggedEntry) bool) *ObservedLo...
method add (line 147) | func (o *ObservedLogs) add(log LoggedEntry) {
function New (line 155) | func New(enab zapcore.LevelEnabler) (zapcore.Core, *ObservedLogs) {
type contextObserver (line 163) | type contextObserver struct
method Level (line 174) | func (co *contextObserver) Level() zapcore.Level {
method Check (line 178) | func (co *contextObserver) Check(ent zapcore.Entry, ce *zapcore.Checke...
method With (line 185) | func (co *contextObserver) With(fields []zapcore.Field) zapcore.Core {
method Write (line 193) | func (co *contextObserver) Write(ent zapcore.Entry, fields []zapcore.F...
method Sync (line 201) | func (co *contextObserver) Sync() error {
FILE: zaptest/observer/observer_test.go
function assertEmpty (line 37) | func assertEmpty(t testing.TB, logs *ObservedLogs) {
function TestObserver (line 42) | func TestObserver(t *testing.T) {
function TestObserverWith (line 76) | func TestObserverWith(t *testing.T) {
function TestFilters (line 128) | func TestFilters(t *testing.T) {
FILE: zaptest/testingt.go
type TestingT (line 25) | type TestingT interface
FILE: zaptest/timeout.go
function Timeout (line 34) | func Timeout(base time.Duration) time.Duration {
function Sleep (line 43) | func Sleep(base time.Duration) {
FILE: zaptest/timeout_test.go
function TestTimeout (line 31) | func TestTimeout(t *testing.T) {
function TestSleep (line 36) | func TestSleep(t *testing.T) {
FILE: zaptest/writer_test.go
function TestSyncer (line 30) | func TestSyncer(t *testing.T) {
function TestDiscarder (line 38) | func TestDiscarder(t *testing.T) {
function TestFailWriter (line 46) | func TestFailWriter(t *testing.T) {
function TestShortWriter (line 54) | func TestShortWriter(t *testing.T) {
function TestBuffer (line 62) | func TestBuffer(t *testing.T) {
Condensed preview — 176 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (918K chars).
[
{
"path": ".codecov.yml",
"chars": 801,
"preview": "coverage:\n range: 80..100\n round: down\n precision: 2\n\n status:\n project: # measuring the overal"
},
{
"path": ".github/ISSUE_TEMPLATE/bug_report.md",
"chars": 384,
"preview": "---\nname: Bug report\nabout: Create a report to help us improve\ntitle: ''\nlabels: ''\nassignees: ''\n\n---\n\n**Describe the b"
},
{
"path": ".github/ISSUE_TEMPLATE/config.yml",
"chars": 130,
"preview": "contact_links:\n - name: Questions\n about: Please use our Discussions page\n url: https://github.com/uber-go/zap/di"
},
{
"path": ".github/ISSUE_TEMPLATE/feature_request.md",
"chars": 769,
"preview": "---\nname: Feature request\nabout: Suggest an idea for this project\ntitle: ''\nlabels: ''\nassignees: ''\n\n---\n\n**Is your fea"
},
{
"path": ".github/dependabot.yml",
"chars": 665,
"preview": "version: 2\nupdates:\n - package-ecosystem: \"github-actions\"\n directory: \"/\"\n schedule:\n interval: \"weekly\"\n\n "
},
{
"path": ".github/workflows/go.yml",
"chars": 1522,
"preview": "name: Go\n\non:\n push:\n branches: [master]\n tags: ['v*']\n pull_request:\n branches: ['*']\n\npermissions:\n conten"
},
{
"path": ".gitignore",
"chars": 320,
"preview": "# Compiled Object files, Static and Dynamic libs (Shared Objects)\n*.o\n*.a\n*.so\n\n# Folders\n_obj\n_test\nvendor\n\n# Architect"
},
{
"path": ".golangci.yml",
"chars": 2385,
"preview": "output:\n # Make output more digestible with quickfix in vim/emacs/etc.\n sort-results: true\n print-issued-lines: false"
},
{
"path": ".readme.tmpl",
"chars": 4130,
"preview": "# :zap: zap [![GoDoc][doc-img]][doc] [![Build Status][ci-img]][ci] [![Coverage Status][cov-img]][cov]\n\n<div align=\"cente"
},
{
"path": "CHANGELOG.md",
"chars": 25617,
"preview": "# Changelog\nAll notable changes to this project will be documented in this file.\n\nThis project adheres to [Semantic Vers"
},
{
"path": "CODE_OF_CONDUCT.md",
"chars": 3226,
"preview": "# Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nIn the interest of fostering an open and welcoming environment, w"
},
{
"path": "CONTRIBUTING.md",
"chars": 2146,
"preview": "# Contributing\n\nWe'd love your help making zap the very best structured logging library in Go!\n\nIf you'd like to add new"
},
{
"path": "FAQ.md",
"chars": 6625,
"preview": "# Frequently Asked Questions\n\n## Design\n\n### Why spend so much effort on logger performance?\n\nOf course, most applicatio"
},
{
"path": "LICENSE",
"chars": 1072,
"preview": "Copyright (c) 2016-2024 Uber Technologies, Inc.\n\nPermission is hereby granted, free of charge, to any person obtaining a"
},
{
"path": "Makefile",
"chars": 1792,
"preview": "# Directory containing the Makefile.\nPROJECT_ROOT = $(dir $(abspath $(lastword $(MAKEFILE_LIST))))\n\nexport GOBIN ?= $(PR"
},
{
"path": "README.md",
"chars": 5594,
"preview": "# :zap: zap\n\n\n<div align=\"center\">\n\nBlazing fast, structured, leveled logging in Go.\n\n\n\n[\nand is made available under the Creative Commons"
},
{
"path": "assets/go.mod",
"chars": 41,
"preview": "module go.uber.org/zap/assets\n\ngo 1.21.5\n"
},
{
"path": "benchmarks/apex_test.go",
"chars": 1777,
"preview": "// Copyright (c) 2016 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "benchmarks/doc.go",
"chars": 1244,
"preview": "// Copyright (c) 2016 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "benchmarks/go.mod",
"chars": 635,
"preview": "module go.uber.org/zap/benchmarks\n\ngo 1.21\n\nreplace go.uber.org/zap => ../\n\nrequire (\n\tgithub.com/apex/log v1.9.0\n\tgithu"
},
{
"path": "benchmarks/go.sum",
"chars": 10356,
"preview": "github.com/apex/log v1.9.0 h1:FHtw/xuaM8AgmvDDTI9fiwoAL25Sq2cxojnZICUU8l0=\ngithub.com/apex/log v1.9.0/go.mod h1:m82fZlWI"
},
{
"path": "benchmarks/kit_test.go",
"chars": 1298,
"preview": "// Copyright (c) 2016 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "benchmarks/log15_test.go",
"chars": 1341,
"preview": "// Copyright (c) 2016 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "benchmarks/logrus_test.go",
"chars": 1825,
"preview": "// Copyright (c) 2016 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "benchmarks/scenario_bench_test.go",
"chars": 17826,
"preview": "// Copyright (c) 2016 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "benchmarks/slog_test.go",
"chars": 2144,
"preview": "// Copyright (c) 2016 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "benchmarks/zap_test.go",
"chars": 4348,
"preview": "// Copyright (c) 2016 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "benchmarks/zerolog_test.go",
"chars": 2338,
"preview": "// Copyright (c) 2016 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "buffer/buffer.go",
"chars": 4380,
"preview": "// Copyright (c) 2016 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "buffer/buffer_test.go",
"chars": 3510,
"preview": "// Copyright (c) 2016 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "buffer/pool.go",
"chars": 1657,
"preview": "// Copyright (c) 2016 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "buffer/pool_test.go",
"chars": 1714,
"preview": "// Copyright (c) 2016 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "checklicense.sh",
"chars": 294,
"preview": "#!/bin/bash -e\n\nERROR_COUNT=0\nwhile read -r file\ndo\n\tcase \"$(head -1 \"${file}\")\" in\n\t\t*\"Copyright (c) \"*\" Uber Technolog"
},
{
"path": "clock_test.go",
"chars": 1863,
"preview": "// Copyright (c) 2020 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "common_test.go",
"chars": 2033,
"preview": "// Copyright (c) 2016 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "config.go",
"chars": 12237,
"preview": "// Copyright (c) 2016 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "config_test.go",
"chars": 6501,
"preview": "// Copyright (c) 2016 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "doc.go",
"chars": 5248,
"preview": "// Copyright (c) 2016 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "encoder.go",
"chars": 2851,
"preview": "// Copyright (c) 2016 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "encoder_test.go",
"chars": 3504,
"preview": "// Copyright (c) 2016 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "error.go",
"chars": 2822,
"preview": "// Copyright (c) 2017 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "error_test.go",
"chars": 4492,
"preview": "// Copyright (c) 2017 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "example_test.go",
"chars": 13988,
"preview": "// Copyright (c) 2016 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "exp/CHANGELOG.md",
"chars": 1562,
"preview": "# Changelog\nAll notable changes to this project will be documented in this file.\n\nThis project adheres to [Semantic Vers"
},
{
"path": "exp/LICENSE",
"chars": 1072,
"preview": "Copyright (c) 2016-2024 Uber Technologies, Inc.\n\nPermission is hereby granted, free of charge, to any person obtaining a"
},
{
"path": "exp/go.mod",
"chars": 331,
"preview": "module go.uber.org/zap/exp\n\ngo 1.19\n\nrequire (\n\tgithub.com/stretchr/testify v1.8.1\n\tgo.uber.org/zap v1.26.0\n)\n\nrequire ("
},
{
"path": "exp/go.sum",
"chars": 1827,
"preview": "github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=\ngithub.com/davecgh/go-spew v1.1"
},
{
"path": "exp/zapfield/zapfield.go",
"chars": 1817,
"preview": "// Copyright (c) 2016-2023 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obt"
},
{
"path": "exp/zapfield/zapfield_test.go",
"chars": 2515,
"preview": "// Copyright (c) 2016-2023 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obt"
},
{
"path": "exp/zapslog/doc.go",
"chars": 1339,
"preview": "// Copyright (c) 2023 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "exp/zapslog/example_test.go",
"chars": 2506,
"preview": "// Copyright (c) 2023 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "exp/zapslog/handler.go",
"chars": 6768,
"preview": "// Copyright (c) 2023 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "exp/zapslog/handler_test.go",
"chars": 11659,
"preview": "// Copyright (c) 2023 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "exp/zapslog/options.go",
"chars": 2535,
"preview": "// Copyright (c) 2023 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "field.go",
"chars": 20058,
"preview": "// Copyright (c) 2016 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "field_test.go",
"chars": 16911,
"preview": "// Copyright (c) 2016 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "flag.go",
"chars": 1671,
"preview": "// Copyright (c) 2016 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "flag_test.go",
"chars": 3316,
"preview": "// Copyright (c) 2016 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "glide.yaml",
"chars": 771,
"preview": "package: go.uber.org/zap\nlicense: MIT\nimport:\n- package: go.uber.org/atomic\n version: ^1\n- package: go.uber.org/multier"
},
{
"path": "global.go",
"chars": 5382,
"preview": "// Copyright (c) 2016 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "global_test.go",
"chars": 9359,
"preview": "// Copyright (c) 2016 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "go.mod",
"chars": 351,
"preview": "module go.uber.org/zap\n\ngo 1.19\n\nrequire (\n\tgithub.com/stretchr/testify v1.8.1\n\tgo.uber.org/goleak v1.3.0\n\tgo.uber.org/m"
},
{
"path": "go.sum",
"chars": 2304,
"preview": "github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=\ngithub.com/davecgh/go-spew v1.1.0/go"
},
{
"path": "http_handler.go",
"chars": 4336,
"preview": "// Copyright (c) 2016 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "http_handler_test.go",
"chars": 8073,
"preview": "// Copyright (c) 2016 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "increase_level_test.go",
"chars": 3471,
"preview": "// Copyright (c) 2020 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "internal/bufferpool/bufferpool.go",
"chars": 1441,
"preview": "// Copyright (c) 2016 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "internal/color/color.go",
"chars": 1510,
"preview": "// Copyright (c) 2016 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "internal/color/color_test.go",
"chars": 1339,
"preview": "// Copyright (c) 2016 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "internal/exit/exit.go",
"chars": 2118,
"preview": "// Copyright (c) 2016 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "internal/exit/exit_test.go",
"chars": 1670,
"preview": "// Copyright (c) 2016 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "internal/level_enabler.go",
"chars": 1639,
"preview": "// Copyright (c) 2022 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "internal/pool/pool.go",
"chars": 1953,
"preview": "// Copyright (c) 2023 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "internal/pool/pool_test.go",
"chars": 3054,
"preview": "// Copyright (c) 2023 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "internal/readme/readme.go",
"chars": 6769,
"preview": "// Copyright (c) 2016 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "internal/stacktrace/stack.go",
"chars": 5569,
"preview": "// Copyright (c) 2023 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "internal/stacktrace/stack_test.go",
"chars": 2994,
"preview": "// Copyright (c) 2023 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "internal/ztest/clock.go",
"chars": 4312,
"preview": "// Copyright (c) 2023 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "internal/ztest/clock_test.go",
"chars": 2207,
"preview": "// Copyright (c) 2023 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "internal/ztest/doc.go",
"chars": 1379,
"preview": "// Copyright (c) 2016 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "internal/ztest/timeout.go",
"chars": 1977,
"preview": "// Copyright (c) 2016 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "internal/ztest/writer.go",
"chars": 2935,
"preview": "// Copyright (c) 2016 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "leak_test.go",
"chars": 1239,
"preview": "// Copyright (c) 2021 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "level.go",
"chars": 5270,
"preview": "// Copyright (c) 2016 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "level_test.go",
"chars": 4326,
"preview": "// Copyright (c) 2016 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "logger.go",
"chars": 14167,
"preview": "// Copyright (c) 2016 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "logger_bench_test.go",
"chars": 8662,
"preview": "// Copyright (c) 2016 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "logger_test.go",
"chars": 29144,
"preview": "// Copyright (c) 2016 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "options.go",
"chars": 6446,
"preview": "// Copyright (c) 2016 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "sink.go",
"chars": 5615,
"preview": "// Copyright (c) 2016-2022 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obt"
},
{
"path": "sink_test.go",
"chars": 3361,
"preview": "// Copyright (c) 2016 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "sink_windows_test.go",
"chars": 2148,
"preview": "// Copyright (c) 2022 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "stacktrace_ext_test.go",
"chars": 7402,
"preview": "// Copyright (c) 2016, 2017 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person ob"
},
{
"path": "sugar.go",
"chars": 16003,
"preview": "// Copyright (c) 2016 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "sugar_test.go",
"chars": 19706,
"preview": "// Copyright (c) 2016 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "time.go",
"chars": 1238,
"preview": "// Copyright (c) 2016 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "time_test.go",
"chars": 1561,
"preview": "// Copyright (c) 2016 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "tools/go.mod",
"chars": 333,
"preview": "module go.uber.org/zap/tools\n\nrequire golang.org/x/vuln v1.1.4\n\nrequire (\n\tgolang.org/x/mod v0.22.0 // indirect\n\tgolang."
},
{
"path": "tools/go.sum",
"chars": 1563,
"preview": "github.com/google/go-cmdtest v0.4.1-0.20220921163831-55ab3332a786 h1:rcv+Ippz6RAtvaGgKxc+8FQIpxHgsF+HBzPyYL2cyVU=\ngithub"
},
{
"path": "tools/tools.go",
"chars": 1258,
"preview": "// Copyright (c) 2019 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "writer.go",
"chars": 3572,
"preview": "// Copyright (c) 2016-2022 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obt"
},
{
"path": "writer_test.go",
"chars": 7084,
"preview": "// Copyright (c) 2016-2022 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obt"
},
{
"path": "zapcore/buffered_write_syncer.go",
"chars": 6254,
"preview": "// Copyright (c) 2021 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "zapcore/buffered_write_syncer_bench_test.go",
"chars": 1820,
"preview": "// Copyright (c) 2021 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "zapcore/buffered_write_syncer_test.go",
"chars": 5330,
"preview": "// Copyright (c) 2021 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "zapcore/clock.go",
"chars": 1844,
"preview": "// Copyright (c) 2021 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "zapcore/clock_test.go",
"chars": 1489,
"preview": "// Copyright (c) 2021 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "zapcore/console_encoder.go",
"chars": 4718,
"preview": "// Copyright (c) 2016 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "zapcore/console_encoder_bench_test.go",
"chars": 1778,
"preview": "// Copyright (c) 2016 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "zapcore/console_encoder_test.go",
"chars": 3766,
"preview": "// Copyright (c) 2016 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "zapcore/core.go",
"chars": 3818,
"preview": "// Copyright (c) 2016 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "zapcore/core_test.go",
"chars": 4755,
"preview": "// Copyright (c) 2016 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "zapcore/doc.go",
"chars": 1381,
"preview": "// Copyright (c) 2016 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "zapcore/encoder.go",
"chars": 16749,
"preview": "// Copyright (c) 2016 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "zapcore/encoder_test.go",
"chars": 24391,
"preview": "// Copyright (c) 2016 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "zapcore/entry.go",
"chars": 9722,
"preview": "// Copyright (c) 2016 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "zapcore/entry_ext_test.go",
"chars": 1961,
"preview": "// Copyright (c) 2023 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "zapcore/entry_test.go",
"chars": 6934,
"preview": "// Copyright (c) 2016 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "zapcore/error.go",
"chars": 4174,
"preview": "// Copyright (c) 2017 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "zapcore/error_test.go",
"chars": 5494,
"preview": "// Copyright (c) 2017 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "zapcore/field.go",
"chars": 7880,
"preview": "// Copyright (c) 2016 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "zapcore/field_test.go",
"chars": 10419,
"preview": "// Copyright (c) 2016 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "zapcore/hook.go",
"chars": 2581,
"preview": "// Copyright (c) 2016 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "zapcore/hook_test.go",
"chars": 2601,
"preview": "// Copyright (c) 2016 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "zapcore/increase_level.go",
"chars": 2514,
"preview": "// Copyright (c) 2020 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "zapcore/increase_level_test.go",
"chars": 3813,
"preview": "// Copyright (c) 2020 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "zapcore/json_encoder.go",
"chars": 16666,
"preview": "// Copyright (c) 2016 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "zapcore/json_encoder_bench_test.go",
"chars": 3655,
"preview": "// Copyright (c) 2016 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "zapcore/json_encoder_impl_test.go",
"chars": 23735,
"preview": "// Copyright (c) 2016 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "zapcore/json_encoder_test.go",
"chars": 7593,
"preview": "// Copyright (c) 2018 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "zapcore/lazy_with.go",
"chars": 2474,
"preview": "// Copyright (c) 2023 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "zapcore/lazy_with_test.go",
"chars": 6853,
"preview": "// Copyright (c) 2023 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "zapcore/leak_test.go",
"chars": 1243,
"preview": "// Copyright (c) 2021 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "zapcore/level.go",
"chars": 6461,
"preview": "// Copyright (c) 2016 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "zapcore/level_strings.go",
"chars": 1804,
"preview": "// Copyright (c) 2016 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "zapcore/level_strings_test.go",
"chars": 1604,
"preview": "// Copyright (c) 2016 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "zapcore/level_test.go",
"chars": 7844,
"preview": "// Copyright (c) 2016 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "zapcore/marshaler.go",
"chars": 2560,
"preview": "// Copyright (c) 2016 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "zapcore/memory_encoder.go",
"chars": 7426,
"preview": "// Copyright (c) 2016 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "zapcore/memory_encoder_test.go",
"chars": 11276,
"preview": "// Copyright (c) 2016 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "zapcore/reflected_encoder.go",
"chars": 1665,
"preview": "// Copyright (c) 2016 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "zapcore/sampler.go",
"chars": 6784,
"preview": "// Copyright (c) 2016-2022 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obt"
},
{
"path": "zapcore/sampler_bench_test.go",
"chars": 5909,
"preview": "// Copyright (c) 2016 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "zapcore/sampler_test.go",
"chars": 8638,
"preview": "// Copyright (c) 2016-2022 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obt"
},
{
"path": "zapcore/tee.go",
"chars": 2551,
"preview": "// Copyright (c) 2016-2022 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obt"
},
{
"path": "zapcore/tee_logger_bench_test.go",
"chars": 2043,
"preview": "// Copyright (c) 2016 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "zapcore/tee_test.go",
"chars": 5741,
"preview": "// Copyright (c) 2016 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "zapcore/write_syncer.go",
"chars": 3371,
"preview": "// Copyright (c) 2016 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "zapcore/write_syncer_bench_test.go",
"chars": 2861,
"preview": "// Copyright (c) 2016 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "zapcore/write_syncer_test.go",
"chars": 4880,
"preview": "// Copyright (c) 2016 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "zapgrpc/internal/test/README.md",
"chars": 101,
"preview": "This submodule exists to test zapgrpc against grpc-go without adding a\ndependency on grpc-go to Zap.\n"
},
{
"path": "zapgrpc/internal/test/go.mod",
"chars": 545,
"preview": "module go.uber.org/zap/zapgrpc/internal/test\n\ngo 1.18\n\nrequire (\n\tgithub.com/stretchr/testify v1.8.1\n\tgo.uber.org/zap v1"
},
{
"path": "zapgrpc/internal/test/go.sum",
"chars": 3398,
"preview": "github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=\ngithub.com/davecgh/go-spew v1.1.0/go"
},
{
"path": "zapgrpc/internal/test/grpc.go",
"chars": 1338,
"preview": "// Copyright (c) 2021 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "zapgrpc/internal/test/grpc_test.go",
"chars": 1853,
"preview": "// Copyright (c) 2021 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "zapgrpc/zapgrpc.go",
"chars": 6647,
"preview": "// Copyright (c) 2016 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "zapgrpc/zapgrpc_test.go",
"chars": 7383,
"preview": "// Copyright (c) 2016 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "zapio/example_test.go",
"chars": 1595,
"preview": "// Copyright (c) 2021 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "zapio/writer.go",
"chars": 4581,
"preview": "// Copyright (c) 2021 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "zapio/writer_test.go",
"chars": 6252,
"preview": "// Copyright (c) 2021 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "zaptest/doc.go",
"chars": 1247,
"preview": "// Copyright (c) 2016 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "zaptest/logger.go",
"chars": 4611,
"preview": "// Copyright (c) 2017 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "zaptest/logger_test.go",
"chars": 5294,
"preview": "// Copyright (c) 2017 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "zaptest/observer/logged_entry.go",
"chars": 1595,
"preview": "// Copyright (c) 2017 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "zaptest/observer/logged_entry_test.go",
"chars": 2287,
"preview": "// Copyright (c) 2017 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "zaptest/observer/observer.go",
"chars": 5974,
"preview": "// Copyright (c) 2016-2022 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obt"
},
{
"path": "zaptest/observer/observer_test.go",
"chars": 8102,
"preview": "// Copyright (c) 2016-2022 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obt"
},
{
"path": "zaptest/testingt.go",
"chars": 1860,
"preview": "// Copyright (c) 2017 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "zaptest/testingt_test.go",
"chars": 1388,
"preview": "// Copyright (c) 2017 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "zaptest/timeout.go",
"chars": 1791,
"preview": "// Copyright (c) 2016 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "zaptest/timeout_test.go",
"chars": 1633,
"preview": "// Copyright (c) 2016 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "zaptest/writer.go",
"chars": 1881,
"preview": "// Copyright (c) 2016 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
},
{
"path": "zaptest/writer_test.go",
"chars": 2477,
"preview": "// Copyright (c) 2016 Uber Technologies, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtainin"
}
]
About this extraction
This page contains the full source code of the uber-go/zap GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 176 files (820.3 KB), approximately 234.0k tokens, and a symbol index with 1372 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.