Initial commit.
This commit is contained in:
24
vendor/github.com/rs/zerolog/.gitignore
generated
vendored
Normal file
24
vendor/github.com/rs/zerolog/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
# Compiled Object files, Static and Dynamic libs (Shared Objects)
|
||||
*.o
|
||||
*.a
|
||||
*.so
|
||||
|
||||
# Folders
|
||||
_obj
|
||||
_test
|
||||
|
||||
# Architecture specific extensions/prefixes
|
||||
*.[568vq]
|
||||
[568vq].out
|
||||
|
||||
*.cgo1.go
|
||||
*.cgo2.c
|
||||
_cgo_defun.c
|
||||
_cgo_gotypes.go
|
||||
_cgo_export.*
|
||||
|
||||
_testmain.go
|
||||
|
||||
*.exe
|
||||
*.test
|
||||
*.prof
|
13
vendor/github.com/rs/zerolog/.travis.yml
generated
vendored
Normal file
13
vendor/github.com/rs/zerolog/.travis.yml
generated
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
language: go
|
||||
go:
|
||||
- "1.7"
|
||||
- "1.8"
|
||||
- "1.9"
|
||||
- "1.10"
|
||||
- "master"
|
||||
matrix:
|
||||
allow_failures:
|
||||
- go: "master"
|
||||
script:
|
||||
- go test -v -race -cpu=1,2,4 -bench . -benchmem ./...
|
||||
- go test -v -tags binary_log -race -cpu=1,2,4 -bench . -benchmem ./...
|
21
vendor/github.com/rs/zerolog/LICENSE
generated
vendored
Normal file
21
vendor/github.com/rs/zerolog/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2017 Olivier Poitrey
|
||||
|
||||
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.
|
510
vendor/github.com/rs/zerolog/README.md
generated
vendored
Normal file
510
vendor/github.com/rs/zerolog/README.md
generated
vendored
Normal file
@@ -0,0 +1,510 @@
|
||||
# Zero Allocation JSON Logger
|
||||
|
||||
[](https://godoc.org/github.com/rs/zerolog) [](https://raw.githubusercontent.com/rs/zerolog/master/LICENSE) [](https://travis-ci.org/rs/zerolog) [](http://gocover.io/github.com/rs/zerolog)
|
||||
|
||||
The zerolog package provides a fast and simple logger dedicated to JSON output.
|
||||
|
||||
Zerolog's API is designed to provide both a great developer experience and stunning [performance](#benchmarks). Its unique chaining API allows zerolog to write JSON (or CBOR) log events by avoiding allocations and reflection.
|
||||
|
||||
Uber's [zap](https://godoc.org/go.uber.org/zap) library pioneered this approach. Zerolog is taking this concept to the next level with a simpler to use API and even better performance.
|
||||
|
||||
To keep the code base and the API simple, zerolog focuses on efficient structured logging only. Pretty logging on the console is made possible using the provided (but inefficient) `zerolog.ConsoleWriter`.
|
||||
|
||||

|
||||
|
||||
## Who uses zerolog
|
||||
|
||||
Find out [who uses zerolog](https://github.com/rs/zerolog/wiki/Who-uses-zerolog) and add your company / project to the list.
|
||||
|
||||
## Features
|
||||
|
||||
* Blazing fast
|
||||
* Low to zero allocation
|
||||
* Level logging
|
||||
* Sampling
|
||||
* Hooks
|
||||
* Contextual fields
|
||||
* `context.Context` integration
|
||||
* `net/http` helpers
|
||||
* JSON and CBOR encoding formats
|
||||
* Pretty logging for development
|
||||
|
||||
## Installation
|
||||
|
||||
```go
|
||||
go get -u github.com/rs/zerolog/log
|
||||
```
|
||||
## Getting Started
|
||||
|
||||
### Simple Logging Example
|
||||
|
||||
For simple logging, import the global logger package **github.com/rs/zerolog/log**
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// UNIX Time is faster and smaller than most timestamps
|
||||
// If you set zerolog.TimeFieldFormat to an empty string,
|
||||
// logs will write with UNIX time
|
||||
zerolog.TimeFieldFormat = ""
|
||||
|
||||
log.Print("hello world")
|
||||
}
|
||||
|
||||
// Output: {"time":1516134303,"level":"debug","message":"hello world"}
|
||||
```
|
||||
> Note: The default log level for `log.Print` is *debug*
|
||||
|
||||
### Leveled Logging
|
||||
|
||||
#### Simple Leveled Logging Example
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
func main() {
|
||||
zerolog.TimeFieldFormat = ""
|
||||
|
||||
log.Info().Msg("hello world")
|
||||
}
|
||||
|
||||
// Output: {"time":1516134303,"level":"info","message":"hello world"}
|
||||
```
|
||||
|
||||
**zerolog** allows for logging at the following levels (from highest to lowest):
|
||||
- panic (`zerolog.PanicLevel`, 5)
|
||||
- fatal (`zerolog.FatalLevel`, 4)
|
||||
- error (`zerolog.ErrorLevel`, 3)
|
||||
- warn (`zerolog.WarnLevel`, 2)
|
||||
- info (`zerolog.InfoLevel`, 1)
|
||||
- debug (`zerolog.DebugLevel`, 0)
|
||||
|
||||
You can set the Global logging level to any of these options using the `SetGlobalLevel` function in the zerolog package, passing in one of the given constants above, e.g. `zerolog.InfoLevel` would be the "info" level. Whichever level is chosen, all logs with a level greater than or equal to that level will be written. To turn off logging entirely, pass the `zerolog.Disabled` constant.
|
||||
|
||||
#### Setting Global Log Level
|
||||
|
||||
This example uses command-line flags to demonstrate various outputs depending on the chosen log level.
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
func main() {
|
||||
zerolog.TimeFieldFormat = ""
|
||||
debug := flag.Bool("debug", false, "sets log level to debug")
|
||||
|
||||
flag.Parse()
|
||||
|
||||
// Default level for this example is info, unless debug flag is present
|
||||
zerolog.SetGlobalLevel(zerolog.InfoLevel)
|
||||
if *debug {
|
||||
zerolog.SetGlobalLevel(zerolog.DebugLevel)
|
||||
}
|
||||
|
||||
log.Debug().Msg("This message appears only when log level set to Debug")
|
||||
log.Info().Msg("This message appears when log level set to Debug or Info")
|
||||
|
||||
if e := log.Debug(); e.Enabled() {
|
||||
// Compute log output only if enabled.
|
||||
value := "bar"
|
||||
e.Str("foo", value).Msg("some debug message")
|
||||
}
|
||||
}
|
||||
```
|
||||
Info Output (no flag)
|
||||
```bash
|
||||
$ ./logLevelExample
|
||||
{"time":1516387492,"level":"info","message":"This message appears when log level set to Debug or Info"}
|
||||
```
|
||||
|
||||
Debug Output (debug flag set)
|
||||
```bash
|
||||
$ ./logLevelExample -debug
|
||||
{"time":1516387573,"level":"debug","message":"This message appears only when log level set to Debug"}
|
||||
{"time":1516387573,"level":"info","message":"This message appears when log level set to Debug or Info"}
|
||||
{"time":1516387573,"level":"debug","foo":"bar","message":"some debug message"}
|
||||
```
|
||||
|
||||
#### Logging Fatal Messages
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
func main() {
|
||||
err := errors.New("A repo man spends his life getting into tense situations")
|
||||
service := "myservice"
|
||||
|
||||
zerolog.TimeFieldFormat = ""
|
||||
|
||||
log.Fatal().
|
||||
Err(err).
|
||||
Str("service", service).
|
||||
Msgf("Cannot start %s", service)
|
||||
}
|
||||
|
||||
// Output: {"time":1516133263,"level":"fatal","error":"A repo man spends his life getting into tense situations","service":"myservice","message":"Cannot start myservice"}
|
||||
// exit status 1
|
||||
```
|
||||
> NOTE: Using `Msgf` generates one allocation even when the logger is disabled.
|
||||
|
||||
### Contextual Logging
|
||||
|
||||
#### Fields can be added to log messages
|
||||
|
||||
```go
|
||||
log.Info().
|
||||
Str("foo", "bar").
|
||||
Int("n", 123).
|
||||
Msg("hello world")
|
||||
|
||||
// Output: {"level":"info","time":1494567715,"foo":"bar","n":123,"message":"hello world"}
|
||||
```
|
||||
|
||||
### Create logger instance to manage different outputs
|
||||
|
||||
```go
|
||||
logger := zerolog.New(os.Stderr).With().Timestamp().Logger()
|
||||
|
||||
logger.Info().Str("foo", "bar").Msg("hello world")
|
||||
|
||||
// Output: {"level":"info","time":1494567715,"message":"hello world","foo":"bar"}
|
||||
```
|
||||
|
||||
### Sub-loggers let you chain loggers with additional context
|
||||
|
||||
```go
|
||||
sublogger := log.With().
|
||||
Str("component": "foo").
|
||||
Logger()
|
||||
sublogger.Info().Msg("hello world")
|
||||
|
||||
// Output: {"level":"info","time":1494567715,"message":"hello world","component":"foo"}
|
||||
```
|
||||
|
||||
### Pretty logging
|
||||
|
||||
```go
|
||||
if isConsole {
|
||||
log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr})
|
||||
}
|
||||
|
||||
log.Info().Str("foo", "bar").Msg("Hello world")
|
||||
|
||||
// Output: 1494567715 |INFO| Hello world foo=bar
|
||||
```
|
||||
|
||||
### Sub dictionary
|
||||
|
||||
```go
|
||||
log.Info().
|
||||
Str("foo", "bar").
|
||||
Dict("dict", zerolog.Dict().
|
||||
Str("bar", "baz").
|
||||
Int("n", 1)
|
||||
).Msg("hello world")
|
||||
|
||||
// Output: {"level":"info","time":1494567715,"foo":"bar","dict":{"bar":"baz","n":1},"message":"hello world"}
|
||||
```
|
||||
|
||||
### Customize automatic field names
|
||||
|
||||
```go
|
||||
zerolog.TimestampFieldName = "t"
|
||||
zerolog.LevelFieldName = "l"
|
||||
zerolog.MessageFieldName = "m"
|
||||
|
||||
log.Info().Msg("hello world")
|
||||
|
||||
// Output: {"l":"info","t":1494567715,"m":"hello world"}
|
||||
```
|
||||
|
||||
### Log with no level nor message
|
||||
|
||||
```go
|
||||
log.Log().Str("foo","bar").Msg("")
|
||||
|
||||
// Output: {"time":1494567715,"foo":"bar"}
|
||||
```
|
||||
|
||||
### Add contextual fields to the global logger
|
||||
|
||||
```go
|
||||
log.Logger = log.With().Str("foo", "bar").Logger()
|
||||
```
|
||||
|
||||
### Thread-safe, lock-free, non-blocking writer
|
||||
|
||||
If your writer might be slow or not thread-safe and you need your log producers to never get slowed down by a slow writer, you can use a `diode.Writer` as follow:
|
||||
|
||||
```go
|
||||
d := diodes.NewManyToOne(1000, diodes.AlertFunc(func(missed int) {
|
||||
fmt.Printf("Dropped %d messages\n", missed)
|
||||
}))
|
||||
w := diode.NewWriter(os.Stdout, d, 10*time.Millisecond)
|
||||
log := zerolog.New(w)
|
||||
log.Print("test")
|
||||
```
|
||||
|
||||
You will need to install `code.cloudfoundry.org/go-diodes` to use this feature.
|
||||
|
||||
### Log Sampling
|
||||
|
||||
```go
|
||||
sampled := log.Sample(&zerolog.BasicSampler{N: 10})
|
||||
sampled.Info().Msg("will be logged every 10 messages")
|
||||
|
||||
// Output: {"time":1494567715,"level":"info","message":"will be logged every 10 messages"}
|
||||
```
|
||||
|
||||
More advanced sampling:
|
||||
|
||||
```go
|
||||
// Will let 5 debug messages per period of 1 second.
|
||||
// Over 5 debug message, 1 every 100 debug messages are logged.
|
||||
// Other levels are not sampled.
|
||||
sampled := log.Sample(zerolog.LevelSampler{
|
||||
DebugSampler: &zerolog.BurstSampler{
|
||||
Burst: 5,
|
||||
Period: 1*time.Second,
|
||||
NextSampler: &zerolog.BasicSampler{N: 100},
|
||||
},
|
||||
})
|
||||
sampled.Debug().Msg("hello world")
|
||||
|
||||
// Output: {"time":1494567715,"level":"debug","message":"hello world"}
|
||||
```
|
||||
|
||||
### Hooks
|
||||
|
||||
```go
|
||||
type SeverityHook struct{}
|
||||
|
||||
func (h SeverityHook) Run(e *zerolog.Event, level zerolog.Level, msg string) {
|
||||
if level != zerolog.NoLevel {
|
||||
e.Str("severity", level.String())
|
||||
}
|
||||
}
|
||||
|
||||
hooked := log.Hook(SeverityHook{})
|
||||
hooked.Warn().Msg("")
|
||||
|
||||
// Output: {"level":"warn","severity":"warn"}
|
||||
```
|
||||
|
||||
### Pass a sub-logger by context
|
||||
|
||||
```go
|
||||
ctx := log.With("component", "module").Logger().WithContext(ctx)
|
||||
|
||||
log.Ctx(ctx).Info().Msg("hello world")
|
||||
|
||||
// Output: {"component":"module","level":"info","message":"hello world"}
|
||||
```
|
||||
|
||||
### Set as standard logger output
|
||||
|
||||
```go
|
||||
log := zerolog.New(os.Stdout).With().
|
||||
Str("foo", "bar").
|
||||
Logger()
|
||||
|
||||
stdlog.SetFlags(0)
|
||||
stdlog.SetOutput(log)
|
||||
|
||||
stdlog.Print("hello world")
|
||||
|
||||
// Output: {"foo":"bar","message":"hello world"}
|
||||
```
|
||||
|
||||
### Integration with `net/http`
|
||||
|
||||
The `github.com/rs/zerolog/hlog` package provides some helpers to integrate zerolog with `http.Handler`.
|
||||
|
||||
In this example we use [alice](https://github.com/justinas/alice) to install logger for better readability.
|
||||
|
||||
```go
|
||||
log := zerolog.New(os.Stdout).With().
|
||||
Timestamp().
|
||||
Str("role", "my-service").
|
||||
Str("host", host).
|
||||
Logger()
|
||||
|
||||
c := alice.New()
|
||||
|
||||
// Install the logger handler with default output on the console
|
||||
c = c.Append(hlog.NewHandler(log))
|
||||
|
||||
// Install some provided extra handler to set some request's context fields.
|
||||
// Thanks to those handler, all our logs will come with some pre-populated fields.
|
||||
c = c.Append(hlog.AccessHandler(func(r *http.Request, status, size int, duration time.Duration) {
|
||||
hlog.FromRequest(r).Info().
|
||||
Str("method", r.Method).
|
||||
Str("url", r.URL.String()).
|
||||
Int("status", status).
|
||||
Int("size", size).
|
||||
Dur("duration", duration).
|
||||
Msg("")
|
||||
}))
|
||||
c = c.Append(hlog.RemoteAddrHandler("ip"))
|
||||
c = c.Append(hlog.UserAgentHandler("user_agent"))
|
||||
c = c.Append(hlog.RefererHandler("referer"))
|
||||
c = c.Append(hlog.RequestIDHandler("req_id", "Request-Id"))
|
||||
|
||||
// Here is your final handler
|
||||
h := c.Then(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
// Get the logger from the request's context. You can safely assume it
|
||||
// will be always there: if the handler is removed, hlog.FromRequest
|
||||
// will return a no-op logger.
|
||||
hlog.FromRequest(r).Info().
|
||||
Str("user", "current user").
|
||||
Str("status", "ok").
|
||||
Msg("Something happened")
|
||||
|
||||
// Output: {"level":"info","time":"2001-02-03T04:05:06Z","role":"my-service","host":"local-hostname","req_id":"b4g0l5t6tfid6dtrapu0","user":"current user","status":"ok","message":"Something happened"}
|
||||
}))
|
||||
http.Handle("/", h)
|
||||
|
||||
if err := http.ListenAndServe(":8080", nil); err != nil {
|
||||
log.Fatal().Err(err).Msg("Startup failed")
|
||||
}
|
||||
```
|
||||
|
||||
## Global Settings
|
||||
|
||||
Some settings can be changed and will by applied to all loggers:
|
||||
|
||||
* `log.Logger`: You can set this value to customize the global logger (the one used by package level methods).
|
||||
* `zerolog.SetGlobalLevel`: Can raise the minimum level of all loggers. Set this to `zerolog.Disable` to disable logging altogether (quiet mode).
|
||||
* `zerolog.DisableSampling`: If argument is `true`, all sampled loggers will stop sampling and issue 100% of their log events.
|
||||
* `zerolog.TimestampFieldName`: Can be set to customize `Timestamp` field name.
|
||||
* `zerolog.LevelFieldName`: Can be set to customize level field name.
|
||||
* `zerolog.MessageFieldName`: Can be set to customize message field name.
|
||||
* `zerolog.ErrorFieldName`: Can be set to customize `Err` field name.
|
||||
* `zerolog.TimeFieldFormat`: Can be set to customize `Time` field value formatting. If set with an empty string, times are formated as UNIX timestamp.
|
||||
// DurationFieldUnit defines the unit for time.Duration type fields added
|
||||
// using the Dur method.
|
||||
* `DurationFieldUnit`: Sets the unit of the fields added by `Dur` (default: `time.Millisecond`).
|
||||
* `DurationFieldInteger`: If set to true, `Dur` fields are formatted as integers instead of floats.
|
||||
|
||||
## Field Types
|
||||
|
||||
### Standard Types
|
||||
|
||||
* `Str`
|
||||
* `Bool`
|
||||
* `Int`, `Int8`, `Int16`, `Int32`, `Int64`
|
||||
* `Uint`, `Uint8`, `Uint16`, `Uint32`, `Uint64`
|
||||
* `Float32`, `Float64`
|
||||
|
||||
### Advanced Fields
|
||||
|
||||
* `Err`: Takes an `error` and render it as a string using the `zerolog.ErrorFieldName` field name.
|
||||
* `Timestamp`: Insert a timestamp field with `zerolog.TimestampFieldName` field name and formatted using `zerolog.TimeFieldFormat`.
|
||||
* `Time`: Adds a field with the time formated with the `zerolog.TimeFieldFormat`.
|
||||
* `Dur`: Adds a field with a `time.Duration`.
|
||||
* `Dict`: Adds a sub-key/value as a field of the event.
|
||||
* `Interface`: Uses reflection to marshal the type.
|
||||
|
||||
## Binary Encoding
|
||||
|
||||
In addition to the default JSON encoding, `zerolog` can produce binary logs using the [cbor](http://cbor.io) encoding. The choice of encoding can be decided at compile time using the build tag `binary_log` as follow:
|
||||
|
||||
```
|
||||
go build -tags binary_log .
|
||||
```
|
||||
|
||||
## Benchmarks
|
||||
|
||||
All operations are allocation free (those numbers *include* JSON encoding):
|
||||
|
||||
```
|
||||
BenchmarkLogEmpty-8 100000000 19.1 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkDisabled-8 500000000 4.07 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkInfo-8 30000000 42.5 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkContextFields-8 30000000 44.9 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkLogFields-8 10000000 184 ns/op 0 B/op 0 allocs/op
|
||||
```
|
||||
|
||||
There are a few Go logging benchmarks and comparisons that include zerolog.
|
||||
|
||||
- [imkira/go-loggers-bench](https://github.com/imkira/go-loggers-bench)
|
||||
- [uber-common/zap](https://github.com/uber-go/zap#performance)
|
||||
|
||||
Using Uber's zap comparison benchmark:
|
||||
|
||||
Log a message and 10 fields:
|
||||
|
||||
| Library | Time | Bytes Allocated | Objects Allocated |
|
||||
| :--- | :---: | :---: | :---: |
|
||||
| zerolog | 767 ns/op | 552 B/op | 6 allocs/op |
|
||||
| :zap: zap | 848 ns/op | 704 B/op | 2 allocs/op |
|
||||
| :zap: zap (sugared) | 1363 ns/op | 1610 B/op | 20 allocs/op |
|
||||
| go-kit | 3614 ns/op | 2895 B/op | 66 allocs/op |
|
||||
| lion | 5392 ns/op | 5807 B/op | 63 allocs/op |
|
||||
| logrus | 5661 ns/op | 6092 B/op | 78 allocs/op |
|
||||
| apex/log | 15332 ns/op | 3832 B/op | 65 allocs/op |
|
||||
| log15 | 20657 ns/op | 5632 B/op | 93 allocs/op |
|
||||
|
||||
Log a message with a logger that already has 10 fields of context:
|
||||
|
||||
| Library | Time | Bytes Allocated | Objects Allocated |
|
||||
| :--- | :---: | :---: | :---: |
|
||||
| zerolog | 52 ns/op | 0 B/op | 0 allocs/op |
|
||||
| :zap: zap | 283 ns/op | 0 B/op | 0 allocs/op |
|
||||
| :zap: zap (sugared) | 337 ns/op | 80 B/op | 2 allocs/op |
|
||||
| lion | 2702 ns/op | 4074 B/op | 38 allocs/op |
|
||||
| go-kit | 3378 ns/op | 3046 B/op | 52 allocs/op |
|
||||
| logrus | 4309 ns/op | 4564 B/op | 63 allocs/op |
|
||||
| apex/log | 13456 ns/op | 2898 B/op | 51 allocs/op |
|
||||
| log15 | 14179 ns/op | 2642 B/op | 44 allocs/op |
|
||||
|
||||
Log a static string, without any context or `printf`-style templating:
|
||||
|
||||
| Library | Time | Bytes Allocated | Objects Allocated |
|
||||
| :--- | :---: | :---: | :---: |
|
||||
| zerolog | 50 ns/op | 0 B/op | 0 allocs/op |
|
||||
| :zap: zap | 236 ns/op | 0 B/op | 0 allocs/op |
|
||||
| standard library | 453 ns/op | 80 B/op | 2 allocs/op |
|
||||
| :zap: zap (sugared) | 337 ns/op | 80 B/op | 2 allocs/op |
|
||||
| go-kit | 508 ns/op | 656 B/op | 13 allocs/op |
|
||||
| lion | 771 ns/op | 1224 B/op | 10 allocs/op |
|
||||
| logrus | 1244 ns/op | 1505 B/op | 27 allocs/op |
|
||||
| apex/log | 2751 ns/op | 584 B/op | 11 allocs/op |
|
||||
| log15 | 5181 ns/op | 1592 B/op | 26 allocs/op |
|
||||
|
||||
## Caveats
|
||||
|
||||
Note that zerolog does de-duplication fields. Using the same key multiple times creates multiple keys in final JSON:
|
||||
|
||||
```go
|
||||
logger := zerolog.New(os.Stderr).With().Timestamp().Logger()
|
||||
logger.Info().
|
||||
Timestamp().
|
||||
Msg("dup")
|
||||
// Output: {"level":"info","time":1494567715,"time":1494567715,"message":"dup"}
|
||||
```
|
||||
|
||||
However, it’s not a big deal as JSON accepts dup keys; the last one prevails.
|
176
vendor/github.com/rs/zerolog/array.go
generated
vendored
Normal file
176
vendor/github.com/rs/zerolog/array.go
generated
vendored
Normal file
@@ -0,0 +1,176 @@
|
||||
package zerolog
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
var arrayPool = &sync.Pool{
|
||||
New: func() interface{} {
|
||||
return &Array{
|
||||
buf: make([]byte, 0, 500),
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
// Array is used to prepopulate an array of items
|
||||
// which can be re-used to add to log messages.
|
||||
type Array struct {
|
||||
buf []byte
|
||||
}
|
||||
|
||||
// Arr creates an array to be added to an Event or Context.
|
||||
func Arr() *Array {
|
||||
a := arrayPool.Get().(*Array)
|
||||
a.buf = a.buf[:0]
|
||||
return a
|
||||
}
|
||||
|
||||
// MarshalZerologArray method here is no-op - since data is
|
||||
// already in the needed format.
|
||||
func (*Array) MarshalZerologArray(*Array) {
|
||||
}
|
||||
|
||||
func (a *Array) write(dst []byte) []byte {
|
||||
dst = appendArrayStart(dst)
|
||||
if len(a.buf) > 0 {
|
||||
dst = append(append(dst, a.buf...))
|
||||
}
|
||||
dst = appendArrayEnd(dst)
|
||||
arrayPool.Put(a)
|
||||
return dst
|
||||
}
|
||||
|
||||
// Object marshals an object that implement the LogObjectMarshaler
|
||||
// interface and append it to the array.
|
||||
func (a *Array) Object(obj LogObjectMarshaler) *Array {
|
||||
e := Dict()
|
||||
obj.MarshalZerologObject(e)
|
||||
e.buf = appendEndMarker(e.buf)
|
||||
a.buf = append(appendArrayDelim(a.buf), e.buf...)
|
||||
eventPool.Put(e)
|
||||
return a
|
||||
}
|
||||
|
||||
// Str append the val as a string to the array.
|
||||
func (a *Array) Str(val string) *Array {
|
||||
a.buf = appendString(appendArrayDelim(a.buf), val)
|
||||
return a
|
||||
}
|
||||
|
||||
// Bytes append the val as a string to the array.
|
||||
func (a *Array) Bytes(val []byte) *Array {
|
||||
a.buf = appendBytes(appendArrayDelim(a.buf), val)
|
||||
return a
|
||||
}
|
||||
|
||||
// Hex append the val as a hex string to the array.
|
||||
func (a *Array) Hex(val []byte) *Array {
|
||||
a.buf = appendHex(appendArrayDelim(a.buf), val)
|
||||
return a
|
||||
}
|
||||
|
||||
// Err append the err as a string to the array.
|
||||
func (a *Array) Err(err error) *Array {
|
||||
a.buf = appendError(appendArrayDelim(a.buf), err)
|
||||
return a
|
||||
}
|
||||
|
||||
// Bool append the val as a bool to the array.
|
||||
func (a *Array) Bool(b bool) *Array {
|
||||
a.buf = appendBool(appendArrayDelim(a.buf), b)
|
||||
return a
|
||||
}
|
||||
|
||||
// Int append i as a int to the array.
|
||||
func (a *Array) Int(i int) *Array {
|
||||
a.buf = appendInt(appendArrayDelim(a.buf), i)
|
||||
return a
|
||||
}
|
||||
|
||||
// Int8 append i as a int8 to the array.
|
||||
func (a *Array) Int8(i int8) *Array {
|
||||
a.buf = appendInt8(appendArrayDelim(a.buf), i)
|
||||
return a
|
||||
}
|
||||
|
||||
// Int16 append i as a int16 to the array.
|
||||
func (a *Array) Int16(i int16) *Array {
|
||||
a.buf = appendInt16(appendArrayDelim(a.buf), i)
|
||||
return a
|
||||
}
|
||||
|
||||
// Int32 append i as a int32 to the array.
|
||||
func (a *Array) Int32(i int32) *Array {
|
||||
a.buf = appendInt32(appendArrayDelim(a.buf), i)
|
||||
return a
|
||||
}
|
||||
|
||||
// Int64 append i as a int64 to the array.
|
||||
func (a *Array) Int64(i int64) *Array {
|
||||
a.buf = appendInt64(appendArrayDelim(a.buf), i)
|
||||
return a
|
||||
}
|
||||
|
||||
// Uint append i as a uint to the array.
|
||||
func (a *Array) Uint(i uint) *Array {
|
||||
a.buf = appendUint(appendArrayDelim(a.buf), i)
|
||||
return a
|
||||
}
|
||||
|
||||
// Uint8 append i as a uint8 to the array.
|
||||
func (a *Array) Uint8(i uint8) *Array {
|
||||
a.buf = appendUint8(appendArrayDelim(a.buf), i)
|
||||
return a
|
||||
}
|
||||
|
||||
// Uint16 append i as a uint16 to the array.
|
||||
func (a *Array) Uint16(i uint16) *Array {
|
||||
a.buf = appendUint16(appendArrayDelim(a.buf), i)
|
||||
return a
|
||||
}
|
||||
|
||||
// Uint32 append i as a uint32 to the array.
|
||||
func (a *Array) Uint32(i uint32) *Array {
|
||||
a.buf = appendUint32(appendArrayDelim(a.buf), i)
|
||||
return a
|
||||
}
|
||||
|
||||
// Uint64 append i as a uint64 to the array.
|
||||
func (a *Array) Uint64(i uint64) *Array {
|
||||
a.buf = appendUint64(appendArrayDelim(a.buf), i)
|
||||
return a
|
||||
}
|
||||
|
||||
// Float32 append f as a float32 to the array.
|
||||
func (a *Array) Float32(f float32) *Array {
|
||||
a.buf = appendFloat32(appendArrayDelim(a.buf), f)
|
||||
return a
|
||||
}
|
||||
|
||||
// Float64 append f as a float64 to the array.
|
||||
func (a *Array) Float64(f float64) *Array {
|
||||
a.buf = appendFloat64(appendArrayDelim(a.buf), f)
|
||||
return a
|
||||
}
|
||||
|
||||
// Time append t formated as string using zerolog.TimeFieldFormat.
|
||||
func (a *Array) Time(t time.Time) *Array {
|
||||
a.buf = appendTime(appendArrayDelim(a.buf), t, TimeFieldFormat)
|
||||
return a
|
||||
}
|
||||
|
||||
// Dur append d to the array.
|
||||
func (a *Array) Dur(d time.Duration) *Array {
|
||||
a.buf = appendDuration(appendArrayDelim(a.buf), d, DurationFieldUnit, DurationFieldInteger)
|
||||
return a
|
||||
}
|
||||
|
||||
// Interface append i marshaled using reflection.
|
||||
func (a *Array) Interface(i interface{}) *Array {
|
||||
if obj, ok := i.(LogObjectMarshaler); ok {
|
||||
return a.Object(obj)
|
||||
}
|
||||
a.buf = appendInterface(appendArrayDelim(a.buf), i)
|
||||
return a
|
||||
}
|
125
vendor/github.com/rs/zerolog/console.go
generated
vendored
Normal file
125
vendor/github.com/rs/zerolog/console.go
generated
vendored
Normal file
@@ -0,0 +1,125 @@
|
||||
package zerolog
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
const (
|
||||
cReset = 0
|
||||
cBold = 1
|
||||
cRed = 31
|
||||
cGreen = 32
|
||||
cYellow = 33
|
||||
cBlue = 34
|
||||
cMagenta = 35
|
||||
cCyan = 36
|
||||
cGray = 37
|
||||
cDarkGray = 90
|
||||
)
|
||||
|
||||
var consoleBufPool = sync.Pool{
|
||||
New: func() interface{} {
|
||||
return bytes.NewBuffer(make([]byte, 0, 100))
|
||||
},
|
||||
}
|
||||
|
||||
// ConsoleWriter reads a JSON object per write operation and output an
|
||||
// optionally colored human readable version on the Out writer.
|
||||
type ConsoleWriter struct {
|
||||
Out io.Writer
|
||||
NoColor bool
|
||||
}
|
||||
|
||||
func (w ConsoleWriter) Write(p []byte) (n int, err error) {
|
||||
var event map[string]interface{}
|
||||
p = decodeIfBinaryToBytes(p)
|
||||
err = json.Unmarshal(p, &event)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
buf := consoleBufPool.Get().(*bytes.Buffer)
|
||||
defer consoleBufPool.Put(buf)
|
||||
lvlColor := cReset
|
||||
level := "????"
|
||||
if l, ok := event[LevelFieldName].(string); ok {
|
||||
if !w.NoColor {
|
||||
lvlColor = levelColor(l)
|
||||
}
|
||||
level = strings.ToUpper(l)[0:4]
|
||||
}
|
||||
fmt.Fprintf(buf, "%s |%s| %s",
|
||||
colorize(event[TimestampFieldName], cDarkGray, !w.NoColor),
|
||||
colorize(level, lvlColor, !w.NoColor),
|
||||
colorize(event[MessageFieldName], cReset, !w.NoColor))
|
||||
fields := make([]string, 0, len(event))
|
||||
for field := range event {
|
||||
switch field {
|
||||
case LevelFieldName, TimestampFieldName, MessageFieldName:
|
||||
continue
|
||||
}
|
||||
fields = append(fields, field)
|
||||
}
|
||||
sort.Strings(fields)
|
||||
for _, field := range fields {
|
||||
fmt.Fprintf(buf, " %s=", colorize(field, cCyan, !w.NoColor))
|
||||
switch value := event[field].(type) {
|
||||
case string:
|
||||
if needsQuote(value) {
|
||||
buf.WriteString(strconv.Quote(value))
|
||||
} else {
|
||||
buf.WriteString(value)
|
||||
}
|
||||
case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, float32, float64:
|
||||
fmt.Fprint(buf, value)
|
||||
default:
|
||||
b, err := json.Marshal(value)
|
||||
if err != nil {
|
||||
fmt.Fprintf(buf, "[error: %v]", err)
|
||||
} else {
|
||||
fmt.Fprint(buf, string(b))
|
||||
}
|
||||
}
|
||||
}
|
||||
buf.WriteByte('\n')
|
||||
buf.WriteTo(w.Out)
|
||||
n = len(p)
|
||||
return
|
||||
}
|
||||
|
||||
func colorize(s interface{}, color int, enabled bool) string {
|
||||
if !enabled {
|
||||
return fmt.Sprintf("%v", s)
|
||||
}
|
||||
return fmt.Sprintf("\x1b[%dm%v\x1b[0m", color, s)
|
||||
}
|
||||
|
||||
func levelColor(level string) int {
|
||||
switch level {
|
||||
case "debug":
|
||||
return cMagenta
|
||||
case "info":
|
||||
return cGreen
|
||||
case "warn":
|
||||
return cYellow
|
||||
case "error", "fatal", "panic":
|
||||
return cRed
|
||||
default:
|
||||
return cReset
|
||||
}
|
||||
}
|
||||
|
||||
func needsQuote(s string) bool {
|
||||
for i := range s {
|
||||
if s[i] < 0x20 || s[i] > 0x7e || s[i] == ' ' || s[i] == '\\' || s[i] == '"' {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
332
vendor/github.com/rs/zerolog/context.go
generated
vendored
Normal file
332
vendor/github.com/rs/zerolog/context.go
generated
vendored
Normal file
@@ -0,0 +1,332 @@
|
||||
package zerolog
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Context configures a new sub-logger with contextual fields.
|
||||
type Context struct {
|
||||
l Logger
|
||||
}
|
||||
|
||||
// Logger returns the logger with the context previously set.
|
||||
func (c Context) Logger() Logger {
|
||||
return c.l
|
||||
}
|
||||
|
||||
// Fields is a helper function to use a map to set fields using type assertion.
|
||||
func (c Context) Fields(fields map[string]interface{}) Context {
|
||||
c.l.context = appendFields(c.l.context, fields)
|
||||
return c
|
||||
}
|
||||
|
||||
// Dict adds the field key with the dict to the logger context.
|
||||
func (c Context) Dict(key string, dict *Event) Context {
|
||||
dict.buf = appendEndMarker(dict.buf)
|
||||
c.l.context = append(appendKey(c.l.context, key), dict.buf...)
|
||||
eventPool.Put(dict)
|
||||
return c
|
||||
}
|
||||
|
||||
// Array adds the field key with an array to the event context.
|
||||
// Use zerolog.Arr() to create the array or pass a type that
|
||||
// implement the LogArrayMarshaler interface.
|
||||
func (c Context) Array(key string, arr LogArrayMarshaler) Context {
|
||||
c.l.context = appendKey(c.l.context, key)
|
||||
if arr, ok := arr.(*Array); ok {
|
||||
c.l.context = arr.write(c.l.context)
|
||||
return c
|
||||
}
|
||||
var a *Array
|
||||
if aa, ok := arr.(*Array); ok {
|
||||
a = aa
|
||||
} else {
|
||||
a = Arr()
|
||||
arr.MarshalZerologArray(a)
|
||||
}
|
||||
c.l.context = a.write(c.l.context)
|
||||
return c
|
||||
}
|
||||
|
||||
// Object marshals an object that implement the LogObjectMarshaler interface.
|
||||
func (c Context) Object(key string, obj LogObjectMarshaler) Context {
|
||||
e := newEvent(levelWriterAdapter{ioutil.Discard}, 0, true)
|
||||
e.Object(key, obj)
|
||||
c.l.context = appendObjectData(c.l.context, e.buf)
|
||||
eventPool.Put(e)
|
||||
return c
|
||||
}
|
||||
|
||||
// Str adds the field key with val as a string to the logger context.
|
||||
func (c Context) Str(key, val string) Context {
|
||||
c.l.context = appendString(appendKey(c.l.context, key), val)
|
||||
return c
|
||||
}
|
||||
|
||||
// Strs adds the field key with val as a string to the logger context.
|
||||
func (c Context) Strs(key string, vals []string) Context {
|
||||
c.l.context = appendStrings(appendKey(c.l.context, key), vals)
|
||||
return c
|
||||
}
|
||||
|
||||
// Bytes adds the field key with val as a []byte to the logger context.
|
||||
func (c Context) Bytes(key string, val []byte) Context {
|
||||
c.l.context = appendBytes(appendKey(c.l.context, key), val)
|
||||
return c
|
||||
}
|
||||
|
||||
// Hex adds the field key with val as a hex string to the logger context.
|
||||
func (c Context) Hex(key string, val []byte) Context {
|
||||
c.l.context = appendHex(appendKey(c.l.context, key), val)
|
||||
return c
|
||||
}
|
||||
|
||||
// RawJSON adds already encoded JSON to context.
|
||||
//
|
||||
// No sanity check is performed on b; it must not contain carriage returns and
|
||||
// be valid JSON.
|
||||
func (c Context) RawJSON(key string, b []byte) Context {
|
||||
c.l.context = appendJSON(appendKey(c.l.context, key), b)
|
||||
return c
|
||||
}
|
||||
|
||||
// AnErr adds the field key with err as a string to the logger context.
|
||||
func (c Context) AnErr(key string, err error) Context {
|
||||
if err != nil {
|
||||
c.l.context = appendError(appendKey(c.l.context, key), err)
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
// Errs adds the field key with errs as an array of strings to the logger context.
|
||||
func (c Context) Errs(key string, errs []error) Context {
|
||||
c.l.context = appendErrors(appendKey(c.l.context, key), errs)
|
||||
return c
|
||||
}
|
||||
|
||||
// Err adds the field "error" with err as a string to the logger context.
|
||||
// To customize the key name, change zerolog.ErrorFieldName.
|
||||
func (c Context) Err(err error) Context {
|
||||
if err != nil {
|
||||
c.l.context = appendError(appendKey(c.l.context, ErrorFieldName), err)
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
// Bool adds the field key with val as a bool to the logger context.
|
||||
func (c Context) Bool(key string, b bool) Context {
|
||||
c.l.context = appendBool(appendKey(c.l.context, key), b)
|
||||
return c
|
||||
}
|
||||
|
||||
// Bools adds the field key with val as a []bool to the logger context.
|
||||
func (c Context) Bools(key string, b []bool) Context {
|
||||
c.l.context = appendBools(appendKey(c.l.context, key), b)
|
||||
return c
|
||||
}
|
||||
|
||||
// Int adds the field key with i as a int to the logger context.
|
||||
func (c Context) Int(key string, i int) Context {
|
||||
c.l.context = appendInt(appendKey(c.l.context, key), i)
|
||||
return c
|
||||
}
|
||||
|
||||
// Ints adds the field key with i as a []int to the logger context.
|
||||
func (c Context) Ints(key string, i []int) Context {
|
||||
c.l.context = appendInts(appendKey(c.l.context, key), i)
|
||||
return c
|
||||
}
|
||||
|
||||
// Int8 adds the field key with i as a int8 to the logger context.
|
||||
func (c Context) Int8(key string, i int8) Context {
|
||||
c.l.context = appendInt8(appendKey(c.l.context, key), i)
|
||||
return c
|
||||
}
|
||||
|
||||
// Ints8 adds the field key with i as a []int8 to the logger context.
|
||||
func (c Context) Ints8(key string, i []int8) Context {
|
||||
c.l.context = appendInts8(appendKey(c.l.context, key), i)
|
||||
return c
|
||||
}
|
||||
|
||||
// Int16 adds the field key with i as a int16 to the logger context.
|
||||
func (c Context) Int16(key string, i int16) Context {
|
||||
c.l.context = appendInt16(appendKey(c.l.context, key), i)
|
||||
return c
|
||||
}
|
||||
|
||||
// Ints16 adds the field key with i as a []int16 to the logger context.
|
||||
func (c Context) Ints16(key string, i []int16) Context {
|
||||
c.l.context = appendInts16(appendKey(c.l.context, key), i)
|
||||
return c
|
||||
}
|
||||
|
||||
// Int32 adds the field key with i as a int32 to the logger context.
|
||||
func (c Context) Int32(key string, i int32) Context {
|
||||
c.l.context = appendInt32(appendKey(c.l.context, key), i)
|
||||
return c
|
||||
}
|
||||
|
||||
// Ints32 adds the field key with i as a []int32 to the logger context.
|
||||
func (c Context) Ints32(key string, i []int32) Context {
|
||||
c.l.context = appendInts32(appendKey(c.l.context, key), i)
|
||||
return c
|
||||
}
|
||||
|
||||
// Int64 adds the field key with i as a int64 to the logger context.
|
||||
func (c Context) Int64(key string, i int64) Context {
|
||||
c.l.context = appendInt64(appendKey(c.l.context, key), i)
|
||||
return c
|
||||
}
|
||||
|
||||
// Ints64 adds the field key with i as a []int64 to the logger context.
|
||||
func (c Context) Ints64(key string, i []int64) Context {
|
||||
c.l.context = appendInts64(appendKey(c.l.context, key), i)
|
||||
return c
|
||||
}
|
||||
|
||||
// Uint adds the field key with i as a uint to the logger context.
|
||||
func (c Context) Uint(key string, i uint) Context {
|
||||
c.l.context = appendUint(appendKey(c.l.context, key), i)
|
||||
return c
|
||||
}
|
||||
|
||||
// Uints adds the field key with i as a []uint to the logger context.
|
||||
func (c Context) Uints(key string, i []uint) Context {
|
||||
c.l.context = appendUints(appendKey(c.l.context, key), i)
|
||||
return c
|
||||
}
|
||||
|
||||
// Uint8 adds the field key with i as a uint8 to the logger context.
|
||||
func (c Context) Uint8(key string, i uint8) Context {
|
||||
c.l.context = appendUint8(appendKey(c.l.context, key), i)
|
||||
return c
|
||||
}
|
||||
|
||||
// Uints8 adds the field key with i as a []uint8 to the logger context.
|
||||
func (c Context) Uints8(key string, i []uint8) Context {
|
||||
c.l.context = appendUints8(appendKey(c.l.context, key), i)
|
||||
return c
|
||||
}
|
||||
|
||||
// Uint16 adds the field key with i as a uint16 to the logger context.
|
||||
func (c Context) Uint16(key string, i uint16) Context {
|
||||
c.l.context = appendUint16(appendKey(c.l.context, key), i)
|
||||
return c
|
||||
}
|
||||
|
||||
// Uints16 adds the field key with i as a []uint16 to the logger context.
|
||||
func (c Context) Uints16(key string, i []uint16) Context {
|
||||
c.l.context = appendUints16(appendKey(c.l.context, key), i)
|
||||
return c
|
||||
}
|
||||
|
||||
// Uint32 adds the field key with i as a uint32 to the logger context.
|
||||
func (c Context) Uint32(key string, i uint32) Context {
|
||||
c.l.context = appendUint32(appendKey(c.l.context, key), i)
|
||||
return c
|
||||
}
|
||||
|
||||
// Uints32 adds the field key with i as a []uint32 to the logger context.
|
||||
func (c Context) Uints32(key string, i []uint32) Context {
|
||||
c.l.context = appendUints32(appendKey(c.l.context, key), i)
|
||||
return c
|
||||
}
|
||||
|
||||
// Uint64 adds the field key with i as a uint64 to the logger context.
|
||||
func (c Context) Uint64(key string, i uint64) Context {
|
||||
c.l.context = appendUint64(appendKey(c.l.context, key), i)
|
||||
return c
|
||||
}
|
||||
|
||||
// Uints64 adds the field key with i as a []uint64 to the logger context.
|
||||
func (c Context) Uints64(key string, i []uint64) Context {
|
||||
c.l.context = appendUints64(appendKey(c.l.context, key), i)
|
||||
return c
|
||||
}
|
||||
|
||||
// Float32 adds the field key with f as a float32 to the logger context.
|
||||
func (c Context) Float32(key string, f float32) Context {
|
||||
c.l.context = appendFloat32(appendKey(c.l.context, key), f)
|
||||
return c
|
||||
}
|
||||
|
||||
// Floats32 adds the field key with f as a []float32 to the logger context.
|
||||
func (c Context) Floats32(key string, f []float32) Context {
|
||||
c.l.context = appendFloats32(appendKey(c.l.context, key), f)
|
||||
return c
|
||||
}
|
||||
|
||||
// Float64 adds the field key with f as a float64 to the logger context.
|
||||
func (c Context) Float64(key string, f float64) Context {
|
||||
c.l.context = appendFloat64(appendKey(c.l.context, key), f)
|
||||
return c
|
||||
}
|
||||
|
||||
// Floats64 adds the field key with f as a []float64 to the logger context.
|
||||
func (c Context) Floats64(key string, f []float64) Context {
|
||||
c.l.context = appendFloats64(appendKey(c.l.context, key), f)
|
||||
return c
|
||||
}
|
||||
|
||||
type timestampHook struct{}
|
||||
|
||||
func (ts timestampHook) Run(e *Event, level Level, msg string) {
|
||||
e.Timestamp()
|
||||
}
|
||||
|
||||
var th = timestampHook{}
|
||||
|
||||
// Timestamp adds the current local time as UNIX timestamp to the logger context with the "time" key.
|
||||
// To customize the key name, change zerolog.TimestampFieldName.
|
||||
//
|
||||
// NOTE: It won't dedupe the "time" key if the *Context has one already.
|
||||
func (c Context) Timestamp() Context {
|
||||
c.l = c.l.Hook(th)
|
||||
return c
|
||||
}
|
||||
|
||||
// Time adds the field key with t formated as string using zerolog.TimeFieldFormat.
|
||||
func (c Context) Time(key string, t time.Time) Context {
|
||||
c.l.context = appendTime(appendKey(c.l.context, key), t, TimeFieldFormat)
|
||||
return c
|
||||
}
|
||||
|
||||
// Times adds the field key with t formated as string using zerolog.TimeFieldFormat.
|
||||
func (c Context) Times(key string, t []time.Time) Context {
|
||||
c.l.context = appendTimes(appendKey(c.l.context, key), t, TimeFieldFormat)
|
||||
return c
|
||||
}
|
||||
|
||||
// Dur adds the fields key with d divided by unit and stored as a float.
|
||||
func (c Context) Dur(key string, d time.Duration) Context {
|
||||
c.l.context = appendDuration(appendKey(c.l.context, key), d, DurationFieldUnit, DurationFieldInteger)
|
||||
return c
|
||||
}
|
||||
|
||||
// Durs adds the fields key with d divided by unit and stored as a float.
|
||||
func (c Context) Durs(key string, d []time.Duration) Context {
|
||||
c.l.context = appendDurations(appendKey(c.l.context, key), d, DurationFieldUnit, DurationFieldInteger)
|
||||
return c
|
||||
}
|
||||
|
||||
// Interface adds the field key with obj marshaled using reflection.
|
||||
func (c Context) Interface(key string, i interface{}) Context {
|
||||
c.l.context = appendInterface(appendKey(c.l.context, key), i)
|
||||
return c
|
||||
}
|
||||
|
||||
type callerHook struct{}
|
||||
|
||||
func (ch callerHook) Run(e *Event, level Level, msg string) {
|
||||
e.caller(4)
|
||||
}
|
||||
|
||||
var ch = callerHook{}
|
||||
|
||||
// Caller adds the file:line of the caller with the zerolog.CallerFieldName key.
|
||||
func (c Context) Caller() Context {
|
||||
c.l = c.l.Hook(ch)
|
||||
return c
|
||||
}
|
46
vendor/github.com/rs/zerolog/ctx.go
generated
vendored
Normal file
46
vendor/github.com/rs/zerolog/ctx.go
generated
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
package zerolog
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io/ioutil"
|
||||
)
|
||||
|
||||
var disabledLogger *Logger
|
||||
|
||||
func init() {
|
||||
l := New(ioutil.Discard).Level(Disabled)
|
||||
disabledLogger = &l
|
||||
}
|
||||
|
||||
type ctxKey struct{}
|
||||
|
||||
// WithContext returns a copy of ctx with l associated. If an instance of Logger
|
||||
// is already in the context, the pointer to this logger is updated with l.
|
||||
//
|
||||
// For instance, to add a field to an existing logger in the context, use this
|
||||
// notation:
|
||||
//
|
||||
// ctx := r.Context()
|
||||
// l := zerolog.Ctx(ctx)
|
||||
// ctx = l.With().Str("foo", "bar").WithContext(ctx)
|
||||
func (l Logger) WithContext(ctx context.Context) context.Context {
|
||||
if lp, ok := ctx.Value(ctxKey{}).(*Logger); ok {
|
||||
// Update existing pointer.
|
||||
*lp = l
|
||||
return ctx
|
||||
}
|
||||
if l.level == Disabled {
|
||||
// Do not store disabled logger.
|
||||
return ctx
|
||||
}
|
||||
return context.WithValue(ctx, ctxKey{}, &l)
|
||||
}
|
||||
|
||||
// Ctx returns the Logger associated with the ctx. If no logger
|
||||
// is associated, a disabled logger is returned.
|
||||
func Ctx(ctx context.Context) *Logger {
|
||||
if l, ok := ctx.Value(ctxKey{}).(*Logger); ok {
|
||||
return l
|
||||
}
|
||||
return disabledLogger
|
||||
}
|
218
vendor/github.com/rs/zerolog/encoder_cbor.go
generated
vendored
Normal file
218
vendor/github.com/rs/zerolog/encoder_cbor.go
generated
vendored
Normal file
@@ -0,0 +1,218 @@
|
||||
// +build binary_log
|
||||
|
||||
package zerolog
|
||||
|
||||
// This file contains bindings to do binary encoding.
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/rs/zerolog/internal/cbor"
|
||||
)
|
||||
|
||||
func appendInterface(dst []byte, i interface{}) []byte {
|
||||
return cbor.AppendInterface(dst, i)
|
||||
}
|
||||
|
||||
func appendKey(dst []byte, s string) []byte {
|
||||
return cbor.AppendKey(dst, s)
|
||||
}
|
||||
|
||||
func appendFloats64(dst []byte, f []float64) []byte {
|
||||
return cbor.AppendFloats64(dst, f)
|
||||
}
|
||||
|
||||
func appendFloat64(dst []byte, f float64) []byte {
|
||||
return cbor.AppendFloat64(dst, f)
|
||||
}
|
||||
|
||||
func appendFloats32(dst []byte, f []float32) []byte {
|
||||
return cbor.AppendFloats32(dst, f)
|
||||
}
|
||||
|
||||
func appendFloat32(dst []byte, f float32) []byte {
|
||||
return cbor.AppendFloat32(dst, f)
|
||||
}
|
||||
|
||||
func appendUints64(dst []byte, i []uint64) []byte {
|
||||
return cbor.AppendUints64(dst, i)
|
||||
}
|
||||
|
||||
func appendUint64(dst []byte, i uint64) []byte {
|
||||
return cbor.AppendUint64(dst, i)
|
||||
}
|
||||
|
||||
func appendUints32(dst []byte, i []uint32) []byte {
|
||||
return cbor.AppendUints32(dst, i)
|
||||
}
|
||||
|
||||
func appendUint32(dst []byte, i uint32) []byte {
|
||||
return cbor.AppendUint32(dst, i)
|
||||
}
|
||||
|
||||
func appendUints16(dst []byte, i []uint16) []byte {
|
||||
return cbor.AppendUints16(dst, i)
|
||||
}
|
||||
|
||||
func appendUint16(dst []byte, i uint16) []byte {
|
||||
return cbor.AppendUint16(dst, i)
|
||||
}
|
||||
|
||||
func appendUints8(dst []byte, i []uint8) []byte {
|
||||
return cbor.AppendUints8(dst, i)
|
||||
}
|
||||
|
||||
func appendUint8(dst []byte, i uint8) []byte {
|
||||
return cbor.AppendUint8(dst, i)
|
||||
}
|
||||
|
||||
func appendUints(dst []byte, i []uint) []byte {
|
||||
return cbor.AppendUints(dst, i)
|
||||
}
|
||||
|
||||
func appendUint(dst []byte, i uint) []byte {
|
||||
return cbor.AppendUint(dst, i)
|
||||
}
|
||||
|
||||
func appendInts64(dst []byte, i []int64) []byte {
|
||||
return cbor.AppendInts64(dst, i)
|
||||
}
|
||||
|
||||
func appendInt64(dst []byte, i int64) []byte {
|
||||
return cbor.AppendInt64(dst, i)
|
||||
}
|
||||
|
||||
func appendInts32(dst []byte, i []int32) []byte {
|
||||
return cbor.AppendInts32(dst, i)
|
||||
}
|
||||
|
||||
func appendInt32(dst []byte, i int32) []byte {
|
||||
return cbor.AppendInt32(dst, i)
|
||||
}
|
||||
|
||||
func appendInts16(dst []byte, i []int16) []byte {
|
||||
return cbor.AppendInts16(dst, i)
|
||||
}
|
||||
|
||||
func appendInt16(dst []byte, i int16) []byte {
|
||||
return cbor.AppendInt16(dst, i)
|
||||
}
|
||||
|
||||
func appendInts8(dst []byte, i []int8) []byte {
|
||||
return cbor.AppendInts8(dst, i)
|
||||
}
|
||||
|
||||
func appendInt8(dst []byte, i int8) []byte {
|
||||
return cbor.AppendInt8(dst, i)
|
||||
}
|
||||
|
||||
func appendInts(dst []byte, i []int) []byte {
|
||||
return cbor.AppendInts(dst, i)
|
||||
}
|
||||
|
||||
func appendInt(dst []byte, i int) []byte {
|
||||
return cbor.AppendInt(dst, i)
|
||||
}
|
||||
|
||||
func appendBools(dst []byte, b []bool) []byte {
|
||||
return cbor.AppendBools(dst, b)
|
||||
}
|
||||
|
||||
func appendBool(dst []byte, b bool) []byte {
|
||||
return cbor.AppendBool(dst, b)
|
||||
}
|
||||
|
||||
func appendError(dst []byte, e error) []byte {
|
||||
return cbor.AppendError(dst, e)
|
||||
}
|
||||
|
||||
func appendErrors(dst []byte, e []error) []byte {
|
||||
return cbor.AppendErrors(dst, e)
|
||||
}
|
||||
|
||||
func appendString(dst []byte, s string) []byte {
|
||||
return cbor.AppendString(dst, s)
|
||||
}
|
||||
|
||||
func appendStrings(dst []byte, s []string) []byte {
|
||||
return cbor.AppendStrings(dst, s)
|
||||
}
|
||||
|
||||
func appendDuration(dst []byte, t time.Duration, d time.Duration, fmt bool) []byte {
|
||||
return cbor.AppendDuration(dst, t, d, fmt)
|
||||
}
|
||||
|
||||
func appendDurations(dst []byte, t []time.Duration, d time.Duration, fmt bool) []byte {
|
||||
return cbor.AppendDurations(dst, t, d, fmt)
|
||||
}
|
||||
|
||||
func appendTimes(dst []byte, t []time.Time, fmt string) []byte {
|
||||
return cbor.AppendTimes(dst, t, fmt)
|
||||
}
|
||||
|
||||
func appendTime(dst []byte, t time.Time, fmt string) []byte {
|
||||
return cbor.AppendTime(dst, t, fmt)
|
||||
}
|
||||
|
||||
func appendEndMarker(dst []byte) []byte {
|
||||
return cbor.AppendEndMarker(dst)
|
||||
}
|
||||
|
||||
func appendLineBreak(dst []byte) []byte {
|
||||
// No line breaks needed in binary format.
|
||||
return dst
|
||||
}
|
||||
|
||||
func appendBeginMarker(dst []byte) []byte {
|
||||
return cbor.AppendBeginMarker(dst)
|
||||
}
|
||||
|
||||
func appendBytes(dst []byte, b []byte) []byte {
|
||||
return cbor.AppendBytes(dst, b)
|
||||
}
|
||||
|
||||
func appendArrayStart(dst []byte) []byte {
|
||||
return cbor.AppendArrayStart(dst)
|
||||
}
|
||||
|
||||
func appendArrayEnd(dst []byte) []byte {
|
||||
return cbor.AppendArrayEnd(dst)
|
||||
}
|
||||
|
||||
func appendArrayDelim(dst []byte) []byte {
|
||||
return cbor.AppendArrayDelim(dst)
|
||||
}
|
||||
|
||||
func appendObjectData(dst []byte, src []byte) []byte {
|
||||
// Map begin character is present in the src, which
|
||||
// should not be copied when appending to existing data.
|
||||
return cbor.AppendObjectData(dst, src[1:])
|
||||
}
|
||||
|
||||
func appendJSON(dst []byte, j []byte) []byte {
|
||||
return cbor.AppendEmbeddedJSON(dst, j)
|
||||
}
|
||||
|
||||
func appendNil(dst []byte) []byte {
|
||||
return cbor.AppendNull(dst)
|
||||
}
|
||||
|
||||
func appendHex(dst []byte, val []byte) []byte {
|
||||
return cbor.AppendHex(dst, val)
|
||||
}
|
||||
|
||||
// decodeIfBinaryToString - converts a binary formatted log msg to a
|
||||
// JSON formatted String Log message.
|
||||
func decodeIfBinaryToString(in []byte) string {
|
||||
return cbor.DecodeIfBinaryToString(in)
|
||||
}
|
||||
|
||||
func decodeObjectToStr(in []byte) string {
|
||||
return cbor.DecodeObjectToStr(in)
|
||||
}
|
||||
|
||||
// decodeIfBinaryToBytes - converts a binary formatted log msg to a
|
||||
// JSON formatted Bytes Log message.
|
||||
func decodeIfBinaryToBytes(in []byte) []byte {
|
||||
return cbor.DecodeIfBinaryToBytes(in)
|
||||
}
|
216
vendor/github.com/rs/zerolog/encoder_json.go
generated
vendored
Normal file
216
vendor/github.com/rs/zerolog/encoder_json.go
generated
vendored
Normal file
@@ -0,0 +1,216 @@
|
||||
// +build !binary_log
|
||||
|
||||
package zerolog
|
||||
|
||||
// encoder_json.go file contains bindings to generate
|
||||
// JSON encoded byte stream.
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/rs/zerolog/internal/json"
|
||||
)
|
||||
|
||||
func appendInterface(dst []byte, i interface{}) []byte {
|
||||
return json.AppendInterface(dst, i)
|
||||
}
|
||||
|
||||
func appendKey(dst []byte, s string) []byte {
|
||||
return json.AppendKey(dst, s)
|
||||
}
|
||||
|
||||
func appendFloats64(dst []byte, f []float64) []byte {
|
||||
return json.AppendFloats64(dst, f)
|
||||
}
|
||||
|
||||
func appendFloat64(dst []byte, f float64) []byte {
|
||||
return json.AppendFloat64(dst, f)
|
||||
}
|
||||
|
||||
func appendFloats32(dst []byte, f []float32) []byte {
|
||||
return json.AppendFloats32(dst, f)
|
||||
}
|
||||
|
||||
func appendFloat32(dst []byte, f float32) []byte {
|
||||
return json.AppendFloat32(dst, f)
|
||||
}
|
||||
|
||||
func appendUints64(dst []byte, i []uint64) []byte {
|
||||
return json.AppendUints64(dst, i)
|
||||
}
|
||||
|
||||
func appendUint64(dst []byte, i uint64) []byte {
|
||||
return strconv.AppendUint(dst, uint64(i), 10)
|
||||
}
|
||||
|
||||
func appendUints32(dst []byte, i []uint32) []byte {
|
||||
return json.AppendUints32(dst, i)
|
||||
}
|
||||
|
||||
func appendUint32(dst []byte, i uint32) []byte {
|
||||
return strconv.AppendUint(dst, uint64(i), 10)
|
||||
}
|
||||
|
||||
func appendUints16(dst []byte, i []uint16) []byte {
|
||||
return json.AppendUints16(dst, i)
|
||||
}
|
||||
|
||||
func appendUint16(dst []byte, i uint16) []byte {
|
||||
return strconv.AppendUint(dst, uint64(i), 10)
|
||||
}
|
||||
|
||||
func appendUints8(dst []byte, i []uint8) []byte {
|
||||
return json.AppendUints8(dst, i)
|
||||
}
|
||||
|
||||
func appendUint8(dst []byte, i uint8) []byte {
|
||||
return strconv.AppendUint(dst, uint64(i), 10)
|
||||
}
|
||||
|
||||
func appendUints(dst []byte, i []uint) []byte {
|
||||
return json.AppendUints(dst, i)
|
||||
}
|
||||
|
||||
func appendUint(dst []byte, i uint) []byte {
|
||||
return strconv.AppendUint(dst, uint64(i), 10)
|
||||
}
|
||||
|
||||
func appendInts64(dst []byte, i []int64) []byte {
|
||||
return json.AppendInts64(dst, i)
|
||||
}
|
||||
|
||||
func appendInt64(dst []byte, i int64) []byte {
|
||||
return strconv.AppendInt(dst, int64(i), 10)
|
||||
}
|
||||
|
||||
func appendInts32(dst []byte, i []int32) []byte {
|
||||
return json.AppendInts32(dst, i)
|
||||
}
|
||||
|
||||
func appendInt32(dst []byte, i int32) []byte {
|
||||
return strconv.AppendInt(dst, int64(i), 10)
|
||||
}
|
||||
|
||||
func appendInts16(dst []byte, i []int16) []byte {
|
||||
return json.AppendInts16(dst, i)
|
||||
}
|
||||
|
||||
func appendInt16(dst []byte, i int16) []byte {
|
||||
return strconv.AppendInt(dst, int64(i), 10)
|
||||
}
|
||||
|
||||
func appendInts8(dst []byte, i []int8) []byte {
|
||||
return json.AppendInts8(dst, i)
|
||||
}
|
||||
|
||||
func appendInt8(dst []byte, i int8) []byte {
|
||||
return strconv.AppendInt(dst, int64(i), 10)
|
||||
}
|
||||
|
||||
func appendInts(dst []byte, i []int) []byte {
|
||||
return json.AppendInts(dst, i)
|
||||
}
|
||||
|
||||
func appendInt(dst []byte, i int) []byte {
|
||||
return strconv.AppendInt(dst, int64(i), 10)
|
||||
}
|
||||
|
||||
func appendBools(dst []byte, b []bool) []byte {
|
||||
return json.AppendBools(dst, b)
|
||||
}
|
||||
|
||||
func appendBool(dst []byte, b bool) []byte {
|
||||
return strconv.AppendBool(dst, b)
|
||||
}
|
||||
|
||||
func appendError(dst []byte, e error) []byte {
|
||||
return json.AppendError(dst, e)
|
||||
}
|
||||
|
||||
func appendErrors(dst []byte, e []error) []byte {
|
||||
return json.AppendErrors(dst, e)
|
||||
}
|
||||
|
||||
func appendString(dst []byte, s string) []byte {
|
||||
return json.AppendString(dst, s)
|
||||
}
|
||||
|
||||
func appendStrings(dst []byte, s []string) []byte {
|
||||
return json.AppendStrings(dst, s)
|
||||
}
|
||||
|
||||
func appendDuration(dst []byte, t time.Duration, d time.Duration, fmt bool) []byte {
|
||||
return json.AppendDuration(dst, t, d, fmt)
|
||||
}
|
||||
|
||||
func appendDurations(dst []byte, t []time.Duration, d time.Duration, fmt bool) []byte {
|
||||
return json.AppendDurations(dst, t, d, fmt)
|
||||
}
|
||||
|
||||
func appendTimes(dst []byte, t []time.Time, fmt string) []byte {
|
||||
return json.AppendTimes(dst, t, fmt)
|
||||
}
|
||||
|
||||
func appendTime(dst []byte, t time.Time, fmt string) []byte {
|
||||
return json.AppendTime(dst, t, fmt)
|
||||
}
|
||||
|
||||
func appendEndMarker(dst []byte) []byte {
|
||||
return append(dst, '}')
|
||||
}
|
||||
|
||||
func appendLineBreak(dst []byte) []byte {
|
||||
return append(dst, '\n')
|
||||
}
|
||||
|
||||
func appendBeginMarker(dst []byte) []byte {
|
||||
return append(dst, '{')
|
||||
}
|
||||
|
||||
func appendBytes(dst []byte, b []byte) []byte {
|
||||
return json.AppendBytes(dst, b)
|
||||
}
|
||||
|
||||
func appendArrayStart(dst []byte) []byte {
|
||||
return append(dst, '[')
|
||||
}
|
||||
|
||||
func appendArrayEnd(dst []byte) []byte {
|
||||
return append(dst, ']')
|
||||
}
|
||||
|
||||
func appendArrayDelim(dst []byte) []byte {
|
||||
if len(dst) > 0 {
|
||||
return append(dst, ',')
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
func appendObjectData(dst []byte, src []byte) []byte {
|
||||
return json.AppendObjectData(dst, src)
|
||||
}
|
||||
|
||||
func appendJSON(dst []byte, j []byte) []byte {
|
||||
return append(dst, j...)
|
||||
}
|
||||
|
||||
func appendNil(dst []byte) []byte {
|
||||
return append(dst, "null"...)
|
||||
}
|
||||
|
||||
func decodeIfBinaryToString(in []byte) string {
|
||||
return string(in)
|
||||
}
|
||||
|
||||
func decodeObjectToStr(in []byte) string {
|
||||
return string(in)
|
||||
}
|
||||
|
||||
func decodeIfBinaryToBytes(in []byte) []byte {
|
||||
return in
|
||||
}
|
||||
|
||||
func appendHex(in []byte, val []byte) []byte {
|
||||
return json.AppendHex(in, val)
|
||||
}
|
599
vendor/github.com/rs/zerolog/event.go
generated
vendored
Normal file
599
vendor/github.com/rs/zerolog/event.go
generated
vendored
Normal file
@@ -0,0 +1,599 @@
|
||||
package zerolog
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
var eventPool = &sync.Pool{
|
||||
New: func() interface{} {
|
||||
return &Event{
|
||||
buf: make([]byte, 0, 500),
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
// Event represents a log event. It is instanced by one of the level method of
|
||||
// Logger and finalized by the Msg or Msgf method.
|
||||
type Event struct {
|
||||
buf []byte
|
||||
w LevelWriter
|
||||
level Level
|
||||
done func(msg string)
|
||||
ch []Hook // hooks from context
|
||||
h []Hook
|
||||
}
|
||||
|
||||
// LogObjectMarshaler provides a strongly-typed and encoding-agnostic interface
|
||||
// to be implemented by types used with Event/Context's Object methods.
|
||||
type LogObjectMarshaler interface {
|
||||
MarshalZerologObject(e *Event)
|
||||
}
|
||||
|
||||
// LogArrayMarshaler provides a strongly-typed and encoding-agnostic interface
|
||||
// to be implemented by types used with Event/Context's Array methods.
|
||||
type LogArrayMarshaler interface {
|
||||
MarshalZerologArray(a *Array)
|
||||
}
|
||||
|
||||
func newEvent(w LevelWriter, level Level, enabled bool) *Event {
|
||||
if !enabled {
|
||||
return &Event{}
|
||||
}
|
||||
e := eventPool.Get().(*Event)
|
||||
e.buf = e.buf[:0]
|
||||
e.h = e.h[:0]
|
||||
e.buf = appendBeginMarker(e.buf)
|
||||
e.w = w
|
||||
e.level = level
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *Event) write() (err error) {
|
||||
if e == nil {
|
||||
return nil
|
||||
}
|
||||
e.buf = appendEndMarker(e.buf)
|
||||
e.buf = appendLineBreak(e.buf)
|
||||
if e.w != nil {
|
||||
_, err = e.w.WriteLevel(e.level, e.buf)
|
||||
}
|
||||
eventPool.Put(e)
|
||||
return
|
||||
}
|
||||
|
||||
// Enabled return false if the *Event is going to be filtered out by
|
||||
// log level or sampling.
|
||||
func (e *Event) Enabled() bool {
|
||||
return e != nil
|
||||
}
|
||||
|
||||
// Msg sends the *Event with msg added as the message field if not empty.
|
||||
//
|
||||
// NOTICE: once this method is called, the *Event should be disposed.
|
||||
// Calling Msg twice can have unexpected result.
|
||||
func (e *Event) Msg(msg string) {
|
||||
if e == nil {
|
||||
return
|
||||
}
|
||||
if len(e.ch) > 0 {
|
||||
e.ch[0].Run(e, e.level, msg)
|
||||
if len(e.ch) > 1 {
|
||||
for _, hook := range e.ch[1:] {
|
||||
hook.Run(e, e.level, msg)
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(e.h) > 0 {
|
||||
e.h[0].Run(e, e.level, msg)
|
||||
if len(e.h) > 1 {
|
||||
for _, hook := range e.h[1:] {
|
||||
hook.Run(e, e.level, msg)
|
||||
}
|
||||
}
|
||||
}
|
||||
if msg != "" {
|
||||
e.buf = appendString(appendKey(e.buf, MessageFieldName), msg)
|
||||
}
|
||||
if e.done != nil {
|
||||
defer e.done(msg)
|
||||
}
|
||||
if err := e.write(); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "zerolog: could not write event: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Msgf sends the event with formated msg added as the message field if not empty.
|
||||
//
|
||||
// NOTICE: once this methid is called, the *Event should be disposed.
|
||||
// Calling Msg twice can have unexpected result.
|
||||
func (e *Event) Msgf(format string, v ...interface{}) {
|
||||
if e == nil {
|
||||
return
|
||||
}
|
||||
e.Msg(fmt.Sprintf(format, v...))
|
||||
}
|
||||
|
||||
// Fields is a helper function to use a map to set fields using type assertion.
|
||||
func (e *Event) Fields(fields map[string]interface{}) *Event {
|
||||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = appendFields(e.buf, fields)
|
||||
return e
|
||||
}
|
||||
|
||||
// Dict adds the field key with a dict to the event context.
|
||||
// Use zerolog.Dict() to create the dictionary.
|
||||
func (e *Event) Dict(key string, dict *Event) *Event {
|
||||
if e == nil {
|
||||
return e
|
||||
}
|
||||
dict.buf = appendEndMarker(dict.buf)
|
||||
e.buf = append(appendKey(e.buf, key), dict.buf...)
|
||||
eventPool.Put(dict)
|
||||
return e
|
||||
}
|
||||
|
||||
// Dict creates an Event to be used with the *Event.Dict method.
|
||||
// Call usual field methods like Str, Int etc to add fields to this
|
||||
// event and give it as argument the *Event.Dict method.
|
||||
func Dict() *Event {
|
||||
return newEvent(nil, 0, true)
|
||||
}
|
||||
|
||||
// Array adds the field key with an array to the event context.
|
||||
// Use zerolog.Arr() to create the array or pass a type that
|
||||
// implement the LogArrayMarshaler interface.
|
||||
func (e *Event) Array(key string, arr LogArrayMarshaler) *Event {
|
||||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = appendKey(e.buf, key)
|
||||
var a *Array
|
||||
if aa, ok := arr.(*Array); ok {
|
||||
a = aa
|
||||
} else {
|
||||
a = Arr()
|
||||
arr.MarshalZerologArray(a)
|
||||
}
|
||||
e.buf = a.write(e.buf)
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *Event) appendObject(obj LogObjectMarshaler) {
|
||||
e.buf = appendBeginMarker(e.buf)
|
||||
obj.MarshalZerologObject(e)
|
||||
e.buf = appendEndMarker(e.buf)
|
||||
}
|
||||
|
||||
// Object marshals an object that implement the LogObjectMarshaler interface.
|
||||
func (e *Event) Object(key string, obj LogObjectMarshaler) *Event {
|
||||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = appendKey(e.buf, key)
|
||||
e.appendObject(obj)
|
||||
return e
|
||||
}
|
||||
|
||||
// Str adds the field key with val as a string to the *Event context.
|
||||
func (e *Event) Str(key, val string) *Event {
|
||||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = appendString(appendKey(e.buf, key), val)
|
||||
return e
|
||||
}
|
||||
|
||||
// Strs adds the field key with vals as a []string to the *Event context.
|
||||
func (e *Event) Strs(key string, vals []string) *Event {
|
||||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = appendStrings(appendKey(e.buf, key), vals)
|
||||
return e
|
||||
}
|
||||
|
||||
// Bytes adds the field key with val as a string to the *Event context.
|
||||
//
|
||||
// Runes outside of normal ASCII ranges will be hex-encoded in the resulting
|
||||
// JSON.
|
||||
func (e *Event) Bytes(key string, val []byte) *Event {
|
||||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = appendBytes(appendKey(e.buf, key), val)
|
||||
return e
|
||||
}
|
||||
|
||||
// Hex adds the field key with val as a hex string to the *Event context.
|
||||
func (e *Event) Hex(key string, val []byte) *Event {
|
||||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = appendHex(appendKey(e.buf, key), val)
|
||||
return e
|
||||
}
|
||||
|
||||
// RawJSON adds already encoded JSON to the log line under key.
|
||||
//
|
||||
// No sanity check is performed on b; it must not contain carriage returns and
|
||||
// be valid JSON.
|
||||
func (e *Event) RawJSON(key string, b []byte) *Event {
|
||||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = appendJSON(appendKey(e.buf, key), b)
|
||||
return e
|
||||
}
|
||||
|
||||
// AnErr adds the field key with err as a string to the *Event context.
|
||||
// If err is nil, no field is added.
|
||||
func (e *Event) AnErr(key string, err error) *Event {
|
||||
if e == nil {
|
||||
return e
|
||||
}
|
||||
if err != nil {
|
||||
e.buf = appendError(appendKey(e.buf, key), err)
|
||||
}
|
||||
return e
|
||||
}
|
||||
|
||||
// Errs adds the field key with errs as an array of strings to the *Event context.
|
||||
// If err is nil, no field is added.
|
||||
func (e *Event) Errs(key string, errs []error) *Event {
|
||||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = appendErrors(appendKey(e.buf, key), errs)
|
||||
return e
|
||||
}
|
||||
|
||||
// Err adds the field "error" with err as a string to the *Event context.
|
||||
// If err is nil, no field is added.
|
||||
// To customize the key name, change zerolog.ErrorFieldName.
|
||||
func (e *Event) Err(err error) *Event {
|
||||
if e == nil {
|
||||
return e
|
||||
}
|
||||
if err != nil {
|
||||
e.buf = appendError(appendKey(e.buf, ErrorFieldName), err)
|
||||
}
|
||||
return e
|
||||
}
|
||||
|
||||
// Bool adds the field key with val as a bool to the *Event context.
|
||||
func (e *Event) Bool(key string, b bool) *Event {
|
||||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = appendBool(appendKey(e.buf, key), b)
|
||||
return e
|
||||
}
|
||||
|
||||
// Bools adds the field key with val as a []bool to the *Event context.
|
||||
func (e *Event) Bools(key string, b []bool) *Event {
|
||||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = appendBools(appendKey(e.buf, key), b)
|
||||
return e
|
||||
}
|
||||
|
||||
// Int adds the field key with i as a int to the *Event context.
|
||||
func (e *Event) Int(key string, i int) *Event {
|
||||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = appendInt(appendKey(e.buf, key), i)
|
||||
return e
|
||||
}
|
||||
|
||||
// Ints adds the field key with i as a []int to the *Event context.
|
||||
func (e *Event) Ints(key string, i []int) *Event {
|
||||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = appendInts(appendKey(e.buf, key), i)
|
||||
return e
|
||||
}
|
||||
|
||||
// Int8 adds the field key with i as a int8 to the *Event context.
|
||||
func (e *Event) Int8(key string, i int8) *Event {
|
||||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = appendInt8(appendKey(e.buf, key), i)
|
||||
return e
|
||||
}
|
||||
|
||||
// Ints8 adds the field key with i as a []int8 to the *Event context.
|
||||
func (e *Event) Ints8(key string, i []int8) *Event {
|
||||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = appendInts8(appendKey(e.buf, key), i)
|
||||
return e
|
||||
}
|
||||
|
||||
// Int16 adds the field key with i as a int16 to the *Event context.
|
||||
func (e *Event) Int16(key string, i int16) *Event {
|
||||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = appendInt16(appendKey(e.buf, key), i)
|
||||
return e
|
||||
}
|
||||
|
||||
// Ints16 adds the field key with i as a []int16 to the *Event context.
|
||||
func (e *Event) Ints16(key string, i []int16) *Event {
|
||||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = appendInts16(appendKey(e.buf, key), i)
|
||||
return e
|
||||
}
|
||||
|
||||
// Int32 adds the field key with i as a int32 to the *Event context.
|
||||
func (e *Event) Int32(key string, i int32) *Event {
|
||||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = appendInt32(appendKey(e.buf, key), i)
|
||||
return e
|
||||
}
|
||||
|
||||
// Ints32 adds the field key with i as a []int32 to the *Event context.
|
||||
func (e *Event) Ints32(key string, i []int32) *Event {
|
||||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = appendInts32(appendKey(e.buf, key), i)
|
||||
return e
|
||||
}
|
||||
|
||||
// Int64 adds the field key with i as a int64 to the *Event context.
|
||||
func (e *Event) Int64(key string, i int64) *Event {
|
||||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = appendInt64(appendKey(e.buf, key), i)
|
||||
return e
|
||||
}
|
||||
|
||||
// Ints64 adds the field key with i as a []int64 to the *Event context.
|
||||
func (e *Event) Ints64(key string, i []int64) *Event {
|
||||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = appendInts64(appendKey(e.buf, key), i)
|
||||
return e
|
||||
}
|
||||
|
||||
// Uint adds the field key with i as a uint to the *Event context.
|
||||
func (e *Event) Uint(key string, i uint) *Event {
|
||||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = appendUint(appendKey(e.buf, key), i)
|
||||
return e
|
||||
}
|
||||
|
||||
// Uints adds the field key with i as a []int to the *Event context.
|
||||
func (e *Event) Uints(key string, i []uint) *Event {
|
||||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = appendUints(appendKey(e.buf, key), i)
|
||||
return e
|
||||
}
|
||||
|
||||
// Uint8 adds the field key with i as a uint8 to the *Event context.
|
||||
func (e *Event) Uint8(key string, i uint8) *Event {
|
||||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = appendUint8(appendKey(e.buf, key), i)
|
||||
return e
|
||||
}
|
||||
|
||||
// Uints8 adds the field key with i as a []int8 to the *Event context.
|
||||
func (e *Event) Uints8(key string, i []uint8) *Event {
|
||||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = appendUints8(appendKey(e.buf, key), i)
|
||||
return e
|
||||
}
|
||||
|
||||
// Uint16 adds the field key with i as a uint16 to the *Event context.
|
||||
func (e *Event) Uint16(key string, i uint16) *Event {
|
||||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = appendUint16(appendKey(e.buf, key), i)
|
||||
return e
|
||||
}
|
||||
|
||||
// Uints16 adds the field key with i as a []int16 to the *Event context.
|
||||
func (e *Event) Uints16(key string, i []uint16) *Event {
|
||||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = appendUints16(appendKey(e.buf, key), i)
|
||||
return e
|
||||
}
|
||||
|
||||
// Uint32 adds the field key with i as a uint32 to the *Event context.
|
||||
func (e *Event) Uint32(key string, i uint32) *Event {
|
||||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = appendUint32(appendKey(e.buf, key), i)
|
||||
return e
|
||||
}
|
||||
|
||||
// Uints32 adds the field key with i as a []int32 to the *Event context.
|
||||
func (e *Event) Uints32(key string, i []uint32) *Event {
|
||||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = appendUints32(appendKey(e.buf, key), i)
|
||||
return e
|
||||
}
|
||||
|
||||
// Uint64 adds the field key with i as a uint64 to the *Event context.
|
||||
func (e *Event) Uint64(key string, i uint64) *Event {
|
||||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = appendUint64(appendKey(e.buf, key), i)
|
||||
return e
|
||||
}
|
||||
|
||||
// Uints64 adds the field key with i as a []int64 to the *Event context.
|
||||
func (e *Event) Uints64(key string, i []uint64) *Event {
|
||||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = appendUints64(appendKey(e.buf, key), i)
|
||||
return e
|
||||
}
|
||||
|
||||
// Float32 adds the field key with f as a float32 to the *Event context.
|
||||
func (e *Event) Float32(key string, f float32) *Event {
|
||||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = appendFloat32(appendKey(e.buf, key), f)
|
||||
return e
|
||||
}
|
||||
|
||||
// Floats32 adds the field key with f as a []float32 to the *Event context.
|
||||
func (e *Event) Floats32(key string, f []float32) *Event {
|
||||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = appendFloats32(appendKey(e.buf, key), f)
|
||||
return e
|
||||
}
|
||||
|
||||
// Float64 adds the field key with f as a float64 to the *Event context.
|
||||
func (e *Event) Float64(key string, f float64) *Event {
|
||||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = appendFloat64(appendKey(e.buf, key), f)
|
||||
return e
|
||||
}
|
||||
|
||||
// Floats64 adds the field key with f as a []float64 to the *Event context.
|
||||
func (e *Event) Floats64(key string, f []float64) *Event {
|
||||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = appendFloats64(appendKey(e.buf, key), f)
|
||||
return e
|
||||
}
|
||||
|
||||
// Timestamp adds the current local time as UNIX timestamp to the *Event context with the "time" key.
|
||||
// To customize the key name, change zerolog.TimestampFieldName.
|
||||
//
|
||||
// NOTE: It won't dedupe the "time" key if the *Event (or *Context) has one
|
||||
// already.
|
||||
func (e *Event) Timestamp() *Event {
|
||||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = appendTime(appendKey(e.buf, TimestampFieldName), TimestampFunc(), TimeFieldFormat)
|
||||
return e
|
||||
}
|
||||
|
||||
// Time adds the field key with t formated as string using zerolog.TimeFieldFormat.
|
||||
func (e *Event) Time(key string, t time.Time) *Event {
|
||||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = appendTime(appendKey(e.buf, key), t, TimeFieldFormat)
|
||||
return e
|
||||
}
|
||||
|
||||
// Times adds the field key with t formated as string using zerolog.TimeFieldFormat.
|
||||
func (e *Event) Times(key string, t []time.Time) *Event {
|
||||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = appendTimes(appendKey(e.buf, key), t, TimeFieldFormat)
|
||||
return e
|
||||
}
|
||||
|
||||
// Dur adds the field key with duration d stored as zerolog.DurationFieldUnit.
|
||||
// If zerolog.DurationFieldInteger is true, durations are rendered as integer
|
||||
// instead of float.
|
||||
func (e *Event) Dur(key string, d time.Duration) *Event {
|
||||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = appendDuration(appendKey(e.buf, key), d, DurationFieldUnit, DurationFieldInteger)
|
||||
return e
|
||||
}
|
||||
|
||||
// Durs adds the field key with duration d stored as zerolog.DurationFieldUnit.
|
||||
// If zerolog.DurationFieldInteger is true, durations are rendered as integer
|
||||
// instead of float.
|
||||
func (e *Event) Durs(key string, d []time.Duration) *Event {
|
||||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = appendDurations(appendKey(e.buf, key), d, DurationFieldUnit, DurationFieldInteger)
|
||||
return e
|
||||
}
|
||||
|
||||
// TimeDiff adds the field key with positive duration between time t and start.
|
||||
// If time t is not greater than start, duration will be 0.
|
||||
// Duration format follows the same principle as Dur().
|
||||
func (e *Event) TimeDiff(key string, t time.Time, start time.Time) *Event {
|
||||
if e == nil {
|
||||
return e
|
||||
}
|
||||
var d time.Duration
|
||||
if t.After(start) {
|
||||
d = t.Sub(start)
|
||||
}
|
||||
e.buf = appendDuration(appendKey(e.buf, key), d, DurationFieldUnit, DurationFieldInteger)
|
||||
return e
|
||||
}
|
||||
|
||||
// Interface adds the field key with i marshaled using reflection.
|
||||
func (e *Event) Interface(key string, i interface{}) *Event {
|
||||
if e == nil {
|
||||
return e
|
||||
}
|
||||
if obj, ok := i.(LogObjectMarshaler); ok {
|
||||
return e.Object(key, obj)
|
||||
}
|
||||
e.buf = appendInterface(appendKey(e.buf, key), i)
|
||||
return e
|
||||
}
|
||||
|
||||
// Caller adds the file:line of the caller with the zerolog.CallerFieldName key.
|
||||
func (e *Event) Caller() *Event {
|
||||
return e.caller(2)
|
||||
}
|
||||
|
||||
func (e *Event) caller(skip int) *Event {
|
||||
if e == nil {
|
||||
return e
|
||||
}
|
||||
_, file, line, ok := runtime.Caller(skip)
|
||||
if !ok {
|
||||
return e
|
||||
}
|
||||
e.buf = appendString(appendKey(e.buf, CallerFieldName), file+":"+strconv.Itoa(line))
|
||||
return e
|
||||
}
|
126
vendor/github.com/rs/zerolog/fields.go
generated
vendored
Normal file
126
vendor/github.com/rs/zerolog/fields.go
generated
vendored
Normal file
@@ -0,0 +1,126 @@
|
||||
package zerolog
|
||||
|
||||
import (
|
||||
"sort"
|
||||
"time"
|
||||
)
|
||||
|
||||
func appendFields(dst []byte, fields map[string]interface{}) []byte {
|
||||
keys := make([]string, 0, len(fields))
|
||||
for key := range fields {
|
||||
keys = append(keys, key)
|
||||
}
|
||||
sort.Strings(keys)
|
||||
for _, key := range keys {
|
||||
dst = appendKey(dst, key)
|
||||
switch val := fields[key].(type) {
|
||||
case string:
|
||||
dst = appendString(dst, val)
|
||||
case []byte:
|
||||
dst = appendBytes(dst, val)
|
||||
case error:
|
||||
dst = appendError(dst, val)
|
||||
case []error:
|
||||
dst = appendErrors(dst, val)
|
||||
case bool:
|
||||
dst = appendBool(dst, val)
|
||||
case int:
|
||||
dst = appendInt(dst, val)
|
||||
case int8:
|
||||
dst = appendInt8(dst, val)
|
||||
case int16:
|
||||
dst = appendInt16(dst, val)
|
||||
case int32:
|
||||
dst = appendInt32(dst, val)
|
||||
case int64:
|
||||
dst = appendInt64(dst, val)
|
||||
case uint:
|
||||
dst = appendUint(dst, val)
|
||||
case uint8:
|
||||
dst = appendUint8(dst, val)
|
||||
case uint16:
|
||||
dst = appendUint16(dst, val)
|
||||
case uint32:
|
||||
dst = appendUint32(dst, val)
|
||||
case uint64:
|
||||
dst = appendUint64(dst, val)
|
||||
case float32:
|
||||
dst = appendFloat32(dst, val)
|
||||
case float64:
|
||||
dst = appendFloat64(dst, val)
|
||||
case time.Time:
|
||||
dst = appendTime(dst, val, TimeFieldFormat)
|
||||
case time.Duration:
|
||||
dst = appendDuration(dst, val, DurationFieldUnit, DurationFieldInteger)
|
||||
case *string:
|
||||
dst = appendString(dst, *val)
|
||||
case *bool:
|
||||
dst = appendBool(dst, *val)
|
||||
case *int:
|
||||
dst = appendInt(dst, *val)
|
||||
case *int8:
|
||||
dst = appendInt8(dst, *val)
|
||||
case *int16:
|
||||
dst = appendInt16(dst, *val)
|
||||
case *int32:
|
||||
dst = appendInt32(dst, *val)
|
||||
case *int64:
|
||||
dst = appendInt64(dst, *val)
|
||||
case *uint:
|
||||
dst = appendUint(dst, *val)
|
||||
case *uint8:
|
||||
dst = appendUint8(dst, *val)
|
||||
case *uint16:
|
||||
dst = appendUint16(dst, *val)
|
||||
case *uint32:
|
||||
dst = appendUint32(dst, *val)
|
||||
case *uint64:
|
||||
dst = appendUint64(dst, *val)
|
||||
case *float32:
|
||||
dst = appendFloat32(dst, *val)
|
||||
case *float64:
|
||||
dst = appendFloat64(dst, *val)
|
||||
case *time.Time:
|
||||
dst = appendTime(dst, *val, TimeFieldFormat)
|
||||
case *time.Duration:
|
||||
dst = appendDuration(dst, *val, DurationFieldUnit, DurationFieldInteger)
|
||||
case []string:
|
||||
dst = appendStrings(dst, val)
|
||||
case []bool:
|
||||
dst = appendBools(dst, val)
|
||||
case []int:
|
||||
dst = appendInts(dst, val)
|
||||
case []int8:
|
||||
dst = appendInts8(dst, val)
|
||||
case []int16:
|
||||
dst = appendInts16(dst, val)
|
||||
case []int32:
|
||||
dst = appendInts32(dst, val)
|
||||
case []int64:
|
||||
dst = appendInts64(dst, val)
|
||||
case []uint:
|
||||
dst = appendUints(dst, val)
|
||||
// case []uint8:
|
||||
// dst = appendUints8(dst, val)
|
||||
case []uint16:
|
||||
dst = appendUints16(dst, val)
|
||||
case []uint32:
|
||||
dst = appendUints32(dst, val)
|
||||
case []uint64:
|
||||
dst = appendUints64(dst, val)
|
||||
case []float32:
|
||||
dst = appendFloats32(dst, val)
|
||||
case []float64:
|
||||
dst = appendFloats64(dst, val)
|
||||
case []time.Time:
|
||||
dst = appendTimes(dst, val, TimeFieldFormat)
|
||||
case []time.Duration:
|
||||
dst = appendDurations(dst, val, DurationFieldUnit, DurationFieldInteger)
|
||||
case nil:
|
||||
dst = appendNil(dst)
|
||||
default:
|
||||
dst = appendInterface(dst, val)
|
||||
}
|
||||
}
|
||||
return dst
|
||||
}
|
67
vendor/github.com/rs/zerolog/globals.go
generated
vendored
Normal file
67
vendor/github.com/rs/zerolog/globals.go
generated
vendored
Normal file
@@ -0,0 +1,67 @@
|
||||
package zerolog
|
||||
|
||||
import "time"
|
||||
import "sync/atomic"
|
||||
|
||||
var (
|
||||
// TimestampFieldName is the field name used for the timestamp field.
|
||||
TimestampFieldName = "time"
|
||||
|
||||
// LevelFieldName is the field name used for the level field.
|
||||
LevelFieldName = "level"
|
||||
|
||||
// MessageFieldName is the field name used for the message field.
|
||||
MessageFieldName = "message"
|
||||
|
||||
// ErrorFieldName is the field name used for error fields.
|
||||
ErrorFieldName = "error"
|
||||
|
||||
// CallerFieldName is the field name used for caller field.
|
||||
CallerFieldName = "caller"
|
||||
|
||||
// TimeFieldFormat defines the time format of the Time field type.
|
||||
// If set to an empty string, the time is formatted as an UNIX timestamp
|
||||
// as integer.
|
||||
TimeFieldFormat = time.RFC3339
|
||||
|
||||
// TimestampFunc defines the function called to generate a timestamp.
|
||||
TimestampFunc = time.Now
|
||||
|
||||
// DurationFieldUnit defines the unit for time.Duration type fields added
|
||||
// using the Dur method.
|
||||
DurationFieldUnit = time.Millisecond
|
||||
|
||||
// DurationFieldInteger renders Dur fields as integer instead of float if
|
||||
// set to true.
|
||||
DurationFieldInteger = false
|
||||
)
|
||||
|
||||
var (
|
||||
gLevel = new(uint32)
|
||||
disableSampling = new(uint32)
|
||||
)
|
||||
|
||||
// SetGlobalLevel sets the global override for log level. If this
|
||||
// values is raised, all Loggers will use at least this value.
|
||||
//
|
||||
// To globally disable logs, set GlobalLevel to Disabled.
|
||||
func SetGlobalLevel(l Level) {
|
||||
atomic.StoreUint32(gLevel, uint32(l))
|
||||
}
|
||||
|
||||
func globalLevel() Level {
|
||||
return Level(atomic.LoadUint32(gLevel))
|
||||
}
|
||||
|
||||
// DisableSampling will disable sampling in all Loggers if true.
|
||||
func DisableSampling(v bool) {
|
||||
var i uint32
|
||||
if v {
|
||||
i = 1
|
||||
}
|
||||
atomic.StoreUint32(disableSampling, i)
|
||||
}
|
||||
|
||||
func samplingDisabled() bool {
|
||||
return atomic.LoadUint32(disableSampling) == 1
|
||||
}
|
51
vendor/github.com/rs/zerolog/hook.go
generated
vendored
Normal file
51
vendor/github.com/rs/zerolog/hook.go
generated
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
package zerolog
|
||||
|
||||
// Hook defines an interface to a log hook.
|
||||
type Hook interface {
|
||||
// Run runs the hook with the event.
|
||||
Run(e *Event, level Level, message string)
|
||||
}
|
||||
|
||||
// LevelHook applies a different hook for each level.
|
||||
type LevelHook struct {
|
||||
NoLevelHook, DebugHook, InfoHook, WarnHook, ErrorHook, FatalHook, PanicHook Hook
|
||||
}
|
||||
|
||||
// Run implements the Hook interface.
|
||||
func (h LevelHook) Run(e *Event, level Level, message string) {
|
||||
switch level {
|
||||
case DebugLevel:
|
||||
if h.DebugHook != nil {
|
||||
h.DebugHook.Run(e, level, message)
|
||||
}
|
||||
case InfoLevel:
|
||||
if h.InfoHook != nil {
|
||||
h.InfoHook.Run(e, level, message)
|
||||
}
|
||||
case WarnLevel:
|
||||
if h.WarnHook != nil {
|
||||
h.WarnHook.Run(e, level, message)
|
||||
}
|
||||
case ErrorLevel:
|
||||
if h.ErrorHook != nil {
|
||||
h.ErrorHook.Run(e, level, message)
|
||||
}
|
||||
case FatalLevel:
|
||||
if h.FatalHook != nil {
|
||||
h.FatalHook.Run(e, level, message)
|
||||
}
|
||||
case PanicLevel:
|
||||
if h.PanicHook != nil {
|
||||
h.PanicHook.Run(e, level, message)
|
||||
}
|
||||
case NoLevel:
|
||||
if h.NoLevelHook != nil {
|
||||
h.NoLevelHook.Run(e, level, message)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// NewLevelHook returns a new LevelHook.
|
||||
func NewLevelHook() LevelHook {
|
||||
return LevelHook{}
|
||||
}
|
74
vendor/github.com/rs/zerolog/internal/cbor/README.md
generated
vendored
Normal file
74
vendor/github.com/rs/zerolog/internal/cbor/README.md
generated
vendored
Normal file
@@ -0,0 +1,74 @@
|
||||
Reference:
|
||||
CBOR Encoding is described in RFC7049 https://tools.ietf.org/html/rfc7049
|
||||
|
||||
|
||||
Tests and benchmark:
|
||||
|
||||
```
|
||||
sprint @ cbor>go test -v -benchmem -bench=.
|
||||
=== RUN TestDecodeInteger
|
||||
--- PASS: TestDecodeInteger (0.00s)
|
||||
=== RUN TestDecodeString
|
||||
--- PASS: TestDecodeString (0.00s)
|
||||
=== RUN TestDecodeArray
|
||||
--- PASS: TestDecodeArray (0.00s)
|
||||
=== RUN TestDecodeMap
|
||||
--- PASS: TestDecodeMap (0.00s)
|
||||
=== RUN TestDecodeBool
|
||||
--- PASS: TestDecodeBool (0.00s)
|
||||
=== RUN TestDecodeFloat
|
||||
--- PASS: TestDecodeFloat (0.00s)
|
||||
=== RUN TestDecodeTimestamp
|
||||
--- PASS: TestDecodeTimestamp (0.00s)
|
||||
=== RUN TestDecodeCbor2Json
|
||||
--- PASS: TestDecodeCbor2Json (0.00s)
|
||||
=== RUN TestAppendString
|
||||
--- PASS: TestAppendString (0.00s)
|
||||
=== RUN TestAppendBytes
|
||||
--- PASS: TestAppendBytes (0.00s)
|
||||
=== RUN TestAppendTimeNow
|
||||
--- PASS: TestAppendTimeNow (0.00s)
|
||||
=== RUN TestAppendTimePastPresentInteger
|
||||
--- PASS: TestAppendTimePastPresentInteger (0.00s)
|
||||
=== RUN TestAppendTimePastPresentFloat
|
||||
--- PASS: TestAppendTimePastPresentFloat (0.00s)
|
||||
=== RUN TestAppendNull
|
||||
--- PASS: TestAppendNull (0.00s)
|
||||
=== RUN TestAppendBool
|
||||
--- PASS: TestAppendBool (0.00s)
|
||||
=== RUN TestAppendBoolArray
|
||||
--- PASS: TestAppendBoolArray (0.00s)
|
||||
=== RUN TestAppendInt
|
||||
--- PASS: TestAppendInt (0.00s)
|
||||
=== RUN TestAppendIntArray
|
||||
--- PASS: TestAppendIntArray (0.00s)
|
||||
=== RUN TestAppendFloat32
|
||||
--- PASS: TestAppendFloat32 (0.00s)
|
||||
goos: linux
|
||||
goarch: amd64
|
||||
pkg: github.com/toravir/zerolog/internal/cbor
|
||||
BenchmarkAppendString/MultiBytesLast-4 30000000 43.3 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkAppendString/NoEncoding-4 30000000 48.2 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkAppendString/EncodingFirst-4 30000000 48.2 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkAppendString/EncodingMiddle-4 30000000 41.7 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkAppendString/EncodingLast-4 30000000 51.8 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkAppendString/MultiBytesFirst-4 50000000 38.0 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkAppendString/MultiBytesMiddle-4 50000000 38.0 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkAppendTime/Integer-4 50000000 39.6 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkAppendTime/Float-4 30000000 56.1 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkAppendInt/uint8-4 50000000 29.1 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkAppendInt/uint16-4 50000000 30.3 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkAppendInt/uint32-4 50000000 37.1 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkAppendInt/int8-4 100000000 21.5 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkAppendInt/int16-4 50000000 25.8 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkAppendInt/int32-4 50000000 26.7 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkAppendInt/int-Positive-4 100000000 21.5 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkAppendInt/int-Negative-4 100000000 20.7 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkAppendInt/uint64-4 50000000 36.7 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkAppendInt/int64-4 30000000 39.6 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkAppendFloat/Float32-4 50000000 23.9 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkAppendFloat/Float64-4 50000000 32.8 ns/op 0 B/op 0 allocs/op
|
||||
PASS
|
||||
ok github.com/toravir/zerolog/internal/cbor 34.969s
|
||||
sprint @ cbor>
|
||||
```
|
43
vendor/github.com/rs/zerolog/internal/cbor/base.go
generated
vendored
Normal file
43
vendor/github.com/rs/zerolog/internal/cbor/base.go
generated
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
package cbor
|
||||
|
||||
// AppendKey adds a key (string) to the binary encoded log message
|
||||
func AppendKey(dst []byte, key string) []byte {
|
||||
if len(dst) < 1 {
|
||||
dst = AppendBeginMarker(dst)
|
||||
}
|
||||
return AppendString(dst, key)
|
||||
}
|
||||
|
||||
// AppendError adds the Error to the log message if error is NOT nil
|
||||
func AppendError(dst []byte, err error) []byte {
|
||||
if err == nil {
|
||||
return append(dst, `null`...)
|
||||
}
|
||||
return AppendString(dst, err.Error())
|
||||
}
|
||||
|
||||
// AppendErrors when given an array of errors,
|
||||
// adds them to the log message if a specific error is nil, then
|
||||
// Nil is added, or else the error string is added.
|
||||
func AppendErrors(dst []byte, errs []error) []byte {
|
||||
if len(errs) == 0 {
|
||||
return AppendArrayEnd(AppendArrayStart(dst))
|
||||
}
|
||||
dst = AppendArrayStart(dst)
|
||||
if errs[0] != nil {
|
||||
dst = AppendString(dst, errs[0].Error())
|
||||
} else {
|
||||
dst = AppendNull(dst)
|
||||
}
|
||||
if len(errs) > 1 {
|
||||
for _, err := range errs[1:] {
|
||||
if err == nil {
|
||||
dst = AppendNull(dst)
|
||||
continue
|
||||
}
|
||||
dst = AppendString(dst, err.Error())
|
||||
}
|
||||
}
|
||||
dst = AppendArrayEnd(dst)
|
||||
return dst
|
||||
}
|
91
vendor/github.com/rs/zerolog/internal/cbor/cbor.go
generated
vendored
Normal file
91
vendor/github.com/rs/zerolog/internal/cbor/cbor.go
generated
vendored
Normal file
@@ -0,0 +1,91 @@
|
||||
// Package cbor provides primitives for storing different data
|
||||
// in the CBOR (binary) format. CBOR is defined in RFC7049.
|
||||
package cbor
|
||||
|
||||
import "time"
|
||||
|
||||
const (
|
||||
majorOffset = 5
|
||||
additionalMax = 23
|
||||
//Non Values
|
||||
additionalTypeBoolFalse byte = 20
|
||||
additionalTypeBoolTrue byte = 21
|
||||
additionalTypeNull byte = 22
|
||||
//Integer (+ve and -ve) Sub-types
|
||||
additionalTypeIntUint8 byte = 24
|
||||
additionalTypeIntUint16 byte = 25
|
||||
additionalTypeIntUint32 byte = 26
|
||||
additionalTypeIntUint64 byte = 27
|
||||
//Float Sub-types
|
||||
additionalTypeFloat16 byte = 25
|
||||
additionalTypeFloat32 byte = 26
|
||||
additionalTypeFloat64 byte = 27
|
||||
additionalTypeBreak byte = 31
|
||||
//Tag Sub-types
|
||||
additionalTypeTimestamp byte = 01
|
||||
additionalTypeEmbeddedJSON byte = 31
|
||||
additionalTypeTagHexString uint16 = 262
|
||||
//Unspecified number of elements
|
||||
additionalTypeInfiniteCount byte = 31
|
||||
)
|
||||
const (
|
||||
majorTypeUnsignedInt byte = iota << majorOffset // Major type 0
|
||||
majorTypeNegativeInt // Major type 1
|
||||
majorTypeByteString // Major type 2
|
||||
majorTypeUtf8String // Major type 3
|
||||
majorTypeArray // Major type 4
|
||||
majorTypeMap // Major type 5
|
||||
majorTypeTags // Major type 6
|
||||
majorTypeSimpleAndFloat // Major type 7
|
||||
)
|
||||
|
||||
const (
|
||||
maskOutAdditionalType byte = (7 << majorOffset)
|
||||
maskOutMajorType byte = 31
|
||||
)
|
||||
|
||||
const (
|
||||
float32Nan = "\xfa\x7f\xc0\x00\x00"
|
||||
float32PosInfinity = "\xfa\x7f\x80\x00\x00"
|
||||
float32NegInfinity = "\xfa\xff\x80\x00\x00"
|
||||
float64Nan = "\xfb\x7f\xf8\x00\x00\x00\x00\x00\x00"
|
||||
float64PosInfinity = "\xfb\x7f\xf0\x00\x00\x00\x00\x00\x00"
|
||||
float64NegInfinity = "\xfb\xff\xf0\x00\x00\x00\x00\x00\x00"
|
||||
)
|
||||
|
||||
// IntegerTimeFieldFormat indicates the format of timestamp decoded
|
||||
// from an integer (time in seconds).
|
||||
var IntegerTimeFieldFormat = time.RFC3339
|
||||
|
||||
// NanoTimeFieldFormat indicates the format of timestamp decoded
|
||||
// from a float value (time in seconds and nano seconds).
|
||||
var NanoTimeFieldFormat = time.RFC3339Nano
|
||||
|
||||
func appendCborTypePrefix(dst []byte, major byte, number uint64) []byte {
|
||||
byteCount := 8
|
||||
var minor byte
|
||||
switch {
|
||||
case number < 256:
|
||||
byteCount = 1
|
||||
minor = additionalTypeIntUint8
|
||||
|
||||
case number < 65536:
|
||||
byteCount = 2
|
||||
minor = additionalTypeIntUint16
|
||||
|
||||
case number < 4294967296:
|
||||
byteCount = 4
|
||||
minor = additionalTypeIntUint32
|
||||
|
||||
default:
|
||||
byteCount = 8
|
||||
minor = additionalTypeIntUint64
|
||||
|
||||
}
|
||||
dst = append(dst, byte(major|minor))
|
||||
byteCount--
|
||||
for ; byteCount >= 0; byteCount-- {
|
||||
dst = append(dst, byte(number>>(uint(byteCount)*8)))
|
||||
}
|
||||
return dst
|
||||
}
|
548
vendor/github.com/rs/zerolog/internal/cbor/decoder.go
generated
vendored
Normal file
548
vendor/github.com/rs/zerolog/internal/cbor/decoder.go
generated
vendored
Normal file
@@ -0,0 +1,548 @@
|
||||
package cbor
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"math"
|
||||
"strconv"
|
||||
"time"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
var decodeTimeZone *time.Location
|
||||
|
||||
const hexTable = "0123456789abcdef"
|
||||
|
||||
func decodeIntAdditonalType(src []byte, minor byte) (int64, uint, error) {
|
||||
val := int64(0)
|
||||
bytesRead := 0
|
||||
if minor <= 23 {
|
||||
val = int64(minor)
|
||||
bytesRead = 0
|
||||
} else {
|
||||
switch minor {
|
||||
case additionalTypeIntUint8:
|
||||
bytesRead = 1
|
||||
case additionalTypeIntUint16:
|
||||
bytesRead = 2
|
||||
case additionalTypeIntUint32:
|
||||
bytesRead = 4
|
||||
case additionalTypeIntUint64:
|
||||
bytesRead = 8
|
||||
default:
|
||||
return 0, 0, fmt.Errorf("Invalid Additional Type: %d in decodeInteger (expected <28)", minor)
|
||||
}
|
||||
for i := 0; i < bytesRead; i++ {
|
||||
val = val * 256
|
||||
val += int64(src[i])
|
||||
}
|
||||
}
|
||||
return val, uint(bytesRead), nil
|
||||
}
|
||||
|
||||
func decodeInteger(src []byte) (int64, uint, error) {
|
||||
major := src[0] & maskOutAdditionalType
|
||||
minor := src[0] & maskOutMajorType
|
||||
if major != majorTypeUnsignedInt && major != majorTypeNegativeInt {
|
||||
return 0, 0, fmt.Errorf("Major type is: %d in decodeInteger!! (expected 0 or 1)", major)
|
||||
}
|
||||
val, bytesRead, err := decodeIntAdditonalType(src[1:], minor)
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
if major == 0 {
|
||||
return val, 1 + bytesRead, nil
|
||||
}
|
||||
return (-1 - val), 1 + bytesRead, nil
|
||||
}
|
||||
|
||||
func decodeFloat(src []byte) (float64, uint, error) {
|
||||
major := (src[0] & maskOutAdditionalType)
|
||||
minor := src[0] & maskOutMajorType
|
||||
if major != majorTypeSimpleAndFloat {
|
||||
return 0, 0, fmt.Errorf("Incorrect Major type is: %d in decodeFloat", major)
|
||||
}
|
||||
|
||||
switch minor {
|
||||
case additionalTypeFloat16:
|
||||
return 0, 0, fmt.Errorf("float16 is not suppported in decodeFloat")
|
||||
case additionalTypeFloat32:
|
||||
switch string(src[1:5]) {
|
||||
case float32Nan:
|
||||
return math.NaN(), 5, nil
|
||||
case float32PosInfinity:
|
||||
return math.Inf(0), 5, nil
|
||||
case float32NegInfinity:
|
||||
return math.Inf(-1), 5, nil
|
||||
}
|
||||
n := uint32(0)
|
||||
for i := 0; i < 4; i++ {
|
||||
n = n * 256
|
||||
n += uint32(src[i+1])
|
||||
}
|
||||
val := math.Float32frombits(n)
|
||||
return float64(val), 5, nil
|
||||
case additionalTypeFloat64:
|
||||
switch string(src[1:9]) {
|
||||
case float64Nan:
|
||||
return math.NaN(), 9, nil
|
||||
case float64PosInfinity:
|
||||
return math.Inf(0), 9, nil
|
||||
case float64NegInfinity:
|
||||
return math.Inf(-1), 9, nil
|
||||
}
|
||||
n := uint64(0)
|
||||
for i := 0; i < 8; i++ {
|
||||
n = n * 256
|
||||
n += uint64(src[i+1])
|
||||
}
|
||||
val := math.Float64frombits(n)
|
||||
return val, 9, nil
|
||||
}
|
||||
return 0, 0, fmt.Errorf("Invalid Additional Type: %d in decodeFloat", minor)
|
||||
}
|
||||
|
||||
func decodeStringComplex(dst []byte, s string, pos uint) []byte {
|
||||
i := int(pos)
|
||||
const hex = "0123456789abcdef"
|
||||
start := 0
|
||||
|
||||
for i < len(s) {
|
||||
b := s[i]
|
||||
if b >= utf8.RuneSelf {
|
||||
r, size := utf8.DecodeRuneInString(s[i:])
|
||||
if r == utf8.RuneError && size == 1 {
|
||||
// In case of error, first append previous simple characters to
|
||||
// the byte slice if any and append a replacement character code
|
||||
// in place of the invalid sequence.
|
||||
if start < i {
|
||||
dst = append(dst, s[start:i]...)
|
||||
}
|
||||
dst = append(dst, `\ufffd`...)
|
||||
i += size
|
||||
start = i
|
||||
continue
|
||||
}
|
||||
i += size
|
||||
continue
|
||||
}
|
||||
if b >= 0x20 && b <= 0x7e && b != '\\' && b != '"' {
|
||||
i++
|
||||
continue
|
||||
}
|
||||
// We encountered a character that needs to be encoded.
|
||||
// Let's append the previous simple characters to the byte slice
|
||||
// and switch our operation to read and encode the remainder
|
||||
// characters byte-by-byte.
|
||||
if start < i {
|
||||
dst = append(dst, s[start:i]...)
|
||||
}
|
||||
switch b {
|
||||
case '"', '\\':
|
||||
dst = append(dst, '\\', b)
|
||||
case '\b':
|
||||
dst = append(dst, '\\', 'b')
|
||||
case '\f':
|
||||
dst = append(dst, '\\', 'f')
|
||||
case '\n':
|
||||
dst = append(dst, '\\', 'n')
|
||||
case '\r':
|
||||
dst = append(dst, '\\', 'r')
|
||||
case '\t':
|
||||
dst = append(dst, '\\', 't')
|
||||
default:
|
||||
dst = append(dst, '\\', 'u', '0', '0', hex[b>>4], hex[b&0xF])
|
||||
}
|
||||
i++
|
||||
start = i
|
||||
}
|
||||
if start < len(s) {
|
||||
dst = append(dst, s[start:]...)
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
func decodeString(src []byte, noQuotes bool) ([]byte, uint, error) {
|
||||
major := src[0] & maskOutAdditionalType
|
||||
minor := src[0] & maskOutMajorType
|
||||
if major != majorTypeByteString {
|
||||
return []byte{}, 0, fmt.Errorf("Major type is: %d in decodeString", major)
|
||||
}
|
||||
result := []byte{'"'}
|
||||
if noQuotes {
|
||||
result = []byte{}
|
||||
}
|
||||
length, bytesRead, err := decodeIntAdditonalType(src[1:], minor)
|
||||
if err != nil {
|
||||
return []byte{}, 0, err
|
||||
}
|
||||
bytesRead++
|
||||
st := bytesRead
|
||||
len := uint(length)
|
||||
bytesRead += len
|
||||
|
||||
result = append(result, src[st:st+len]...)
|
||||
if noQuotes {
|
||||
return result, bytesRead, nil
|
||||
}
|
||||
return append(result, '"'), bytesRead, nil
|
||||
}
|
||||
|
||||
func decodeUTF8String(src []byte) ([]byte, uint, error) {
|
||||
major := src[0] & maskOutAdditionalType
|
||||
minor := src[0] & maskOutMajorType
|
||||
if major != majorTypeUtf8String {
|
||||
return []byte{}, 0, fmt.Errorf("Major type is: %d in decodeUTF8String", major)
|
||||
}
|
||||
result := []byte{'"'}
|
||||
length, bytesRead, err := decodeIntAdditonalType(src[1:], minor)
|
||||
if err != nil {
|
||||
return []byte{}, 0, err
|
||||
}
|
||||
bytesRead++
|
||||
st := bytesRead
|
||||
len := uint(length)
|
||||
bytesRead += len
|
||||
|
||||
for i := st; i < bytesRead; i++ {
|
||||
// Check if the character needs encoding. Control characters, slashes,
|
||||
// and the double quote need json encoding. Bytes above the ascii
|
||||
// boundary needs utf8 encoding.
|
||||
if src[i] < 0x20 || src[i] > 0x7e || src[i] == '\\' || src[i] == '"' {
|
||||
// We encountered a character that needs to be encoded. Switch
|
||||
// to complex version of the algorithm.
|
||||
dst := []byte{'"'}
|
||||
dst = decodeStringComplex(dst, string(src[st:st+len]), i-st)
|
||||
return append(dst, '"'), bytesRead, nil
|
||||
}
|
||||
}
|
||||
// The string has no need for encoding an therefore is directly
|
||||
// appended to the byte slice.
|
||||
result = append(result, src[st:st+len]...)
|
||||
return append(result, '"'), bytesRead, nil
|
||||
}
|
||||
|
||||
func array2Json(src []byte, dst io.Writer) (uint, error) {
|
||||
dst.Write([]byte{'['})
|
||||
major := (src[0] & maskOutAdditionalType)
|
||||
minor := src[0] & maskOutMajorType
|
||||
if major != majorTypeArray {
|
||||
return 0, fmt.Errorf("Major type is: %d in array2Json", major)
|
||||
}
|
||||
len := 0
|
||||
bytesRead := uint(0)
|
||||
unSpecifiedCount := false
|
||||
if minor == additionalTypeInfiniteCount {
|
||||
unSpecifiedCount = true
|
||||
bytesRead = 1
|
||||
} else {
|
||||
var length int64
|
||||
var err error
|
||||
length, bytesRead, err = decodeIntAdditonalType(src[1:], minor)
|
||||
if err != nil {
|
||||
fmt.Println("Error!!!")
|
||||
return 0, err
|
||||
}
|
||||
len = int(length)
|
||||
bytesRead++
|
||||
}
|
||||
curPos := bytesRead
|
||||
for i := 0; unSpecifiedCount || i < len; i++ {
|
||||
bc, err := Cbor2JsonOneObject(src[curPos:], dst)
|
||||
if err != nil {
|
||||
if src[curPos] == byte(majorTypeSimpleAndFloat|additionalTypeBreak) {
|
||||
bytesRead++
|
||||
break
|
||||
}
|
||||
return 0, err
|
||||
}
|
||||
curPos += bc
|
||||
bytesRead += bc
|
||||
if unSpecifiedCount {
|
||||
if src[curPos] == byte(majorTypeSimpleAndFloat|additionalTypeBreak) {
|
||||
bytesRead++
|
||||
break
|
||||
}
|
||||
dst.Write([]byte{','})
|
||||
} else if i+1 < len {
|
||||
dst.Write([]byte{','})
|
||||
}
|
||||
}
|
||||
dst.Write([]byte{']'})
|
||||
return bytesRead, nil
|
||||
}
|
||||
|
||||
func map2Json(src []byte, dst io.Writer) (uint, error) {
|
||||
major := (src[0] & maskOutAdditionalType)
|
||||
minor := src[0] & maskOutMajorType
|
||||
if major != majorTypeMap {
|
||||
return 0, fmt.Errorf("Major type is: %d in map2Json", major)
|
||||
}
|
||||
len := 0
|
||||
bytesRead := uint(0)
|
||||
unSpecifiedCount := false
|
||||
if minor == additionalTypeInfiniteCount {
|
||||
unSpecifiedCount = true
|
||||
bytesRead = 1
|
||||
} else {
|
||||
var length int64
|
||||
var err error
|
||||
length, bytesRead, err = decodeIntAdditonalType(src[1:], minor)
|
||||
if err != nil {
|
||||
fmt.Println("Error!!!")
|
||||
return 0, err
|
||||
}
|
||||
len = int(length)
|
||||
bytesRead++
|
||||
}
|
||||
if len%2 == 1 {
|
||||
return 0, fmt.Errorf("Invalid Length of map %d - has to be even", len)
|
||||
}
|
||||
dst.Write([]byte{'{'})
|
||||
curPos := bytesRead
|
||||
for i := 0; unSpecifiedCount || i < len; i++ {
|
||||
bc, err := Cbor2JsonOneObject(src[curPos:], dst)
|
||||
if err != nil {
|
||||
//We hit the BREAK
|
||||
if src[curPos] == byte(majorTypeSimpleAndFloat|additionalTypeBreak) {
|
||||
bytesRead++
|
||||
break
|
||||
}
|
||||
return 0, err
|
||||
}
|
||||
curPos += bc
|
||||
bytesRead += bc
|
||||
if i%2 == 0 {
|
||||
//Even position values are keys
|
||||
dst.Write([]byte{':'})
|
||||
} else {
|
||||
if unSpecifiedCount {
|
||||
if src[curPos] == byte(majorTypeSimpleAndFloat|additionalTypeBreak) {
|
||||
bytesRead++
|
||||
break
|
||||
}
|
||||
dst.Write([]byte{','})
|
||||
} else if i+1 < len {
|
||||
dst.Write([]byte{','})
|
||||
}
|
||||
}
|
||||
}
|
||||
dst.Write([]byte{'}'})
|
||||
return bytesRead, nil
|
||||
}
|
||||
|
||||
func decodeTagData(src []byte) ([]byte, uint, error) {
|
||||
major := (src[0] & maskOutAdditionalType)
|
||||
minor := src[0] & maskOutMajorType
|
||||
if major != majorTypeTags {
|
||||
return nil, 0, fmt.Errorf("Major type is: %d in decodeTagData", major)
|
||||
}
|
||||
if minor == additionalTypeTimestamp {
|
||||
tsMajor := src[1] & maskOutAdditionalType
|
||||
if tsMajor == majorTypeUnsignedInt || tsMajor == majorTypeNegativeInt {
|
||||
n, bc, err := decodeInteger(src[1:])
|
||||
if err != nil {
|
||||
return []byte{}, 0, err
|
||||
}
|
||||
t := time.Unix(n, 0)
|
||||
if decodeTimeZone != nil {
|
||||
t = t.In(decodeTimeZone)
|
||||
} else {
|
||||
t = t.In(time.UTC)
|
||||
}
|
||||
tsb := []byte{}
|
||||
tsb = append(tsb, '"')
|
||||
tsb = t.AppendFormat(tsb, IntegerTimeFieldFormat)
|
||||
tsb = append(tsb, '"')
|
||||
return tsb, 1 + bc, nil
|
||||
} else if tsMajor == majorTypeSimpleAndFloat {
|
||||
n, bc, err := decodeFloat(src[1:])
|
||||
if err != nil {
|
||||
return []byte{}, 0, err
|
||||
}
|
||||
secs := int64(n)
|
||||
n -= float64(secs)
|
||||
n *= float64(1e9)
|
||||
t := time.Unix(secs, int64(n))
|
||||
if decodeTimeZone != nil {
|
||||
t = t.In(decodeTimeZone)
|
||||
} else {
|
||||
t = t.In(time.UTC)
|
||||
}
|
||||
tsb := []byte{}
|
||||
tsb = append(tsb, '"')
|
||||
tsb = t.AppendFormat(tsb, NanoTimeFieldFormat)
|
||||
tsb = append(tsb, '"')
|
||||
return tsb, 1 + bc, nil
|
||||
} else {
|
||||
return nil, 0, fmt.Errorf("TS format is neigther int nor float: %d", tsMajor)
|
||||
}
|
||||
} else if minor == additionalTypeEmbeddedJSON {
|
||||
dataMajor := src[1] & maskOutAdditionalType
|
||||
if dataMajor == majorTypeByteString {
|
||||
emb, bc, err := decodeString(src[1:], true)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
return emb, 1 + bc, nil
|
||||
}
|
||||
return nil, 0, fmt.Errorf("Unsupported embedded Type: %d in decodeEmbeddedJSON", dataMajor)
|
||||
} else if minor == additionalTypeIntUint16 {
|
||||
val,_,_ := decodeIntAdditonalType(src[1:], minor)
|
||||
if uint16(val) == additionalTypeTagHexString {
|
||||
emb, bc, _ := decodeString(src[3:], true)
|
||||
dst := []byte{'"'}
|
||||
for _, v := range emb {
|
||||
dst = append(dst, hexTable[v>>4], hexTable[v&0x0f])
|
||||
}
|
||||
return append(dst, '"'), 3+bc, nil
|
||||
}
|
||||
}
|
||||
return nil, 0, fmt.Errorf("Unsupported Additional Type: %d in decodeTagData", minor)
|
||||
}
|
||||
|
||||
func decodeSimpleFloat(src []byte) ([]byte, uint, error) {
|
||||
major := (src[0] & maskOutAdditionalType)
|
||||
minor := src[0] & maskOutMajorType
|
||||
if major != majorTypeSimpleAndFloat {
|
||||
return nil, 0, fmt.Errorf("Major type is: %d in decodeSimpleFloat", major)
|
||||
}
|
||||
switch minor {
|
||||
case additionalTypeBoolTrue:
|
||||
return []byte("true"), 1, nil
|
||||
case additionalTypeBoolFalse:
|
||||
return []byte("false"), 1, nil
|
||||
case additionalTypeNull:
|
||||
return []byte("null"), 1, nil
|
||||
|
||||
case additionalTypeFloat16:
|
||||
fallthrough
|
||||
case additionalTypeFloat32:
|
||||
fallthrough
|
||||
case additionalTypeFloat64:
|
||||
v, bc, err := decodeFloat(src)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
ba := []byte{}
|
||||
switch {
|
||||
case math.IsNaN(v):
|
||||
return []byte("\"NaN\""), bc, nil
|
||||
case math.IsInf(v, 1):
|
||||
return []byte("\"+Inf\""), bc, nil
|
||||
case math.IsInf(v, -1):
|
||||
return []byte("\"-Inf\""), bc, nil
|
||||
}
|
||||
if bc == 5 {
|
||||
ba = strconv.AppendFloat(ba, v, 'f', -1, 32)
|
||||
} else {
|
||||
ba = strconv.AppendFloat(ba, v, 'f', -1, 64)
|
||||
}
|
||||
return ba, bc, nil
|
||||
default:
|
||||
return nil, 0, fmt.Errorf("Invalid Additional Type: %d in decodeSimpleFloat", minor)
|
||||
}
|
||||
}
|
||||
|
||||
// Cbor2JsonOneObject takes in byte array and decodes ONE CBOR Object
|
||||
// usually a MAP. Use this when only ONE CBOR object needs decoding.
|
||||
// Decoded string is written to the dst.
|
||||
// Returns the bytes decoded and if any error was encountered.
|
||||
func Cbor2JsonOneObject(src []byte, dst io.Writer) (uint, error) {
|
||||
var err error
|
||||
major := (src[0] & maskOutAdditionalType)
|
||||
bc := uint(0)
|
||||
var s []byte
|
||||
switch major {
|
||||
case majorTypeUnsignedInt:
|
||||
fallthrough
|
||||
case majorTypeNegativeInt:
|
||||
var n int64
|
||||
n, bc, err = decodeInteger(src)
|
||||
dst.Write([]byte(strconv.Itoa(int(n))))
|
||||
|
||||
case majorTypeByteString:
|
||||
s, bc, err = decodeString(src, false)
|
||||
dst.Write(s)
|
||||
|
||||
case majorTypeUtf8String:
|
||||
s, bc, err = decodeUTF8String(src)
|
||||
dst.Write(s)
|
||||
|
||||
case majorTypeArray:
|
||||
bc, err = array2Json(src, dst)
|
||||
|
||||
case majorTypeMap:
|
||||
bc, err = map2Json(src, dst)
|
||||
|
||||
case majorTypeTags:
|
||||
s, bc, err = decodeTagData(src)
|
||||
dst.Write(s)
|
||||
|
||||
case majorTypeSimpleAndFloat:
|
||||
s, bc, err = decodeSimpleFloat(src)
|
||||
dst.Write(s)
|
||||
}
|
||||
return bc, err
|
||||
}
|
||||
|
||||
// Cbor2JsonManyObjects decodes all the CBOR Objects present in the
|
||||
// source byte array. It keeps on decoding until it runs out of bytes.
|
||||
// Decoded string is written to the dst. At the end of every CBOR Object
|
||||
// newline is written to the output stream.
|
||||
// Returns the number of bytes decoded and if any error was encountered.
|
||||
func Cbor2JsonManyObjects(src []byte, dst io.Writer) (uint, error) {
|
||||
curPos := uint(0)
|
||||
totalBytes := uint(len(src))
|
||||
for curPos < totalBytes {
|
||||
bc, err := Cbor2JsonOneObject(src[curPos:], dst)
|
||||
if err != nil {
|
||||
return curPos, err
|
||||
}
|
||||
dst.Write([]byte("\n"))
|
||||
curPos += bc
|
||||
}
|
||||
return curPos, nil
|
||||
}
|
||||
|
||||
// Detect if the bytes to be printed is Binary or not.
|
||||
func binaryFmt(p []byte) bool {
|
||||
if len(p) > 0 && p[0] > 0x7F {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// DecodeIfBinaryToString converts a binary formatted log msg to a
|
||||
// JSON formatted String Log message - suitable for printing to Console/Syslog.
|
||||
func DecodeIfBinaryToString(in []byte) string {
|
||||
if binaryFmt(in) {
|
||||
var b bytes.Buffer
|
||||
Cbor2JsonManyObjects(in, &b)
|
||||
return b.String()
|
||||
}
|
||||
return string(in)
|
||||
}
|
||||
|
||||
// DecodeObjectToStr checks if the input is a binary format, if so,
|
||||
// it will decode a single Object and return the decoded string.
|
||||
func DecodeObjectToStr(in []byte) string {
|
||||
if binaryFmt(in) {
|
||||
var b bytes.Buffer
|
||||
Cbor2JsonOneObject(in, &b)
|
||||
return b.String()
|
||||
}
|
||||
return string(in)
|
||||
}
|
||||
|
||||
// DecodeIfBinaryToBytes checks if the input is a binary format, if so,
|
||||
// it will decode all Objects and return the decoded string as byte array.
|
||||
func DecodeIfBinaryToBytes(in []byte) []byte {
|
||||
if binaryFmt(in) {
|
||||
var b bytes.Buffer
|
||||
Cbor2JsonManyObjects(in, &b)
|
||||
return b.Bytes()
|
||||
}
|
||||
return in
|
||||
}
|
63
vendor/github.com/rs/zerolog/internal/cbor/string.go
generated
vendored
Normal file
63
vendor/github.com/rs/zerolog/internal/cbor/string.go
generated
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
package cbor
|
||||
|
||||
// AppendStrings encodes and adds an array of strings to the dst byte array.
|
||||
func AppendStrings(dst []byte, vals []string) []byte {
|
||||
major := majorTypeArray
|
||||
l := len(vals)
|
||||
if l <= additionalMax {
|
||||
lb := byte(l)
|
||||
dst = append(dst, byte(major|lb))
|
||||
} else {
|
||||
dst = appendCborTypePrefix(dst, major, uint64(l))
|
||||
}
|
||||
for _, v := range vals {
|
||||
dst = AppendString(dst, v)
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// AppendString encodes and adds a string to the dst byte array.
|
||||
func AppendString(dst []byte, s string) []byte {
|
||||
major := majorTypeUtf8String
|
||||
|
||||
l := len(s)
|
||||
if l <= additionalMax {
|
||||
lb := byte(l)
|
||||
dst = append(dst, byte(major|lb))
|
||||
} else {
|
||||
dst = appendCborTypePrefix(dst, majorTypeUtf8String, uint64(l))
|
||||
}
|
||||
return append(dst, s...)
|
||||
}
|
||||
|
||||
// AppendBytes encodes and adds an array of bytes to the dst byte array.
|
||||
func AppendBytes(dst, s []byte) []byte {
|
||||
major := majorTypeByteString
|
||||
|
||||
l := len(s)
|
||||
if l <= additionalMax {
|
||||
lb := byte(l)
|
||||
dst = append(dst, byte(major|lb))
|
||||
} else {
|
||||
dst = appendCborTypePrefix(dst, major, uint64(l))
|
||||
}
|
||||
return append(dst, s...)
|
||||
}
|
||||
|
||||
// AppendEmbeddedJSON adds a tag and embeds input JSON as such.
|
||||
func AppendEmbeddedJSON(dst, s []byte) []byte {
|
||||
major := majorTypeTags
|
||||
minor := additionalTypeEmbeddedJSON
|
||||
dst = append(dst, byte(major|minor))
|
||||
|
||||
major = majorTypeByteString
|
||||
|
||||
l := len(s)
|
||||
if l <= additionalMax {
|
||||
lb := byte(l)
|
||||
dst = append(dst, byte(major|lb))
|
||||
} else {
|
||||
dst = appendCborTypePrefix(dst, major, uint64(l))
|
||||
}
|
||||
return append(dst, s...)
|
||||
}
|
93
vendor/github.com/rs/zerolog/internal/cbor/time.go
generated
vendored
Normal file
93
vendor/github.com/rs/zerolog/internal/cbor/time.go
generated
vendored
Normal file
@@ -0,0 +1,93 @@
|
||||
package cbor
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
func appendIntegerTimestamp(dst []byte, t time.Time) []byte {
|
||||
major := majorTypeTags
|
||||
minor := additionalTypeTimestamp
|
||||
dst = append(dst, byte(major|minor))
|
||||
secs := t.Unix()
|
||||
var val uint64
|
||||
if secs < 0 {
|
||||
major = majorTypeNegativeInt
|
||||
val = uint64(-secs - 1)
|
||||
} else {
|
||||
major = majorTypeUnsignedInt
|
||||
val = uint64(secs)
|
||||
}
|
||||
dst = appendCborTypePrefix(dst, major, uint64(val))
|
||||
return dst
|
||||
}
|
||||
|
||||
func appendFloatTimestamp(dst []byte, t time.Time) []byte {
|
||||
major := majorTypeTags
|
||||
minor := additionalTypeTimestamp
|
||||
dst = append(dst, byte(major|minor))
|
||||
secs := t.Unix()
|
||||
nanos := t.Nanosecond()
|
||||
var val float64
|
||||
val = float64(secs)*1.0 + float64(nanos)*1E-9
|
||||
return AppendFloat64(dst, val)
|
||||
}
|
||||
|
||||
// AppendTime encodes and adds a timestamp to the dst byte array.
|
||||
func AppendTime(dst []byte, t time.Time, unused string) []byte {
|
||||
utc := t.UTC()
|
||||
if utc.Nanosecond() == 0 {
|
||||
return appendIntegerTimestamp(dst, utc)
|
||||
}
|
||||
return appendFloatTimestamp(dst, utc)
|
||||
}
|
||||
|
||||
// AppendTimes encodes and adds an array of timestamps to the dst byte array.
|
||||
func AppendTimes(dst []byte, vals []time.Time, unused string) []byte {
|
||||
major := majorTypeArray
|
||||
l := len(vals)
|
||||
if l == 0 {
|
||||
return AppendArrayEnd(AppendArrayStart(dst))
|
||||
}
|
||||
if l <= additionalMax {
|
||||
lb := byte(l)
|
||||
dst = append(dst, byte(major|lb))
|
||||
} else {
|
||||
dst = appendCborTypePrefix(dst, major, uint64(l))
|
||||
}
|
||||
|
||||
for _, t := range vals {
|
||||
dst = AppendTime(dst, t, unused)
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// AppendDuration encodes and adds a duration to the dst byte array.
|
||||
// useInt field indicates whether to store the duration as seconds (integer) or
|
||||
// as seconds+nanoseconds (float).
|
||||
func AppendDuration(dst []byte, d time.Duration, unit time.Duration, useInt bool) []byte {
|
||||
if useInt {
|
||||
return AppendInt64(dst, int64(d/unit))
|
||||
}
|
||||
return AppendFloat64(dst, float64(d)/float64(unit))
|
||||
}
|
||||
|
||||
// AppendDurations encodes and adds an array of durations to the dst byte array.
|
||||
// useInt field indicates whether to store the duration as seconds (integer) or
|
||||
// as seconds+nanoseconds (float).
|
||||
func AppendDurations(dst []byte, vals []time.Duration, unit time.Duration, useInt bool) []byte {
|
||||
major := majorTypeArray
|
||||
l := len(vals)
|
||||
if l == 0 {
|
||||
return AppendArrayEnd(AppendArrayStart(dst))
|
||||
}
|
||||
if l <= additionalMax {
|
||||
lb := byte(l)
|
||||
dst = append(dst, byte(major|lb))
|
||||
} else {
|
||||
dst = appendCborTypePrefix(dst, major, uint64(l))
|
||||
}
|
||||
for _, d := range vals {
|
||||
dst = AppendDuration(dst, d, unit, useInt)
|
||||
}
|
||||
return dst
|
||||
}
|
438
vendor/github.com/rs/zerolog/internal/cbor/types.go
generated
vendored
Normal file
438
vendor/github.com/rs/zerolog/internal/cbor/types.go
generated
vendored
Normal file
@@ -0,0 +1,438 @@
|
||||
package cbor
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"math"
|
||||
)
|
||||
|
||||
// AppendNull inserts a 'Nil' object into the dst byte array.
|
||||
func AppendNull(dst []byte) []byte {
|
||||
return append(dst, byte(majorTypeSimpleAndFloat|additionalTypeNull))
|
||||
}
|
||||
|
||||
// AppendBeginMarker inserts a map start into the dst byte array.
|
||||
func AppendBeginMarker(dst []byte) []byte {
|
||||
return append(dst, byte(majorTypeMap|additionalTypeInfiniteCount))
|
||||
}
|
||||
|
||||
// AppendEndMarker inserts a map end into the dst byte array.
|
||||
func AppendEndMarker(dst []byte) []byte {
|
||||
return append(dst, byte(majorTypeSimpleAndFloat|additionalTypeBreak))
|
||||
}
|
||||
|
||||
// AppendBool encodes and inserts a boolean value into the dst byte array.
|
||||
func AppendBool(dst []byte, val bool) []byte {
|
||||
b := additionalTypeBoolFalse
|
||||
if val {
|
||||
b = additionalTypeBoolTrue
|
||||
}
|
||||
return append(dst, byte(majorTypeSimpleAndFloat|b))
|
||||
}
|
||||
|
||||
// AppendBools encodes and inserts an array of boolean values into the dst byte array.
|
||||
func AppendBools(dst []byte, vals []bool) []byte {
|
||||
major := majorTypeArray
|
||||
l := len(vals)
|
||||
if l == 0 {
|
||||
return AppendArrayEnd(AppendArrayStart(dst))
|
||||
}
|
||||
if l <= additionalMax {
|
||||
lb := byte(l)
|
||||
dst = append(dst, byte(major|lb))
|
||||
} else {
|
||||
dst = appendCborTypePrefix(dst, major, uint64(l))
|
||||
}
|
||||
for _, v := range vals {
|
||||
dst = AppendBool(dst, v)
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// AppendInt encodes and inserts an integer value into the dst byte array.
|
||||
func AppendInt(dst []byte, val int) []byte {
|
||||
major := majorTypeUnsignedInt
|
||||
contentVal := val
|
||||
if val < 0 {
|
||||
major = majorTypeNegativeInt
|
||||
contentVal = -val - 1
|
||||
}
|
||||
if contentVal <= additionalMax {
|
||||
lb := byte(contentVal)
|
||||
dst = append(dst, byte(major|lb))
|
||||
} else {
|
||||
dst = appendCborTypePrefix(dst, major, uint64(contentVal))
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// AppendInts encodes and inserts an array of integer values into the dst byte array.
|
||||
func AppendInts(dst []byte, vals []int) []byte {
|
||||
major := majorTypeArray
|
||||
l := len(vals)
|
||||
if l == 0 {
|
||||
return AppendArrayEnd(AppendArrayStart(dst))
|
||||
}
|
||||
if l <= additionalMax {
|
||||
lb := byte(l)
|
||||
dst = append(dst, byte(major|lb))
|
||||
} else {
|
||||
dst = appendCborTypePrefix(dst, major, uint64(l))
|
||||
}
|
||||
for _, v := range vals {
|
||||
dst = AppendInt(dst, v)
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// AppendInt8 encodes and inserts an int8 value into the dst byte array.
|
||||
func AppendInt8(dst []byte, val int8) []byte {
|
||||
return AppendInt(dst, int(val))
|
||||
}
|
||||
|
||||
// AppendInts8 encodes and inserts an array of integer values into the dst byte array.
|
||||
func AppendInts8(dst []byte, vals []int8) []byte {
|
||||
major := majorTypeArray
|
||||
l := len(vals)
|
||||
if l == 0 {
|
||||
return AppendArrayEnd(AppendArrayStart(dst))
|
||||
}
|
||||
if l <= additionalMax {
|
||||
lb := byte(l)
|
||||
dst = append(dst, byte(major|lb))
|
||||
} else {
|
||||
dst = appendCborTypePrefix(dst, major, uint64(l))
|
||||
}
|
||||
for _, v := range vals {
|
||||
dst = AppendInt(dst, int(v))
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// AppendInt16 encodes and inserts a int16 value into the dst byte array.
|
||||
func AppendInt16(dst []byte, val int16) []byte {
|
||||
return AppendInt(dst, int(val))
|
||||
}
|
||||
|
||||
// AppendInts16 encodes and inserts an array of int16 values into the dst byte array.
|
||||
func AppendInts16(dst []byte, vals []int16) []byte {
|
||||
major := majorTypeArray
|
||||
l := len(vals)
|
||||
if l == 0 {
|
||||
return AppendArrayEnd(AppendArrayStart(dst))
|
||||
}
|
||||
if l <= additionalMax {
|
||||
lb := byte(l)
|
||||
dst = append(dst, byte(major|lb))
|
||||
} else {
|
||||
dst = appendCborTypePrefix(dst, major, uint64(l))
|
||||
}
|
||||
for _, v := range vals {
|
||||
dst = AppendInt(dst, int(v))
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// AppendInt32 encodes and inserts a int32 value into the dst byte array.
|
||||
func AppendInt32(dst []byte, val int32) []byte {
|
||||
return AppendInt(dst, int(val))
|
||||
}
|
||||
|
||||
// AppendInts32 encodes and inserts an array of int32 values into the dst byte array.
|
||||
func AppendInts32(dst []byte, vals []int32) []byte {
|
||||
major := majorTypeArray
|
||||
l := len(vals)
|
||||
if l == 0 {
|
||||
return AppendArrayEnd(AppendArrayStart(dst))
|
||||
}
|
||||
if l <= additionalMax {
|
||||
lb := byte(l)
|
||||
dst = append(dst, byte(major|lb))
|
||||
} else {
|
||||
dst = appendCborTypePrefix(dst, major, uint64(l))
|
||||
}
|
||||
for _, v := range vals {
|
||||
dst = AppendInt(dst, int(v))
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// AppendInt64 encodes and inserts a int64 value into the dst byte array.
|
||||
func AppendInt64(dst []byte, val int64) []byte {
|
||||
major := majorTypeUnsignedInt
|
||||
contentVal := val
|
||||
if val < 0 {
|
||||
major = majorTypeNegativeInt
|
||||
contentVal = -val - 1
|
||||
}
|
||||
if contentVal <= additionalMax {
|
||||
lb := byte(contentVal)
|
||||
dst = append(dst, byte(major|lb))
|
||||
} else {
|
||||
dst = appendCborTypePrefix(dst, major, uint64(contentVal))
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// AppendInts64 encodes and inserts an array of int64 values into the dst byte array.
|
||||
func AppendInts64(dst []byte, vals []int64) []byte {
|
||||
major := majorTypeArray
|
||||
l := len(vals)
|
||||
if l == 0 {
|
||||
return AppendArrayEnd(AppendArrayStart(dst))
|
||||
}
|
||||
if l <= additionalMax {
|
||||
lb := byte(l)
|
||||
dst = append(dst, byte(major|lb))
|
||||
} else {
|
||||
dst = appendCborTypePrefix(dst, major, uint64(l))
|
||||
}
|
||||
for _, v := range vals {
|
||||
dst = AppendInt64(dst, v)
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// AppendUint encodes and inserts an unsigned integer value into the dst byte array.
|
||||
func AppendUint(dst []byte, val uint) []byte {
|
||||
return AppendInt64(dst, int64(val))
|
||||
}
|
||||
|
||||
// AppendUints encodes and inserts an array of unsigned integer values into the dst byte array.
|
||||
func AppendUints(dst []byte, vals []uint) []byte {
|
||||
major := majorTypeArray
|
||||
l := len(vals)
|
||||
if l == 0 {
|
||||
return AppendArrayEnd(AppendArrayStart(dst))
|
||||
}
|
||||
if l <= additionalMax {
|
||||
lb := byte(l)
|
||||
dst = append(dst, byte(major|lb))
|
||||
} else {
|
||||
dst = appendCborTypePrefix(dst, major, uint64(l))
|
||||
}
|
||||
for _, v := range vals {
|
||||
dst = AppendUint(dst, v)
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// AppendUint8 encodes and inserts a unsigned int8 value into the dst byte array.
|
||||
func AppendUint8(dst []byte, val uint8) []byte {
|
||||
return AppendUint(dst, uint(val))
|
||||
}
|
||||
|
||||
// AppendUints8 encodes and inserts an array of uint8 values into the dst byte array.
|
||||
func AppendUints8(dst []byte, vals []uint8) []byte {
|
||||
major := majorTypeArray
|
||||
l := len(vals)
|
||||
if l == 0 {
|
||||
return AppendArrayEnd(AppendArrayStart(dst))
|
||||
}
|
||||
if l <= additionalMax {
|
||||
lb := byte(l)
|
||||
dst = append(dst, byte(major|lb))
|
||||
} else {
|
||||
dst = appendCborTypePrefix(dst, major, uint64(l))
|
||||
}
|
||||
for _, v := range vals {
|
||||
dst = AppendUint8(dst, v)
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// AppendUint16 encodes and inserts a uint16 value into the dst byte array.
|
||||
func AppendUint16(dst []byte, val uint16) []byte {
|
||||
return AppendUint(dst, uint(val))
|
||||
}
|
||||
|
||||
// AppendUints16 encodes and inserts an array of uint16 values into the dst byte array.
|
||||
func AppendUints16(dst []byte, vals []uint16) []byte {
|
||||
major := majorTypeArray
|
||||
l := len(vals)
|
||||
if l == 0 {
|
||||
return AppendArrayEnd(AppendArrayStart(dst))
|
||||
}
|
||||
if l <= additionalMax {
|
||||
lb := byte(l)
|
||||
dst = append(dst, byte(major|lb))
|
||||
} else {
|
||||
dst = appendCborTypePrefix(dst, major, uint64(l))
|
||||
}
|
||||
for _, v := range vals {
|
||||
dst = AppendUint16(dst, v)
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// AppendUint32 encodes and inserts a uint32 value into the dst byte array.
|
||||
func AppendUint32(dst []byte, val uint32) []byte {
|
||||
return AppendUint(dst, uint(val))
|
||||
}
|
||||
|
||||
// AppendUints32 encodes and inserts an array of uint32 values into the dst byte array.
|
||||
func AppendUints32(dst []byte, vals []uint32) []byte {
|
||||
major := majorTypeArray
|
||||
l := len(vals)
|
||||
if l == 0 {
|
||||
return AppendArrayEnd(AppendArrayStart(dst))
|
||||
}
|
||||
if l <= additionalMax {
|
||||
lb := byte(l)
|
||||
dst = append(dst, byte(major|lb))
|
||||
} else {
|
||||
dst = appendCborTypePrefix(dst, major, uint64(l))
|
||||
}
|
||||
for _, v := range vals {
|
||||
dst = AppendUint32(dst, v)
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// AppendUint64 encodes and inserts a uint64 value into the dst byte array.
|
||||
func AppendUint64(dst []byte, val uint64) []byte {
|
||||
major := majorTypeUnsignedInt
|
||||
contentVal := val
|
||||
if contentVal <= additionalMax {
|
||||
lb := byte(contentVal)
|
||||
dst = append(dst, byte(major|lb))
|
||||
} else {
|
||||
dst = appendCborTypePrefix(dst, major, uint64(contentVal))
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// AppendUints64 encodes and inserts an array of uint64 values into the dst byte array.
|
||||
func AppendUints64(dst []byte, vals []uint64) []byte {
|
||||
major := majorTypeArray
|
||||
l := len(vals)
|
||||
if l == 0 {
|
||||
return AppendArrayEnd(AppendArrayStart(dst))
|
||||
}
|
||||
if l <= additionalMax {
|
||||
lb := byte(l)
|
||||
dst = append(dst, byte(major|lb))
|
||||
} else {
|
||||
dst = appendCborTypePrefix(dst, major, uint64(l))
|
||||
}
|
||||
for _, v := range vals {
|
||||
dst = AppendUint64(dst, v)
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// AppendFloat32 encodes and inserts a single precision float value into the dst byte array.
|
||||
func AppendFloat32(dst []byte, val float32) []byte {
|
||||
switch {
|
||||
case math.IsNaN(float64(val)):
|
||||
return append(dst, "\xfa\x7f\xc0\x00\x00"...)
|
||||
case math.IsInf(float64(val), 1):
|
||||
return append(dst, "\xfa\x7f\x80\x00\x00"...)
|
||||
case math.IsInf(float64(val), -1):
|
||||
return append(dst, "\xfa\xff\x80\x00\x00"...)
|
||||
}
|
||||
major := majorTypeSimpleAndFloat
|
||||
subType := additionalTypeFloat32
|
||||
n := math.Float32bits(val)
|
||||
var buf [4]byte
|
||||
for i := uint(0); i < 4; i++ {
|
||||
buf[i] = byte(n >> ((3 - i) * 8))
|
||||
}
|
||||
return append(append(dst, byte(major|subType)), buf[0], buf[1], buf[2], buf[3])
|
||||
}
|
||||
|
||||
// AppendFloats32 encodes and inserts an array of single precision float value into the dst byte array.
|
||||
func AppendFloats32(dst []byte, vals []float32) []byte {
|
||||
major := majorTypeArray
|
||||
l := len(vals)
|
||||
if l == 0 {
|
||||
return AppendArrayEnd(AppendArrayStart(dst))
|
||||
}
|
||||
if l <= additionalMax {
|
||||
lb := byte(l)
|
||||
dst = append(dst, byte(major|lb))
|
||||
} else {
|
||||
dst = appendCborTypePrefix(dst, major, uint64(l))
|
||||
}
|
||||
for _, v := range vals {
|
||||
dst = AppendFloat32(dst, v)
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// AppendFloat64 encodes and inserts a double precision float value into the dst byte array.
|
||||
func AppendFloat64(dst []byte, val float64) []byte {
|
||||
switch {
|
||||
case math.IsNaN(val):
|
||||
return append(dst, "\xfb\x7f\xf8\x00\x00\x00\x00\x00\x00"...)
|
||||
case math.IsInf(val, 1):
|
||||
return append(dst, "\xfb\x7f\xf0\x00\x00\x00\x00\x00\x00"...)
|
||||
case math.IsInf(val, -1):
|
||||
return append(dst, "\xfb\xff\xf0\x00\x00\x00\x00\x00\x00"...)
|
||||
}
|
||||
major := majorTypeSimpleAndFloat
|
||||
subType := additionalTypeFloat64
|
||||
n := math.Float64bits(val)
|
||||
dst = append(dst, byte(major|subType))
|
||||
for i := uint(1); i <= 8; i++ {
|
||||
b := byte(n >> ((8 - i) * 8))
|
||||
dst = append(dst, b)
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// AppendFloats64 encodes and inserts an array of double precision float values into the dst byte array.
|
||||
func AppendFloats64(dst []byte, vals []float64) []byte {
|
||||
major := majorTypeArray
|
||||
l := len(vals)
|
||||
if l == 0 {
|
||||
return AppendArrayEnd(AppendArrayStart(dst))
|
||||
}
|
||||
if l <= additionalMax {
|
||||
lb := byte(l)
|
||||
dst = append(dst, byte(major|lb))
|
||||
} else {
|
||||
dst = appendCborTypePrefix(dst, major, uint64(l))
|
||||
}
|
||||
for _, v := range vals {
|
||||
dst = AppendFloat64(dst, v)
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// AppendInterface takes an arbitrary object and converts it to JSON and embeds it dst.
|
||||
func AppendInterface(dst []byte, i interface{}) []byte {
|
||||
marshaled, err := json.Marshal(i)
|
||||
if err != nil {
|
||||
return AppendString(dst, fmt.Sprintf("marshaling error: %v", err))
|
||||
}
|
||||
return AppendEmbeddedJSON(dst, marshaled)
|
||||
}
|
||||
|
||||
// AppendObjectData takes an object in form of a byte array and appends to dst.
|
||||
func AppendObjectData(dst []byte, o []byte) []byte {
|
||||
return append(dst, o...)
|
||||
}
|
||||
|
||||
// AppendArrayStart adds markers to indicate the start of an array.
|
||||
func AppendArrayStart(dst []byte) []byte {
|
||||
return append(dst, byte(majorTypeArray|additionalTypeInfiniteCount))
|
||||
}
|
||||
|
||||
// AppendArrayEnd adds markers to indicate the end of an array.
|
||||
func AppendArrayEnd(dst []byte) []byte {
|
||||
return append(dst, byte(majorTypeSimpleAndFloat|additionalTypeBreak))
|
||||
}
|
||||
|
||||
// AppendArrayDelim adds markers to indicate end of a particular array element.
|
||||
func AppendArrayDelim(dst []byte) []byte {
|
||||
//No delimiters needed in cbor
|
||||
return dst
|
||||
}
|
||||
|
||||
func AppendHex (dst []byte, val []byte) []byte {
|
||||
dst = append(dst, byte(majorTypeTags|additionalTypeIntUint16))
|
||||
dst = append(dst, byte(additionalTypeTagHexString>>8))
|
||||
dst = append(dst, byte(additionalTypeTagHexString&0xff))
|
||||
return AppendBytes(dst, val)
|
||||
}
|
44
vendor/github.com/rs/zerolog/internal/json/base.go
generated
vendored
Normal file
44
vendor/github.com/rs/zerolog/internal/json/base.go
generated
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
package json
|
||||
|
||||
// AppendKey appends a new key to the output JSON.
|
||||
func AppendKey(dst []byte, key string) []byte {
|
||||
if len(dst) > 1 && dst[len(dst)-1] != '{' {
|
||||
dst = append(dst, ',')
|
||||
}
|
||||
dst = AppendString(dst, key)
|
||||
return append(dst, ':')
|
||||
}
|
||||
|
||||
// AppendError encodes the error string to json and appends
|
||||
// the encoded string to the input byte slice.
|
||||
func AppendError(dst []byte, err error) []byte {
|
||||
if err == nil {
|
||||
return append(dst, `null`...)
|
||||
}
|
||||
return AppendString(dst, err.Error())
|
||||
}
|
||||
|
||||
// AppendErrors encodes the error strings to json and
|
||||
// appends the encoded string list to the input byte slice.
|
||||
func AppendErrors(dst []byte, errs []error) []byte {
|
||||
if len(errs) == 0 {
|
||||
return append(dst, '[', ']')
|
||||
}
|
||||
dst = append(dst, '[')
|
||||
if errs[0] != nil {
|
||||
dst = AppendString(dst, errs[0].Error())
|
||||
} else {
|
||||
dst = append(dst, "null"...)
|
||||
}
|
||||
if len(errs) > 1 {
|
||||
for _, err := range errs[1:] {
|
||||
if err == nil {
|
||||
dst = append(dst, ",null"...)
|
||||
continue
|
||||
}
|
||||
dst = AppendString(append(dst, ','), err.Error())
|
||||
}
|
||||
}
|
||||
dst = append(dst, ']')
|
||||
return dst
|
||||
}
|
85
vendor/github.com/rs/zerolog/internal/json/bytes.go
generated
vendored
Normal file
85
vendor/github.com/rs/zerolog/internal/json/bytes.go
generated
vendored
Normal file
@@ -0,0 +1,85 @@
|
||||
package json
|
||||
|
||||
import "unicode/utf8"
|
||||
|
||||
// AppendBytes is a mirror of appendString with []byte arg
|
||||
func AppendBytes(dst, s []byte) []byte {
|
||||
dst = append(dst, '"')
|
||||
for i := 0; i < len(s); i++ {
|
||||
if !noEscapeTable[s[i]] {
|
||||
dst = appendBytesComplex(dst, s, i)
|
||||
return append(dst, '"')
|
||||
}
|
||||
}
|
||||
dst = append(dst, s...)
|
||||
return append(dst, '"')
|
||||
}
|
||||
|
||||
// AppendHex encodes the input bytes to a hex string and appends
|
||||
// the encoded string to the input byte slice.
|
||||
//
|
||||
// The operation loops though each byte and encodes it as hex using
|
||||
// the hex lookup table.
|
||||
func AppendHex(dst, s []byte) []byte {
|
||||
dst = append(dst, '"')
|
||||
for _, v := range s {
|
||||
dst = append(dst, hex[v>>4], hex[v&0x0f])
|
||||
}
|
||||
return append(dst, '"')
|
||||
}
|
||||
|
||||
// appendBytesComplex is a mirror of the appendStringComplex
|
||||
// with []byte arg
|
||||
func appendBytesComplex(dst, s []byte, i int) []byte {
|
||||
start := 0
|
||||
for i < len(s) {
|
||||
b := s[i]
|
||||
if b >= utf8.RuneSelf {
|
||||
r, size := utf8.DecodeRune(s[i:])
|
||||
if r == utf8.RuneError && size == 1 {
|
||||
if start < i {
|
||||
dst = append(dst, s[start:i]...)
|
||||
}
|
||||
dst = append(dst, `\ufffd`...)
|
||||
i += size
|
||||
start = i
|
||||
continue
|
||||
}
|
||||
i += size
|
||||
continue
|
||||
}
|
||||
if noEscapeTable[b] {
|
||||
i++
|
||||
continue
|
||||
}
|
||||
// We encountered a character that needs to be encoded.
|
||||
// Let's append the previous simple characters to the byte slice
|
||||
// and switch our operation to read and encode the remainder
|
||||
// characters byte-by-byte.
|
||||
if start < i {
|
||||
dst = append(dst, s[start:i]...)
|
||||
}
|
||||
switch b {
|
||||
case '"', '\\':
|
||||
dst = append(dst, '\\', b)
|
||||
case '\b':
|
||||
dst = append(dst, '\\', 'b')
|
||||
case '\f':
|
||||
dst = append(dst, '\\', 'f')
|
||||
case '\n':
|
||||
dst = append(dst, '\\', 'n')
|
||||
case '\r':
|
||||
dst = append(dst, '\\', 'r')
|
||||
case '\t':
|
||||
dst = append(dst, '\\', 't')
|
||||
default:
|
||||
dst = append(dst, '\\', 'u', '0', '0', hex[b>>4], hex[b&0xF])
|
||||
}
|
||||
i++
|
||||
start = i
|
||||
}
|
||||
if start < len(s) {
|
||||
dst = append(dst, s[start:]...)
|
||||
}
|
||||
return dst
|
||||
}
|
121
vendor/github.com/rs/zerolog/internal/json/string.go
generated
vendored
Normal file
121
vendor/github.com/rs/zerolog/internal/json/string.go
generated
vendored
Normal file
@@ -0,0 +1,121 @@
|
||||
package json
|
||||
|
||||
import "unicode/utf8"
|
||||
|
||||
const hex = "0123456789abcdef"
|
||||
|
||||
var noEscapeTable = [256]bool{}
|
||||
|
||||
func init() {
|
||||
for i := 0; i <= 0x7e; i++ {
|
||||
noEscapeTable[i] = i >= 0x20 && i != '\\' && i != '"'
|
||||
}
|
||||
}
|
||||
|
||||
// AppendStrings encodes the input strings to json and
|
||||
// appends the encoded string list to the input byte slice.
|
||||
func AppendStrings(dst []byte, vals []string) []byte {
|
||||
if len(vals) == 0 {
|
||||
return append(dst, '[', ']')
|
||||
}
|
||||
dst = append(dst, '[')
|
||||
dst = AppendString(dst, vals[0])
|
||||
if len(vals) > 1 {
|
||||
for _, val := range vals[1:] {
|
||||
dst = AppendString(append(dst, ','), val)
|
||||
}
|
||||
}
|
||||
dst = append(dst, ']')
|
||||
return dst
|
||||
}
|
||||
|
||||
// AppendString encodes the input string to json and appends
|
||||
// the encoded string to the input byte slice.
|
||||
//
|
||||
// The operation loops though each byte in the string looking
|
||||
// for characters that need json or utf8 encoding. If the string
|
||||
// does not need encoding, then the string is appended in it's
|
||||
// entirety to the byte slice.
|
||||
// If we encounter a byte that does need encoding, switch up
|
||||
// the operation and perform a byte-by-byte read-encode-append.
|
||||
func AppendString(dst []byte, s string) []byte {
|
||||
// Start with a double quote.
|
||||
dst = append(dst, '"')
|
||||
// Loop through each character in the string.
|
||||
for i := 0; i < len(s); i++ {
|
||||
// Check if the character needs encoding. Control characters, slashes,
|
||||
// and the double quote need json encoding. Bytes above the ascii
|
||||
// boundary needs utf8 encoding.
|
||||
if !noEscapeTable[s[i]] {
|
||||
// We encountered a character that needs to be encoded. Switch
|
||||
// to complex version of the algorithm.
|
||||
dst = appendStringComplex(dst, s, i)
|
||||
return append(dst, '"')
|
||||
}
|
||||
}
|
||||
// The string has no need for encoding an therefore is directly
|
||||
// appended to the byte slice.
|
||||
dst = append(dst, s...)
|
||||
// End with a double quote
|
||||
return append(dst, '"')
|
||||
}
|
||||
|
||||
// appendStringComplex is used by appendString to take over an in
|
||||
// progress JSON string encoding that encountered a character that needs
|
||||
// to be encoded.
|
||||
func appendStringComplex(dst []byte, s string, i int) []byte {
|
||||
start := 0
|
||||
for i < len(s) {
|
||||
b := s[i]
|
||||
if b >= utf8.RuneSelf {
|
||||
r, size := utf8.DecodeRuneInString(s[i:])
|
||||
if r == utf8.RuneError && size == 1 {
|
||||
// In case of error, first append previous simple characters to
|
||||
// the byte slice if any and append a remplacement character code
|
||||
// in place of the invalid sequence.
|
||||
if start < i {
|
||||
dst = append(dst, s[start:i]...)
|
||||
}
|
||||
dst = append(dst, `\ufffd`...)
|
||||
i += size
|
||||
start = i
|
||||
continue
|
||||
}
|
||||
i += size
|
||||
continue
|
||||
}
|
||||
if noEscapeTable[b] {
|
||||
i++
|
||||
continue
|
||||
}
|
||||
// We encountered a character that needs to be encoded.
|
||||
// Let's append the previous simple characters to the byte slice
|
||||
// and switch our operation to read and encode the remainder
|
||||
// characters byte-by-byte.
|
||||
if start < i {
|
||||
dst = append(dst, s[start:i]...)
|
||||
}
|
||||
switch b {
|
||||
case '"', '\\':
|
||||
dst = append(dst, '\\', b)
|
||||
case '\b':
|
||||
dst = append(dst, '\\', 'b')
|
||||
case '\f':
|
||||
dst = append(dst, '\\', 'f')
|
||||
case '\n':
|
||||
dst = append(dst, '\\', 'n')
|
||||
case '\r':
|
||||
dst = append(dst, '\\', 'r')
|
||||
case '\t':
|
||||
dst = append(dst, '\\', 't')
|
||||
default:
|
||||
dst = append(dst, '\\', 'u', '0', '0', hex[b>>4], hex[b&0xF])
|
||||
}
|
||||
i++
|
||||
start = i
|
||||
}
|
||||
if start < len(s) {
|
||||
dst = append(dst, s[start:]...)
|
||||
}
|
||||
return dst
|
||||
}
|
76
vendor/github.com/rs/zerolog/internal/json/time.go
generated
vendored
Normal file
76
vendor/github.com/rs/zerolog/internal/json/time.go
generated
vendored
Normal file
@@ -0,0 +1,76 @@
|
||||
package json
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
// AppendTime formats the input time with the given format
|
||||
// and appends the encoded string to the input byte slice.
|
||||
func AppendTime(dst []byte, t time.Time, format string) []byte {
|
||||
if format == "" {
|
||||
return AppendInt64(dst, t.Unix())
|
||||
}
|
||||
return append(t.AppendFormat(append(dst, '"'), format), '"')
|
||||
}
|
||||
|
||||
// AppendTimes converts the input times with the given format
|
||||
// and appends the encoded string list to the input byte slice.
|
||||
func AppendTimes(dst []byte, vals []time.Time, format string) []byte {
|
||||
if format == "" {
|
||||
return appendUnixTimes(dst, vals)
|
||||
}
|
||||
if len(vals) == 0 {
|
||||
return append(dst, '[', ']')
|
||||
}
|
||||
dst = append(dst, '[')
|
||||
dst = append(vals[0].AppendFormat(append(dst, '"'), format), '"')
|
||||
if len(vals) > 1 {
|
||||
for _, t := range vals[1:] {
|
||||
dst = append(t.AppendFormat(append(dst, ',', '"'), format), '"')
|
||||
}
|
||||
}
|
||||
dst = append(dst, ']')
|
||||
return dst
|
||||
}
|
||||
|
||||
func appendUnixTimes(dst []byte, vals []time.Time) []byte {
|
||||
if len(vals) == 0 {
|
||||
return append(dst, '[', ']')
|
||||
}
|
||||
dst = append(dst, '[')
|
||||
dst = strconv.AppendInt(dst, vals[0].Unix(), 10)
|
||||
if len(vals) > 1 {
|
||||
for _, t := range vals[1:] {
|
||||
dst = strconv.AppendInt(dst, t.Unix(), 10)
|
||||
}
|
||||
}
|
||||
dst = append(dst, ']')
|
||||
return dst
|
||||
}
|
||||
|
||||
// AppendDuration formats the input duration with the given unit & format
|
||||
// and appends the encoded string to the input byte slice.
|
||||
func AppendDuration(dst []byte, d time.Duration, unit time.Duration, useInt bool) []byte {
|
||||
if useInt {
|
||||
return strconv.AppendInt(dst, int64(d/unit), 10)
|
||||
}
|
||||
return AppendFloat64(dst, float64(d)/float64(unit))
|
||||
}
|
||||
|
||||
// AppendDurations formats the input durations with the given unit & format
|
||||
// and appends the encoded string list to the input byte slice.
|
||||
func AppendDurations(dst []byte, vals []time.Duration, unit time.Duration, useInt bool) []byte {
|
||||
if len(vals) == 0 {
|
||||
return append(dst, '[', ']')
|
||||
}
|
||||
dst = append(dst, '[')
|
||||
dst = AppendDuration(dst, vals[0], unit, useInt)
|
||||
if len(vals) > 1 {
|
||||
for _, d := range vals[1:] {
|
||||
dst = AppendDuration(append(dst, ','), d, unit, useInt)
|
||||
}
|
||||
}
|
||||
dst = append(dst, ']')
|
||||
return dst
|
||||
}
|
347
vendor/github.com/rs/zerolog/internal/json/types.go
generated
vendored
Normal file
347
vendor/github.com/rs/zerolog/internal/json/types.go
generated
vendored
Normal file
@@ -0,0 +1,347 @@
|
||||
package json
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"math"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// AppendBool converts the input bool to a string and
|
||||
// appends the encoded string to the input byte slice.
|
||||
func AppendBool(dst []byte, val bool) []byte {
|
||||
return strconv.AppendBool(dst, val)
|
||||
}
|
||||
|
||||
// AppendBools encodes the input bools to json and
|
||||
// appends the encoded string list to the input byte slice.
|
||||
func AppendBools(dst []byte, vals []bool) []byte {
|
||||
if len(vals) == 0 {
|
||||
return append(dst, '[', ']')
|
||||
}
|
||||
dst = append(dst, '[')
|
||||
dst = strconv.AppendBool(dst, vals[0])
|
||||
if len(vals) > 1 {
|
||||
for _, val := range vals[1:] {
|
||||
dst = strconv.AppendBool(append(dst, ','), val)
|
||||
}
|
||||
}
|
||||
dst = append(dst, ']')
|
||||
return dst
|
||||
}
|
||||
|
||||
// AppendInt converts the input int to a string and
|
||||
// appends the encoded string to the input byte slice.
|
||||
func AppendInt(dst []byte, val int) []byte {
|
||||
return strconv.AppendInt(dst, int64(val), 10)
|
||||
}
|
||||
|
||||
// AppendInts encodes the input ints to json and
|
||||
// appends the encoded string list to the input byte slice.
|
||||
func AppendInts(dst []byte, vals []int) []byte {
|
||||
if len(vals) == 0 {
|
||||
return append(dst, '[', ']')
|
||||
}
|
||||
dst = append(dst, '[')
|
||||
dst = strconv.AppendInt(dst, int64(vals[0]), 10)
|
||||
if len(vals) > 1 {
|
||||
for _, val := range vals[1:] {
|
||||
dst = strconv.AppendInt(append(dst, ','), int64(val), 10)
|
||||
}
|
||||
}
|
||||
dst = append(dst, ']')
|
||||
return dst
|
||||
}
|
||||
|
||||
// AppendInt8 converts the input []int8 to a string and
|
||||
// appends the encoded string to the input byte slice.
|
||||
func AppendInt8(dst []byte, val int8) []byte {
|
||||
return strconv.AppendInt(dst, int64(val), 10)
|
||||
}
|
||||
|
||||
// AppendInts8 encodes the input int8s to json and
|
||||
// appends the encoded string list to the input byte slice.
|
||||
func AppendInts8(dst []byte, vals []int8) []byte {
|
||||
if len(vals) == 0 {
|
||||
return append(dst, '[', ']')
|
||||
}
|
||||
dst = append(dst, '[')
|
||||
dst = strconv.AppendInt(dst, int64(vals[0]), 10)
|
||||
if len(vals) > 1 {
|
||||
for _, val := range vals[1:] {
|
||||
dst = strconv.AppendInt(append(dst, ','), int64(val), 10)
|
||||
}
|
||||
}
|
||||
dst = append(dst, ']')
|
||||
return dst
|
||||
}
|
||||
|
||||
// AppendInt16 converts the input int16 to a string and
|
||||
// appends the encoded string to the input byte slice.
|
||||
func AppendInt16(dst []byte, val int16) []byte {
|
||||
return strconv.AppendInt(dst, int64(val), 10)
|
||||
}
|
||||
|
||||
// AppendInts16 encodes the input int16s to json and
|
||||
// appends the encoded string list to the input byte slice.
|
||||
func AppendInts16(dst []byte, vals []int16) []byte {
|
||||
if len(vals) == 0 {
|
||||
return append(dst, '[', ']')
|
||||
}
|
||||
dst = append(dst, '[')
|
||||
dst = strconv.AppendInt(dst, int64(vals[0]), 10)
|
||||
if len(vals) > 1 {
|
||||
for _, val := range vals[1:] {
|
||||
dst = strconv.AppendInt(append(dst, ','), int64(val), 10)
|
||||
}
|
||||
}
|
||||
dst = append(dst, ']')
|
||||
return dst
|
||||
}
|
||||
|
||||
// AppendInt32 converts the input int32 to a string and
|
||||
// appends the encoded string to the input byte slice.
|
||||
func AppendInt32(dst []byte, val int32) []byte {
|
||||
return strconv.AppendInt(dst, int64(val), 10)
|
||||
}
|
||||
|
||||
// AppendInts32 encodes the input int32s to json and
|
||||
// appends the encoded string list to the input byte slice.
|
||||
func AppendInts32(dst []byte, vals []int32) []byte {
|
||||
if len(vals) == 0 {
|
||||
return append(dst, '[', ']')
|
||||
}
|
||||
dst = append(dst, '[')
|
||||
dst = strconv.AppendInt(dst, int64(vals[0]), 10)
|
||||
if len(vals) > 1 {
|
||||
for _, val := range vals[1:] {
|
||||
dst = strconv.AppendInt(append(dst, ','), int64(val), 10)
|
||||
}
|
||||
}
|
||||
dst = append(dst, ']')
|
||||
return dst
|
||||
}
|
||||
|
||||
// AppendInt64 converts the input int64 to a string and
|
||||
// appends the encoded string to the input byte slice.
|
||||
func AppendInt64(dst []byte, val int64) []byte {
|
||||
return strconv.AppendInt(dst, val, 10)
|
||||
}
|
||||
|
||||
// AppendInts64 encodes the input int64s to json and
|
||||
// appends the encoded string list to the input byte slice.
|
||||
func AppendInts64(dst []byte, vals []int64) []byte {
|
||||
if len(vals) == 0 {
|
||||
return append(dst, '[', ']')
|
||||
}
|
||||
dst = append(dst, '[')
|
||||
dst = strconv.AppendInt(dst, vals[0], 10)
|
||||
if len(vals) > 1 {
|
||||
for _, val := range vals[1:] {
|
||||
dst = strconv.AppendInt(append(dst, ','), val, 10)
|
||||
}
|
||||
}
|
||||
dst = append(dst, ']')
|
||||
return dst
|
||||
}
|
||||
|
||||
// AppendUint converts the input uint to a string and
|
||||
// appends the encoded string to the input byte slice.
|
||||
func AppendUint(dst []byte, val uint) []byte {
|
||||
return strconv.AppendUint(dst, uint64(val), 10)
|
||||
}
|
||||
|
||||
// AppendUints encodes the input uints to json and
|
||||
// appends the encoded string list to the input byte slice.
|
||||
func AppendUints(dst []byte, vals []uint) []byte {
|
||||
if len(vals) == 0 {
|
||||
return append(dst, '[', ']')
|
||||
}
|
||||
dst = append(dst, '[')
|
||||
dst = strconv.AppendUint(dst, uint64(vals[0]), 10)
|
||||
if len(vals) > 1 {
|
||||
for _, val := range vals[1:] {
|
||||
dst = strconv.AppendUint(append(dst, ','), uint64(val), 10)
|
||||
}
|
||||
}
|
||||
dst = append(dst, ']')
|
||||
return dst
|
||||
}
|
||||
|
||||
// AppendUint8 converts the input uint8 to a string and
|
||||
// appends the encoded string to the input byte slice.
|
||||
func AppendUint8(dst []byte, val uint8) []byte {
|
||||
return strconv.AppendUint(dst, uint64(val), 10)
|
||||
}
|
||||
|
||||
// AppendUints8 encodes the input uint8s to json and
|
||||
// appends the encoded string list to the input byte slice.
|
||||
func AppendUints8(dst []byte, vals []uint8) []byte {
|
||||
if len(vals) == 0 {
|
||||
return append(dst, '[', ']')
|
||||
}
|
||||
dst = append(dst, '[')
|
||||
dst = strconv.AppendUint(dst, uint64(vals[0]), 10)
|
||||
if len(vals) > 1 {
|
||||
for _, val := range vals[1:] {
|
||||
dst = strconv.AppendUint(append(dst, ','), uint64(val), 10)
|
||||
}
|
||||
}
|
||||
dst = append(dst, ']')
|
||||
return dst
|
||||
}
|
||||
|
||||
// AppendUint16 converts the input uint16 to a string and
|
||||
// appends the encoded string to the input byte slice.
|
||||
func AppendUint16(dst []byte, val uint16) []byte {
|
||||
return strconv.AppendUint(dst, uint64(val), 10)
|
||||
}
|
||||
|
||||
// AppendUints16 encodes the input uint16s to json and
|
||||
// appends the encoded string list to the input byte slice.
|
||||
func AppendUints16(dst []byte, vals []uint16) []byte {
|
||||
if len(vals) == 0 {
|
||||
return append(dst, '[', ']')
|
||||
}
|
||||
dst = append(dst, '[')
|
||||
dst = strconv.AppendUint(dst, uint64(vals[0]), 10)
|
||||
if len(vals) > 1 {
|
||||
for _, val := range vals[1:] {
|
||||
dst = strconv.AppendUint(append(dst, ','), uint64(val), 10)
|
||||
}
|
||||
}
|
||||
dst = append(dst, ']')
|
||||
return dst
|
||||
}
|
||||
|
||||
// AppendUint32 converts the input uint32 to a string and
|
||||
// appends the encoded string to the input byte slice.
|
||||
func AppendUint32(dst []byte, val uint32) []byte {
|
||||
return strconv.AppendUint(dst, uint64(val), 10)
|
||||
}
|
||||
|
||||
// AppendUints32 encodes the input uint32s to json and
|
||||
// appends the encoded string list to the input byte slice.
|
||||
func AppendUints32(dst []byte, vals []uint32) []byte {
|
||||
if len(vals) == 0 {
|
||||
return append(dst, '[', ']')
|
||||
}
|
||||
dst = append(dst, '[')
|
||||
dst = strconv.AppendUint(dst, uint64(vals[0]), 10)
|
||||
if len(vals) > 1 {
|
||||
for _, val := range vals[1:] {
|
||||
dst = strconv.AppendUint(append(dst, ','), uint64(val), 10)
|
||||
}
|
||||
}
|
||||
dst = append(dst, ']')
|
||||
return dst
|
||||
}
|
||||
|
||||
// AppendUint64 converts the input uint64 to a string and
|
||||
// appends the encoded string to the input byte slice.
|
||||
func AppendUint64(dst []byte, val uint64) []byte {
|
||||
return strconv.AppendUint(dst, uint64(val), 10)
|
||||
}
|
||||
|
||||
// AppendUints64 encodes the input uint64s to json and
|
||||
// appends the encoded string list to the input byte slice.
|
||||
func AppendUints64(dst []byte, vals []uint64) []byte {
|
||||
if len(vals) == 0 {
|
||||
return append(dst, '[', ']')
|
||||
}
|
||||
dst = append(dst, '[')
|
||||
dst = strconv.AppendUint(dst, vals[0], 10)
|
||||
if len(vals) > 1 {
|
||||
for _, val := range vals[1:] {
|
||||
dst = strconv.AppendUint(append(dst, ','), val, 10)
|
||||
}
|
||||
}
|
||||
dst = append(dst, ']')
|
||||
return dst
|
||||
}
|
||||
|
||||
// AppendFloat converts the input float to a string and
|
||||
// appends the encoded string to the input byte slice.
|
||||
func AppendFloat(dst []byte, val float64, bitSize int) []byte {
|
||||
// JSON does not permit NaN or Infinity. A typical JSON encoder would fail
|
||||
// with an error, but a logging library wants the data to get thru so we
|
||||
// make a tradeoff and store those types as string.
|
||||
switch {
|
||||
case math.IsNaN(val):
|
||||
return append(dst, `"NaN"`...)
|
||||
case math.IsInf(val, 1):
|
||||
return append(dst, `"+Inf"`...)
|
||||
case math.IsInf(val, -1):
|
||||
return append(dst, `"-Inf"`...)
|
||||
}
|
||||
return strconv.AppendFloat(dst, val, 'f', -1, bitSize)
|
||||
}
|
||||
|
||||
// AppendFloat32 converts the input float32 to a string and
|
||||
// appends the encoded string to the input byte slice.
|
||||
func AppendFloat32(dst []byte, val float32) []byte {
|
||||
return AppendFloat(dst, float64(val), 32)
|
||||
}
|
||||
|
||||
// AppendFloats32 encodes the input float32s to json and
|
||||
// appends the encoded string list to the input byte slice.
|
||||
func AppendFloats32(dst []byte, vals []float32) []byte {
|
||||
if len(vals) == 0 {
|
||||
return append(dst, '[', ']')
|
||||
}
|
||||
dst = append(dst, '[')
|
||||
dst = AppendFloat(dst, float64(vals[0]), 32)
|
||||
if len(vals) > 1 {
|
||||
for _, val := range vals[1:] {
|
||||
dst = AppendFloat(append(dst, ','), float64(val), 32)
|
||||
}
|
||||
}
|
||||
dst = append(dst, ']')
|
||||
return dst
|
||||
}
|
||||
|
||||
// AppendFloat64 converts the input float64 to a string and
|
||||
// appends the encoded string to the input byte slice.
|
||||
func AppendFloat64(dst []byte, val float64) []byte {
|
||||
return AppendFloat(dst, val, 64)
|
||||
}
|
||||
|
||||
// AppendFloats64 encodes the input float64s to json and
|
||||
// appends the encoded string list to the input byte slice.
|
||||
func AppendFloats64(dst []byte, vals []float64) []byte {
|
||||
if len(vals) == 0 {
|
||||
return append(dst, '[', ']')
|
||||
}
|
||||
dst = append(dst, '[')
|
||||
dst = AppendFloat(dst, vals[0], 32)
|
||||
if len(vals) > 1 {
|
||||
for _, val := range vals[1:] {
|
||||
dst = AppendFloat(append(dst, ','), val, 64)
|
||||
}
|
||||
}
|
||||
dst = append(dst, ']')
|
||||
return dst
|
||||
}
|
||||
|
||||
// AppendInterface marshals the input interface to a string and
|
||||
// appends the encoded string to the input byte slice.
|
||||
func AppendInterface(dst []byte, i interface{}) []byte {
|
||||
marshaled, err := json.Marshal(i)
|
||||
if err != nil {
|
||||
return AppendString(dst, fmt.Sprintf("marshaling error: %v", err))
|
||||
}
|
||||
return append(dst, marshaled...)
|
||||
}
|
||||
|
||||
func AppendObjectData(dst []byte, o []byte) []byte {
|
||||
// Two conditions we want to put a ',' between existing content and
|
||||
// new content:
|
||||
// 1. new content starts with '{' - which shd be dropped OR
|
||||
// 2. existing content has already other fields
|
||||
if o[0] == '{' {
|
||||
o[0] = ','
|
||||
} else if len(dst) > 1 {
|
||||
dst = append(dst, ',')
|
||||
}
|
||||
return append(dst, o...)
|
||||
}
|
376
vendor/github.com/rs/zerolog/log.go
generated
vendored
Normal file
376
vendor/github.com/rs/zerolog/log.go
generated
vendored
Normal file
@@ -0,0 +1,376 @@
|
||||
// Package zerolog provides a lightweight logging library dedicated to JSON logging.
|
||||
//
|
||||
// A global Logger can be use for simple logging:
|
||||
//
|
||||
// import "github.com/rs/zerolog/log"
|
||||
//
|
||||
// log.Info().Msg("hello world")
|
||||
// // Output: {"time":1494567715,"level":"info","message":"hello world"}
|
||||
//
|
||||
// NOTE: To import the global logger, import the "log" subpackage "github.com/rs/zerolog/log".
|
||||
//
|
||||
// Fields can be added to log messages:
|
||||
//
|
||||
// log.Info().Str("foo", "bar").Msg("hello world")
|
||||
// // Output: {"time":1494567715,"level":"info","message":"hello world","foo":"bar"}
|
||||
//
|
||||
// Create logger instance to manage different outputs:
|
||||
//
|
||||
// logger := zerolog.New(os.Stderr).With().Timestamp().Logger()
|
||||
// logger.Info().
|
||||
// Str("foo", "bar").
|
||||
// Msg("hello world")
|
||||
// // Output: {"time":1494567715,"level":"info","message":"hello world","foo":"bar"}
|
||||
//
|
||||
// Sub-loggers let you chain loggers with additional context:
|
||||
//
|
||||
// sublogger := log.With().Str("component": "foo").Logger()
|
||||
// sublogger.Info().Msg("hello world")
|
||||
// // Output: {"time":1494567715,"level":"info","message":"hello world","component":"foo"}
|
||||
//
|
||||
// Level logging
|
||||
//
|
||||
// zerolog.SetGlobalLevel(zerolog.InfoLevel)
|
||||
//
|
||||
// log.Debug().Msg("filtered out message")
|
||||
// log.Info().Msg("routed message")
|
||||
//
|
||||
// if e := log.Debug(); e.Enabled() {
|
||||
// // Compute log output only if enabled.
|
||||
// value := compute()
|
||||
// e.Str("foo": value).Msg("some debug message")
|
||||
// }
|
||||
// // Output: {"level":"info","time":1494567715,"routed message"}
|
||||
//
|
||||
// Customize automatic field names:
|
||||
//
|
||||
// log.TimestampFieldName = "t"
|
||||
// log.LevelFieldName = "p"
|
||||
// log.MessageFieldName = "m"
|
||||
//
|
||||
// log.Info().Msg("hello world")
|
||||
// // Output: {"t":1494567715,"p":"info","m":"hello world"}
|
||||
//
|
||||
// Log with no level and message:
|
||||
//
|
||||
// log.Log().Str("foo","bar").Msg("")
|
||||
// // Output: {"time":1494567715,"foo":"bar"}
|
||||
//
|
||||
// Add contextual fields to global Logger:
|
||||
//
|
||||
// log.Logger = log.With().Str("foo", "bar").Logger()
|
||||
//
|
||||
// Sample logs:
|
||||
//
|
||||
// sampled := log.Sample(&zerolog.BasicSampler{N: 10})
|
||||
// sampled.Info().Msg("will be logged every 10 messages")
|
||||
//
|
||||
// Log with contextual hooks:
|
||||
//
|
||||
// // Create the hook:
|
||||
// type SeverityHook struct{}
|
||||
//
|
||||
// func (h SeverityHook) Run(e *zerolog.Event, level zerolog.Level, msg string) {
|
||||
// if level != zerolog.NoLevel {
|
||||
// e.Str("severity", level.String())
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // And use it:
|
||||
// var h SeverityHook
|
||||
// log := zerolog.New(os.Stdout).Hook(h)
|
||||
// log.Warn().Msg("")
|
||||
// // Output: {"level":"warn","severity":"warn"}
|
||||
//
|
||||
//
|
||||
// Caveats
|
||||
//
|
||||
// There is no fields deduplication out-of-the-box.
|
||||
// Using the same key multiple times creates new key in final JSON each time.
|
||||
//
|
||||
// logger := zerolog.New(os.Stderr).With().Timestamp().Logger()
|
||||
// logger.Info().
|
||||
// Timestamp().
|
||||
// Msg("dup")
|
||||
// // Output: {"level":"info","time":1494567715,"time":1494567715,"message":"dup"}
|
||||
//
|
||||
// However, it’s not a big deal though as JSON accepts dup keys,
|
||||
// the last one prevails.
|
||||
package zerolog
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// Level defines log levels.
|
||||
type Level uint8
|
||||
|
||||
const (
|
||||
// DebugLevel defines debug log level.
|
||||
DebugLevel Level = iota
|
||||
// InfoLevel defines info log level.
|
||||
InfoLevel
|
||||
// WarnLevel defines warn log level.
|
||||
WarnLevel
|
||||
// ErrorLevel defines error log level.
|
||||
ErrorLevel
|
||||
// FatalLevel defines fatal log level.
|
||||
FatalLevel
|
||||
// PanicLevel defines panic log level.
|
||||
PanicLevel
|
||||
// NoLevel defines an absent log level.
|
||||
NoLevel
|
||||
// Disabled disables the logger.
|
||||
Disabled
|
||||
)
|
||||
|
||||
func (l Level) String() string {
|
||||
switch l {
|
||||
case DebugLevel:
|
||||
return "debug"
|
||||
case InfoLevel:
|
||||
return "info"
|
||||
case WarnLevel:
|
||||
return "warn"
|
||||
case ErrorLevel:
|
||||
return "error"
|
||||
case FatalLevel:
|
||||
return "fatal"
|
||||
case PanicLevel:
|
||||
return "panic"
|
||||
case NoLevel:
|
||||
return ""
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// A Logger represents an active logging object that generates lines
|
||||
// of JSON output to an io.Writer. Each logging operation makes a single
|
||||
// call to the Writer's Write method. There is no guaranty on access
|
||||
// serialization to the Writer. If your Writer is not thread safe,
|
||||
// you may consider a sync wrapper.
|
||||
type Logger struct {
|
||||
w LevelWriter
|
||||
level Level
|
||||
sampler Sampler
|
||||
context []byte
|
||||
hooks []Hook
|
||||
}
|
||||
|
||||
// New creates a root logger with given output writer. If the output writer implements
|
||||
// the LevelWriter interface, the WriteLevel method will be called instead of the Write
|
||||
// one.
|
||||
//
|
||||
// Each logging operation makes a single call to the Writer's Write method. There is no
|
||||
// guaranty on access serialization to the Writer. If your Writer is not thread safe,
|
||||
// you may consider using sync wrapper.
|
||||
func New(w io.Writer) Logger {
|
||||
if w == nil {
|
||||
w = ioutil.Discard
|
||||
}
|
||||
lw, ok := w.(LevelWriter)
|
||||
if !ok {
|
||||
lw = levelWriterAdapter{w}
|
||||
}
|
||||
return Logger{w: lw}
|
||||
}
|
||||
|
||||
// Nop returns a disabled logger for which all operation are no-op.
|
||||
func Nop() Logger {
|
||||
return New(nil).Level(Disabled)
|
||||
}
|
||||
|
||||
// Output duplicates the current logger and sets w as its output.
|
||||
func (l Logger) Output(w io.Writer) Logger {
|
||||
l2 := New(w)
|
||||
l2.level = l.level
|
||||
l2.sampler = l.sampler
|
||||
if len(l.hooks) > 0 {
|
||||
l2.hooks = append(l2.hooks, l.hooks...)
|
||||
}
|
||||
if l.context != nil {
|
||||
l2.context = make([]byte, len(l.context), cap(l.context))
|
||||
copy(l2.context, l.context)
|
||||
}
|
||||
return l2
|
||||
}
|
||||
|
||||
// With creates a child logger with the field added to its context.
|
||||
func (l Logger) With() Context {
|
||||
context := l.context
|
||||
l.context = make([]byte, 0, 500)
|
||||
if context != nil {
|
||||
l.context = append(l.context, context...)
|
||||
}
|
||||
return Context{l}
|
||||
}
|
||||
|
||||
// UpdateContext updates the internal logger's context.
|
||||
//
|
||||
// Use this method with caution. If unsure, prefer the With method.
|
||||
func (l *Logger) UpdateContext(update func(c Context) Context) {
|
||||
if l == disabledLogger {
|
||||
return
|
||||
}
|
||||
if cap(l.context) == 0 {
|
||||
l.context = make([]byte, 0, 500)
|
||||
}
|
||||
c := update(Context{*l})
|
||||
l.context = c.l.context
|
||||
}
|
||||
|
||||
// Level creates a child logger with the minimum accepted level set to level.
|
||||
func (l Logger) Level(lvl Level) Logger {
|
||||
l.level = lvl
|
||||
return l
|
||||
}
|
||||
|
||||
// Sample returns a logger with the s sampler.
|
||||
func (l Logger) Sample(s Sampler) Logger {
|
||||
l.sampler = s
|
||||
return l
|
||||
}
|
||||
|
||||
// Hook returns a logger with the h Hook.
|
||||
func (l Logger) Hook(h Hook) Logger {
|
||||
l.hooks = append(l.hooks, h)
|
||||
return l
|
||||
}
|
||||
|
||||
// Debug starts a new message with debug level.
|
||||
//
|
||||
// You must call Msg on the returned event in order to send the event.
|
||||
func (l *Logger) Debug() *Event {
|
||||
return l.newEvent(DebugLevel, nil)
|
||||
}
|
||||
|
||||
// Info starts a new message with info level.
|
||||
//
|
||||
// You must call Msg on the returned event in order to send the event.
|
||||
func (l *Logger) Info() *Event {
|
||||
return l.newEvent(InfoLevel, nil)
|
||||
}
|
||||
|
||||
// Warn starts a new message with warn level.
|
||||
//
|
||||
// You must call Msg on the returned event in order to send the event.
|
||||
func (l *Logger) Warn() *Event {
|
||||
return l.newEvent(WarnLevel, nil)
|
||||
}
|
||||
|
||||
// Error starts a new message with error level.
|
||||
//
|
||||
// You must call Msg on the returned event in order to send the event.
|
||||
func (l *Logger) Error() *Event {
|
||||
return l.newEvent(ErrorLevel, nil)
|
||||
}
|
||||
|
||||
// Fatal starts a new message with fatal level. The os.Exit(1) function
|
||||
// is called by the Msg method.
|
||||
//
|
||||
// You must call Msg on the returned event in order to send the event.
|
||||
func (l *Logger) Fatal() *Event {
|
||||
return l.newEvent(FatalLevel, func(msg string) { os.Exit(1) })
|
||||
}
|
||||
|
||||
// Panic starts a new message with panic level. The message is also sent
|
||||
// to the panic function.
|
||||
//
|
||||
// You must call Msg on the returned event in order to send the event.
|
||||
func (l *Logger) Panic() *Event {
|
||||
return l.newEvent(PanicLevel, func(msg string) { panic(msg) })
|
||||
}
|
||||
|
||||
// WithLevel starts a new message with level.
|
||||
//
|
||||
// You must call Msg on the returned event in order to send the event.
|
||||
func (l *Logger) WithLevel(level Level) *Event {
|
||||
switch level {
|
||||
case DebugLevel:
|
||||
return l.Debug()
|
||||
case InfoLevel:
|
||||
return l.Info()
|
||||
case WarnLevel:
|
||||
return l.Warn()
|
||||
case ErrorLevel:
|
||||
return l.Error()
|
||||
case FatalLevel:
|
||||
return l.Fatal()
|
||||
case PanicLevel:
|
||||
return l.Panic()
|
||||
case NoLevel:
|
||||
return l.Log()
|
||||
case Disabled:
|
||||
return nil
|
||||
default:
|
||||
panic("zerolog: WithLevel(): invalid level: " + strconv.Itoa(int(level)))
|
||||
}
|
||||
}
|
||||
|
||||
// Log starts a new message with no level. Setting GlobalLevel to Disabled
|
||||
// will still disable events produced by this method.
|
||||
//
|
||||
// You must call Msg on the returned event in order to send the event.
|
||||
func (l *Logger) Log() *Event {
|
||||
return l.newEvent(NoLevel, nil)
|
||||
}
|
||||
|
||||
// Print sends a log event using debug level and no extra field.
|
||||
// Arguments are handled in the manner of fmt.Print.
|
||||
func (l *Logger) Print(v ...interface{}) {
|
||||
if e := l.Debug(); e.Enabled() {
|
||||
e.Msg(fmt.Sprint(v...))
|
||||
}
|
||||
}
|
||||
|
||||
// Printf sends a log event using debug level and no extra field.
|
||||
// Arguments are handled in the manner of fmt.Printf.
|
||||
func (l *Logger) Printf(format string, v ...interface{}) {
|
||||
if e := l.Debug(); e.Enabled() {
|
||||
e.Msg(fmt.Sprintf(format, v...))
|
||||
}
|
||||
}
|
||||
|
||||
// Write implements the io.Writer interface. This is useful to set as a writer
|
||||
// for the standard library log.
|
||||
func (l Logger) Write(p []byte) (n int, err error) {
|
||||
n = len(p)
|
||||
if n > 0 && p[n-1] == '\n' {
|
||||
// Trim CR added by stdlog.
|
||||
p = p[0 : n-1]
|
||||
}
|
||||
l.Log().Msg(string(p))
|
||||
return
|
||||
}
|
||||
|
||||
func (l *Logger) newEvent(level Level, done func(string)) *Event {
|
||||
enabled := l.should(level)
|
||||
if !enabled {
|
||||
return nil
|
||||
}
|
||||
e := newEvent(l.w, level, true)
|
||||
e.done = done
|
||||
e.ch = l.hooks
|
||||
if level != NoLevel {
|
||||
e.Str(LevelFieldName, level.String())
|
||||
}
|
||||
if l.context != nil && len(l.context) > 0 {
|
||||
e.buf = appendObjectData(e.buf, l.context)
|
||||
}
|
||||
return e
|
||||
}
|
||||
|
||||
// should returns true if the log event should be logged.
|
||||
func (l *Logger) should(lvl Level) bool {
|
||||
if lvl < l.level || lvl < globalLevel() {
|
||||
return false
|
||||
}
|
||||
if l.sampler != nil && !samplingDisabled() {
|
||||
return l.sampler.Sample(lvl)
|
||||
}
|
||||
return true
|
||||
}
|
BIN
vendor/github.com/rs/zerolog/pretty.png
generated
vendored
Normal file
BIN
vendor/github.com/rs/zerolog/pretty.png
generated
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 377 KiB |
126
vendor/github.com/rs/zerolog/sampler.go
generated
vendored
Normal file
126
vendor/github.com/rs/zerolog/sampler.go
generated
vendored
Normal file
@@ -0,0 +1,126 @@
|
||||
package zerolog
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
// Often samples log every ~ 10 events.
|
||||
Often = RandomSampler(10)
|
||||
// Sometimes samples log every ~ 100 events.
|
||||
Sometimes = RandomSampler(100)
|
||||
// Rarely samples log every ~ 1000 events.
|
||||
Rarely = RandomSampler(1000)
|
||||
)
|
||||
|
||||
// Sampler defines an interface to a log sampler.
|
||||
type Sampler interface {
|
||||
// Sample returns true if the event should be part of the sample, false if
|
||||
// the event should be dropped.
|
||||
Sample(lvl Level) bool
|
||||
}
|
||||
|
||||
// RandomSampler use a PRNG to randomly sample an event out of N events,
|
||||
// regardless of their level.
|
||||
type RandomSampler uint32
|
||||
|
||||
// Sample implements the Sampler interface.
|
||||
func (s RandomSampler) Sample(lvl Level) bool {
|
||||
if s <= 0 {
|
||||
return false
|
||||
}
|
||||
if rand.Intn(int(s)) != 0 {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// BasicSampler is a sampler that will send every Nth events, regardless of
|
||||
// there level.
|
||||
type BasicSampler struct {
|
||||
N uint32
|
||||
counter uint32
|
||||
}
|
||||
|
||||
// Sample implements the Sampler interface.
|
||||
func (s *BasicSampler) Sample(lvl Level) bool {
|
||||
c := atomic.AddUint32(&s.counter, 1)
|
||||
return c%s.N == 0
|
||||
}
|
||||
|
||||
// BurstSampler lets Burst events pass per Period then pass the decision to
|
||||
// NextSampler. If Sampler is not set, all subsequent events are rejected.
|
||||
type BurstSampler struct {
|
||||
// Burst is the maximum number of event per period allowed before calling
|
||||
// NextSampler.
|
||||
Burst uint32
|
||||
// Period defines the burst period. If 0, NextSampler is always called.
|
||||
Period time.Duration
|
||||
// NextSampler is the sampler used after the burst is reached. If nil,
|
||||
// events are always rejected after the burst.
|
||||
NextSampler Sampler
|
||||
|
||||
counter uint32
|
||||
resetAt int64
|
||||
}
|
||||
|
||||
// Sample implements the Sampler interface.
|
||||
func (s *BurstSampler) Sample(lvl Level) bool {
|
||||
if s.Burst > 0 && s.Period > 0 {
|
||||
if s.inc() <= s.Burst {
|
||||
return true
|
||||
}
|
||||
}
|
||||
if s.NextSampler == nil {
|
||||
return false
|
||||
}
|
||||
return s.NextSampler.Sample(lvl)
|
||||
}
|
||||
|
||||
func (s *BurstSampler) inc() uint32 {
|
||||
now := time.Now().UnixNano()
|
||||
resetAt := atomic.LoadInt64(&s.resetAt)
|
||||
var c uint32
|
||||
if now > resetAt {
|
||||
c = 1
|
||||
atomic.StoreUint32(&s.counter, c)
|
||||
newResetAt := now + s.Period.Nanoseconds()
|
||||
reset := atomic.CompareAndSwapInt64(&s.resetAt, resetAt, newResetAt)
|
||||
if !reset {
|
||||
// Lost the race with another goroutine trying to reset.
|
||||
c = atomic.AddUint32(&s.counter, 1)
|
||||
}
|
||||
} else {
|
||||
c = atomic.AddUint32(&s.counter, 1)
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
// LevelSampler applies a different sampler for each level.
|
||||
type LevelSampler struct {
|
||||
DebugSampler, InfoSampler, WarnSampler, ErrorSampler Sampler
|
||||
}
|
||||
|
||||
func (s LevelSampler) Sample(lvl Level) bool {
|
||||
switch lvl {
|
||||
case DebugLevel:
|
||||
if s.DebugSampler != nil {
|
||||
return s.DebugSampler.Sample(lvl)
|
||||
}
|
||||
case InfoLevel:
|
||||
if s.InfoSampler != nil {
|
||||
return s.InfoSampler.Sample(lvl)
|
||||
}
|
||||
case WarnLevel:
|
||||
if s.WarnSampler != nil {
|
||||
return s.WarnSampler.Sample(lvl)
|
||||
}
|
||||
case ErrorLevel:
|
||||
if s.ErrorSampler != nil {
|
||||
return s.ErrorSampler.Sample(lvl)
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
57
vendor/github.com/rs/zerolog/syslog.go
generated
vendored
Normal file
57
vendor/github.com/rs/zerolog/syslog.go
generated
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
// +build !windows
|
||||
// +build !binary_log
|
||||
|
||||
package zerolog
|
||||
|
||||
import (
|
||||
"io"
|
||||
)
|
||||
|
||||
// SyslogWriter is an interface matching a syslog.Writer struct.
|
||||
type SyslogWriter interface {
|
||||
io.Writer
|
||||
Debug(m string) error
|
||||
Info(m string) error
|
||||
Warning(m string) error
|
||||
Err(m string) error
|
||||
Emerg(m string) error
|
||||
Crit(m string) error
|
||||
}
|
||||
|
||||
type syslogWriter struct {
|
||||
w SyslogWriter
|
||||
}
|
||||
|
||||
// SyslogLevelWriter wraps a SyslogWriter and call the right syslog level
|
||||
// method matching the zerolog level.
|
||||
func SyslogLevelWriter(w SyslogWriter) LevelWriter {
|
||||
return syslogWriter{w}
|
||||
}
|
||||
|
||||
func (sw syslogWriter) Write(p []byte) (n int, err error) {
|
||||
return sw.w.Write(p)
|
||||
}
|
||||
|
||||
// WriteLevel implements LevelWriter interface.
|
||||
func (sw syslogWriter) WriteLevel(level Level, p []byte) (n int, err error) {
|
||||
switch level {
|
||||
case DebugLevel:
|
||||
err = sw.w.Debug(string(p))
|
||||
case InfoLevel:
|
||||
err = sw.w.Info(string(p))
|
||||
case WarnLevel:
|
||||
err = sw.w.Warning(string(p))
|
||||
case ErrorLevel:
|
||||
err = sw.w.Err(string(p))
|
||||
case FatalLevel:
|
||||
err = sw.w.Emerg(string(p))
|
||||
case PanicLevel:
|
||||
err = sw.w.Crit(string(p))
|
||||
case NoLevel:
|
||||
err = sw.w.Info(string(p))
|
||||
default:
|
||||
panic("invalid level")
|
||||
}
|
||||
n = len(p)
|
||||
return
|
||||
}
|
100
vendor/github.com/rs/zerolog/writer.go
generated
vendored
Normal file
100
vendor/github.com/rs/zerolog/writer.go
generated
vendored
Normal file
@@ -0,0 +1,100 @@
|
||||
package zerolog
|
||||
|
||||
import (
|
||||
"io"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// LevelWriter defines as interface a writer may implement in order
|
||||
// to receive level information with payload.
|
||||
type LevelWriter interface {
|
||||
io.Writer
|
||||
WriteLevel(level Level, p []byte) (n int, err error)
|
||||
}
|
||||
|
||||
type levelWriterAdapter struct {
|
||||
io.Writer
|
||||
}
|
||||
|
||||
func (lw levelWriterAdapter) WriteLevel(l Level, p []byte) (n int, err error) {
|
||||
return lw.Write(p)
|
||||
}
|
||||
|
||||
type syncWriter struct {
|
||||
mu sync.Mutex
|
||||
lw LevelWriter
|
||||
}
|
||||
|
||||
// SyncWriter wraps w so that each call to Write is synchronized with a mutex.
|
||||
// This syncer can be the call to writer's Write method is not thread safe.
|
||||
// Note that os.File Write operation is using write() syscall which is supposed
|
||||
// to be thread-safe on POSIX systems. So there is no need to use this with
|
||||
// os.File on such systems as zerolog guaranties to issue a single Write call
|
||||
// per log event.
|
||||
func SyncWriter(w io.Writer) io.Writer {
|
||||
if lw, ok := w.(LevelWriter); ok {
|
||||
return &syncWriter{lw: lw}
|
||||
}
|
||||
return &syncWriter{lw: levelWriterAdapter{w}}
|
||||
}
|
||||
|
||||
// Write implements the io.Writer interface.
|
||||
func (s *syncWriter) Write(p []byte) (n int, err error) {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
return s.lw.Write(p)
|
||||
}
|
||||
|
||||
// WriteLevel implements the LevelWriter interface.
|
||||
func (s *syncWriter) WriteLevel(l Level, p []byte) (n int, err error) {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
return s.lw.WriteLevel(l, p)
|
||||
}
|
||||
|
||||
type multiLevelWriter struct {
|
||||
writers []LevelWriter
|
||||
}
|
||||
|
||||
func (t multiLevelWriter) Write(p []byte) (n int, err error) {
|
||||
for _, w := range t.writers {
|
||||
n, err = w.Write(p)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if n != len(p) {
|
||||
err = io.ErrShortWrite
|
||||
return
|
||||
}
|
||||
}
|
||||
return len(p), nil
|
||||
}
|
||||
|
||||
func (t multiLevelWriter) WriteLevel(l Level, p []byte) (n int, err error) {
|
||||
for _, w := range t.writers {
|
||||
n, err = w.WriteLevel(l, p)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if n != len(p) {
|
||||
err = io.ErrShortWrite
|
||||
return
|
||||
}
|
||||
}
|
||||
return len(p), nil
|
||||
}
|
||||
|
||||
// MultiLevelWriter creates a writer that duplicates its writes to all the
|
||||
// provided writers, similar to the Unix tee(1) command. If some writers
|
||||
// implement LevelWriter, their WriteLevel method will be used instead of Write.
|
||||
func MultiLevelWriter(writers ...io.Writer) LevelWriter {
|
||||
lwriters := make([]LevelWriter, 0, len(writers))
|
||||
for _, w := range writers {
|
||||
if lw, ok := w.(LevelWriter); ok {
|
||||
lwriters = append(lwriters, lw)
|
||||
} else {
|
||||
lwriters = append(lwriters, levelWriterAdapter{w})
|
||||
}
|
||||
}
|
||||
return multiLevelWriter{lwriters}
|
||||
}
|
Reference in New Issue
Block a user