mirror of
https://github.com/rs/zerolog
synced 2026-06-08 17:13:30 +00:00
Compare commits
16 Commits
v1.3.0
...
binary_flag
| Author | SHA1 | Date | |
|---|---|---|---|
| a6bc163a87 | |||
| 9a92fd2536 | |||
| 7d8f9e5cf0 | |||
| 8eb285b62b | |||
| 27e0a22cbc | |||
| fcbdf23e9e | |||
| cbec2377ee | |||
| b53826c57a | |||
| 1cc67e6325 | |||
| c2fc1c63dc | |||
| c3d02683c7 | |||
| 1251b38a89 | |||
| c8e50a6043 | |||
| 9a65e7ccd2 | |||
| 89e128fdc1 | |||
| 9d194eb6f5 |
@@ -2,6 +2,7 @@ language: go
|
||||
go:
|
||||
- 1.7
|
||||
- 1.8
|
||||
- 1.9
|
||||
- tip
|
||||
matrix:
|
||||
allow_failures:
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
|
||||
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](#performance). Its unique chaining API allows zerolog to write JSON log events by avoiding allocations and reflection.
|
||||
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 log events by avoiding allocations and reflection.
|
||||
|
||||
The uber's [zap](https://godoc.org/go.uber.org/zap) library pioneered this approach. Zerolog is taking this concept to the next level with simpler to use API and even better performance.
|
||||
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 JSON logging only. Pretty logging on the console is made possible using the provided (but inefficient) `zerolog.ConsoleWriter`.
|
||||
|
||||
@@ -18,48 +18,150 @@ To keep the code base and the API simple, zerolog focuses on JSON logging only.
|
||||
* Low to zero allocation
|
||||
* Level logging
|
||||
* Sampling
|
||||
* Hooks
|
||||
* Contextual fields
|
||||
* `context.Context` integration
|
||||
* `net/http` helpers
|
||||
* Pretty logging for development
|
||||
|
||||
## Usage
|
||||
## 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
|
||||
import "github.com/rs/zerolog/log"
|
||||
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"}
|
||||
```
|
||||
|
||||
### A global logger can be use for simple logging
|
||||
**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
|
||||
log.Print("hello world")
|
||||
package main
|
||||
|
||||
// Output: {"level":"debug","time":1494567715,"message":"hello world"}
|
||||
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
|
||||
log.Info().Msg("hello world")
|
||||
package main
|
||||
|
||||
// Output: {"level":"info","time":1494567715,"message":"hello world"}
|
||||
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
|
||||
|
||||
NOTE: To import the global logger, import the `log` subpackage `github.com/rs/zerolog/log`.
|
||||
|
||||
```go
|
||||
log.Fatal().
|
||||
Err(err).
|
||||
Str("service", service).
|
||||
Msgf("Cannot start %s", service)
|
||||
|
||||
// Output: {"level":"fatal","time":1494567715,"message":"Cannot start myservice","error":"some error","service":"myservice"}
|
||||
// Exit 1
|
||||
```
|
||||
|
||||
NOTE: Using `Msgf` generates one allocation even when the logger is disabled.
|
||||
|
||||
### Fields can be added to log messages
|
||||
|
||||
#### Fields can be added to log messages
|
||||
```go
|
||||
log.Info().
|
||||
Str("foo", "bar").
|
||||
@@ -90,22 +192,7 @@ sublogger.Info().Msg("hello world")
|
||||
// Output: {"level":"info","time":1494567715,"message":"hello world","component":"foo"}
|
||||
```
|
||||
|
||||
### Level logging
|
||||
|
||||
```go
|
||||
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,"message":"routed message"}
|
||||
```
|
||||
|
||||
### Pretty logging
|
||||
|
||||
@@ -185,6 +272,22 @@ 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
|
||||
|
||||
@@ -358,4 +461,3 @@ Log a static string, without any context or `printf`-style templating:
|
||||
| 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 |
|
||||
|
||||
|
||||
@@ -3,8 +3,6 @@ package zerolog
|
||||
import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/rs/zerolog/internal/json"
|
||||
)
|
||||
|
||||
var arrayPool = &sync.Pool{
|
||||
@@ -53,109 +51,109 @@ func (a *Array) Object(obj LogObjectMarshaler) *Array {
|
||||
|
||||
// Str append the val as a string to the array.
|
||||
func (a *Array) Str(val string) *Array {
|
||||
a.buf = json.AppendString(append(a.buf, ','), val)
|
||||
a.buf = appendString(append(a.buf, ','), val)
|
||||
return a
|
||||
}
|
||||
|
||||
// Bytes append the val as a string to the array.
|
||||
func (a *Array) Bytes(val []byte) *Array {
|
||||
a.buf = json.AppendBytes(append(a.buf, ','), val)
|
||||
a.buf = appendBytes(append(a.buf, ','), val)
|
||||
return a
|
||||
}
|
||||
|
||||
// Err append the err as a string to the array.
|
||||
func (a *Array) Err(err error) *Array {
|
||||
a.buf = json.AppendError(append(a.buf, ','), err)
|
||||
a.buf = appendError(append(a.buf, ','), err)
|
||||
return a
|
||||
}
|
||||
|
||||
// Bool append the val as a bool to the array.
|
||||
func (a *Array) Bool(b bool) *Array {
|
||||
a.buf = json.AppendBool(append(a.buf, ','), b)
|
||||
a.buf = appendBool(append(a.buf, ','), b)
|
||||
return a
|
||||
}
|
||||
|
||||
// Int append i as a int to the array.
|
||||
func (a *Array) Int(i int) *Array {
|
||||
a.buf = json.AppendInt(append(a.buf, ','), i)
|
||||
a.buf = appendInt(append(a.buf, ','), i)
|
||||
return a
|
||||
}
|
||||
|
||||
// Int8 append i as a int8 to the array.
|
||||
func (a *Array) Int8(i int8) *Array {
|
||||
a.buf = json.AppendInt8(append(a.buf, ','), i)
|
||||
a.buf = appendInt8(append(a.buf, ','), i)
|
||||
return a
|
||||
}
|
||||
|
||||
// Int16 append i as a int16 to the array.
|
||||
func (a *Array) Int16(i int16) *Array {
|
||||
a.buf = json.AppendInt16(append(a.buf, ','), i)
|
||||
a.buf = appendInt16(append(a.buf, ','), i)
|
||||
return a
|
||||
}
|
||||
|
||||
// Int32 append i as a int32 to the array.
|
||||
func (a *Array) Int32(i int32) *Array {
|
||||
a.buf = json.AppendInt32(append(a.buf, ','), i)
|
||||
a.buf = appendInt32(append(a.buf, ','), i)
|
||||
return a
|
||||
}
|
||||
|
||||
// Int64 append i as a int64 to the array.
|
||||
func (a *Array) Int64(i int64) *Array {
|
||||
a.buf = json.AppendInt64(append(a.buf, ','), i)
|
||||
a.buf = appendInt64(append(a.buf, ','), i)
|
||||
return a
|
||||
}
|
||||
|
||||
// Uint append i as a uint to the array.
|
||||
func (a *Array) Uint(i uint) *Array {
|
||||
a.buf = json.AppendUint(append(a.buf, ','), i)
|
||||
a.buf = appendUint(append(a.buf, ','), i)
|
||||
return a
|
||||
}
|
||||
|
||||
// Uint8 append i as a uint8 to the array.
|
||||
func (a *Array) Uint8(i uint8) *Array {
|
||||
a.buf = json.AppendUint8(append(a.buf, ','), i)
|
||||
a.buf = appendUint8(append(a.buf, ','), i)
|
||||
return a
|
||||
}
|
||||
|
||||
// Uint16 append i as a uint16 to the array.
|
||||
func (a *Array) Uint16(i uint16) *Array {
|
||||
a.buf = json.AppendUint16(append(a.buf, ','), i)
|
||||
a.buf = appendUint16(append(a.buf, ','), i)
|
||||
return a
|
||||
}
|
||||
|
||||
// Uint32 append i as a uint32 to the array.
|
||||
func (a *Array) Uint32(i uint32) *Array {
|
||||
a.buf = json.AppendUint32(append(a.buf, ','), i)
|
||||
a.buf = appendUint32(append(a.buf, ','), i)
|
||||
return a
|
||||
}
|
||||
|
||||
// Uint64 append i as a uint64 to the array.
|
||||
func (a *Array) Uint64(i uint64) *Array {
|
||||
a.buf = json.AppendUint64(append(a.buf, ','), i)
|
||||
a.buf = appendUint64(append(a.buf, ','), i)
|
||||
return a
|
||||
}
|
||||
|
||||
// Float32 append f as a float32 to the array.
|
||||
func (a *Array) Float32(f float32) *Array {
|
||||
a.buf = json.AppendFloat32(append(a.buf, ','), f)
|
||||
a.buf = appendFloat32(append(a.buf, ','), f)
|
||||
return a
|
||||
}
|
||||
|
||||
// Float64 append f as a float64 to the array.
|
||||
func (a *Array) Float64(f float64) *Array {
|
||||
a.buf = json.AppendFloat64(append(a.buf, ','), f)
|
||||
a.buf = appendFloat64(append(a.buf, ','), f)
|
||||
return a
|
||||
}
|
||||
|
||||
// Time append t formated as string using zerolog.TimeFieldFormat.
|
||||
func (a *Array) Time(t time.Time) *Array {
|
||||
a.buf = json.AppendTime(append(a.buf, ','), t, TimeFieldFormat)
|
||||
a.buf = appendTime(append(a.buf, ','), t, TimeFieldFormat)
|
||||
return a
|
||||
}
|
||||
|
||||
// Dur append d to the array.
|
||||
func (a *Array) Dur(d time.Duration) *Array {
|
||||
a.buf = json.AppendDuration(append(a.buf, ','), d, DurationFieldUnit, DurationFieldInteger)
|
||||
a.buf = appendDuration(append(a.buf, ','), d, DurationFieldUnit, DurationFieldInteger)
|
||||
return a
|
||||
}
|
||||
|
||||
@@ -164,6 +162,6 @@ func (a *Array) Interface(i interface{}) *Array {
|
||||
if obj, ok := i.(LogObjectMarshaler); ok {
|
||||
return a.Object(obj)
|
||||
}
|
||||
a.buf = json.AppendInterface(append(a.buf, ','), i)
|
||||
a.buf = appendInterface(append(a.buf, ','), i)
|
||||
return a
|
||||
}
|
||||
|
||||
@@ -215,3 +215,130 @@ func BenchmarkLogFieldType(b *testing.B) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkContextFieldType(b *testing.B) {
|
||||
oldFormat := TimeFieldFormat
|
||||
TimeFieldFormat = ""
|
||||
defer func() { TimeFieldFormat = oldFormat }()
|
||||
bools := []bool{true, false, true, false, true, false, true, false, true, false}
|
||||
ints := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
|
||||
floats := []float64{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
|
||||
strings := []string{"a", "b", "c", "d", "e", "f", "g", "h", "i", "j"}
|
||||
durations := []time.Duration{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
|
||||
times := []time.Time{
|
||||
time.Unix(0, 0),
|
||||
time.Unix(1, 0),
|
||||
time.Unix(2, 0),
|
||||
time.Unix(3, 0),
|
||||
time.Unix(4, 0),
|
||||
time.Unix(5, 0),
|
||||
time.Unix(6, 0),
|
||||
time.Unix(7, 0),
|
||||
time.Unix(8, 0),
|
||||
time.Unix(9, 0),
|
||||
}
|
||||
interfaces := []struct {
|
||||
Pub string
|
||||
Tag string `json:"tag"`
|
||||
priv int
|
||||
}{
|
||||
{"a", "a", 0},
|
||||
{"a", "a", 0},
|
||||
{"a", "a", 0},
|
||||
{"a", "a", 0},
|
||||
{"a", "a", 0},
|
||||
{"a", "a", 0},
|
||||
{"a", "a", 0},
|
||||
{"a", "a", 0},
|
||||
{"a", "a", 0},
|
||||
{"a", "a", 0},
|
||||
}
|
||||
objects := []obj{
|
||||
obj{"a", "a", 0},
|
||||
obj{"a", "a", 0},
|
||||
obj{"a", "a", 0},
|
||||
obj{"a", "a", 0},
|
||||
obj{"a", "a", 0},
|
||||
obj{"a", "a", 0},
|
||||
obj{"a", "a", 0},
|
||||
obj{"a", "a", 0},
|
||||
obj{"a", "a", 0},
|
||||
obj{"a", "a", 0},
|
||||
}
|
||||
errs := []error{errors.New("a"), errors.New("b"), errors.New("c"), errors.New("d"), errors.New("e")}
|
||||
types := map[string]func(c Context) Context{
|
||||
"Bool": func(c Context) Context {
|
||||
return c.Bool("k", bools[0])
|
||||
},
|
||||
"Bools": func(c Context) Context {
|
||||
return c.Bools("k", bools)
|
||||
},
|
||||
"Int": func(c Context) Context {
|
||||
return c.Int("k", ints[0])
|
||||
},
|
||||
"Ints": func(c Context) Context {
|
||||
return c.Ints("k", ints)
|
||||
},
|
||||
"Float": func(c Context) Context {
|
||||
return c.Float64("k", floats[0])
|
||||
},
|
||||
"Floats": func(c Context) Context {
|
||||
return c.Floats64("k", floats)
|
||||
},
|
||||
"Str": func(c Context) Context {
|
||||
return c.Str("k", strings[0])
|
||||
},
|
||||
"Strs": func(c Context) Context {
|
||||
return c.Strs("k", strings)
|
||||
},
|
||||
"Err": func(c Context) Context {
|
||||
return c.Err(errs[0])
|
||||
},
|
||||
"Errs": func(c Context) Context {
|
||||
return c.Errs("k", errs)
|
||||
},
|
||||
"Time": func(c Context) Context {
|
||||
return c.Time("k", times[0])
|
||||
},
|
||||
"Times": func(c Context) Context {
|
||||
return c.Times("k", times)
|
||||
},
|
||||
"Dur": func(c Context) Context {
|
||||
return c.Dur("k", durations[0])
|
||||
},
|
||||
"Durs": func(c Context) Context {
|
||||
return c.Durs("k", durations)
|
||||
},
|
||||
"Interface": func(c Context) Context {
|
||||
return c.Interface("k", interfaces[0])
|
||||
},
|
||||
"Interfaces": func(c Context) Context {
|
||||
return c.Interface("k", interfaces)
|
||||
},
|
||||
"Interface(Object)": func(c Context) Context {
|
||||
return c.Interface("k", objects[0])
|
||||
},
|
||||
"Interface(Objects)": func(c Context) Context {
|
||||
return c.Interface("k", objects)
|
||||
},
|
||||
"Object": func(c Context) Context {
|
||||
return c.Object("k", objects[0])
|
||||
},
|
||||
"Timestamp": func(c Context) Context {
|
||||
return c.Timestamp()
|
||||
},
|
||||
}
|
||||
logger := New(ioutil.Discard)
|
||||
b.ResetTimer()
|
||||
for name := range types {
|
||||
f := types[name]
|
||||
b.Run(name, func(b *testing.B) {
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
for pb.Next() {
|
||||
l := f(logger.With()).Logger()
|
||||
l.Info().Msg("")
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
+62
-46
@@ -3,8 +3,6 @@ package zerolog
|
||||
import (
|
||||
"io/ioutil"
|
||||
"time"
|
||||
|
||||
"github.com/rs/zerolog/internal/json"
|
||||
)
|
||||
|
||||
// Context configures a new sub-logger with contextual fields.
|
||||
@@ -26,7 +24,7 @@ func (c Context) Fields(fields map[string]interface{}) Context {
|
||||
// Dict adds the field key with the dict to the logger context.
|
||||
func (c Context) Dict(key string, dict *Event) Context {
|
||||
dict.buf = append(dict.buf, '}')
|
||||
c.l.context = append(json.AppendKey(c.l.context, key), dict.buf...)
|
||||
c.l.context = append(appendKey(c.l.context, key), dict.buf...)
|
||||
eventPool.Put(dict)
|
||||
return c
|
||||
}
|
||||
@@ -35,7 +33,7 @@ func (c Context) Dict(key string, dict *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 = json.AppendKey(c.l.context, key)
|
||||
c.l.context = appendKey(c.l.context, key)
|
||||
if arr, ok := arr.(*Array); ok {
|
||||
c.l.context = arr.write(c.l.context)
|
||||
return c
|
||||
@@ -63,33 +61,33 @@ func (c Context) Object(key string, obj LogObjectMarshaler) Context {
|
||||
|
||||
// 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 = json.AppendString(json.AppendKey(c.l.context, key), val)
|
||||
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 = json.AppendStrings(json.AppendKey(c.l.context, key), vals)
|
||||
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 = json.AppendBytes(json.AppendKey(c.l.context, key), val)
|
||||
c.l.context = appendBytes(appendKey(c.l.context, key), val)
|
||||
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 = json.AppendError(json.AppendKey(c.l.context, key), err)
|
||||
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 = json.AppendErrors(json.AppendKey(c.l.context, key), errs)
|
||||
c.l.context = appendErrors(appendKey(c.l.context, key), errs)
|
||||
return c
|
||||
}
|
||||
|
||||
@@ -97,204 +95,222 @@ func (c Context) Errs(key string, errs []error) Context {
|
||||
// To customize the key name, change zerolog.ErrorFieldName.
|
||||
func (c Context) Err(err error) Context {
|
||||
if err != nil {
|
||||
c.l.context = json.AppendError(json.AppendKey(c.l.context, ErrorFieldName), err)
|
||||
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 = json.AppendBool(json.AppendKey(c.l.context, key), b)
|
||||
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 = json.AppendBools(json.AppendKey(c.l.context, key), b)
|
||||
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 = json.AppendInt(json.AppendKey(c.l.context, key), i)
|
||||
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 = json.AppendInts(json.AppendKey(c.l.context, key), i)
|
||||
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 = json.AppendInt8(json.AppendKey(c.l.context, key), i)
|
||||
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 = json.AppendInts8(json.AppendKey(c.l.context, key), i)
|
||||
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 = json.AppendInt16(json.AppendKey(c.l.context, key), i)
|
||||
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 = json.AppendInts16(json.AppendKey(c.l.context, key), i)
|
||||
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 = json.AppendInt32(json.AppendKey(c.l.context, key), i)
|
||||
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 = json.AppendInts32(json.AppendKey(c.l.context, key), i)
|
||||
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 = json.AppendInt64(json.AppendKey(c.l.context, key), i)
|
||||
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 = json.AppendInts64(json.AppendKey(c.l.context, key), i)
|
||||
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 = json.AppendUint(json.AppendKey(c.l.context, key), i)
|
||||
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 = json.AppendUints(json.AppendKey(c.l.context, key), i)
|
||||
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 = json.AppendUint8(json.AppendKey(c.l.context, key), i)
|
||||
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 = json.AppendUints8(json.AppendKey(c.l.context, key), i)
|
||||
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 = json.AppendUint16(json.AppendKey(c.l.context, key), i)
|
||||
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 = json.AppendUints16(json.AppendKey(c.l.context, key), i)
|
||||
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 = json.AppendUint32(json.AppendKey(c.l.context, key), i)
|
||||
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 = json.AppendUints32(json.AppendKey(c.l.context, key), i)
|
||||
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 = json.AppendUint64(json.AppendKey(c.l.context, key), i)
|
||||
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 = json.AppendUints64(json.AppendKey(c.l.context, key), i)
|
||||
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 = json.AppendFloat32(json.AppendKey(c.l.context, key), f)
|
||||
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 = json.AppendFloats32(json.AppendKey(c.l.context, key), f)
|
||||
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 = json.AppendFloat64(json.AppendKey(c.l.context, key), f)
|
||||
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 = json.AppendFloats64(json.AppendKey(c.l.context, key), f)
|
||||
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.
|
||||
func (c Context) Timestamp() Context {
|
||||
if len(c.l.context) > 0 {
|
||||
c.l.context[0] = 1
|
||||
} else {
|
||||
c.l.context = append(c.l.context, 1)
|
||||
}
|
||||
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 = json.AppendTime(json.AppendKey(c.l.context, key), t, TimeFieldFormat)
|
||||
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 = json.AppendTimes(json.AppendKey(c.l.context, key), t, TimeFieldFormat)
|
||||
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 = json.AppendDuration(json.AppendKey(c.l.context, key), d, DurationFieldUnit, DurationFieldInteger)
|
||||
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 = json.AppendDurations(json.AppendKey(c.l.context, key), d, DurationFieldUnit, DurationFieldInteger)
|
||||
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 = json.AppendInterface(json.AppendKey(c.l.context, key), i)
|
||||
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
|
||||
}
|
||||
|
||||
+161
@@ -0,0 +1,161 @@
|
||||
// +build !zerolog_binary
|
||||
|
||||
package zerolog
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/rs/zerolog/internal/json"
|
||||
)
|
||||
|
||||
func appendKey(dst []byte, key string) []byte {
|
||||
return json.AppendKey(dst, key)
|
||||
}
|
||||
|
||||
func appendError(dst []byte, err error) []byte {
|
||||
return json.AppendError(dst, err)
|
||||
}
|
||||
|
||||
func appendErrors(dst []byte, errs []error) []byte {
|
||||
return json.AppendErrors(dst, errs)
|
||||
}
|
||||
|
||||
func appendStrings(dst []byte, vals []string) []byte {
|
||||
return json.AppendStrings(dst, vals)
|
||||
}
|
||||
|
||||
func appendString(dst []byte, s string) []byte {
|
||||
return json.AppendString(dst, s)
|
||||
}
|
||||
|
||||
func appendBytes(dst, b []byte) []byte {
|
||||
return json.AppendBytes(dst, b)
|
||||
}
|
||||
|
||||
func appendTime(dst []byte, t time.Time, format string) []byte {
|
||||
return json.AppendTime(dst, t, format)
|
||||
}
|
||||
|
||||
func appendTimes(dst []byte, vals []time.Time, format string) []byte {
|
||||
return json.AppendTimes(dst, vals, format)
|
||||
}
|
||||
|
||||
func appendDuration(dst []byte, d time.Duration, unit time.Duration, useInt bool) []byte {
|
||||
return json.AppendDuration(dst, d, unit, useInt)
|
||||
}
|
||||
|
||||
func appendDurations(dst []byte, vals []time.Duration, unit time.Duration, useInt bool) []byte {
|
||||
return json.AppendDurations(dst, vals, unit, useInt)
|
||||
}
|
||||
|
||||
func appendBool(dst []byte, val bool) []byte {
|
||||
return json.AppendBool(dst, val)
|
||||
}
|
||||
|
||||
func appendBools(dst []byte, vals []bool) []byte {
|
||||
return json.AppendBools(dst, vals)
|
||||
}
|
||||
|
||||
func appendInt(dst []byte, val int) []byte {
|
||||
return json.AppendInt(dst, val)
|
||||
}
|
||||
|
||||
func appendInts(dst []byte, vals []int) []byte {
|
||||
return json.AppendInts(dst, vals)
|
||||
}
|
||||
|
||||
func appendInt8(dst []byte, val int8) []byte {
|
||||
return json.AppendInt8(dst, val)
|
||||
}
|
||||
|
||||
func appendInts8(dst []byte, vals []int8) []byte {
|
||||
return json.AppendInts8(dst, vals)
|
||||
}
|
||||
|
||||
func appendInt16(dst []byte, val int16) []byte {
|
||||
return json.AppendInt16(dst, val)
|
||||
}
|
||||
|
||||
func appendInts16(dst []byte, vals []int16) []byte {
|
||||
return json.AppendInts16(dst, vals)
|
||||
}
|
||||
|
||||
func appendInt32(dst []byte, val int32) []byte {
|
||||
return json.AppendInt32(dst, val)
|
||||
}
|
||||
|
||||
func appendInts32(dst []byte, vals []int32) []byte {
|
||||
return json.AppendInts32(dst, vals)
|
||||
}
|
||||
|
||||
func appendInt64(dst []byte, val int64) []byte {
|
||||
return json.AppendInt64(dst, val)
|
||||
}
|
||||
|
||||
func appendInts64(dst []byte, vals []int64) []byte {
|
||||
return json.AppendInts64(dst, vals)
|
||||
}
|
||||
|
||||
func appendUint(dst []byte, val uint) []byte {
|
||||
return json.AppendUint(dst, val)
|
||||
}
|
||||
|
||||
func appendUints(dst []byte, vals []uint) []byte {
|
||||
return json.AppendUints(dst, vals)
|
||||
}
|
||||
|
||||
func appendUint8(dst []byte, val uint8) []byte {
|
||||
return json.AppendUint8(dst, val)
|
||||
}
|
||||
|
||||
func appendUints8(dst []byte, vals []uint8) []byte {
|
||||
return json.AppendUints8(dst, vals)
|
||||
}
|
||||
|
||||
func appendUint16(dst []byte, val uint16) []byte {
|
||||
return json.AppendUint16(dst, val)
|
||||
}
|
||||
|
||||
func appendUints16(dst []byte, vals []uint16) []byte {
|
||||
return json.AppendUints16(dst, vals)
|
||||
}
|
||||
|
||||
func appendUint32(dst []byte, val uint32) []byte {
|
||||
return json.AppendUint32(dst, val)
|
||||
}
|
||||
|
||||
func appendUints32(dst []byte, vals []uint32) []byte {
|
||||
return json.AppendUints32(dst, vals)
|
||||
}
|
||||
|
||||
func appendUint64(dst []byte, val uint64) []byte {
|
||||
return json.AppendUint64(dst, val)
|
||||
}
|
||||
|
||||
func appendUints64(dst []byte, vals []uint64) []byte {
|
||||
return json.AppendUints64(dst, vals)
|
||||
}
|
||||
|
||||
func appendFloat(dst []byte, val float64, bitSize int) []byte {
|
||||
return json.AppendFloat(dst, val, bitSize)
|
||||
}
|
||||
|
||||
func appendFloat32(dst []byte, val float32) []byte {
|
||||
return json.AppendFloat32(dst, val)
|
||||
}
|
||||
|
||||
func appendFloats32(dst []byte, vals []float32) []byte {
|
||||
return json.AppendFloats32(dst, vals)
|
||||
}
|
||||
|
||||
func appendFloat64(dst []byte, val float64) []byte {
|
||||
return json.AppendFloat64(dst, val)
|
||||
}
|
||||
|
||||
func appendFloats64(dst []byte, vals []float64) []byte {
|
||||
return json.AppendFloats64(dst, vals)
|
||||
}
|
||||
|
||||
func appendInterface(dst []byte, i interface{}) []byte {
|
||||
return json.AppendInterface(dst, i)
|
||||
}
|
||||
@@ -0,0 +1,161 @@
|
||||
// +build zerolog_binary
|
||||
|
||||
package zerolog
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/rs/zerolog/internal/cbor"
|
||||
)
|
||||
|
||||
func appendKey(dst []byte, key string) []byte {
|
||||
return cbor.AppendKey(dst, key)
|
||||
}
|
||||
|
||||
func appendError(dst []byte, err error) []byte {
|
||||
return cbor.AppendError(dst, err)
|
||||
}
|
||||
|
||||
func appendErrors(dst []byte, errs []error) []byte {
|
||||
return cbor.AppendErrors(dst, errs)
|
||||
}
|
||||
|
||||
func appendStrings(dst []byte, vals []string) []byte {
|
||||
return cbor.AppendStrings(dst, vals)
|
||||
}
|
||||
|
||||
func appendString(dst []byte, s string) []byte {
|
||||
return cbor.AppendString(dst, s)
|
||||
}
|
||||
|
||||
func appendBytes(dst, b []byte) []byte {
|
||||
return cbor.AppendBytes(dst, b)
|
||||
}
|
||||
|
||||
func appendTime(dst []byte, t time.Time, format string) []byte {
|
||||
return cbor.AppendTime(dst, t, format)
|
||||
}
|
||||
|
||||
func appendTimes(dst []byte, vals []time.Time, format string) []byte {
|
||||
return cbor.AppendTimes(dst, vals, format)
|
||||
}
|
||||
|
||||
func appendDuration(dst []byte, d time.Duration, unit time.Duration, useInt bool) []byte {
|
||||
return cbor.AppendDuration(dst, d, unit, useInt)
|
||||
}
|
||||
|
||||
func appendDurations(dst []byte, vals []time.Duration, unit time.Duration, useInt bool) []byte {
|
||||
return cbor.AppendDurations(dst, vals, unit, useInt)
|
||||
}
|
||||
|
||||
func appendBool(dst []byte, val bool) []byte {
|
||||
return cbor.AppendBool(dst, val)
|
||||
}
|
||||
|
||||
func appendBools(dst []byte, vals []bool) []byte {
|
||||
return cbor.AppendBools(dst, vals)
|
||||
}
|
||||
|
||||
func appendInt(dst []byte, val int) []byte {
|
||||
return cbor.AppendInt(dst, val)
|
||||
}
|
||||
|
||||
func appendInts(dst []byte, vals []int) []byte {
|
||||
return cbor.AppendInts(dst, vals)
|
||||
}
|
||||
|
||||
func appendInt8(dst []byte, val int8) []byte {
|
||||
return cbor.AppendInt8(dst, val)
|
||||
}
|
||||
|
||||
func appendInts8(dst []byte, vals []int8) []byte {
|
||||
return cbor.AppendInts8(dst, vals)
|
||||
}
|
||||
|
||||
func appendInt16(dst []byte, val int16) []byte {
|
||||
return cbor.AppendInt16(dst, val)
|
||||
}
|
||||
|
||||
func appendInts16(dst []byte, vals []int16) []byte {
|
||||
return cbor.AppendInts16(dst, vals)
|
||||
}
|
||||
|
||||
func appendInt32(dst []byte, val int32) []byte {
|
||||
return cbor.AppendInt32(dst, val)
|
||||
}
|
||||
|
||||
func appendInts32(dst []byte, vals []int32) []byte {
|
||||
return cbor.AppendInts32(dst, vals)
|
||||
}
|
||||
|
||||
func appendInt64(dst []byte, val int64) []byte {
|
||||
return cbor.AppendInt64(dst, val)
|
||||
}
|
||||
|
||||
func appendInts64(dst []byte, vals []int64) []byte {
|
||||
return cbor.AppendInts64(dst, vals)
|
||||
}
|
||||
|
||||
func appendUint(dst []byte, val uint) []byte {
|
||||
return cbor.AppendUint(dst, val)
|
||||
}
|
||||
|
||||
func appendUints(dst []byte, vals []uint) []byte {
|
||||
return cbor.AppendUints(dst, vals)
|
||||
}
|
||||
|
||||
func appendUint8(dst []byte, val uint8) []byte {
|
||||
return cbor.AppendUint8(dst, val)
|
||||
}
|
||||
|
||||
func appendUints8(dst []byte, vals []uint8) []byte {
|
||||
return cbor.AppendUints8(dst, vals)
|
||||
}
|
||||
|
||||
func appendUint16(dst []byte, val uint16) []byte {
|
||||
return cbor.AppendUint16(dst, val)
|
||||
}
|
||||
|
||||
func appendUints16(dst []byte, vals []uint16) []byte {
|
||||
return cbor.AppendUints16(dst, vals)
|
||||
}
|
||||
|
||||
func appendUint32(dst []byte, val uint32) []byte {
|
||||
return cbor.AppendUint32(dst, val)
|
||||
}
|
||||
|
||||
func appendUints32(dst []byte, vals []uint32) []byte {
|
||||
return cbor.AppendUints32(dst, vals)
|
||||
}
|
||||
|
||||
func appendUint64(dst []byte, val uint64) []byte {
|
||||
return cbor.AppendUint64(dst, val)
|
||||
}
|
||||
|
||||
func appendUints64(dst []byte, vals []uint64) []byte {
|
||||
return cbor.AppendUints64(dst, vals)
|
||||
}
|
||||
|
||||
func appendFloat(dst []byte, val float64, bitSize int) []byte {
|
||||
return cbor.AppendFloat(dst, val, bitSize)
|
||||
}
|
||||
|
||||
func appendFloat32(dst []byte, val float32) []byte {
|
||||
return cbor.AppendFloat32(dst, val)
|
||||
}
|
||||
|
||||
func appendFloats32(dst []byte, vals []float32) []byte {
|
||||
return cbor.AppendFloats32(dst, vals)
|
||||
}
|
||||
|
||||
func appendFloat64(dst []byte, val float64) []byte {
|
||||
return cbor.AppendFloat64(dst, val)
|
||||
}
|
||||
|
||||
func appendFloats64(dst []byte, vals []float64) []byte {
|
||||
return cbor.AppendFloats64(dst, vals)
|
||||
}
|
||||
|
||||
func appendInterface(dst []byte, i interface{}) []byte {
|
||||
return cbor.AppendInterface(dst, i)
|
||||
}
|
||||
@@ -4,10 +4,10 @@ import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/rs/zerolog/internal/json"
|
||||
)
|
||||
|
||||
var eventPool = &sync.Pool{
|
||||
@@ -21,11 +21,12 @@ var eventPool = &sync.Pool{
|
||||
// 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
|
||||
enabled bool
|
||||
done func(msg string)
|
||||
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
|
||||
@@ -46,15 +47,15 @@ func newEvent(w LevelWriter, level Level, enabled bool) *Event {
|
||||
}
|
||||
e := eventPool.Get().(*Event)
|
||||
e.buf = e.buf[:1]
|
||||
e.h = e.h[:0]
|
||||
e.buf[0] = '{'
|
||||
e.w = w
|
||||
e.level = level
|
||||
e.enabled = true
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *Event) write() (err error) {
|
||||
if !e.enabled {
|
||||
if e == nil {
|
||||
return nil
|
||||
}
|
||||
e.buf = append(e.buf, '}', '\n')
|
||||
@@ -66,7 +67,7 @@ func (e *Event) write() (err error) {
|
||||
// Enabled return false if the *Event is going to be filtered out by
|
||||
// log level or sampling.
|
||||
func (e *Event) Enabled() bool {
|
||||
return e.enabled
|
||||
return e != nil
|
||||
}
|
||||
|
||||
// Msg sends the *Event with msg added as the message field if not empty.
|
||||
@@ -74,11 +75,27 @@ func (e *Event) Enabled() bool {
|
||||
// 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.enabled {
|
||||
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 = json.AppendString(json.AppendKey(e.buf, MessageFieldName), msg)
|
||||
e.buf = appendString(appendKey(e.buf, MessageFieldName), msg)
|
||||
}
|
||||
if e.done != nil {
|
||||
defer e.done(msg)
|
||||
@@ -93,24 +110,15 @@ func (e *Event) Msg(msg string) {
|
||||
// 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.enabled {
|
||||
if e == nil {
|
||||
return
|
||||
}
|
||||
msg := fmt.Sprintf(format, v...)
|
||||
if msg != "" {
|
||||
e.buf = json.AppendString(json.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)
|
||||
}
|
||||
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.enabled {
|
||||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = appendFields(e.buf, fields)
|
||||
@@ -120,10 +128,10 @@ func (e *Event) Fields(fields map[string]interface{}) *Event {
|
||||
// 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.enabled {
|
||||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = append(append(json.AppendKey(e.buf, key), dict.buf...), '}')
|
||||
e.buf = append(append(appendKey(e.buf, key), dict.buf...), '}')
|
||||
eventPool.Put(dict)
|
||||
return e
|
||||
}
|
||||
@@ -139,10 +147,10 @@ func Dict() *Event {
|
||||
// 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.enabled {
|
||||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = json.AppendKey(e.buf, key)
|
||||
e.buf = appendKey(e.buf, key)
|
||||
var a *Array
|
||||
if aa, ok := arr.(*Array); ok {
|
||||
a = aa
|
||||
@@ -170,29 +178,29 @@ func (e *Event) appendObject(obj LogObjectMarshaler) {
|
||||
|
||||
// Object marshals an object that implement the LogObjectMarshaler interface.
|
||||
func (e *Event) Object(key string, obj LogObjectMarshaler) *Event {
|
||||
if !e.enabled {
|
||||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = json.AppendKey(e.buf, key)
|
||||
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.enabled {
|
||||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = json.AppendString(json.AppendKey(e.buf, key), val)
|
||||
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.enabled {
|
||||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = json.AppendStrings(json.AppendKey(e.buf, key), vals)
|
||||
e.buf = appendStrings(appendKey(e.buf, key), vals)
|
||||
return e
|
||||
}
|
||||
|
||||
@@ -201,21 +209,21 @@ func (e *Event) Strs(key string, vals []string) *Event {
|
||||
// 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.enabled {
|
||||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = json.AppendBytes(json.AppendKey(e.buf, key), val)
|
||||
e.buf = appendBytes(appendKey(e.buf, key), val)
|
||||
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.enabled {
|
||||
if e == nil {
|
||||
return e
|
||||
}
|
||||
if err != nil {
|
||||
e.buf = json.AppendError(json.AppendKey(e.buf, key), err)
|
||||
e.buf = appendError(appendKey(e.buf, key), err)
|
||||
}
|
||||
return e
|
||||
}
|
||||
@@ -223,10 +231,10 @@ func (e *Event) AnErr(key string, err error) *Event {
|
||||
// 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.enabled {
|
||||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = json.AppendErrors(json.AppendKey(e.buf, key), errs)
|
||||
e.buf = appendErrors(appendKey(e.buf, key), errs)
|
||||
return e
|
||||
}
|
||||
|
||||
@@ -234,274 +242,274 @@ func (e *Event) Errs(key string, errs []error) *Event {
|
||||
// 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.enabled {
|
||||
if e == nil {
|
||||
return e
|
||||
}
|
||||
if err != nil {
|
||||
e.buf = json.AppendError(json.AppendKey(e.buf, ErrorFieldName), err)
|
||||
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.enabled {
|
||||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = json.AppendBool(json.AppendKey(e.buf, key), b)
|
||||
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.enabled {
|
||||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = json.AppendBools(json.AppendKey(e.buf, key), b)
|
||||
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.enabled {
|
||||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = json.AppendInt(json.AppendKey(e.buf, key), i)
|
||||
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.enabled {
|
||||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = json.AppendInts(json.AppendKey(e.buf, key), i)
|
||||
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.enabled {
|
||||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = json.AppendInt8(json.AppendKey(e.buf, key), i)
|
||||
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.enabled {
|
||||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = json.AppendInts8(json.AppendKey(e.buf, key), i)
|
||||
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.enabled {
|
||||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = json.AppendInt16(json.AppendKey(e.buf, key), i)
|
||||
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.enabled {
|
||||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = json.AppendInts16(json.AppendKey(e.buf, key), i)
|
||||
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.enabled {
|
||||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = json.AppendInt32(json.AppendKey(e.buf, key), i)
|
||||
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.enabled {
|
||||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = json.AppendInts32(json.AppendKey(e.buf, key), i)
|
||||
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.enabled {
|
||||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = json.AppendInt64(json.AppendKey(e.buf, key), i)
|
||||
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.enabled {
|
||||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = json.AppendInts64(json.AppendKey(e.buf, key), i)
|
||||
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.enabled {
|
||||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = json.AppendUint(json.AppendKey(e.buf, key), i)
|
||||
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.enabled {
|
||||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = json.AppendUints(json.AppendKey(e.buf, key), i)
|
||||
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.enabled {
|
||||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = json.AppendUint8(json.AppendKey(e.buf, key), i)
|
||||
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.enabled {
|
||||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = json.AppendUints8(json.AppendKey(e.buf, key), i)
|
||||
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.enabled {
|
||||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = json.AppendUint16(json.AppendKey(e.buf, key), i)
|
||||
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.enabled {
|
||||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = json.AppendUints16(json.AppendKey(e.buf, key), i)
|
||||
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.enabled {
|
||||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = json.AppendUint32(json.AppendKey(e.buf, key), i)
|
||||
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.enabled {
|
||||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = json.AppendUints32(json.AppendKey(e.buf, key), i)
|
||||
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.enabled {
|
||||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = json.AppendUint64(json.AppendKey(e.buf, key), i)
|
||||
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.enabled {
|
||||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = json.AppendUints64(json.AppendKey(e.buf, key), i)
|
||||
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.enabled {
|
||||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = json.AppendFloat32(json.AppendKey(e.buf, key), f)
|
||||
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.enabled {
|
||||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = json.AppendFloats32(json.AppendKey(e.buf, key), f)
|
||||
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.enabled {
|
||||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = json.AppendFloat64(json.AppendKey(e.buf, key), f)
|
||||
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.enabled {
|
||||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = json.AppendFloats64(json.AppendKey(e.buf, key), f)
|
||||
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.
|
||||
func (e *Event) Timestamp() *Event {
|
||||
if !e.enabled {
|
||||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = json.AppendTime(json.AppendKey(e.buf, TimestampFieldName), TimestampFunc(), TimeFieldFormat)
|
||||
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.enabled {
|
||||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = json.AppendTime(json.AppendKey(e.buf, key), t, TimeFieldFormat)
|
||||
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.enabled {
|
||||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = json.AppendTimes(json.AppendKey(e.buf, key), t, TimeFieldFormat)
|
||||
e.buf = appendTimes(appendKey(e.buf, key), t, TimeFieldFormat)
|
||||
return e
|
||||
}
|
||||
|
||||
@@ -509,10 +517,10 @@ func (e *Event) Times(key string, t []time.Time) *Event {
|
||||
// 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.enabled {
|
||||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = json.AppendDuration(json.AppendKey(e.buf, key), d, DurationFieldUnit, DurationFieldInteger)
|
||||
e.buf = appendDuration(appendKey(e.buf, key), d, DurationFieldUnit, DurationFieldInteger)
|
||||
return e
|
||||
}
|
||||
|
||||
@@ -520,10 +528,10 @@ func (e *Event) Dur(key string, d time.Duration) *Event {
|
||||
// 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.enabled {
|
||||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = json.AppendDurations(json.AppendKey(e.buf, key), d, DurationFieldUnit, DurationFieldInteger)
|
||||
e.buf = appendDurations(appendKey(e.buf, key), d, DurationFieldUnit, DurationFieldInteger)
|
||||
return e
|
||||
}
|
||||
|
||||
@@ -531,25 +539,42 @@ func (e *Event) Durs(key string, d []time.Duration) *Event {
|
||||
// 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.enabled {
|
||||
if e == nil {
|
||||
return e
|
||||
}
|
||||
var d time.Duration
|
||||
if t.After(start) {
|
||||
d = t.Sub(start)
|
||||
}
|
||||
e.buf = json.AppendDuration(json.AppendKey(e.buf, key), d, DurationFieldUnit, DurationFieldInteger)
|
||||
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.enabled {
|
||||
if e == nil {
|
||||
return e
|
||||
}
|
||||
if obj, ok := i.(LogObjectMarshaler); ok {
|
||||
return e.Object(key, obj)
|
||||
}
|
||||
e.buf = json.AppendInterface(json.AppendKey(e.buf, key), i)
|
||||
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
|
||||
}
|
||||
|
||||
@@ -3,8 +3,6 @@ package zerolog
|
||||
import (
|
||||
"sort"
|
||||
"time"
|
||||
|
||||
"github.com/rs/zerolog/internal/json"
|
||||
)
|
||||
|
||||
func appendFields(dst []byte, fields map[string]interface{}) []byte {
|
||||
@@ -14,82 +12,82 @@ func appendFields(dst []byte, fields map[string]interface{}) []byte {
|
||||
}
|
||||
sort.Strings(keys)
|
||||
for _, key := range keys {
|
||||
dst = json.AppendKey(dst, key)
|
||||
dst = appendKey(dst, key)
|
||||
switch val := fields[key].(type) {
|
||||
case string:
|
||||
dst = json.AppendString(dst, val)
|
||||
dst = appendString(dst, val)
|
||||
case []byte:
|
||||
dst = json.AppendBytes(dst, val)
|
||||
dst = appendBytes(dst, val)
|
||||
case error:
|
||||
dst = json.AppendError(dst, val)
|
||||
dst = appendError(dst, val)
|
||||
case []error:
|
||||
dst = json.AppendErrors(dst, val)
|
||||
dst = appendErrors(dst, val)
|
||||
case bool:
|
||||
dst = json.AppendBool(dst, val)
|
||||
dst = appendBool(dst, val)
|
||||
case int:
|
||||
dst = json.AppendInt(dst, val)
|
||||
dst = appendInt(dst, val)
|
||||
case int8:
|
||||
dst = json.AppendInt8(dst, val)
|
||||
dst = appendInt8(dst, val)
|
||||
case int16:
|
||||
dst = json.AppendInt16(dst, val)
|
||||
dst = appendInt16(dst, val)
|
||||
case int32:
|
||||
dst = json.AppendInt32(dst, val)
|
||||
dst = appendInt32(dst, val)
|
||||
case int64:
|
||||
dst = json.AppendInt64(dst, val)
|
||||
dst = appendInt64(dst, val)
|
||||
case uint:
|
||||
dst = json.AppendUint(dst, val)
|
||||
dst = appendUint(dst, val)
|
||||
case uint8:
|
||||
dst = json.AppendUint8(dst, val)
|
||||
dst = appendUint8(dst, val)
|
||||
case uint16:
|
||||
dst = json.AppendUint16(dst, val)
|
||||
dst = appendUint16(dst, val)
|
||||
case uint32:
|
||||
dst = json.AppendUint32(dst, val)
|
||||
dst = appendUint32(dst, val)
|
||||
case uint64:
|
||||
dst = json.AppendUint64(dst, val)
|
||||
dst = appendUint64(dst, val)
|
||||
case float32:
|
||||
dst = json.AppendFloat32(dst, val)
|
||||
dst = appendFloat32(dst, val)
|
||||
case float64:
|
||||
dst = json.AppendFloat64(dst, val)
|
||||
dst = appendFloat64(dst, val)
|
||||
case time.Time:
|
||||
dst = json.AppendTime(dst, val, TimeFieldFormat)
|
||||
dst = appendTime(dst, val, TimeFieldFormat)
|
||||
case time.Duration:
|
||||
dst = json.AppendDuration(dst, val, DurationFieldUnit, DurationFieldInteger)
|
||||
dst = appendDuration(dst, val, DurationFieldUnit, DurationFieldInteger)
|
||||
case []string:
|
||||
dst = json.AppendStrings(dst, val)
|
||||
dst = appendStrings(dst, val)
|
||||
case []bool:
|
||||
dst = json.AppendBools(dst, val)
|
||||
dst = appendBools(dst, val)
|
||||
case []int:
|
||||
dst = json.AppendInts(dst, val)
|
||||
dst = appendInts(dst, val)
|
||||
case []int8:
|
||||
dst = json.AppendInts8(dst, val)
|
||||
dst = appendInts8(dst, val)
|
||||
case []int16:
|
||||
dst = json.AppendInts16(dst, val)
|
||||
dst = appendInts16(dst, val)
|
||||
case []int32:
|
||||
dst = json.AppendInts32(dst, val)
|
||||
dst = appendInts32(dst, val)
|
||||
case []int64:
|
||||
dst = json.AppendInts64(dst, val)
|
||||
dst = appendInts64(dst, val)
|
||||
case []uint:
|
||||
dst = json.AppendUints(dst, val)
|
||||
dst = appendUints(dst, val)
|
||||
// case []uint8:
|
||||
// dst = appendUints8(dst, val)
|
||||
case []uint16:
|
||||
dst = json.AppendUints16(dst, val)
|
||||
dst = appendUints16(dst, val)
|
||||
case []uint32:
|
||||
dst = json.AppendUints32(dst, val)
|
||||
dst = appendUints32(dst, val)
|
||||
case []uint64:
|
||||
dst = json.AppendUints64(dst, val)
|
||||
dst = appendUints64(dst, val)
|
||||
case []float32:
|
||||
dst = json.AppendFloats32(dst, val)
|
||||
dst = appendFloats32(dst, val)
|
||||
case []float64:
|
||||
dst = json.AppendFloats64(dst, val)
|
||||
dst = appendFloats64(dst, val)
|
||||
case []time.Time:
|
||||
dst = json.AppendTimes(dst, val, TimeFieldFormat)
|
||||
dst = appendTimes(dst, val, TimeFieldFormat)
|
||||
case []time.Duration:
|
||||
dst = json.AppendDurations(dst, val, DurationFieldUnit, DurationFieldInteger)
|
||||
dst = appendDurations(dst, val, DurationFieldUnit, DurationFieldInteger)
|
||||
case nil:
|
||||
dst = append(dst, "null"...)
|
||||
default:
|
||||
dst = json.AppendInterface(dst, val)
|
||||
dst = appendInterface(dst, val)
|
||||
}
|
||||
}
|
||||
return dst
|
||||
|
||||
@@ -16,6 +16,9 @@ var (
|
||||
// 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.
|
||||
|
||||
+1
-1
@@ -124,7 +124,7 @@ func RefererHandler(fieldKey string) func(next http.Handler) http.Handler {
|
||||
|
||||
type idKey struct{}
|
||||
|
||||
// IDFromRequest returns the unique id accociated to the request if any.
|
||||
// IDFromRequest returns the unique id associated to the request if any.
|
||||
func IDFromRequest(r *http.Request) (id xid.ID, ok bool) {
|
||||
if r == nil {
|
||||
return
|
||||
|
||||
@@ -67,5 +67,5 @@ func Example_handler() {
|
||||
|
||||
h.ServeHTTP(httptest.NewRecorder(), &http.Request{})
|
||||
|
||||
// Output: {"time":"2001-02-03T04:05:06Z","level":"info","role":"my-service","host":"local-hostname","user":"current user","status":"ok","message":"Something happend"}
|
||||
// Output: {"level":"info","role":"my-service","host":"local-hostname","user":"current user","status":"ok","time":"2001-02-03T04:05:06Z","message":"Something happend"}
|
||||
}
|
||||
|
||||
@@ -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{}
|
||||
}
|
||||
+236
@@ -0,0 +1,236 @@
|
||||
package zerolog
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"bytes"
|
||||
"io/ioutil"
|
||||
)
|
||||
|
||||
type LevelNameHook struct{}
|
||||
|
||||
func (h LevelNameHook) Run(e *Event, level Level, msg string) {
|
||||
levelName := level.String()
|
||||
if level == NoLevel {
|
||||
levelName = "nolevel"
|
||||
}
|
||||
e.Str("level_name", levelName)
|
||||
}
|
||||
|
||||
type SimpleHook struct{}
|
||||
|
||||
func (h SimpleHook) Run(e *Event, level Level, msg string) {
|
||||
e.Bool("has_level", level != NoLevel)
|
||||
e.Str("test", "logged")
|
||||
}
|
||||
|
||||
type CopyHook struct{}
|
||||
|
||||
func (h CopyHook) Run(e *Event, level Level, msg string) {
|
||||
hasLevel := level != NoLevel
|
||||
e.Bool("copy_has_level", hasLevel)
|
||||
if hasLevel {
|
||||
e.Str("copy_level", level.String())
|
||||
}
|
||||
e.Str("copy_msg", msg)
|
||||
}
|
||||
|
||||
type NopHook struct{}
|
||||
|
||||
func (h NopHook) Run(e *Event, level Level, msg string) {
|
||||
}
|
||||
|
||||
var (
|
||||
levelNameHook LevelNameHook
|
||||
simpleHook SimpleHook
|
||||
copyHook CopyHook
|
||||
nopHook NopHook
|
||||
)
|
||||
|
||||
func TestHook(t *testing.T) {
|
||||
t.Run("Message", func(t *testing.T) {
|
||||
out := &bytes.Buffer{}
|
||||
log := New(out).Hook(levelNameHook)
|
||||
log.Log().Msg("test message")
|
||||
if got, want := out.String(), `{"level_name":"nolevel","message":"test message"}`+"\n"; got != want {
|
||||
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
|
||||
}
|
||||
})
|
||||
t.Run("NoLevel", func(t *testing.T) {
|
||||
out := &bytes.Buffer{}
|
||||
log := New(out).Hook(levelNameHook)
|
||||
log.Log().Msg("")
|
||||
if got, want := out.String(), `{"level_name":"nolevel"}`+"\n"; got != want {
|
||||
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
|
||||
}
|
||||
})
|
||||
t.Run("Print", func(t *testing.T) {
|
||||
out := &bytes.Buffer{}
|
||||
log := New(out).Hook(levelNameHook)
|
||||
log.Print("")
|
||||
if got, want := out.String(), `{"level":"debug","level_name":"debug"}`+"\n"; got != want {
|
||||
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
|
||||
}
|
||||
})
|
||||
t.Run("Error", func(t *testing.T) {
|
||||
out := &bytes.Buffer{}
|
||||
log := New(out).Hook(levelNameHook)
|
||||
log.Error().Msg("")
|
||||
if got, want := out.String(), `{"level":"error","level_name":"error"}`+"\n"; got != want {
|
||||
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
|
||||
}
|
||||
})
|
||||
t.Run("Copy/1", func(t *testing.T) {
|
||||
out := &bytes.Buffer{}
|
||||
log := New(out).Hook(copyHook)
|
||||
log.Log().Msg("")
|
||||
if got, want := out.String(), `{"copy_has_level":false,"copy_msg":""}`+"\n"; got != want {
|
||||
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
|
||||
}
|
||||
})
|
||||
t.Run("Copy/2", func(t *testing.T) {
|
||||
out := &bytes.Buffer{}
|
||||
log := New(out).Hook(copyHook)
|
||||
log.Info().Msg("a message")
|
||||
if got, want := out.String(), `{"level":"info","copy_has_level":true,"copy_level":"info","copy_msg":"a message","message":"a message"}`+"\n"; got != want {
|
||||
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
|
||||
}
|
||||
})
|
||||
t.Run("Multi", func(t *testing.T) {
|
||||
out := &bytes.Buffer{}
|
||||
log := New(out).Hook(levelNameHook).Hook(simpleHook)
|
||||
log.Error().Msg("")
|
||||
if got, want := out.String(), `{"level":"error","level_name":"error","has_level":true,"test":"logged"}`+"\n"; got != want {
|
||||
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
|
||||
}
|
||||
})
|
||||
t.Run("Multi/Message", func(t *testing.T) {
|
||||
out := &bytes.Buffer{}
|
||||
log := New(out).Hook(levelNameHook).Hook(simpleHook)
|
||||
log.Error().Msg("a message")
|
||||
if got, want := out.String(), `{"level":"error","level_name":"error","has_level":true,"test":"logged","message":"a message"}`+"\n"; got != want {
|
||||
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
|
||||
}
|
||||
})
|
||||
t.Run("Output/single/pre", func(t *testing.T) {
|
||||
ignored := &bytes.Buffer{}
|
||||
out := &bytes.Buffer{}
|
||||
log := New(ignored).Hook(levelNameHook).Output(out)
|
||||
log.Error().Msg("")
|
||||
if got, want := out.String(), `{"level":"error","level_name":"error"}`+"\n"; got != want {
|
||||
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
|
||||
}
|
||||
})
|
||||
t.Run("Output/single/post", func(t *testing.T) {
|
||||
ignored := &bytes.Buffer{}
|
||||
out := &bytes.Buffer{}
|
||||
log := New(ignored).Output(out).Hook(levelNameHook)
|
||||
log.Error().Msg("")
|
||||
if got, want := out.String(), `{"level":"error","level_name":"error"}`+"\n"; got != want {
|
||||
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
|
||||
}
|
||||
})
|
||||
t.Run("Output/multi/pre", func(t *testing.T) {
|
||||
ignored := &bytes.Buffer{}
|
||||
out := &bytes.Buffer{}
|
||||
log := New(ignored).Hook(levelNameHook).Hook(simpleHook).Output(out)
|
||||
log.Error().Msg("")
|
||||
if got, want := out.String(), `{"level":"error","level_name":"error","has_level":true,"test":"logged"}`+"\n"; got != want {
|
||||
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
|
||||
}
|
||||
})
|
||||
t.Run("Output/multi/post", func(t *testing.T) {
|
||||
ignored := &bytes.Buffer{}
|
||||
out := &bytes.Buffer{}
|
||||
log := New(ignored).Output(out).Hook(levelNameHook).Hook(simpleHook)
|
||||
log.Error().Msg("")
|
||||
if got, want := out.String(), `{"level":"error","level_name":"error","has_level":true,"test":"logged"}`+"\n"; got != want {
|
||||
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
|
||||
}
|
||||
})
|
||||
t.Run("Output/mixed", func(t *testing.T) {
|
||||
ignored := &bytes.Buffer{}
|
||||
out := &bytes.Buffer{}
|
||||
log := New(ignored).Hook(levelNameHook).Output(out).Hook(simpleHook)
|
||||
log.Error().Msg("")
|
||||
if got, want := out.String(), `{"level":"error","level_name":"error","has_level":true,"test":"logged"}`+"\n"; got != want {
|
||||
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
|
||||
}
|
||||
})
|
||||
t.Run("With/single/pre", func(t *testing.T) {
|
||||
out := &bytes.Buffer{}
|
||||
log := New(out).Hook(levelNameHook).With().Str("with", "pre").Logger()
|
||||
log.Error().Msg("")
|
||||
if got, want := out.String(), `{"level":"error","with":"pre","level_name":"error"}`+"\n"; got != want {
|
||||
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
|
||||
}
|
||||
})
|
||||
t.Run("With/single/post", func(t *testing.T) {
|
||||
out := &bytes.Buffer{}
|
||||
log := New(out).With().Str("with", "post").Logger().Hook(levelNameHook)
|
||||
log.Error().Msg("")
|
||||
if got, want := out.String(), `{"level":"error","with":"post","level_name":"error"}`+"\n"; got != want {
|
||||
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
|
||||
}
|
||||
})
|
||||
t.Run("With/multi/pre", func(t *testing.T) {
|
||||
out := &bytes.Buffer{}
|
||||
log := New(out).Hook(levelNameHook).Hook(simpleHook).With().Str("with", "pre").Logger()
|
||||
log.Error().Msg("")
|
||||
if got, want := out.String(), `{"level":"error","with":"pre","level_name":"error","has_level":true,"test":"logged"}`+"\n"; got != want {
|
||||
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
|
||||
}
|
||||
})
|
||||
t.Run("With/multi/post", func(t *testing.T) {
|
||||
out := &bytes.Buffer{}
|
||||
log := New(out).With().Str("with", "post").Logger().Hook(levelNameHook).Hook(simpleHook)
|
||||
log.Error().Msg("")
|
||||
if got, want := out.String(), `{"level":"error","with":"post","level_name":"error","has_level":true,"test":"logged"}`+"\n"; got != want {
|
||||
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
|
||||
}
|
||||
})
|
||||
t.Run("With/mixed", func(t *testing.T) {
|
||||
out := &bytes.Buffer{}
|
||||
log := New(out).Hook(levelNameHook).With().Str("with", "mixed").Logger().Hook(simpleHook)
|
||||
log.Error().Msg("")
|
||||
if got, want := out.String(), `{"level":"error","with":"mixed","level_name":"error","has_level":true,"test":"logged"}`+"\n"; got != want {
|
||||
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
|
||||
}
|
||||
})
|
||||
t.Run("None", func(t *testing.T) {
|
||||
out := &bytes.Buffer{}
|
||||
log := New(out)
|
||||
log.Error().Msg("")
|
||||
if got, want := out.String(), `{"level":"error"}`+"\n"; got != want {
|
||||
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func BenchmarkHooks(b *testing.B) {
|
||||
logger := New(ioutil.Discard)
|
||||
b.ResetTimer()
|
||||
b.Run("Nop/Single", func(b *testing.B) {
|
||||
log := logger.Hook(nopHook)
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
for pb.Next() {
|
||||
log.Log().Msg("")
|
||||
}
|
||||
})
|
||||
})
|
||||
b.Run("Nop/Multi", func(b *testing.B) {
|
||||
log := logger.Hook(nopHook).Hook(nopHook)
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
for pb.Next() {
|
||||
log.Log().Msg("")
|
||||
}
|
||||
})
|
||||
})
|
||||
b.Run("Simple", func(b *testing.B) {
|
||||
log := logger.Hook(simpleHook)
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
for pb.Next() {
|
||||
log.Log().Msg("")
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
@@ -65,6 +65,23 @@
|
||||
// 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"}
|
||||
//
|
||||
package zerolog
|
||||
|
||||
import (
|
||||
@@ -73,8 +90,6 @@ import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strconv"
|
||||
|
||||
"github.com/rs/zerolog/internal/json"
|
||||
)
|
||||
|
||||
// Level defines log levels.
|
||||
@@ -93,6 +108,8 @@ const (
|
||||
FatalLevel
|
||||
// PanicLevel defines panic log level.
|
||||
PanicLevel
|
||||
// NoLevel defines an absent log level.
|
||||
NoLevel
|
||||
// Disabled disables the logger.
|
||||
Disabled
|
||||
)
|
||||
@@ -111,12 +128,12 @@ func (l Level) String() string {
|
||||
return "fatal"
|
||||
case PanicLevel:
|
||||
return "panic"
|
||||
case NoLevel:
|
||||
return ""
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
var disabledEvent = newEvent(levelWriterAdapter{ioutil.Discard}, 0, false)
|
||||
|
||||
// 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
|
||||
@@ -127,6 +144,7 @@ type Logger struct {
|
||||
level Level
|
||||
sampler Sampler
|
||||
context []byte
|
||||
hooks []Hook
|
||||
}
|
||||
|
||||
// New creates a root logger with given output writer. If the output writer implements
|
||||
@@ -157,8 +175,13 @@ func (l Logger) Output(w io.Writer) Logger {
|
||||
l2 := New(w)
|
||||
l2.level = l.level
|
||||
l2.sampler = l.sampler
|
||||
l2.context = make([]byte, len(l.context), cap(l.context))
|
||||
copy(l2.context, l.context)
|
||||
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
|
||||
}
|
||||
|
||||
@@ -168,9 +191,6 @@ func (l Logger) With() Context {
|
||||
l.context = make([]byte, 0, 500)
|
||||
if context != nil {
|
||||
l.context = append(l.context, context...)
|
||||
} else {
|
||||
// first byte of context is presence of timestamp or not
|
||||
l.context = append(l.context, 0)
|
||||
}
|
||||
return Context{l}
|
||||
}
|
||||
@@ -183,7 +203,7 @@ func (l *Logger) UpdateContext(update func(c Context) Context) {
|
||||
return
|
||||
}
|
||||
if cap(l.context) == 0 {
|
||||
l.context = make([]byte, 1, 500) // first byte is timestamp flag
|
||||
l.context = make([]byte, 0, 500)
|
||||
}
|
||||
c := update(Context{*l})
|
||||
l.context = c.l.context
|
||||
@@ -201,54 +221,60 @@ func (l Logger) Sample(s Sampler) Logger {
|
||||
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, true, nil)
|
||||
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, true, nil)
|
||||
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, true, nil)
|
||||
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, true, nil)
|
||||
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, true, func(msg string) { os.Exit(1) })
|
||||
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, true, func(msg string) { panic(msg) })
|
||||
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 {
|
||||
func (l *Logger) WithLevel(level Level) *Event {
|
||||
switch level {
|
||||
case DebugLevel:
|
||||
return l.Debug()
|
||||
@@ -262,8 +288,10 @@ func (l Logger) WithLevel(level Level) *Event {
|
||||
return l.Fatal()
|
||||
case PanicLevel:
|
||||
return l.Panic()
|
||||
case NoLevel:
|
||||
return l.Log()
|
||||
case Disabled:
|
||||
return disabledEvent
|
||||
return nil
|
||||
default:
|
||||
panic("zerolog: WithLevel(): invalid level: " + strconv.Itoa(int(level)))
|
||||
}
|
||||
@@ -273,15 +301,13 @@ func (l Logger) WithLevel(level Level) *Event {
|
||||
// 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 {
|
||||
// We use panic level with addLevelField=false to make Log passthrough all
|
||||
// levels except Disabled.
|
||||
return l.newEvent(PanicLevel, false, nil)
|
||||
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{}) {
|
||||
func (l *Logger) Print(v ...interface{}) {
|
||||
if e := l.Debug(); e.Enabled() {
|
||||
e.Msg(fmt.Sprint(v...))
|
||||
}
|
||||
@@ -289,7 +315,7 @@ func (l Logger) Print(v ...interface{}) {
|
||||
|
||||
// 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{}) {
|
||||
func (l *Logger) Printf(format string, v ...interface{}) {
|
||||
if e := l.Debug(); e.Enabled() {
|
||||
e.Msg(fmt.Sprintf(format, v...))
|
||||
}
|
||||
@@ -307,35 +333,28 @@ func (l Logger) Write(p []byte) (n int, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (l Logger) newEvent(level Level, addLevelField bool, done func(string)) *Event {
|
||||
func (l *Logger) newEvent(level Level, done func(string)) *Event {
|
||||
enabled := l.should(level)
|
||||
if !enabled {
|
||||
return disabledEvent
|
||||
return nil
|
||||
}
|
||||
lvl := InfoLevel
|
||||
if addLevelField {
|
||||
lvl = level
|
||||
}
|
||||
e := newEvent(l.w, lvl, true)
|
||||
e := newEvent(l.w, level, true)
|
||||
e.done = done
|
||||
if l.context != nil && len(l.context) > 0 && l.context[0] > 0 {
|
||||
// first byte of context is ts flag
|
||||
e.buf = json.AppendTime(json.AppendKey(e.buf, TimestampFieldName), TimestampFunc(), TimeFieldFormat)
|
||||
}
|
||||
if addLevelField {
|
||||
e.ch = l.hooks
|
||||
if level != NoLevel {
|
||||
e.Str(LevelFieldName, level.String())
|
||||
}
|
||||
if l.context != nil && len(l.context) > 1 {
|
||||
if len(l.context) > 0 {
|
||||
if len(e.buf) > 1 {
|
||||
e.buf = append(e.buf, ',')
|
||||
}
|
||||
e.buf = append(e.buf, l.context[1:]...)
|
||||
e.buf = append(e.buf, l.context...)
|
||||
}
|
||||
return e
|
||||
}
|
||||
|
||||
// should returns true if the log event should be logged.
|
||||
func (l Logger) should(lvl Level) bool {
|
||||
func (l *Logger) should(lvl Level) bool {
|
||||
if lvl < l.level || lvl < globalLevel() {
|
||||
return false
|
||||
}
|
||||
|
||||
+14
-2
@@ -22,7 +22,7 @@ func With() zerolog.Context {
|
||||
return Logger.With()
|
||||
}
|
||||
|
||||
// Level crestes a child logger with the minium accepted level set to level.
|
||||
// Level creates a child logger with the minimum accepted level set to level.
|
||||
func Level(level zerolog.Level) zerolog.Logger {
|
||||
return Logger.Level(level)
|
||||
}
|
||||
@@ -32,6 +32,11 @@ func Sample(s zerolog.Sampler) zerolog.Logger {
|
||||
return Logger.Sample(s)
|
||||
}
|
||||
|
||||
// Hook returns a logger with the h Hook.
|
||||
func Hook(h zerolog.Hook) zerolog.Logger {
|
||||
return Logger.Hook(h)
|
||||
}
|
||||
|
||||
// Debug starts a new message with debug level.
|
||||
//
|
||||
// You must call Msg on the returned event in order to send the event.
|
||||
@@ -76,8 +81,15 @@ func Panic() *zerolog.Event {
|
||||
return Logger.Panic()
|
||||
}
|
||||
|
||||
// WithLevel starts a new message with level.
|
||||
//
|
||||
// You must call Msg on the returned event in order to send the event.
|
||||
func WithLevel(level zerolog.Level) *zerolog.Event {
|
||||
return Logger.WithLevel(level)
|
||||
}
|
||||
|
||||
// Log starts a new message with no level. Setting zerolog.GlobalLevel to
|
||||
// zerlog.Disabled will still disable events produced by this method.
|
||||
// zerolog.Disabled will still disable events produced by this method.
|
||||
//
|
||||
// You must call Msg on the returned event in order to send the event.
|
||||
func Log() *zerolog.Event {
|
||||
|
||||
@@ -0,0 +1,141 @@
|
||||
package log_test
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"flag"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
// setup would normally be an init() function, however, there seems
|
||||
// to be something awry with the testing framework when we set the
|
||||
// global Logger from an init()
|
||||
func setup() {
|
||||
// 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 = ""
|
||||
// In order to always output a static time to stdout for these
|
||||
// examples to pass, we need to override zerolog.TimestampFunc
|
||||
// and log.Logger globals -- you would not normally need to do this
|
||||
zerolog.TimestampFunc = func() time.Time {
|
||||
return time.Date(2008, 1, 8, 17, 5, 05, 0, time.UTC)
|
||||
}
|
||||
log.Logger = zerolog.New(os.Stdout).With().Timestamp().Logger()
|
||||
}
|
||||
|
||||
// Simple logging example using the Print function in the log package
|
||||
// Note that both Print and Printf are at the debug log level by default
|
||||
func ExamplePrint() {
|
||||
setup()
|
||||
|
||||
log.Print("hello world")
|
||||
// Output: {"level":"debug","time":1199811905,"message":"hello world"}
|
||||
}
|
||||
|
||||
// Simple logging example using the Printf function in the log package
|
||||
func ExamplePrintf() {
|
||||
setup()
|
||||
|
||||
log.Printf("hello %s", "world")
|
||||
// Output: {"level":"debug","time":1199811905,"message":"hello world"}
|
||||
}
|
||||
|
||||
// Example of a log with no particular "level"
|
||||
func ExampleLog() {
|
||||
setup()
|
||||
log.Log().Msg("hello world")
|
||||
|
||||
// Output: {"time":1199811905,"message":"hello world"}
|
||||
}
|
||||
|
||||
// Example of a log at a particular "level" (in this case, "debug")
|
||||
func ExampleDebug() {
|
||||
setup()
|
||||
log.Debug().Msg("hello world")
|
||||
|
||||
// Output: {"level":"debug","time":1199811905,"message":"hello world"}
|
||||
}
|
||||
|
||||
// Example of a log at a particular "level" (in this case, "info")
|
||||
func ExampleInfo() {
|
||||
setup()
|
||||
log.Info().Msg("hello world")
|
||||
|
||||
// Output: {"level":"info","time":1199811905,"message":"hello world"}
|
||||
}
|
||||
|
||||
// Example of a log at a particular "level" (in this case, "warn")
|
||||
func ExampleWarn() {
|
||||
setup()
|
||||
log.Warn().Msg("hello world")
|
||||
|
||||
// Output: {"level":"warn","time":1199811905,"message":"hello world"}
|
||||
}
|
||||
|
||||
// Example of a log at a particular "level" (in this case, "error")
|
||||
func ExampleError() {
|
||||
setup()
|
||||
log.Error().Msg("hello world")
|
||||
|
||||
// Output: {"level":"error","time":1199811905,"message":"hello world"}
|
||||
}
|
||||
|
||||
// Example of a log at a particular "level" (in this case, "fatal")
|
||||
func ExampleFatal() {
|
||||
setup()
|
||||
err := errors.New("A repo man spends his life getting into tense situations")
|
||||
service := "myservice"
|
||||
|
||||
log.Fatal().
|
||||
Err(err).
|
||||
Str("service", service).
|
||||
Msgf("Cannot start %s", service)
|
||||
|
||||
// Outputs: {"level":"fatal","time":1199811905,"error":"A repo man spends his life getting into tense situations","service":"myservice","message":"Cannot start myservice"}
|
||||
}
|
||||
|
||||
// TODO: Panic
|
||||
|
||||
// This example uses command-line flags to demonstrate various outputs
|
||||
// depending on the chosen log level.
|
||||
func Example_LevelFlag() {
|
||||
setup()
|
||||
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")
|
||||
}
|
||||
|
||||
// Output: {"level":"info","time":1199811905,"message":"This message appears when log level set to Debug or Info"}
|
||||
}
|
||||
|
||||
// TODO: Output
|
||||
|
||||
// TODO: With
|
||||
|
||||
// TODO: Level
|
||||
|
||||
// TODO: Sample
|
||||
|
||||
// TODO: Hook
|
||||
|
||||
// TODO: WithLevel
|
||||
|
||||
// TODO: Ctx
|
||||
@@ -49,6 +49,33 @@ func ExampleLogger_Sample() {
|
||||
// {"level":"info","message":"message 4"}
|
||||
}
|
||||
|
||||
type LevelNameHook struct{}
|
||||
|
||||
func (h LevelNameHook) Run(e *zerolog.Event, l zerolog.Level, msg string) {
|
||||
if l != zerolog.NoLevel {
|
||||
e.Str("level_name", l.String())
|
||||
} else {
|
||||
e.Str("level_name", "NoLevel")
|
||||
}
|
||||
}
|
||||
|
||||
type MessageHook string
|
||||
|
||||
func (h MessageHook) Run(e *zerolog.Event, l zerolog.Level, msg string) {
|
||||
e.Str("the_message", msg)
|
||||
}
|
||||
|
||||
func ExampleLogger_Hook() {
|
||||
var levelNameHook LevelNameHook
|
||||
var messageHook MessageHook = "The message"
|
||||
|
||||
log := zerolog.New(os.Stdout).Hook(levelNameHook).Hook(messageHook)
|
||||
|
||||
log.Info().Msg("hello world")
|
||||
|
||||
// Output: {"level":"info","level_name":"info","the_message":"hello world","message":"hello world"}
|
||||
}
|
||||
|
||||
func ExampleLogger_Print() {
|
||||
log := zerolog.New(os.Stdout)
|
||||
|
||||
|
||||
+83
-7
@@ -3,7 +3,9 @@ package zerolog
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
@@ -74,7 +76,7 @@ func TestInfo(t *testing.T) {
|
||||
|
||||
func TestWith(t *testing.T) {
|
||||
out := &bytes.Buffer{}
|
||||
log := New(out).With().
|
||||
ctx := New(out).With().
|
||||
Str("foo", "bar").
|
||||
AnErr("some_err", nil).
|
||||
Err(errors.New("some error")).
|
||||
@@ -91,10 +93,12 @@ func TestWith(t *testing.T) {
|
||||
Uint64("uint64", 10).
|
||||
Float32("float32", 11).
|
||||
Float64("float64", 12).
|
||||
Time("time", time.Time{}).
|
||||
Logger()
|
||||
Time("time", time.Time{})
|
||||
_, file, line, _ := runtime.Caller(0)
|
||||
caller := fmt.Sprintf("%s:%d", file, line+3)
|
||||
log := ctx.Caller().Logger()
|
||||
log.Log().Msg("")
|
||||
if got, want := out.String(), `{"foo":"bar","error":"some error","bool":true,"int":1,"int8":2,"int16":3,"int32":4,"int64":5,"uint":6,"uint8":7,"uint16":8,"uint32":9,"uint64":10,"float32":11,"float64":12,"time":"0001-01-01T00:00:00Z"}`+"\n"; got != want {
|
||||
if got, want := out.String(), `{"foo":"bar","error":"some error","bool":true,"int":1,"int8":2,"int16":3,"int32":4,"int64":5,"uint":6,"uint8":7,"uint16":8,"uint32":9,"uint64":10,"float32":11,"float64":12,"time":"0001-01-01T00:00:00Z","caller":"`+caller+`"}`+"\n"; got != want {
|
||||
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
|
||||
}
|
||||
}
|
||||
@@ -132,7 +136,10 @@ func TestFields(t *testing.T) {
|
||||
out := &bytes.Buffer{}
|
||||
log := New(out)
|
||||
now := time.Now()
|
||||
_, file, line, _ := runtime.Caller(0)
|
||||
caller := fmt.Sprintf("%s:%d", file, line+3)
|
||||
log.Log().
|
||||
Caller().
|
||||
Str("string", "foo").
|
||||
Bytes("bytes", []byte("bar")).
|
||||
AnErr("some_err", nil).
|
||||
@@ -154,7 +161,7 @@ func TestFields(t *testing.T) {
|
||||
Time("time", time.Time{}).
|
||||
TimeDiff("diff", now, now.Add(-10*time.Second)).
|
||||
Msg("")
|
||||
if got, want := out.String(), `{"string":"foo","bytes":"bar","error":"some error","bool":true,"int":1,"int8":2,"int16":3,"int32":4,"int64":5,"uint":6,"uint8":7,"uint16":8,"uint32":9,"uint64":10,"float32":11,"float64":12,"dur":1000,"time":"0001-01-01T00:00:00Z","diff":10000}`+"\n"; got != want {
|
||||
if got, want := out.String(), `{"caller":"`+caller+`","string":"foo","bytes":"bar","error":"some error","bool":true,"int":1,"int8":2,"int16":3,"int32":4,"int64":5,"uint":6,"uint8":7,"uint16":8,"uint32":9,"uint64":10,"float32":11,"float64":12,"dur":1000,"time":"0001-01-01T00:00:00Z","diff":10000}`+"\n"; got != want {
|
||||
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
|
||||
}
|
||||
}
|
||||
@@ -273,7 +280,8 @@ func TestFieldsDisabled(t *testing.T) {
|
||||
|
||||
func TestMsgf(t *testing.T) {
|
||||
out := &bytes.Buffer{}
|
||||
New(out).Log().Msgf("one %s %.1f %d %v", "two", 3.4, 5, errors.New("six"))
|
||||
log := New(out)
|
||||
log.Log().Msgf("one %s %.1f %d %v", "two", 3.4, 5, errors.New("six"))
|
||||
if got, want := out.String(), `{"message":"one two 3.4 5 six"}`+"\n"; got != want {
|
||||
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
|
||||
}
|
||||
@@ -298,6 +306,42 @@ func TestLevel(t *testing.T) {
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("NoLevel/Disabled", func(t *testing.T) {
|
||||
out := &bytes.Buffer{}
|
||||
log := New(out).Level(Disabled)
|
||||
log.Log().Msg("test")
|
||||
if got, want := out.String(), ""; got != want {
|
||||
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("NoLevel/Info", func(t *testing.T) {
|
||||
out := &bytes.Buffer{}
|
||||
log := New(out).Level(InfoLevel)
|
||||
log.Log().Msg("test")
|
||||
if got, want := out.String(), `{"message":"test"}`+"\n"; got != want {
|
||||
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("NoLevel/Panic", func(t *testing.T) {
|
||||
out := &bytes.Buffer{}
|
||||
log := New(out).Level(PanicLevel)
|
||||
log.Log().Msg("test")
|
||||
if got, want := out.String(), `{"message":"test"}`+"\n"; got != want {
|
||||
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("NoLevel/WithLevel", func(t *testing.T) {
|
||||
out := &bytes.Buffer{}
|
||||
log := New(out).Level(InfoLevel)
|
||||
log.WithLevel(NoLevel).Msg("test")
|
||||
if got, want := out.String(), `{"message":"test"}`+"\n"; got != want {
|
||||
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Info", func(t *testing.T) {
|
||||
out := &bytes.Buffer{}
|
||||
log := New(out).Level(InfoLevel)
|
||||
@@ -351,10 +395,12 @@ func TestLevelWriter(t *testing.T) {
|
||||
log.Info().Msg("2")
|
||||
log.Warn().Msg("3")
|
||||
log.Error().Msg("4")
|
||||
log.Log().Msg("nolevel-1")
|
||||
log.WithLevel(DebugLevel).Msg("5")
|
||||
log.WithLevel(InfoLevel).Msg("6")
|
||||
log.WithLevel(WarnLevel).Msg("7")
|
||||
log.WithLevel(ErrorLevel).Msg("8")
|
||||
log.WithLevel(NoLevel).Msg("nolevel-2")
|
||||
|
||||
want := []struct {
|
||||
l Level
|
||||
@@ -364,10 +410,12 @@ func TestLevelWriter(t *testing.T) {
|
||||
{InfoLevel, `{"level":"info","message":"2"}` + "\n"},
|
||||
{WarnLevel, `{"level":"warn","message":"3"}` + "\n"},
|
||||
{ErrorLevel, `{"level":"error","message":"4"}` + "\n"},
|
||||
{NoLevel, `{"message":"nolevel-1"}` + "\n"},
|
||||
{DebugLevel, `{"level":"debug","message":"5"}` + "\n"},
|
||||
{InfoLevel, `{"level":"info","message":"6"}` + "\n"},
|
||||
{WarnLevel, `{"level":"warn","message":"7"}` + "\n"},
|
||||
{ErrorLevel, `{"level":"error","message":"8"}` + "\n"},
|
||||
{NoLevel, `{"message":"nolevel-2"}` + "\n"},
|
||||
}
|
||||
if got := lw.ops; !reflect.DeepEqual(got, want) {
|
||||
t.Errorf("invalid ops:\ngot:\n%v\nwant:\n%v", got, want)
|
||||
@@ -385,7 +433,7 @@ func TestContextTimestamp(t *testing.T) {
|
||||
log := New(out).With().Timestamp().Str("foo", "bar").Logger()
|
||||
log.Log().Msg("hello world")
|
||||
|
||||
if got, want := out.String(), `{"time":"2001-02-03T04:05:06Z","foo":"bar","message":"hello world"}`+"\n"; got != want {
|
||||
if got, want := out.String(), `{"foo":"bar","time":"2001-02-03T04:05:06Z","message":"hello world"}`+"\n"; got != want {
|
||||
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
|
||||
}
|
||||
}
|
||||
@@ -405,3 +453,31 @@ func TestEventTimestamp(t *testing.T) {
|
||||
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestOutputWithoutTimestamp(t *testing.T) {
|
||||
ignoredOut := &bytes.Buffer{}
|
||||
out := &bytes.Buffer{}
|
||||
log := New(ignoredOut).Output(out).With().Str("foo", "bar").Logger()
|
||||
log.Log().Msg("hello world")
|
||||
|
||||
if got, want := out.String(), `{"foo":"bar","message":"hello world"}`+"\n"; got != want {
|
||||
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestOutputWithTimestamp(t *testing.T) {
|
||||
TimestampFunc = func() time.Time {
|
||||
return time.Date(2001, time.February, 3, 4, 5, 6, 7, time.UTC)
|
||||
}
|
||||
defer func() {
|
||||
TimestampFunc = time.Now
|
||||
}()
|
||||
ignoredOut := &bytes.Buffer{}
|
||||
out := &bytes.Buffer{}
|
||||
log := New(ignoredOut).Output(out).With().Timestamp().Str("foo", "bar").Logger()
|
||||
log.Log().Msg("hello world")
|
||||
|
||||
if got, want := out.String(), `{"foo":"bar","time":"2001-02-03T04:05:06Z","message":"hello world"}`+"\n"; got != want {
|
||||
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
+3
-5
@@ -31,10 +31,8 @@ func (s RandomSampler) Sample(lvl Level) bool {
|
||||
if s <= 0 {
|
||||
return false
|
||||
}
|
||||
if s > 0 {
|
||||
if rand.Intn(int(s)) != 0 {
|
||||
return false
|
||||
}
|
||||
if rand.Intn(int(s)) != 0 {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
@@ -70,7 +68,7 @@ type BurstSampler struct {
|
||||
|
||||
// Sample implements the Sampler interface.
|
||||
func (s *BurstSampler) Sample(lvl Level) bool {
|
||||
if s.Burst > 9 && s.Period > 0 {
|
||||
if s.Burst > 0 && s.Period > 0 {
|
||||
if s.inc() <= s.Burst {
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -44,6 +44,8 @@ func (sw syslogWriter) WriteLevel(level Level, p []byte) (n int, err error) {
|
||||
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")
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
// +build !windows
|
||||
|
||||
package zerolog
|
||||
|
||||
import "testing"
|
||||
@@ -46,11 +48,13 @@ func TestSyslogWriter(t *testing.T) {
|
||||
log.Info().Msg("info")
|
||||
log.Warn().Msg("warn")
|
||||
log.Error().Msg("error")
|
||||
log.Log().Msg("nolevel")
|
||||
want := []syslogEvent{
|
||||
{"Debug", `{"level":"debug","message":"debug"}` + "\n"},
|
||||
{"Info", `{"level":"info","message":"info"}` + "\n"},
|
||||
{"Warning", `{"level":"warn","message":"warn"}` + "\n"},
|
||||
{"Err", `{"level":"error","message":"error"}` + "\n"},
|
||||
{"Info", `{"message":"nolevel"}` + "\n"},
|
||||
}
|
||||
if got := sw.events; !reflect.DeepEqual(got, want) {
|
||||
t.Errorf("Invalid syslog message routing: want %v, got %v", want, got)
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
// +build !windows
|
||||
|
||||
package zerolog
|
||||
|
||||
import (
|
||||
@@ -12,11 +14,13 @@ func TestMultiSyslogWriter(t *testing.T) {
|
||||
log.Info().Msg("info")
|
||||
log.Warn().Msg("warn")
|
||||
log.Error().Msg("error")
|
||||
log.Log().Msg("nolevel")
|
||||
want := []syslogEvent{
|
||||
{"Debug", `{"level":"debug","message":"debug"}` + "\n"},
|
||||
{"Info", `{"level":"info","message":"info"}` + "\n"},
|
||||
{"Warning", `{"level":"warn","message":"warn"}` + "\n"},
|
||||
{"Err", `{"level":"error","message":"error"}` + "\n"},
|
||||
{"Info", `{"message":"nolevel"}` + "\n"},
|
||||
}
|
||||
if got := sw.events; !reflect.DeepEqual(got, want) {
|
||||
t.Errorf("Invalid syslog message routing: want %v, got %v", want, got)
|
||||
|
||||
Reference in New Issue
Block a user