1
0
mirror of https://github.com/rs/zerolog synced 2026-06-08 17:13:30 +00:00

Compare commits

...

7 Commits

Author SHA1 Message Date
Olivier Poitrey a6bc163a87 Switch encoder using build tags 2018-02-10 20:44:33 -08:00
Olivier Poitrey 9a92fd2536 Fix typoes 2018-02-10 18:57:53 -08:00
Olivier Poitrey 7d8f9e5cf0 Fix unit tests 2018-02-08 21:29:16 -08:00
Dan Gillis 8eb285b62b Updates to README.md to help with readability (#32)
* Added missed >m< in github.com
* Added backquotes to denote "code" where appropriate
* Cleanup based on feedback
* Added three examples from README
* Removed Output for 3 examples
* Updated Setting Global Log Level section w/ flags
* Removed unnecessary blank lines
* Moved flags from init into main
* Update log_example_test.go
* Cosmetic change based on Olivier's feedback
* Pushed back to original
* New Examples for Log package
* Removed extra spaces
* Reorganized file and added examples
2018-02-08 21:00:09 -08:00
Olivier Poitrey 27e0a22cbc Add the ability to capture the logger caller file and line number
Fixes #34, #22
2018-02-07 13:54:26 -08:00
Olivier Poitrey fcbdf23e9e Use new hook internally to handle timestamp in context 2018-02-07 13:31:00 -08:00
Olivier Poitrey cbec2377ee Add benchmarks for context 2018-02-07 13:07:46 -08:00
15 changed files with 928 additions and 216 deletions
+125 -40
View File
@@ -6,7 +6,7 @@ The zerolog package provides a fast and simple logger dedicated to JSON output.
Zerolog's API is designed to provide both a great developer experience and stunning [performance](#benchmarks). Its unique chaining API allows zerolog to write JSON 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`.
@@ -24,43 +24,144 @@ To keep the code base and the API simple, zerolog focuses on JSON logging only.
* `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").
@@ -91,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
@@ -375,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 |
+19 -21
View File
@@ -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
}
+127
View File
@@ -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
View File
@@ -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
View File
@@ -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)
}
+161
View File
@@ -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)
}
+71 -45
View File
@@ -4,10 +4,10 @@ import (
"fmt"
"io/ioutil"
"os"
"runtime"
"strconv"
"sync"
"time"
"github.com/rs/zerolog/internal/json"
)
var eventPool = &sync.Pool{
@@ -25,6 +25,7 @@ type Event struct {
w LevelWriter
level Level
done func(msg string)
ch []Hook // hooks from context
h []Hook
}
@@ -77,6 +78,14 @@ func (e *Event) Msg(msg string) {
if e == nil {
return
}
if len(e.ch) > 0 {
e.ch[0].Run(e, e.level, msg)
if len(e.ch) > 1 {
for _, hook := range e.ch[1:] {
hook.Run(e, e.level, msg)
}
}
}
if len(e.h) > 0 {
e.h[0].Run(e, e.level, msg)
if len(e.h) > 1 {
@@ -86,7 +95,7 @@ func (e *Event) Msg(msg string) {
}
}
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)
@@ -122,7 +131,7 @@ func (e *Event) Dict(key string, dict *Event) *Event {
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
}
@@ -141,7 +150,7 @@ func (e *Event) Array(key string, arr LogArrayMarshaler) *Event {
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
@@ -172,7 +181,7 @@ func (e *Event) Object(key string, obj LogObjectMarshaler) *Event {
if e == nil {
return e
}
e.buf = json.AppendKey(e.buf, key)
e.buf = appendKey(e.buf, key)
e.appendObject(obj)
return e
}
@@ -182,7 +191,7 @@ func (e *Event) Str(key, val string) *Event {
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
}
@@ -191,7 +200,7 @@ func (e *Event) Strs(key string, vals []string) *Event {
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
}
@@ -203,7 +212,7 @@ func (e *Event) Bytes(key string, val []byte) *Event {
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
}
@@ -214,7 +223,7 @@ func (e *Event) AnErr(key string, err error) *Event {
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
}
@@ -225,7 +234,7 @@ func (e *Event) Errs(key string, errs []error) *Event {
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
}
@@ -237,7 +246,7 @@ func (e *Event) Err(err error) *Event {
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
}
@@ -247,7 +256,7 @@ func (e *Event) Bool(key string, b bool) *Event {
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
}
@@ -256,7 +265,7 @@ func (e *Event) Bools(key string, b []bool) *Event {
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
}
@@ -265,7 +274,7 @@ func (e *Event) Int(key string, i int) *Event {
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
}
@@ -274,7 +283,7 @@ func (e *Event) Ints(key string, i []int) *Event {
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
}
@@ -283,7 +292,7 @@ func (e *Event) Int8(key string, i int8) *Event {
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
}
@@ -292,7 +301,7 @@ func (e *Event) Ints8(key string, i []int8) *Event {
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
}
@@ -301,7 +310,7 @@ func (e *Event) Int16(key string, i int16) *Event {
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
}
@@ -310,7 +319,7 @@ func (e *Event) Ints16(key string, i []int16) *Event {
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
}
@@ -319,7 +328,7 @@ func (e *Event) Int32(key string, i int32) *Event {
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
}
@@ -328,7 +337,7 @@ func (e *Event) Ints32(key string, i []int32) *Event {
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
}
@@ -337,7 +346,7 @@ func (e *Event) Int64(key string, i int64) *Event {
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
}
@@ -346,7 +355,7 @@ func (e *Event) Ints64(key string, i []int64) *Event {
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
}
@@ -355,7 +364,7 @@ func (e *Event) Uint(key string, i uint) *Event {
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
}
@@ -364,7 +373,7 @@ func (e *Event) Uints(key string, i []uint) *Event {
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
}
@@ -373,7 +382,7 @@ func (e *Event) Uint8(key string, i uint8) *Event {
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
}
@@ -382,7 +391,7 @@ func (e *Event) Uints8(key string, i []uint8) *Event {
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
}
@@ -391,7 +400,7 @@ func (e *Event) Uint16(key string, i uint16) *Event {
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
}
@@ -400,7 +409,7 @@ func (e *Event) Uints16(key string, i []uint16) *Event {
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
}
@@ -409,7 +418,7 @@ func (e *Event) Uint32(key string, i uint32) *Event {
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
}
@@ -418,7 +427,7 @@ func (e *Event) Uints32(key string, i []uint32) *Event {
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
}
@@ -427,7 +436,7 @@ func (e *Event) Uint64(key string, i uint64) *Event {
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
}
@@ -436,7 +445,7 @@ func (e *Event) Uints64(key string, i []uint64) *Event {
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
}
@@ -445,7 +454,7 @@ func (e *Event) Float32(key string, f float32) *Event {
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
}
@@ -454,7 +463,7 @@ func (e *Event) Floats32(key string, f []float32) *Event {
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
}
@@ -463,7 +472,7 @@ func (e *Event) Float64(key string, f float64) *Event {
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
}
@@ -472,7 +481,7 @@ func (e *Event) Floats64(key string, f []float64) *Event {
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
}
@@ -482,7 +491,7 @@ func (e *Event) Timestamp() *Event {
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
}
@@ -491,7 +500,7 @@ func (e *Event) Time(key string, t time.Time) *Event {
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
}
@@ -500,7 +509,7 @@ func (e *Event) Times(key string, t []time.Time) *Event {
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
}
@@ -511,7 +520,7 @@ func (e *Event) Dur(key string, d time.Duration) *Event {
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
}
@@ -522,7 +531,7 @@ func (e *Event) Durs(key string, d []time.Duration) *Event {
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
}
@@ -537,7 +546,7 @@ func (e *Event) TimeDiff(key string, t time.Time, start time.Time) *Event {
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
}
@@ -549,6 +558,23 @@ func (e *Event) Interface(key string, i interface{}) *Event {
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
}
+36 -38
View File
@@ -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
+3
View File
@@ -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
View File
@@ -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
+1 -1
View File
@@ -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"}
}
+4 -15
View File
@@ -90,8 +90,6 @@ import (
"io/ioutil"
"os"
"strconv"
"github.com/rs/zerolog/internal/json"
)
// Level defines log levels.
@@ -193,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}
}
@@ -208,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
@@ -345,21 +340,15 @@ func (l *Logger) newEvent(level Level, done func(string)) *Event {
}
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)
}
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:]...)
}
if len(l.hooks) > 0 {
e.h = append(e.h, l.hooks...)
e.buf = append(e.buf, l.context...)
}
return e
}
+2 -2
View File
@@ -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)
}
@@ -89,7 +89,7 @@ func WithLevel(level zerolog.Level) *zerolog.Event {
}
// 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 {
+141
View File
@@ -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
+14 -7
View File
@@ -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)
}
}
@@ -426,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)
}
}
@@ -470,7 +477,7 @@ func TestOutputWithTimestamp(t *testing.T) {
log := New(ignoredOut).Output(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)
}
}