Write directly into a single shared buffer per event for even better perf
This commit is contained in:
parent
19dfb55aa8
commit
d0cfcbbafe
10
README.md
10
README.md
|
@ -15,11 +15,11 @@ The zerolog package provides a fast and simple logger dedicated to JSON output.
|
||||||
All operations are allocation free (those numbers *include* JSON encoding):
|
All operations are allocation free (those numbers *include* JSON encoding):
|
||||||
|
|
||||||
```
|
```
|
||||||
BenchmarkLogEmpty-8 50000000 22 ns/op 0 B/op 0 allocs/op
|
BenchmarkLogEmpty-8 50000000 19.8 ns/op 0 B/op 0 allocs/op
|
||||||
BenchmarkDisabled-8 100000000 9 ns/op 0 B/op 0 allocs/op
|
BenchmarkDisabled-8 100000000 4.73 ns/op 0 B/op 0 allocs/op
|
||||||
BenchmarkInfo-8 10000000 210 ns/op 0 B/op 0 allocs/op
|
BenchmarkInfo-8 10000000 85.1 ns/op 0 B/op 0 allocs/op
|
||||||
BenchmarkContextFields-8 10000000 254 ns/op 0 B/op 0 allocs/op
|
BenchmarkContextFields-8 10000000 81.9 ns/op 0 B/op 0 allocs/op
|
||||||
BenchmarkLogFields-8 5000000 377 ns/op 0 B/op 0 allocs/op
|
BenchmarkLogFields-8 5000000 247 ns/op 0 B/op 0 allocs/op
|
||||||
```
|
```
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -44,9 +45,9 @@ func BenchmarkInfo(b *testing.B) {
|
||||||
func BenchmarkContextFields(b *testing.B) {
|
func BenchmarkContextFields(b *testing.B) {
|
||||||
logger := New(ioutil.Discard).With().
|
logger := New(ioutil.Discard).With().
|
||||||
Str("string", "four!").
|
Str("string", "four!").
|
||||||
Str("time", "now"). // XXX
|
Time("time", time.Time{}).
|
||||||
Str("duration", "123"). //XXX
|
Int("int", 123).
|
||||||
Str("another string", "done!").
|
Float32("float", -2.203230293249593).
|
||||||
Logger()
|
Logger()
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
b.RunParallel(func(pb *testing.PB) {
|
b.RunParallel(func(pb *testing.PB) {
|
||||||
|
@ -63,9 +64,9 @@ func BenchmarkLogFields(b *testing.B) {
|
||||||
for pb.Next() {
|
for pb.Next() {
|
||||||
logger.Info().
|
logger.Info().
|
||||||
Str("string", "four!").
|
Str("string", "four!").
|
||||||
Str("time", "now"). // XXX
|
Time("time", time.Time{}).
|
||||||
Str("duration", "123"). //XXX
|
Int("int", 123).
|
||||||
Str("another string", "done!").
|
Float32("float", -2.203230293249593).
|
||||||
Msg(fakeMessage)
|
Msg(fakeMessage)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
76
context.go
76
context.go
|
@ -12,108 +12,118 @@ func (c Context) Logger() Logger {
|
||||||
return c.l
|
return c.l
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c Context) append(f field) Context {
|
|
||||||
return Context{
|
|
||||||
l: Logger{
|
|
||||||
parent: c.l,
|
|
||||||
w: c.l.w,
|
|
||||||
field: f.compileJSON(),
|
|
||||||
level: c.l.level,
|
|
||||||
sample: c.l.sample,
|
|
||||||
counter: c.l.counter,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Dict adds the field key with the dict to the logger context.
|
// Dict adds the field key with the dict to the logger context.
|
||||||
func (c Context) Dict(key string, dict Event) Context {
|
func (c Context) Dict(key string, dict *Event) Context {
|
||||||
dict.buf.WriteByte('}')
|
dict.buf = append(dict.buf, '}')
|
||||||
return c.append(fRaw(key, dict.buf.String()))
|
c.l.context = append(appendKey(c.l.context, key), dict.buf...)
|
||||||
|
eventPool.Put(dict)
|
||||||
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
// Str adds the field key with val as a string to the logger context.
|
// Str adds the field key with val as a string to the logger context.
|
||||||
func (c Context) Str(key, val string) Context {
|
func (c Context) Str(key, val string) Context {
|
||||||
return c.append(fStr(key, val))
|
c.l.context = appendString(c.l.context, key, val)
|
||||||
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
// Err adds the field "error" with err as a string to the logger context.
|
// Err adds the field "error" with err as a string to the logger context.
|
||||||
// To customize the key name, change zerolog.ErrorFieldName.
|
// To customize the key name, change zerolog.ErrorFieldName.
|
||||||
func (c Context) Err(err error) Context {
|
func (c Context) Err(err error) Context {
|
||||||
return c.append(fErr(err))
|
c.l.context = appendError(c.l.context, err)
|
||||||
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bool adds the field key with val as a Boolean to the logger context.
|
// Bool adds the field key with val as a Boolean to the logger context.
|
||||||
func (c Context) Bool(key string, b bool) Context {
|
func (c Context) Bool(key string, b bool) Context {
|
||||||
return c.append(fBool(key, b))
|
c.l.context = appendBool(c.l.context, key, b)
|
||||||
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
// Int adds the field key with i as a int to the logger context.
|
// Int adds the field key with i as a int to the logger context.
|
||||||
func (c Context) Int(key string, i int) Context {
|
func (c Context) Int(key string, i int) Context {
|
||||||
return c.append(fInt(key, i))
|
c.l.context = appendInt(c.l.context, key, i)
|
||||||
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
// Int8 adds the field key with i as a int8 to the logger context.
|
// Int8 adds the field key with i as a int8 to the logger context.
|
||||||
func (c Context) Int8(key string, i int8) Context {
|
func (c Context) Int8(key string, i int8) Context {
|
||||||
return c.append(fInt8(key, i))
|
c.l.context = appendInt8(c.l.context, key, i)
|
||||||
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
// Int16 adds the field key with i as a int16 to the logger context.
|
// Int16 adds the field key with i as a int16 to the logger context.
|
||||||
func (c Context) Int16(key string, i int16) Context {
|
func (c Context) Int16(key string, i int16) Context {
|
||||||
return c.append(fInt16(key, i))
|
c.l.context = appendInt16(c.l.context, key, i)
|
||||||
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
// Int32 adds the field key with i as a int32 to the logger context.
|
// Int32 adds the field key with i as a int32 to the logger context.
|
||||||
func (c Context) Int32(key string, i int32) Context {
|
func (c Context) Int32(key string, i int32) Context {
|
||||||
return c.append(fInt32(key, i))
|
c.l.context = appendInt32(c.l.context, key, i)
|
||||||
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
// Int64 adds the field key with i as a int64 to the logger context.
|
// Int64 adds the field key with i as a int64 to the logger context.
|
||||||
func (c Context) Int64(key string, i int64) Context {
|
func (c Context) Int64(key string, i int64) Context {
|
||||||
return c.append(fInt64(key, i))
|
c.l.context = appendInt64(c.l.context, key, i)
|
||||||
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
// Uint adds the field key with i as a uint to the logger context.
|
// Uint adds the field key with i as a uint to the logger context.
|
||||||
func (c Context) Uint(key string, i uint) Context {
|
func (c Context) Uint(key string, i uint) Context {
|
||||||
return c.append(fUint(key, i))
|
c.l.context = appendUint(c.l.context, key, i)
|
||||||
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
// Uint8 adds the field key with i as a uint8 to the logger context.
|
// Uint8 adds the field key with i as a uint8 to the logger context.
|
||||||
func (c Context) Uint8(key string, i uint8) Context {
|
func (c Context) Uint8(key string, i uint8) Context {
|
||||||
return c.append(fUint8(key, i))
|
c.l.context = appendUint8(c.l.context, key, i)
|
||||||
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
// Uint16 adds the field key with i as a uint16 to the logger context.
|
// Uint16 adds the field key with i as a uint16 to the logger context.
|
||||||
func (c Context) Uint16(key string, i uint16) Context {
|
func (c Context) Uint16(key string, i uint16) Context {
|
||||||
return c.append(fUint16(key, i))
|
c.l.context = appendUint16(c.l.context, key, i)
|
||||||
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
// Uint32 adds the field key with i as a uint32 to the logger context.
|
// Uint32 adds the field key with i as a uint32 to the logger context.
|
||||||
func (c Context) Uint32(key string, i uint32) Context {
|
func (c Context) Uint32(key string, i uint32) Context {
|
||||||
return c.append(fUint32(key, i))
|
c.l.context = appendUint32(c.l.context, key, i)
|
||||||
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
// Uint64 adds the field key with i as a uint64 to the logger context.
|
// Uint64 adds the field key with i as a uint64 to the logger context.
|
||||||
func (c Context) Uint64(key string, i uint64) Context {
|
func (c Context) Uint64(key string, i uint64) Context {
|
||||||
return c.append(fUint64(key, i))
|
c.l.context = appendUint64(c.l.context, key, i)
|
||||||
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
// Float32 adds the field key with f as a float32 to the logger context.
|
// Float32 adds the field key with f as a float32 to the logger context.
|
||||||
func (c Context) Float32(key string, f float32) Context {
|
func (c Context) Float32(key string, f float32) Context {
|
||||||
return c.append(fFloat32(key, f))
|
c.l.context = appendFloat32(c.l.context, key, f)
|
||||||
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
// Float64 adds the field key with f as a float64 to the logger context.
|
// Float64 adds the field key with f as a float64 to the logger context.
|
||||||
func (c Context) Float64(key string, f float64) Context {
|
func (c Context) Float64(key string, f float64) Context {
|
||||||
return c.append(fFloat64(key, f))
|
c.l.context = appendFloat64(c.l.context, key, f)
|
||||||
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
// Timestamp adds the current local time as UNIX timestamp to the logger context with the "time" key.
|
// 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.
|
// To customize the key name, change zerolog.TimestampFieldName.
|
||||||
func (c Context) Timestamp() Context {
|
func (c Context) Timestamp() Context {
|
||||||
return c.append(fTimestamp())
|
if len(c.l.context) > 0 {
|
||||||
|
c.l.context[0] = 1
|
||||||
|
} else {
|
||||||
|
c.l.context = append(c.l.context, 1)
|
||||||
|
}
|
||||||
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
// Time adds the field key with t formated as string using zerolog.TimeFieldFormat.
|
// Time adds the field key with t formated as string using zerolog.TimeFieldFormat.
|
||||||
func (c Context) Time(key string, t time.Time) Context {
|
func (c Context) Time(key string, t time.Time) Context {
|
||||||
return c.append(fTime(key, t))
|
c.l.context = appendTime(c.l.context, key, t)
|
||||||
|
return c
|
||||||
}
|
}
|
||||||
|
|
204
event.go
204
event.go
|
@ -1,83 +1,69 @@
|
||||||
package zerolog
|
package zerolog
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
var pool = &sync.Pool{
|
var eventPool = &sync.Pool{
|
||||||
New: func() interface{} {
|
New: func() interface{} {
|
||||||
return bytes.NewBuffer(make([]byte, 500))
|
return &Event{
|
||||||
|
buf: make([]byte, 0, 500),
|
||||||
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// Event represents a log event. It is instancied by one of the level method of
|
// Event represents a log event. It is instancied by one of the level method of
|
||||||
// Logger and finalized by the Msg or Msgf method.
|
// Logger and finalized by the Msg or Msgf method.
|
||||||
type Event struct {
|
type Event struct {
|
||||||
buf *bytes.Buffer
|
buf []byte
|
||||||
w LevelWriter
|
w LevelWriter
|
||||||
level Level
|
level Level
|
||||||
enabled bool
|
enabled bool
|
||||||
done func(msg string)
|
done func(msg string)
|
||||||
}
|
}
|
||||||
|
|
||||||
func newEvent(w LevelWriter, level Level, enabled bool) Event {
|
func newEvent(w LevelWriter, level Level, enabled bool) *Event {
|
||||||
if !enabled {
|
if !enabled {
|
||||||
return Event{}
|
return &Event{}
|
||||||
}
|
|
||||||
buf := pool.Get().(*bytes.Buffer)
|
|
||||||
buf.Reset()
|
|
||||||
buf.WriteByte('{')
|
|
||||||
return Event{
|
|
||||||
buf: buf,
|
|
||||||
w: w,
|
|
||||||
level: level,
|
|
||||||
enabled: true,
|
|
||||||
}
|
}
|
||||||
|
e := eventPool.Get().(*Event)
|
||||||
|
e.buf = e.buf[:1]
|
||||||
|
e.buf[0] = '{'
|
||||||
|
e.w = w
|
||||||
|
e.level = level
|
||||||
|
e.enabled = true
|
||||||
|
return e
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e Event) write() (n int, err error) {
|
func (e *Event) write() (n int, err error) {
|
||||||
if !e.enabled {
|
if !e.enabled {
|
||||||
return 0, nil
|
return 0, nil
|
||||||
}
|
}
|
||||||
e.buf.WriteByte('}')
|
e.buf = append(e.buf, '}', '\n')
|
||||||
e.buf.WriteByte('\n')
|
n, err = e.w.WriteLevel(e.level, e.buf)
|
||||||
n, err = e.w.WriteLevel(e.level, e.buf.Bytes())
|
eventPool.Put(e)
|
||||||
pool.Put(e.buf)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e Event) append(f field) Event {
|
// Enabled return false if the *Event is going to be filtered out by
|
||||||
if !e.enabled {
|
|
||||||
return e
|
|
||||||
}
|
|
||||||
if e.buf.Len() > 1 {
|
|
||||||
e.buf.WriteByte(',')
|
|
||||||
}
|
|
||||||
f.writeJSON(e.buf)
|
|
||||||
return e
|
|
||||||
}
|
|
||||||
|
|
||||||
// Enabled return false if the event is going to be filtered out by
|
|
||||||
// log level or sampling.
|
// log level or sampling.
|
||||||
func (e Event) Enabled() bool {
|
func (e *Event) Enabled() bool {
|
||||||
return e.enabled
|
return e.enabled
|
||||||
}
|
}
|
||||||
|
|
||||||
// Msg sends the event with msg added as the message field if not empty.
|
// Msg sends the *Event with msg added as the message field if not empty.
|
||||||
//
|
//
|
||||||
// NOTICE: once this methid is called, the Event should be disposed.
|
// NOTICE: once this methid is called, the *Event should be disposed.
|
||||||
// Calling Msg twice can have unexpected result.
|
// Calling Msg twice can have unexpected result.
|
||||||
func (e Event) Msg(msg string) (n int, err error) {
|
func (e *Event) Msg(msg string) (n int, err error) {
|
||||||
if !e.enabled {
|
if !e.enabled {
|
||||||
return 0, nil
|
return 0, nil
|
||||||
}
|
}
|
||||||
if msg != "" {
|
if msg != "" {
|
||||||
e.append(fStr(MessageFieldName, msg))
|
e.buf = appendString(e.buf, MessageFieldName, msg)
|
||||||
}
|
}
|
||||||
if e.done != nil {
|
if e.done != nil {
|
||||||
defer e.done(msg)
|
defer e.done(msg)
|
||||||
|
@ -85,17 +71,17 @@ func (e Event) Msg(msg string) (n int, err error) {
|
||||||
return e.write()
|
return e.write()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Msgf sends the event with formated msg added as the message field if not empty.
|
// Msgf sends the *Event with formated msg added as the message field if not empty.
|
||||||
//
|
//
|
||||||
// NOTICE: once this methid is called, the Event should be disposed.
|
// NOTICE: once this methid is called, the *Event should be disposed.
|
||||||
// Calling Msg twice can have unexpected result.
|
// Calling Msg twice can have unexpected result.
|
||||||
func (e Event) Msgf(format string, v ...interface{}) (n int, err error) {
|
func (e *Event) Msgf(format string, v ...interface{}) (n int, err error) {
|
||||||
if !e.enabled {
|
if !e.enabled {
|
||||||
return 0, nil
|
return 0, nil
|
||||||
}
|
}
|
||||||
msg := fmt.Sprintf(format, v...)
|
msg := fmt.Sprintf(format, v...)
|
||||||
if msg != "" {
|
if msg != "" {
|
||||||
e.append(fStr(MessageFieldName, msg))
|
e.buf = appendString(e.buf, MessageFieldName, msg)
|
||||||
}
|
}
|
||||||
if e.done != nil {
|
if e.done != nil {
|
||||||
defer e.done(msg)
|
defer e.done(msg)
|
||||||
|
@ -103,161 +89,175 @@ func (e Event) Msgf(format string, v ...interface{}) (n int, err error) {
|
||||||
return e.write()
|
return e.write()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dict adds the field key with a dict to the event context.
|
// Dict adds the field key with a dict to the *Event context.
|
||||||
// Use zerolog.Dict() to create the dictionary.
|
// Use zerolog.Dict() to create the dictionary.
|
||||||
func (e Event) Dict(key string, dict Event) Event {
|
func (e *Event) Dict(key string, dict *Event) *Event {
|
||||||
if !e.enabled {
|
if !e.enabled {
|
||||||
return e
|
return e
|
||||||
}
|
}
|
||||||
if e.buf.Len() > 1 {
|
e.buf = append(append(appendKey(e.buf, key), dict.buf...), '}')
|
||||||
e.buf.WriteByte(',')
|
eventPool.Put(dict)
|
||||||
}
|
|
||||||
io.Copy(e.buf, dict.buf)
|
|
||||||
e.buf.WriteByte('}')
|
|
||||||
return e
|
return e
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dict creates an Event to be used with the event.Dict method.
|
// Dict creates an Event to be used with the *Event.Dict method.
|
||||||
// Call usual field methods like Str, Int etc to add fields to this
|
// Call usual field methods like Str, Int etc to add fields to this
|
||||||
// event and give it as argument the event.Dict method.
|
// event and give it as argument the *Event.Dict method.
|
||||||
func Dict() Event {
|
func Dict() *Event {
|
||||||
return newEvent(levelWriterAdapter{ioutil.Discard}, 0, true)
|
return newEvent(levelWriterAdapter{ioutil.Discard}, 0, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Str adds the field key with val as a string to the event context.
|
// Str adds the field key with val as a string to the *Event context.
|
||||||
func (e Event) Str(key, val string) Event {
|
func (e *Event) Str(key, val string) *Event {
|
||||||
if !e.enabled {
|
if !e.enabled {
|
||||||
return e
|
return e
|
||||||
}
|
}
|
||||||
return e.append(fStr(key, val))
|
e.buf = appendString(e.buf, key, val)
|
||||||
|
return e
|
||||||
}
|
}
|
||||||
|
|
||||||
// Err adds the field "error" with err as a string to the event context.
|
// Err adds the field "error" with err as a string to the *Event context.
|
||||||
// To customize the key name, change zerolog.ErrorFieldName.
|
// To customize the key name, change zerolog.ErrorFieldName.
|
||||||
func (e Event) Err(err error) Event {
|
func (e *Event) Err(err error) *Event {
|
||||||
if !e.enabled {
|
if !e.enabled {
|
||||||
return e
|
return e
|
||||||
}
|
}
|
||||||
return e.append(fErr(err))
|
e.buf = appendError(e.buf, err)
|
||||||
|
return e
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bool adds the field key with val as a Boolean to the event context.
|
// Bool adds the field key with val as a Boolean to the *Event context.
|
||||||
func (e Event) Bool(key string, b bool) Event {
|
func (e *Event) Bool(key string, b bool) *Event {
|
||||||
if !e.enabled {
|
if !e.enabled {
|
||||||
return e
|
return e
|
||||||
}
|
}
|
||||||
return e.append(fBool(key, b))
|
e.buf = appendBool(e.buf, key, b)
|
||||||
|
return e
|
||||||
}
|
}
|
||||||
|
|
||||||
// Int adds the field key with i as a int to the event context.
|
// Int adds the field key with i as a int to the *Event context.
|
||||||
func (e Event) Int(key string, i int) Event {
|
func (e *Event) Int(key string, i int) *Event {
|
||||||
if !e.enabled {
|
if !e.enabled {
|
||||||
return e
|
return e
|
||||||
}
|
}
|
||||||
return e.append(fInt(key, i))
|
e.buf = appendInt(e.buf, key, i)
|
||||||
|
return e
|
||||||
}
|
}
|
||||||
|
|
||||||
// Int8 adds the field key with i as a int8 to the event context.
|
// Int8 adds the field key with i as a int8 to the *Event context.
|
||||||
func (e Event) Int8(key string, i int8) Event {
|
func (e *Event) Int8(key string, i int8) *Event {
|
||||||
if !e.enabled {
|
if !e.enabled {
|
||||||
return e
|
return e
|
||||||
}
|
}
|
||||||
return e.append(fInt8(key, i))
|
e.buf = appendInt8(e.buf, key, i)
|
||||||
|
return e
|
||||||
}
|
}
|
||||||
|
|
||||||
// Int16 adds the field key with i as a int16 to the event context.
|
// Int16 adds the field key with i as a int16 to the *Event context.
|
||||||
func (e Event) Int16(key string, i int16) Event {
|
func (e *Event) Int16(key string, i int16) *Event {
|
||||||
if !e.enabled {
|
if !e.enabled {
|
||||||
return e
|
return e
|
||||||
}
|
}
|
||||||
return e.append(fInt16(key, i))
|
e.buf = appendInt16(e.buf, key, i)
|
||||||
|
return e
|
||||||
}
|
}
|
||||||
|
|
||||||
// Int32 adds the field key with i as a int32 to the event context.
|
// Int32 adds the field key with i as a int32 to the *Event context.
|
||||||
func (e Event) Int32(key string, i int32) Event {
|
func (e *Event) Int32(key string, i int32) *Event {
|
||||||
if !e.enabled {
|
if !e.enabled {
|
||||||
return e
|
return e
|
||||||
}
|
}
|
||||||
return e.append(fInt32(key, i))
|
e.buf = appendInt32(e.buf, key, i)
|
||||||
|
return e
|
||||||
}
|
}
|
||||||
|
|
||||||
// Int64 adds the field key with i as a int64 to the event context.
|
// Int64 adds the field key with i as a int64 to the *Event context.
|
||||||
func (e Event) Int64(key string, i int64) Event {
|
func (e *Event) Int64(key string, i int64) *Event {
|
||||||
if !e.enabled {
|
if !e.enabled {
|
||||||
return e
|
return e
|
||||||
}
|
}
|
||||||
return e.append(fInt64(key, i))
|
e.buf = appendInt64(e.buf, key, i)
|
||||||
|
return e
|
||||||
}
|
}
|
||||||
|
|
||||||
// Uint adds the field key with i as a uint to the event context.
|
// Uint adds the field key with i as a uint to the *Event context.
|
||||||
func (e Event) Uint(key string, i uint) Event {
|
func (e *Event) Uint(key string, i uint) *Event {
|
||||||
if !e.enabled {
|
if !e.enabled {
|
||||||
return e
|
return e
|
||||||
}
|
}
|
||||||
return e.append(fUint(key, i))
|
e.buf = appendUint(e.buf, key, i)
|
||||||
|
return e
|
||||||
}
|
}
|
||||||
|
|
||||||
// Uint8 adds the field key with i as a uint8 to the event context.
|
// Uint8 adds the field key with i as a uint8 to the *Event context.
|
||||||
func (e Event) Uint8(key string, i uint8) Event {
|
func (e *Event) Uint8(key string, i uint8) *Event {
|
||||||
if !e.enabled {
|
if !e.enabled {
|
||||||
return e
|
return e
|
||||||
}
|
}
|
||||||
return e.append(fUint8(key, i))
|
e.buf = appendUint8(e.buf, key, i)
|
||||||
|
return e
|
||||||
}
|
}
|
||||||
|
|
||||||
// Uint16 adds the field key with i as a uint16 to the event context.
|
// Uint16 adds the field key with i as a uint16 to the *Event context.
|
||||||
func (e Event) Uint16(key string, i uint16) Event {
|
func (e *Event) Uint16(key string, i uint16) *Event {
|
||||||
if !e.enabled {
|
if !e.enabled {
|
||||||
return e
|
return e
|
||||||
}
|
}
|
||||||
return e.append(fUint16(key, i))
|
e.buf = appendUint16(e.buf, key, i)
|
||||||
|
return e
|
||||||
}
|
}
|
||||||
|
|
||||||
// Uint32 adds the field key with i as a uint32 to the event context.
|
// Uint32 adds the field key with i as a uint32 to the *Event context.
|
||||||
func (e Event) Uint32(key string, i uint32) Event {
|
func (e *Event) Uint32(key string, i uint32) *Event {
|
||||||
if !e.enabled {
|
if !e.enabled {
|
||||||
return e
|
return e
|
||||||
}
|
}
|
||||||
return e.append(fUint32(key, i))
|
e.buf = appendUint32(e.buf, key, i)
|
||||||
|
return e
|
||||||
}
|
}
|
||||||
|
|
||||||
// Uint64 adds the field key with i as a uint64 to the event context.
|
// Uint64 adds the field key with i as a uint64 to the *Event context.
|
||||||
func (e Event) Uint64(key string, i uint64) Event {
|
func (e *Event) Uint64(key string, i uint64) *Event {
|
||||||
if !e.enabled {
|
if !e.enabled {
|
||||||
return e
|
return e
|
||||||
}
|
}
|
||||||
return e.append(fUint64(key, i))
|
e.buf = appendUint64(e.buf, key, i)
|
||||||
|
return e
|
||||||
}
|
}
|
||||||
|
|
||||||
// Float32 adds the field key with f as a float32 to the event context.
|
// Float32 adds the field key with f as a float32 to the *Event context.
|
||||||
func (e Event) Float32(key string, f float32) Event {
|
func (e *Event) Float32(key string, f float32) *Event {
|
||||||
if !e.enabled {
|
if !e.enabled {
|
||||||
return e
|
return e
|
||||||
}
|
}
|
||||||
return e.append(fFloat32(key, f))
|
e.buf = appendFloat32(e.buf, key, f)
|
||||||
|
return e
|
||||||
}
|
}
|
||||||
|
|
||||||
// Float64 adds the field key with f as a float64 to the event context.
|
// Float64 adds the field key with f as a float64 to the *Event context.
|
||||||
func (e Event) Float64(key string, f float64) Event {
|
func (e *Event) Float64(key string, f float64) *Event {
|
||||||
if !e.enabled {
|
if !e.enabled {
|
||||||
return e
|
return e
|
||||||
}
|
}
|
||||||
return e.append(fFloat64(key, f))
|
e.buf = appendFloat64(e.buf, key, f)
|
||||||
|
return e
|
||||||
}
|
}
|
||||||
|
|
||||||
// Timestamp adds the current local time as UNIX timestamp to the event context with the "time" key.
|
// 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.
|
// To customize the key name, change zerolog.TimestampFieldName.
|
||||||
func (e Event) Timestamp() Event {
|
func (e *Event) Timestamp() *Event {
|
||||||
if !e.enabled {
|
if !e.enabled {
|
||||||
return e
|
return e
|
||||||
}
|
}
|
||||||
return e.append(fTimestamp())
|
e.buf = appendTimestamp(e.buf)
|
||||||
|
return e
|
||||||
}
|
}
|
||||||
|
|
||||||
// Time adds the field key with t formated as string using zerolog.TimeFieldFormat.
|
// Time adds the field key with t formated as string using zerolog.TimeFieldFormat.
|
||||||
func (e Event) Time(key string, t time.Time) Event {
|
func (e *Event) Time(key string, t time.Time) *Event {
|
||||||
if !e.enabled {
|
if !e.enabled {
|
||||||
return e
|
return e
|
||||||
}
|
}
|
||||||
return e.append(fTime(key, t))
|
e.buf = appendTime(e.buf, key, t)
|
||||||
|
return e
|
||||||
}
|
}
|
||||||
|
|
211
field.go
211
field.go
|
@ -1,141 +1,94 @@
|
||||||
package zerolog
|
package zerolog
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
var now = time.Now
|
var now = time.Now
|
||||||
|
|
||||||
type fieldMode uint8
|
func appendKey(dst []byte, key string) []byte {
|
||||||
|
if len(dst) > 1 {
|
||||||
const (
|
dst = append(dst, ',')
|
||||||
zeroFieldMode fieldMode = iota
|
|
||||||
rawFieldMode
|
|
||||||
quotedFieldMode
|
|
||||||
precomputedFieldMode
|
|
||||||
timestampFieldMode
|
|
||||||
)
|
|
||||||
|
|
||||||
// field define a logger field.
|
|
||||||
type field struct {
|
|
||||||
key string
|
|
||||||
mode fieldMode
|
|
||||||
val string
|
|
||||||
json []byte
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f field) writeJSON(buf *bytes.Buffer) {
|
|
||||||
switch f.mode {
|
|
||||||
case zeroFieldMode:
|
|
||||||
return
|
|
||||||
case precomputedFieldMode:
|
|
||||||
buf.Write(f.json)
|
|
||||||
return
|
|
||||||
case timestampFieldMode:
|
|
||||||
writeJSONString(buf, TimestampFieldName)
|
|
||||||
buf.WriteByte(':')
|
|
||||||
buf.WriteString(strconv.FormatInt(now().Unix(), 10))
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
writeJSONString(buf, f.key)
|
dst = appendJSONString(dst, key)
|
||||||
buf.WriteByte(':')
|
return append(dst, ':')
|
||||||
switch f.mode {
|
}
|
||||||
case quotedFieldMode:
|
|
||||||
writeJSONString(buf, f.val)
|
func appendString(dst []byte, key, val string) []byte {
|
||||||
case rawFieldMode:
|
return appendJSONString(appendKey(dst, key), val)
|
||||||
buf.WriteString(f.val)
|
}
|
||||||
default:
|
|
||||||
panic("unknown field mode")
|
func appendError(dst []byte, err error) []byte {
|
||||||
|
return appendJSONString(appendKey(dst, ErrorFieldName), err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
func appendBool(dst []byte, key string, val bool) []byte {
|
||||||
|
return strconv.AppendBool(appendKey(dst, key), val)
|
||||||
|
}
|
||||||
|
|
||||||
|
func appendInt(dst []byte, key string, val int) []byte {
|
||||||
|
return strconv.AppendInt(appendKey(dst, key), int64(val), 10)
|
||||||
|
}
|
||||||
|
|
||||||
|
func appendInt8(dst []byte, key string, val int8) []byte {
|
||||||
|
return strconv.AppendInt(appendKey(dst, key), int64(val), 10)
|
||||||
|
}
|
||||||
|
|
||||||
|
func appendInt16(dst []byte, key string, val int16) []byte {
|
||||||
|
return strconv.AppendInt(appendKey(dst, key), int64(val), 10)
|
||||||
|
}
|
||||||
|
|
||||||
|
func appendInt32(dst []byte, key string, val int32) []byte {
|
||||||
|
return strconv.AppendInt(appendKey(dst, key), int64(val), 10)
|
||||||
|
}
|
||||||
|
|
||||||
|
func appendInt64(dst []byte, key string, val int64) []byte {
|
||||||
|
return strconv.AppendInt(appendKey(dst, key), int64(val), 10)
|
||||||
|
}
|
||||||
|
|
||||||
|
func appendUint(dst []byte, key string, val uint) []byte {
|
||||||
|
return strconv.AppendUint(appendKey(dst, key), uint64(val), 10)
|
||||||
|
}
|
||||||
|
|
||||||
|
func appendUint8(dst []byte, key string, val uint8) []byte {
|
||||||
|
return strconv.AppendUint(appendKey(dst, key), uint64(val), 10)
|
||||||
|
}
|
||||||
|
|
||||||
|
func appendUint16(dst []byte, key string, val uint16) []byte {
|
||||||
|
return strconv.AppendUint(appendKey(dst, key), uint64(val), 10)
|
||||||
|
}
|
||||||
|
|
||||||
|
func appendUint32(dst []byte, key string, val uint32) []byte {
|
||||||
|
return strconv.AppendUint(appendKey(dst, key), uint64(val), 10)
|
||||||
|
}
|
||||||
|
|
||||||
|
func appendUint64(dst []byte, key string, val uint64) []byte {
|
||||||
|
return strconv.AppendUint(appendKey(dst, key), uint64(val), 10)
|
||||||
|
}
|
||||||
|
|
||||||
|
func appendFloat32(dst []byte, key string, val float32) []byte {
|
||||||
|
return strconv.AppendFloat(appendKey(dst, key), float64(val), 'f', -1, 32)
|
||||||
|
}
|
||||||
|
|
||||||
|
func appendFloat64(dst []byte, key string, val float64) []byte {
|
||||||
|
return strconv.AppendFloat(appendKey(dst, key), float64(val), 'f', -1, 32)
|
||||||
|
}
|
||||||
|
|
||||||
|
func appendTime(dst []byte, key string, t time.Time) []byte {
|
||||||
|
return append(t.AppendFormat(append(appendKey(dst, key), '"'), TimeFieldFormat), '"')
|
||||||
|
}
|
||||||
|
|
||||||
|
func appendTimestamp(dst []byte) []byte {
|
||||||
|
return appendInt64(dst, TimestampFieldName, now().Unix())
|
||||||
|
}
|
||||||
|
|
||||||
|
func appendObject(dst []byte, key string, obj interface{}) []byte {
|
||||||
|
marshaled, err := json.Marshal(obj)
|
||||||
|
if err != nil {
|
||||||
|
return appendString(dst, key, fmt.Sprintf("marshaling error: %v", err))
|
||||||
}
|
}
|
||||||
}
|
return append(appendKey(dst, key), marshaled...)
|
||||||
|
|
||||||
func (f field) compileJSON() field {
|
|
||||||
switch f.mode {
|
|
||||||
case zeroFieldMode, precomputedFieldMode, timestampFieldMode:
|
|
||||||
return f
|
|
||||||
}
|
|
||||||
buf := &bytes.Buffer{}
|
|
||||||
f.writeJSON(buf)
|
|
||||||
cf := field{
|
|
||||||
mode: precomputedFieldMode,
|
|
||||||
json: buf.Bytes(),
|
|
||||||
}
|
|
||||||
return cf
|
|
||||||
}
|
|
||||||
|
|
||||||
func fStr(key, val string) field {
|
|
||||||
return field{key, quotedFieldMode, val, nil}
|
|
||||||
}
|
|
||||||
|
|
||||||
func fErr(err error) field {
|
|
||||||
return field{ErrorFieldName, quotedFieldMode, err.Error(), nil}
|
|
||||||
}
|
|
||||||
|
|
||||||
func fBool(key string, b bool) field {
|
|
||||||
if b {
|
|
||||||
return field{key, rawFieldMode, "true", nil}
|
|
||||||
}
|
|
||||||
return field{key, rawFieldMode, "false", nil}
|
|
||||||
}
|
|
||||||
|
|
||||||
func fInt(key string, i int) field {
|
|
||||||
return field{key, rawFieldMode, strconv.FormatInt(int64(i), 10), nil}
|
|
||||||
}
|
|
||||||
|
|
||||||
func fInt8(key string, i int8) field {
|
|
||||||
return field{key, rawFieldMode, strconv.FormatInt(int64(i), 10), nil}
|
|
||||||
}
|
|
||||||
|
|
||||||
func fInt16(key string, i int16) field {
|
|
||||||
return field{key, rawFieldMode, strconv.FormatInt(int64(i), 10), nil}
|
|
||||||
}
|
|
||||||
|
|
||||||
func fInt32(key string, i int32) field {
|
|
||||||
return field{key, rawFieldMode, strconv.FormatInt(int64(i), 10), nil}
|
|
||||||
}
|
|
||||||
|
|
||||||
func fInt64(key string, i int64) field {
|
|
||||||
return field{key, rawFieldMode, strconv.FormatInt(i, 10), nil}
|
|
||||||
}
|
|
||||||
|
|
||||||
func fUint(key string, i uint) field {
|
|
||||||
return field{key, rawFieldMode, strconv.FormatUint(uint64(i), 10), nil}
|
|
||||||
}
|
|
||||||
|
|
||||||
func fUint8(key string, i uint8) field {
|
|
||||||
return field{key, rawFieldMode, strconv.FormatUint(uint64(i), 10), nil}
|
|
||||||
}
|
|
||||||
|
|
||||||
func fUint16(key string, i uint16) field {
|
|
||||||
return field{key, rawFieldMode, strconv.FormatUint(uint64(i), 10), nil}
|
|
||||||
}
|
|
||||||
|
|
||||||
func fUint32(key string, i uint32) field {
|
|
||||||
return field{key, rawFieldMode, strconv.FormatUint(uint64(i), 10), nil}
|
|
||||||
}
|
|
||||||
|
|
||||||
func fUint64(key string, i uint64) field {
|
|
||||||
return field{key, rawFieldMode, strconv.FormatUint(i, 10), nil}
|
|
||||||
}
|
|
||||||
|
|
||||||
func fFloat32(key string, f float32) field {
|
|
||||||
return field{key, rawFieldMode, strconv.FormatFloat(float64(f), 'f', -1, 32), nil}
|
|
||||||
}
|
|
||||||
|
|
||||||
func fFloat64(key string, f float64) field {
|
|
||||||
return field{key, rawFieldMode, strconv.FormatFloat(f, 'f', -1, 64), nil}
|
|
||||||
}
|
|
||||||
|
|
||||||
func fTimestamp() field {
|
|
||||||
return field{mode: timestampFieldMode}
|
|
||||||
}
|
|
||||||
|
|
||||||
func fTime(key string, t time.Time) field {
|
|
||||||
return field{key, quotedFieldMode, t.Format(TimeFieldFormat), nil}
|
|
||||||
}
|
|
||||||
|
|
||||||
func fRaw(key string, raw string) field {
|
|
||||||
return field{key, rawFieldMode, raw, nil}
|
|
||||||
}
|
}
|
||||||
|
|
78
json.go
78
json.go
|
@ -1,42 +1,31 @@
|
||||||
package zerolog
|
package zerolog
|
||||||
|
|
||||||
import (
|
import "unicode/utf8"
|
||||||
"bytes"
|
|
||||||
"unicode/utf8"
|
|
||||||
)
|
|
||||||
|
|
||||||
const hex = "0123456789abcdef"
|
const hex = "0123456789abcdef"
|
||||||
|
|
||||||
func writeJSONString(buf *bytes.Buffer, s string) {
|
func appendJSONString(dst []byte, s string) []byte {
|
||||||
buf.WriteByte('"')
|
dst = append(dst, '"')
|
||||||
for i := 0; i < len(s); {
|
for i := 0; i < len(s); {
|
||||||
if b := s[i]; b < utf8.RuneSelf {
|
if b := s[i]; b < utf8.RuneSelf {
|
||||||
switch b {
|
switch b {
|
||||||
case '"', '\\':
|
case '"', '\\':
|
||||||
buf.WriteByte('\\')
|
dst = append(dst, '\\', b)
|
||||||
buf.WriteByte(b)
|
|
||||||
case '\b':
|
case '\b':
|
||||||
buf.WriteByte('\\')
|
dst = append(dst, '\\', 'b')
|
||||||
buf.WriteByte('b')
|
|
||||||
case '\f':
|
case '\f':
|
||||||
buf.WriteByte('\\')
|
dst = append(dst, '\\', 'f')
|
||||||
buf.WriteByte('f')
|
|
||||||
case '\n':
|
case '\n':
|
||||||
buf.WriteByte('\\')
|
dst = append(dst, '\\', 'n')
|
||||||
buf.WriteByte('n')
|
|
||||||
case '\r':
|
case '\r':
|
||||||
buf.WriteByte('\\')
|
dst = append(dst, '\\', 'r')
|
||||||
buf.WriteByte('r')
|
|
||||||
case '\t':
|
case '\t':
|
||||||
buf.WriteByte('\\')
|
dst = append(dst, '\\', 't')
|
||||||
buf.WriteByte('t')
|
|
||||||
default:
|
default:
|
||||||
if b >= 0x20 {
|
if b >= 0x20 {
|
||||||
buf.WriteByte(b)
|
dst = append(dst, b)
|
||||||
} else {
|
} else {
|
||||||
buf.WriteString(`\u00`)
|
dst = append(dst, '\\', 'u', '0', '0', hex[b>>4], hex[b&0xF])
|
||||||
buf.WriteByte(hex[b>>4])
|
|
||||||
buf.WriteByte(hex[b&0xF])
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
i++
|
i++
|
||||||
|
@ -44,12 +33,51 @@ func writeJSONString(buf *bytes.Buffer, s string) {
|
||||||
}
|
}
|
||||||
r, size := utf8.DecodeRuneInString(s[i:])
|
r, size := utf8.DecodeRuneInString(s[i:])
|
||||||
if r == utf8.RuneError && size == 1 {
|
if r == utf8.RuneError && size == 1 {
|
||||||
buf.WriteString(`\ufffd`)
|
dst = append(dst, `\ufffd`...)
|
||||||
i++
|
i++
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
buf.WriteString(s[i : i+size])
|
dst = append(dst, s[i:i+size]...)
|
||||||
i += size
|
i += size
|
||||||
}
|
}
|
||||||
buf.WriteByte('"')
|
return append(dst, '"')
|
||||||
|
}
|
||||||
|
|
||||||
|
func appendJSONBytes(dst []byte, s []byte) []byte {
|
||||||
|
dst = append(dst, '"')
|
||||||
|
for i := 0; i < len(s); {
|
||||||
|
if b := s[i]; b < utf8.RuneSelf {
|
||||||
|
switch b {
|
||||||
|
case '"', '\\':
|
||||||
|
dst = append(dst, '\\', b)
|
||||||
|
case '\b':
|
||||||
|
dst = append(dst, '\\', 'b')
|
||||||
|
case '\f':
|
||||||
|
dst = append(dst, '\\', 'f')
|
||||||
|
case '\n':
|
||||||
|
dst = append(dst, '\\', 'n')
|
||||||
|
case '\r':
|
||||||
|
dst = append(dst, '\\', 'r')
|
||||||
|
case '\t':
|
||||||
|
dst = append(dst, '\\', 't')
|
||||||
|
default:
|
||||||
|
if b >= 0x20 {
|
||||||
|
dst = append(dst, b)
|
||||||
|
} else {
|
||||||
|
dst = append(dst, '\\', 'u', '0', '0', hex[b>>4], hex[b&0xF])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
i++
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
r, size := utf8.DecodeRune(s[i:])
|
||||||
|
if r == utf8.RuneError && size == 1 {
|
||||||
|
dst = append(dst, `\ufffd`...)
|
||||||
|
i++
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
dst = append(dst, s[i:i+size]...)
|
||||||
|
i += size
|
||||||
|
}
|
||||||
|
return append(dst, '"')
|
||||||
}
|
}
|
||||||
|
|
64
log.go
64
log.go
|
@ -74,10 +74,6 @@ import (
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
)
|
)
|
||||||
|
|
||||||
type parentLogger interface {
|
|
||||||
addContextField(Event)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Level defines log levels.
|
// Level defines log levels.
|
||||||
type Level uint8
|
type Level uint8
|
||||||
|
|
||||||
|
@ -133,13 +129,11 @@ var disabledEvent = newEvent(levelWriterAdapter{ioutil.Discard}, 0, false)
|
||||||
// serialization to the Writer. If your Writer is not thread safe,
|
// serialization to the Writer. If your Writer is not thread safe,
|
||||||
// you may consider a sync wrapper.
|
// you may consider a sync wrapper.
|
||||||
type Logger struct {
|
type Logger struct {
|
||||||
root bool
|
|
||||||
parent parentLogger
|
|
||||||
w LevelWriter
|
w LevelWriter
|
||||||
field field
|
|
||||||
level Level
|
level Level
|
||||||
sample uint32
|
sample uint32
|
||||||
counter *uint32
|
counter *uint32
|
||||||
|
context []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
// New creates a root logger with given output writer. If the output writer implements
|
// New creates a root logger with given output writer. If the output writer implements
|
||||||
|
@ -157,25 +151,30 @@ func New(w io.Writer) Logger {
|
||||||
if !ok {
|
if !ok {
|
||||||
lw = levelWriterAdapter{w}
|
lw = levelWriterAdapter{w}
|
||||||
}
|
}
|
||||||
return Logger{
|
return Logger{w: lw}
|
||||||
root: true,
|
|
||||||
w: lw,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// With creates a child logger with the field added to its context.
|
// With creates a child logger with the field added to its context.
|
||||||
func (l Logger) With() Context {
|
func (l Logger) With() Context {
|
||||||
|
context := l.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}
|
return Context{l}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Level crestes a child logger with the minium accepted level set to level.
|
// Level crestes a child logger with the minium accepted level set to level.
|
||||||
func (l Logger) Level(lvl Level) Logger {
|
func (l Logger) Level(lvl Level) Logger {
|
||||||
return Logger{
|
return Logger{
|
||||||
parent: l,
|
|
||||||
w: l.w,
|
w: l.w,
|
||||||
level: lvl,
|
level: lvl,
|
||||||
sample: l.sample,
|
sample: l.sample,
|
||||||
counter: l.counter,
|
counter: l.counter,
|
||||||
|
context: l.context,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -184,45 +183,45 @@ func (l Logger) Sample(every int) Logger {
|
||||||
if every == 0 {
|
if every == 0 {
|
||||||
// Create a child with no sampling.
|
// Create a child with no sampling.
|
||||||
return Logger{
|
return Logger{
|
||||||
parent: l,
|
|
||||||
w: l.w,
|
w: l.w,
|
||||||
level: l.level,
|
level: l.level,
|
||||||
|
context: l.context,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Logger{
|
return Logger{
|
||||||
parent: l,
|
|
||||||
w: l.w,
|
w: l.w,
|
||||||
level: l.level,
|
level: l.level,
|
||||||
sample: uint32(every),
|
sample: uint32(every),
|
||||||
counter: new(uint32),
|
counter: new(uint32),
|
||||||
|
context: l.context,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Debug starts a new message with debug level.
|
// Debug starts a new message with debug level.
|
||||||
//
|
//
|
||||||
// You must call Msg on the returned event in order to send the event.
|
// You must call Msg on the returned event in order to send the event.
|
||||||
func (l Logger) Debug() Event {
|
func (l Logger) Debug() *Event {
|
||||||
return l.newEvent(DebugLevel, true, nil)
|
return l.newEvent(DebugLevel, true, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Info starts a new message with info level.
|
// Info starts a new message with info level.
|
||||||
//
|
//
|
||||||
// You must call Msg on the returned event in order to send the event.
|
// You must call Msg on the returned event in order to send the event.
|
||||||
func (l Logger) Info() Event {
|
func (l Logger) Info() *Event {
|
||||||
return l.newEvent(InfoLevel, true, nil)
|
return l.newEvent(InfoLevel, true, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Warn starts a new message with warn level.
|
// Warn starts a new message with warn level.
|
||||||
//
|
//
|
||||||
// You must call Msg on the returned event in order to send the event.
|
// You must call Msg on the returned event in order to send the event.
|
||||||
func (l Logger) Warn() Event {
|
func (l Logger) Warn() *Event {
|
||||||
return l.newEvent(WarnLevel, true, nil)
|
return l.newEvent(WarnLevel, true, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Error starts a new message with error level.
|
// Error starts a new message with error level.
|
||||||
//
|
//
|
||||||
// You must call Msg on the returned event in order to send the event.
|
// You must call Msg on the returned event in order to send the event.
|
||||||
func (l Logger) Error() Event {
|
func (l Logger) Error() *Event {
|
||||||
return l.newEvent(ErrorLevel, true, nil)
|
return l.newEvent(ErrorLevel, true, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -230,7 +229,7 @@ func (l Logger) Error() Event {
|
||||||
// is called by the Msg method.
|
// is called by the Msg method.
|
||||||
//
|
//
|
||||||
// You must call Msg on the returned event in order to send the event.
|
// You must call Msg on the returned event in order to send the event.
|
||||||
func (l Logger) Fatal() Event {
|
func (l Logger) Fatal() *Event {
|
||||||
return l.newEvent(FatalLevel, true, func(msg string) { os.Exit(1) })
|
return l.newEvent(FatalLevel, true, func(msg string) { os.Exit(1) })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -238,7 +237,7 @@ func (l Logger) Fatal() Event {
|
||||||
// to the panic function.
|
// to the panic function.
|
||||||
//
|
//
|
||||||
// You must call Msg on the returned event in order to send the event.
|
// You must call Msg on the returned event in order to send the event.
|
||||||
func (l Logger) Panic() Event {
|
func (l Logger) Panic() *Event {
|
||||||
return l.newEvent(PanicLevel, true, func(msg string) { panic(msg) })
|
return l.newEvent(PanicLevel, true, func(msg string) { panic(msg) })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -246,11 +245,11 @@ func (l Logger) Panic() Event {
|
||||||
// will still disable events produced by this method.
|
// will still disable events produced by this method.
|
||||||
//
|
//
|
||||||
// You must call Msg on the returned event in order to send the event.
|
// You must call Msg on the returned event in order to send the event.
|
||||||
func (l Logger) Log() Event {
|
func (l Logger) Log() *Event {
|
||||||
return l.newEvent(ErrorLevel, false, nil)
|
return l.newEvent(ErrorLevel, false, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l Logger) newEvent(level Level, addLevelField bool, done func(string)) Event {
|
func (l Logger) newEvent(level Level, addLevelField bool, done func(string)) *Event {
|
||||||
enabled := l.should(level)
|
enabled := l.should(level)
|
||||||
if !enabled {
|
if !enabled {
|
||||||
return disabledEvent
|
return disabledEvent
|
||||||
|
@ -266,7 +265,17 @@ func (l Logger) newEvent(level Level, addLevelField bool, done func(string)) Eve
|
||||||
if l.sample > 0 && SampleFieldName != "" {
|
if l.sample > 0 && SampleFieldName != "" {
|
||||||
e.Uint32(SampleFieldName, l.sample)
|
e.Uint32(SampleFieldName, l.sample)
|
||||||
}
|
}
|
||||||
l.addContextField(e)
|
if l.context != nil && len(l.context) > 0 {
|
||||||
|
if l.context[0] > 0 { // ts flag
|
||||||
|
e.buf = appendTimestamp(e.buf)
|
||||||
|
}
|
||||||
|
if len(l.context) > 1 {
|
||||||
|
if len(e.buf) > 1 {
|
||||||
|
e.buf = append(e.buf, ',')
|
||||||
|
}
|
||||||
|
e.buf = append(e.buf, l.context[1:]...)
|
||||||
|
}
|
||||||
|
}
|
||||||
return e
|
return e
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -281,12 +290,3 @@ func (l Logger) should(lvl Level) bool {
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l Logger) addContextField(e Event) {
|
|
||||||
if !l.root {
|
|
||||||
l.parent.addContextField(e)
|
|
||||||
}
|
|
||||||
if l.field.mode != zeroFieldMode {
|
|
||||||
e.append(l.field)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
14
log/log.go
14
log/log.go
|
@ -28,28 +28,28 @@ func Sample(every int) zerolog.Logger {
|
||||||
// Debug starts a new message with debug level.
|
// Debug starts a new message with debug level.
|
||||||
//
|
//
|
||||||
// You must call Msg on the returned event in order to send the event.
|
// You must call Msg on the returned event in order to send the event.
|
||||||
func Debug() zerolog.Event {
|
func Debug() *zerolog.Event {
|
||||||
return Logger.Debug()
|
return Logger.Debug()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Info starts a new message with info level.
|
// Info starts a new message with info level.
|
||||||
//
|
//
|
||||||
// You must call Msg on the returned event in order to send the event.
|
// You must call Msg on the returned event in order to send the event.
|
||||||
func Info() zerolog.Event {
|
func Info() *zerolog.Event {
|
||||||
return Logger.Info()
|
return Logger.Info()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Warn starts a new message with warn level.
|
// Warn starts a new message with warn level.
|
||||||
//
|
//
|
||||||
// You must call Msg on the returned event in order to send the event.
|
// You must call Msg on the returned event in order to send the event.
|
||||||
func Warn() zerolog.Event {
|
func Warn() *zerolog.Event {
|
||||||
return Logger.Warn()
|
return Logger.Warn()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Error starts a new message with error level.
|
// Error starts a new message with error level.
|
||||||
//
|
//
|
||||||
// You must call Msg on the returned event in order to send the event.
|
// You must call Msg on the returned event in order to send the event.
|
||||||
func Error() zerolog.Event {
|
func Error() *zerolog.Event {
|
||||||
return Logger.Error()
|
return Logger.Error()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,7 +57,7 @@ func Error() zerolog.Event {
|
||||||
// is called by the Msg method.
|
// is called by the Msg method.
|
||||||
//
|
//
|
||||||
// You must call Msg on the returned event in order to send the event.
|
// You must call Msg on the returned event in order to send the event.
|
||||||
func Fatal() zerolog.Event {
|
func Fatal() *zerolog.Event {
|
||||||
return Logger.Fatal()
|
return Logger.Fatal()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,7 +65,7 @@ func Fatal() zerolog.Event {
|
||||||
// to the panic function.
|
// to the panic function.
|
||||||
//
|
//
|
||||||
// You must call Msg on the returned event in order to send the event.
|
// You must call Msg on the returned event in order to send the event.
|
||||||
func Panic() zerolog.Event {
|
func Panic() *zerolog.Event {
|
||||||
return Logger.Panic()
|
return Logger.Panic()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,6 +73,6 @@ func Panic() zerolog.Event {
|
||||||
// zerlog.Disabled will still disable events produced by this method.
|
// zerlog.Disabled will still disable events produced by this method.
|
||||||
//
|
//
|
||||||
// You must call Msg on the returned event in order to send the event.
|
// You must call Msg on the returned event in order to send the event.
|
||||||
func Log() zerolog.Event {
|
func Log() *zerolog.Event {
|
||||||
return Logger.Log()
|
return Logger.Log()
|
||||||
}
|
}
|
||||||
|
|
|
@ -111,7 +111,7 @@ func ExampleEvent_Dict() {
|
||||||
).
|
).
|
||||||
Msg("hello world")
|
Msg("hello world")
|
||||||
|
|
||||||
// Output: {"foo":"bar",{"bar":"baz","n":1},"message":"hello world"}
|
// Output: {"foo":"bar","dict":{"bar":"baz","n":1},"message":"hello world"}
|
||||||
}
|
}
|
||||||
|
|
||||||
func ExampleContext_Dict() {
|
func ExampleContext_Dict() {
|
||||||
|
|
Loading…
Reference in New Issue