Compare commits
1 Commits
master
...
dependabot
Author | SHA1 | Date |
---|---|---|
dependabot[bot] | 5e6ec5804d |
|
@ -4,17 +4,17 @@ jobs:
|
|||
test:
|
||||
strategy:
|
||||
matrix:
|
||||
go-version: [1.18.x, 1.19.x]
|
||||
go-version: [1.15.x, 1.16.x]
|
||||
os: [ubuntu-latest, macos-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- name: Install Go
|
||||
uses: actions/setup-go@v4
|
||||
uses: actions/setup-go@v2
|
||||
with:
|
||||
go-version: ${{ matrix.go-version }}
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
- uses: actions/cache@v3
|
||||
- uses: actions/cache@v2
|
||||
with:
|
||||
path: ~/go/pkg/mod
|
||||
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
|
||||
|
|
255
README.md
255
README.md
|
@ -1,26 +1,20 @@
|
|||
###zlog
|
||||
|
||||
opinionated defaults on zerolog
|
||||
|
||||
|
||||
|
||||
# Zero Allocation JSON Logger
|
||||
|
||||
[![godoc](http://img.shields.io/badge/godoc-reference-blue.svg?style=flat)](https://godoc.org/tuxpa.in/a/zlog) [![license](http://img.shields.io/badge/license-MIT-red.svg?style=flat)](https://raw.githubusercontent.com/rs/zlog/master/LICENSE) [![Build Status](https://travis-ci.org/rs/zlog.svg?branch=master)](https://travis-ci.org/rs/zlog) [![Coverage](http://gocover.io/_badge/tuxpa.in/a/zlog)](http://gocover.io/tuxpa.in/a/zlog)
|
||||
[![godoc](http://img.shields.io/badge/godoc-reference-blue.svg?style=flat)](https://godoc.org/github.com/rs/zerolog) [![license](http://img.shields.io/badge/license-MIT-red.svg?style=flat)](https://raw.githubusercontent.com/rs/zerolog/master/LICENSE) [![Build Status](https://travis-ci.org/rs/zerolog.svg?branch=master)](https://travis-ci.org/rs/zerolog) [![Coverage](http://gocover.io/_badge/github.com/rs/zerolog)](http://gocover.io/github.com/rs/zerolog)
|
||||
|
||||
The zlog package provides a fast and simple logger dedicated to JSON output.
|
||||
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 zlog to write JSON (or CBOR) log events by avoiding allocations and reflection.
|
||||
Zerolog's API is designed to provide both a great developer experience and stunning [performance](#benchmarks). Its unique chaining API allows zerolog to write JSON (or CBOR) log events by avoiding allocations and reflection.
|
||||
|
||||
Uber's [zap](https://godoc.org/go.uber.org/zap) library pioneered this approach. Zerolog is taking this concept to the next level with a simpler to use API and even better performance.
|
||||
|
||||
To keep the code base and the API simple, zlog focuses on efficient structured logging only. Pretty logging on the console is made possible using the provided (but inefficient) [`zlog.ConsoleWriter`](#pretty-logging).
|
||||
To keep the code base and the API simple, zerolog focuses on efficient structured logging only. Pretty logging on the console is made possible using the provided (but inefficient) [`zerolog.ConsoleWriter`](#pretty-logging).
|
||||
|
||||
![Pretty Logging Image](pretty.png)
|
||||
|
||||
## Who uses zlog
|
||||
## Who uses zerolog
|
||||
|
||||
Find out [who uses zlog](https://tuxpa.in/a/zlog/wiki/Who-uses-zlog) and add your company / project to the list.
|
||||
Find out [who uses zerolog](https://github.com/rs/zerolog/wiki/Who-uses-zerolog) and add your company / project to the list.
|
||||
|
||||
## Features
|
||||
|
||||
|
@ -30,7 +24,7 @@ Find out [who uses zlog](https://tuxpa.in/a/zlog/wiki/Who-uses-zlog) and add you
|
|||
* [Sampling](#log-sampling)
|
||||
* [Hooks](#hooks)
|
||||
* [Contextual fields](#contextual-logging)
|
||||
* [`context.Context` integration](#contextcontext-integration)
|
||||
* `context.Context` integration
|
||||
* [Integration with `net/http`](#integration-with-nethttp)
|
||||
* [JSON and CBOR encoding formats](#binary-encoding)
|
||||
* [Pretty logging for development](#pretty-logging)
|
||||
|
@ -39,26 +33,26 @@ Find out [who uses zlog](https://tuxpa.in/a/zlog/wiki/Who-uses-zlog) and add you
|
|||
## Installation
|
||||
|
||||
```bash
|
||||
go get -u tuxpa.in/a/zlog/log
|
||||
go get -u github.com/rs/zerolog/log
|
||||
```
|
||||
|
||||
## Getting Started
|
||||
|
||||
### Simple Logging Example
|
||||
|
||||
For simple logging, import the global logger package **tuxpa.in/a/zlog/log**
|
||||
For simple logging, import the global logger package **github.com/rs/zerolog/log**
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"tuxpa.in/a/zlog"
|
||||
"tuxpa.in/a/zlog/log"
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// UNIX Time is faster and smaller than most timestamps
|
||||
zlog.TimeFieldFormat = zlog.TimeFormatUnix
|
||||
zerolog.TimeFieldFormat = zerolog.TimeFormatUnix
|
||||
|
||||
log.Print("hello world")
|
||||
}
|
||||
|
@ -70,24 +64,24 @@ func main() {
|
|||
|
||||
### Contextual Logging
|
||||
|
||||
**zlog** allows data to be added to log messages in the form of key:value pairs. The data added to the message adds "context" about the log event that can be critical for debugging as well as myriad other purposes. An example of this is below:
|
||||
**zerolog** allows data to be added to log messages in the form of key:value pairs. The data added to the message adds "context" about the log event that can be critical for debugging as well as myriad other purposes. An example of this is below:
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"tuxpa.in/a/zlog"
|
||||
"tuxpa.in/a/zlog/log"
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
func main() {
|
||||
zlog.TimeFieldFormat = zlog.TimeFormatUnix
|
||||
zerolog.TimeFieldFormat = zerolog.TimeFormatUnix
|
||||
|
||||
log.Debug().
|
||||
Str("Scale", "833 cents").
|
||||
Float64("Interval", 833.09).
|
||||
Msg("Fibonacci is everywhere")
|
||||
|
||||
|
||||
log.Debug().
|
||||
Str("Name", "Tom").
|
||||
Send()
|
||||
|
@ -107,12 +101,12 @@ func main() {
|
|||
package main
|
||||
|
||||
import (
|
||||
"tuxpa.in/a/zlog"
|
||||
"tuxpa.in/a/zlog/log"
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
func main() {
|
||||
zlog.TimeFieldFormat = zlog.TimeFormatUnix
|
||||
zerolog.TimeFieldFormat = zerolog.TimeFormatUnix
|
||||
|
||||
log.Info().Msg("hello world")
|
||||
}
|
||||
|
@ -120,19 +114,19 @@ func main() {
|
|||
// Output: {"time":1516134303,"level":"info","message":"hello world"}
|
||||
```
|
||||
|
||||
> It is very important to note that when using the **zlog** chaining API, as shown above (`log.Info().Msg("hello world"`), the chain must have either the `Msg` or `Msgf` method call. If you forget to add either of these, the log will not occur and there is no compile time error to alert you of this.
|
||||
> It is very important to note that when using the **zerolog** chaining API, as shown above (`log.Info().Msg("hello world"`), the chain must have either the `Msg` or `Msgf` method call. If you forget to add either of these, the log will not occur and there is no compile time error to alert you of this.
|
||||
|
||||
**zlog** allows for logging at the following levels (from highest to lowest):
|
||||
**zerolog** allows for logging at the following levels (from highest to lowest):
|
||||
|
||||
* panic (`zlog.PanicLevel`, 5)
|
||||
* fatal (`zlog.FatalLevel`, 4)
|
||||
* error (`zlog.ErrorLevel`, 3)
|
||||
* warn (`zlog.WarnLevel`, 2)
|
||||
* info (`zlog.InfoLevel`, 1)
|
||||
* debug (`zlog.DebugLevel`, 0)
|
||||
* trace (`zlog.TraceLevel`, -1)
|
||||
* panic (`zerolog.PanicLevel`, 5)
|
||||
* fatal (`zerolog.FatalLevel`, 4)
|
||||
* error (`zerolog.ErrorLevel`, 3)
|
||||
* warn (`zerolog.WarnLevel`, 2)
|
||||
* info (`zerolog.InfoLevel`, 1)
|
||||
* debug (`zerolog.DebugLevel`, 0)
|
||||
* trace (`zerolog.TraceLevel`, -1)
|
||||
|
||||
You can set the Global logging level to any of these options using the `SetGlobalLevel` function in the zlog package, passing in one of the given constants above, e.g. `zlog.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 `zlog.Disabled` constant.
|
||||
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
|
||||
|
||||
|
@ -144,20 +138,20 @@ package main
|
|||
import (
|
||||
"flag"
|
||||
|
||||
"tuxpa.in/a/zlog"
|
||||
"tuxpa.in/a/zlog/log"
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
func main() {
|
||||
zlog.TimeFieldFormat = zlog.TimeFormatUnix
|
||||
zerolog.TimeFieldFormat = zerolog.TimeFormatUnix
|
||||
debug := flag.Bool("debug", false, "sets log level to debug")
|
||||
|
||||
flag.Parse()
|
||||
|
||||
// Default level for this example is info, unless debug flag is present
|
||||
zlog.SetGlobalLevel(zlog.InfoLevel)
|
||||
zerolog.SetGlobalLevel(zerolog.InfoLevel)
|
||||
if *debug {
|
||||
zlog.SetGlobalLevel(zlog.DebugLevel)
|
||||
zerolog.SetGlobalLevel(zerolog.DebugLevel)
|
||||
}
|
||||
|
||||
log.Debug().Msg("This message appears only when log level set to Debug")
|
||||
|
@ -195,12 +189,12 @@ You may choose to log without a specific level by using the `Log` method. You ma
|
|||
package main
|
||||
|
||||
import (
|
||||
"tuxpa.in/a/zlog"
|
||||
"tuxpa.in/a/zlog/log"
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
func main() {
|
||||
zlog.TimeFieldFormat = zlog.TimeFormatUnix
|
||||
zerolog.TimeFieldFormat = zerolog.TimeFormatUnix
|
||||
|
||||
log.Log().
|
||||
Str("foo", "bar").
|
||||
|
@ -220,12 +214,12 @@ package main
|
|||
import (
|
||||
"errors"
|
||||
|
||||
"tuxpa.in/a/zlog"
|
||||
"tuxpa.in/a/zlog/log"
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
func main() {
|
||||
zlog.TimeFieldFormat = zlog.TimeFormatUnix
|
||||
zerolog.TimeFieldFormat = zerolog.TimeFormatUnix
|
||||
|
||||
err := errors.New("seems we have an error here")
|
||||
log.Error().Err(err).Msg("")
|
||||
|
@ -234,26 +228,26 @@ func main() {
|
|||
// Output: {"level":"error","error":"seems we have an error here","time":1609085256}
|
||||
```
|
||||
|
||||
> The default field name for errors is `error`, you can change this by setting `zlog.ErrorFieldName` to meet your needs.
|
||||
> The default field name for errors is `error`, you can change this by setting `zerolog.ErrorFieldName` to meet your needs.
|
||||
|
||||
#### Error Logging with Stacktrace
|
||||
|
||||
Using `github.com/pkg/errors`, you can add a formatted stacktrace to your errors.
|
||||
Using `github.com/pkg/errors`, you can add a formatted stacktrace to your errors.
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/pkg/errors"
|
||||
"tuxpa.in/a/zlog/pkgerrors"
|
||||
"github.com/rs/zerolog/pkgerrors"
|
||||
|
||||
"tuxpa.in/a/zlog"
|
||||
"tuxpa.in/a/zlog/log"
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
func main() {
|
||||
zlog.TimeFieldFormat = zlog.TimeFormatUnix
|
||||
zlog.ErrorStackMarshaler = pkgerrors.MarshalStack
|
||||
zerolog.TimeFieldFormat = zerolog.TimeFormatUnix
|
||||
zerolog.ErrorStackMarshaler = pkgerrors.MarshalStack
|
||||
|
||||
err := outer()
|
||||
log.Error().Stack().Err(err).Msg("")
|
||||
|
@ -282,7 +276,7 @@ func outer() error {
|
|||
// Output: {"level":"error","stack":[{"func":"inner","line":"20","source":"errors.go"},{"func":"middle","line":"24","source":"errors.go"},{"func":"outer","line":"32","source":"errors.go"},{"func":"main","line":"15","source":"errors.go"},{"func":"main","line":"204","source":"proc.go"},{"func":"goexit","line":"1374","source":"asm_amd64.s"}],"error":"seems we have an error here","time":1609086683}
|
||||
```
|
||||
|
||||
> zlog.ErrorStackMarshaler must be set in order for the stack to output anything.
|
||||
> zerolog.ErrorStackMarshaler must be set in order for the stack to output anything.
|
||||
|
||||
#### Logging Fatal Messages
|
||||
|
||||
|
@ -292,15 +286,15 @@ package main
|
|||
import (
|
||||
"errors"
|
||||
|
||||
"tuxpa.in/a/zlog"
|
||||
"tuxpa.in/a/zlog/log"
|
||||
"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"
|
||||
|
||||
zlog.TimeFieldFormat = zlog.TimeFormatUnix
|
||||
zerolog.TimeFieldFormat = zerolog.TimeFormatUnix
|
||||
|
||||
log.Fatal().
|
||||
Err(err).
|
||||
|
@ -318,7 +312,7 @@ func main() {
|
|||
### Create logger instance to manage different outputs
|
||||
|
||||
```go
|
||||
logger := zlog.New(os.Stderr).With().Timestamp().Logger()
|
||||
logger := zerolog.New(os.Stderr).With().Timestamp().Logger()
|
||||
|
||||
logger.Info().Str("foo", "bar").Msg("hello world")
|
||||
|
||||
|
@ -338,10 +332,10 @@ sublogger.Info().Msg("hello world")
|
|||
|
||||
### Pretty logging
|
||||
|
||||
To log a human-friendly, colorized output, use `zlog.ConsoleWriter`:
|
||||
To log a human-friendly, colorized output, use `zerolog.ConsoleWriter`:
|
||||
|
||||
```go
|
||||
log.Logger = log.Output(zlog.ConsoleWriter{Out: os.Stderr})
|
||||
log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr})
|
||||
|
||||
log.Info().Str("foo", "bar").Msg("Hello world")
|
||||
|
||||
|
@ -351,7 +345,7 @@ log.Info().Str("foo", "bar").Msg("Hello world")
|
|||
To customize the configuration and formatting:
|
||||
|
||||
```go
|
||||
output := zlog.ConsoleWriter{Out: os.Stdout, TimeFormat: time.RFC3339}
|
||||
output := zerolog.ConsoleWriter{Out: os.Stdout, TimeFormat: time.RFC3339}
|
||||
output.FormatLevel = func(i interface{}) string {
|
||||
return strings.ToUpper(fmt.Sprintf("| %-6s|", i))
|
||||
}
|
||||
|
@ -365,7 +359,7 @@ output.FormatFieldValue = func(i interface{}) string {
|
|||
return strings.ToUpper(fmt.Sprintf("%s", i))
|
||||
}
|
||||
|
||||
log := zlog.New(output).With().Timestamp().Logger()
|
||||
log := zerolog.New(output).With().Timestamp().Logger()
|
||||
|
||||
log.Info().Str("foo", "bar").Msg("Hello World")
|
||||
|
||||
|
@ -377,7 +371,7 @@ log.Info().Str("foo", "bar").Msg("Hello World")
|
|||
```go
|
||||
log.Info().
|
||||
Str("foo", "bar").
|
||||
Dict("dict", zlog.Dict().
|
||||
Dict("dict", zerolog.Dict().
|
||||
Str("bar", "baz").
|
||||
Int("n", 1),
|
||||
).Msg("hello world")
|
||||
|
@ -388,9 +382,9 @@ log.Info().
|
|||
### Customize automatic field names
|
||||
|
||||
```go
|
||||
zlog.TimestampFieldName = "t"
|
||||
zlog.LevelFieldName = "l"
|
||||
zlog.MessageFieldName = "m"
|
||||
zerolog.TimestampFieldName = "t"
|
||||
zerolog.LevelFieldName = "l"
|
||||
zerolog.MessageFieldName = "m"
|
||||
|
||||
log.Info().Msg("hello world")
|
||||
|
||||
|
@ -405,8 +399,6 @@ log.Logger = log.With().Str("foo", "bar").Logger()
|
|||
|
||||
### Add file and line number to log
|
||||
|
||||
Equivalent of `Llongfile`:
|
||||
|
||||
```go
|
||||
log.Logger = log.With().Caller().Logger()
|
||||
log.Info().Msg("hello world")
|
||||
|
@ -414,25 +406,6 @@ log.Info().Msg("hello world")
|
|||
// Output: {"level": "info", "message": "hello world", "caller": "/go/src/your_project/some_file:21"}
|
||||
```
|
||||
|
||||
Equivalent of `Lshortfile`:
|
||||
|
||||
```go
|
||||
zlog.CallerMarshalFunc = func(pc uintptr, file string, line int) string {
|
||||
short := file
|
||||
for i := len(file) - 1; i > 0; i-- {
|
||||
if file[i] == '/' {
|
||||
short = file[i+1:]
|
||||
break
|
||||
}
|
||||
}
|
||||
file = short
|
||||
return file + ":" + strconv.Itoa(line)
|
||||
}
|
||||
log.Logger = log.With().Caller().Logger()
|
||||
log.Info().Msg("hello world")
|
||||
|
||||
// Output: {"level": "info", "message": "hello world", "caller": "some_file:21"}
|
||||
```
|
||||
|
||||
### Thread-safe, lock-free, non-blocking writer
|
||||
|
||||
|
@ -442,7 +415,7 @@ If your writer might be slow or not thread-safe and you need your log producers
|
|||
wr := diode.NewWriter(os.Stdout, 1000, 10*time.Millisecond, func(missed int) {
|
||||
fmt.Printf("Logger Dropped %d messages", missed)
|
||||
})
|
||||
log := zlog.New(wr)
|
||||
log := zerolog.New(wr)
|
||||
log.Print("test")
|
||||
```
|
||||
|
||||
|
@ -451,7 +424,7 @@ You will need to install `code.cloudfoundry.org/go-diodes` to use this feature.
|
|||
### Log Sampling
|
||||
|
||||
```go
|
||||
sampled := log.Sample(&zlog.BasicSampler{N: 10})
|
||||
sampled := log.Sample(&zerolog.BasicSampler{N: 10})
|
||||
sampled.Info().Msg("will be logged every 10 messages")
|
||||
|
||||
// Output: {"time":1494567715,"level":"info","message":"will be logged every 10 messages"}
|
||||
|
@ -463,11 +436,11 @@ More advanced sampling:
|
|||
// Will let 5 debug messages per period of 1 second.
|
||||
// Over 5 debug message, 1 every 100 debug messages are logged.
|
||||
// Other levels are not sampled.
|
||||
sampled := log.Sample(zlog.LevelSampler{
|
||||
DebugSampler: &zlog.BurstSampler{
|
||||
sampled := log.Sample(zerolog.LevelSampler{
|
||||
DebugSampler: &zerolog.BurstSampler{
|
||||
Burst: 5,
|
||||
Period: 1*time.Second,
|
||||
NextSampler: &zlog.BasicSampler{N: 100},
|
||||
NextSampler: &zerolog.BasicSampler{N: 100},
|
||||
},
|
||||
})
|
||||
sampled.Debug().Msg("hello world")
|
||||
|
@ -480,8 +453,8 @@ sampled.Debug().Msg("hello world")
|
|||
```go
|
||||
type SeverityHook struct{}
|
||||
|
||||
func (h SeverityHook) Run(e *zlog.Event, level zlog.Level, msg string) {
|
||||
if level != zlog.NoLevel {
|
||||
func (h SeverityHook) Run(e *zerolog.Event, level zerolog.Level, msg string) {
|
||||
if level != zerolog.NoLevel {
|
||||
e.Str("severity", level.String())
|
||||
}
|
||||
}
|
||||
|
@ -505,7 +478,7 @@ log.Ctx(ctx).Info().Msg("hello world")
|
|||
### Set as standard logger output
|
||||
|
||||
```go
|
||||
stdlog := zlog.New(os.Stdout).With().
|
||||
log := zerolog.New(os.Stdout).With().
|
||||
Str("foo", "bar").
|
||||
Logger()
|
||||
|
||||
|
@ -517,38 +490,14 @@ stdlog.Print("hello world")
|
|||
// Output: {"foo":"bar","message":"hello world"}
|
||||
```
|
||||
|
||||
### context.Context integration
|
||||
|
||||
The `Logger` instance could be attached to `context.Context` values with `logger.WithContext(ctx)`
|
||||
and extracted from it using `zerolog.Ctx(ctx)`.
|
||||
|
||||
Example to add logger to context:
|
||||
```go
|
||||
// this code attach logger instance to context fields
|
||||
ctx := context.Background()
|
||||
logger := zerolog.New(os.Stdout)
|
||||
ctx = logger.WithContext(ctx)
|
||||
someFunc(ctx)
|
||||
```
|
||||
|
||||
Extracting logger from context:
|
||||
```go
|
||||
func someFunc(ctx context.Context) {
|
||||
// get logger from context. if it's nill, then `zerolog.DefaultContextLogger` is returned,
|
||||
// if `DefaultContextLogger` is nil, then disabled logger returned.
|
||||
logger := zerolog.Ctx(ctx)
|
||||
logger.Info().Msg("Hello")
|
||||
}
|
||||
```
|
||||
|
||||
### Integration with `net/http`
|
||||
|
||||
The `tuxpa.in/a/zlog/hlog` package provides some helpers to integrate zlog with `http.Handler`.
|
||||
The `github.com/rs/zerolog/hlog` package provides some helpers to integrate zerolog with `http.Handler`.
|
||||
|
||||
In this example we use [alice](https://github.com/justinas/alice) to install logger for better readability.
|
||||
|
||||
```go
|
||||
log := zlog.New(os.Stdout).With().
|
||||
log := zerolog.New(os.Stdout).With().
|
||||
Timestamp().
|
||||
Str("role", "my-service").
|
||||
Str("host", host).
|
||||
|
@ -595,15 +544,15 @@ if err := http.ListenAndServe(":8080", nil); err != nil {
|
|||
```
|
||||
|
||||
## Multiple Log Output
|
||||
`zlog.MultiLevelWriter` may be used to send the log message to multiple outputs.
|
||||
`zerolog.MultiLevelWriter` may be used to send the log message to multiple outputs.
|
||||
In this example, we send the log message to both `os.Stdout` and the in-built ConsoleWriter.
|
||||
```go
|
||||
func main() {
|
||||
consoleWriter := zlog.ConsoleWriter{Out: os.Stdout}
|
||||
consoleWriter := zerolog.ConsoleWriter{Out: os.Stdout}
|
||||
|
||||
multi := zlog.MultiLevelWriter(consoleWriter, os.Stdout)
|
||||
multi := zerolog.MultiLevelWriter(consoleWriter, os.Stdout)
|
||||
|
||||
logger := zlog.New(multi).With().Timestamp().Logger()
|
||||
logger := zerolog.New(multi).With().Timestamp().Logger()
|
||||
|
||||
logger.Info().Msg("Hello World!")
|
||||
}
|
||||
|
@ -611,23 +560,23 @@ func main() {
|
|||
// Output (Line 1: Console; Line 2: Stdout)
|
||||
// 12:36PM INF Hello World!
|
||||
// {"level":"info","time":"2019-11-07T12:36:38+03:00","message":"Hello World!"}
|
||||
```
|
||||
```
|
||||
|
||||
## Global Settings
|
||||
|
||||
Some settings can be changed and will be applied to all loggers:
|
||||
|
||||
* `log.Logger`: You can set this value to customize the global logger (the one used by package level methods).
|
||||
* `zlog.SetGlobalLevel`: Can raise the minimum level of all loggers. Call this with `zlog.Disabled` to disable logging altogether (quiet mode).
|
||||
* `zlog.DisableSampling`: If argument is `true`, all sampled loggers will stop sampling and issue 100% of their log events.
|
||||
* `zlog.TimestampFieldName`: Can be set to customize `Timestamp` field name.
|
||||
* `zlog.LevelFieldName`: Can be set to customize level field name.
|
||||
* `zlog.MessageFieldName`: Can be set to customize message field name.
|
||||
* `zlog.ErrorFieldName`: Can be set to customize `Err` field name.
|
||||
* `zlog.TimeFieldFormat`: Can be set to customize `Time` field value formatting. If set with `zlog.TimeFormatUnix`, `zlog.TimeFormatUnixMs` or `zlog.TimeFormatUnixMicro`, times are formated as UNIX timestamp.
|
||||
* `zlog.DurationFieldUnit`: Can be set to customize the unit for time.Duration type fields added by `Dur` (default: `time.Millisecond`).
|
||||
* `zlog.DurationFieldInteger`: If set to `true`, `Dur` fields are formatted as integers instead of floats (default: `false`).
|
||||
* `zlog.ErrorHandler`: Called whenever zlog fails to write an event on its output. If not set, an error is printed on the stderr. This handler must be thread safe and non-blocking.
|
||||
* `zerolog.SetGlobalLevel`: Can raise the minimum level of all loggers. Call this with `zerolog.Disabled` to disable logging altogether (quiet mode).
|
||||
* `zerolog.DisableSampling`: If argument is `true`, all sampled loggers will stop sampling and issue 100% of their log events.
|
||||
* `zerolog.TimestampFieldName`: Can be set to customize `Timestamp` field name.
|
||||
* `zerolog.LevelFieldName`: Can be set to customize level field name.
|
||||
* `zerolog.MessageFieldName`: Can be set to customize message field name.
|
||||
* `zerolog.ErrorFieldName`: Can be set to customize `Err` field name.
|
||||
* `zerolog.TimeFieldFormat`: Can be set to customize `Time` field value formatting. If set with `zerolog.TimeFormatUnix`, `zerolog.TimeFormatUnixMs` or `zerolog.TimeFormatUnixMicro`, times are formated as UNIX timestamp.
|
||||
* `zerolog.DurationFieldUnit`: Can be set to customize the unit for time.Duration type fields added by `Dur` (default: `time.Millisecond`).
|
||||
* `zerolog.DurationFieldInteger`: If set to `true`, `Dur` fields are formatted as integers instead of floats (default: `false`).
|
||||
* `zerolog.ErrorHandler`: Called whenever zerolog fails to write an event on its output. If not set, an error is printed on the stderr. This handler must be thread safe and non-blocking.
|
||||
|
||||
## Field Types
|
||||
|
||||
|
@ -641,10 +590,10 @@ Some settings can be changed and will be applied to all loggers:
|
|||
|
||||
### Advanced Fields
|
||||
|
||||
* `Err`: Takes an `error` and renders it as a string using the `zlog.ErrorFieldName` field name.
|
||||
* `Err`: Takes an `error` and renders it as a string using the `zerolog.ErrorFieldName` field name.
|
||||
* `Func`: Run a `func` only if the level is enabled.
|
||||
* `Timestamp`: Inserts a timestamp field with `zlog.TimestampFieldName` field name, formatted using `zlog.TimeFieldFormat`.
|
||||
* `Time`: Adds a field with time formatted with `zlog.TimeFieldFormat`.
|
||||
* `Timestamp`: Inserts a timestamp field with `zerolog.TimestampFieldName` field name, formatted using `zerolog.TimeFieldFormat`.
|
||||
* `Time`: Adds a field with time formatted with `zerolog.TimeFieldFormat`.
|
||||
* `Dur`: Adds a field with `time.Duration`.
|
||||
* `Dict`: Adds a sub-key/value as a field of the event.
|
||||
* `RawJSON`: Adds a field with an already encoded JSON (`[]byte`)
|
||||
|
@ -655,24 +604,20 @@ Most fields are also available in the slice format (`Strs` for `[]string`, `Errs
|
|||
|
||||
## Binary Encoding
|
||||
|
||||
<<<<<<< HEAD
|
||||
In addition to the default JSON encoding, `zlog` can produce binary logs using [CBOR](http://cbor.io) encoding. The choice of encoding can be decided at compile time using the build tag `binary_log` as follows:
|
||||
=======
|
||||
In addition to the default JSON encoding, `zerolog` can produce binary logs using [CBOR](https://cbor.io) encoding. The choice of encoding can be decided at compile time using the build tag `binary_log` as follows:
|
||||
>>>>>>> github
|
||||
In addition to the default JSON encoding, `zerolog` can produce binary logs using [CBOR](http://cbor.io) encoding. The choice of encoding can be decided at compile time using the build tag `binary_log` as follows:
|
||||
|
||||
```bash
|
||||
go build -tags binary_log .
|
||||
```
|
||||
|
||||
To Decode binary encoded log files you can use any CBOR decoder. One has been tested to work
|
||||
with zlog library is [CSD](https://github.com/toravir/csd/).
|
||||
with zerolog library is [CSD](https://github.com/toravir/csd/).
|
||||
|
||||
## Related Projects
|
||||
|
||||
* [grpc-zlog](https://github.com/cheapRoc/grpc-zlog): Implementation of `grpclog.LoggerV2` interface using `zlog`
|
||||
* [overlog](https://github.com/Trendyol/overlog): Implementation of `Mapped Diagnostic Context` interface using `zlog`
|
||||
* [zlogr](https://github.com/go-logr/zlogr): Implementation of `logr.LogSink` interface using `zlog`
|
||||
* [grpc-zerolog](https://github.com/cheapRoc/grpc-zerolog): Implementation of `grpclog.LoggerV2` interface using `zerolog`
|
||||
* [overlog](https://github.com/Trendyol/overlog): Implementation of `Mapped Diagnostic Context` interface using `zerolog`
|
||||
* [zerologr](https://github.com/go-logr/zerologr): Implementation of `logr.LogSink` interface using `zerolog`
|
||||
|
||||
## Benchmarks
|
||||
|
||||
|
@ -688,7 +633,7 @@ BenchmarkContextFields-8 30000000 44.9 ns/op 0 B/op 0 allocs/op
|
|||
BenchmarkLogFields-8 10000000 184 ns/op 0 B/op 0 allocs/op
|
||||
```
|
||||
|
||||
There are a few Go logging benchmarks and comparisons that include zlog.
|
||||
There are a few Go logging benchmarks and comparisons that include zerolog.
|
||||
|
||||
* [imkira/go-loggers-bench](https://github.com/imkira/go-loggers-bench)
|
||||
* [uber-common/zap](https://github.com/uber-go/zap#performance)
|
||||
|
@ -699,7 +644,7 @@ Log a message and 10 fields:
|
|||
|
||||
| Library | Time | Bytes Allocated | Objects Allocated |
|
||||
| :--- | :---: | :---: | :---: |
|
||||
| zlog | 767 ns/op | 552 B/op | 6 allocs/op |
|
||||
| zerolog | 767 ns/op | 552 B/op | 6 allocs/op |
|
||||
| :zap: zap | 848 ns/op | 704 B/op | 2 allocs/op |
|
||||
| :zap: zap (sugared) | 1363 ns/op | 1610 B/op | 20 allocs/op |
|
||||
| go-kit | 3614 ns/op | 2895 B/op | 66 allocs/op |
|
||||
|
@ -712,7 +657,7 @@ Log a message with a logger that already has 10 fields of context:
|
|||
|
||||
| Library | Time | Bytes Allocated | Objects Allocated |
|
||||
| :--- | :---: | :---: | :---: |
|
||||
| zlog | 52 ns/op | 0 B/op | 0 allocs/op |
|
||||
| zerolog | 52 ns/op | 0 B/op | 0 allocs/op |
|
||||
| :zap: zap | 283 ns/op | 0 B/op | 0 allocs/op |
|
||||
| :zap: zap (sugared) | 337 ns/op | 80 B/op | 2 allocs/op |
|
||||
| lion | 2702 ns/op | 4074 B/op | 38 allocs/op |
|
||||
|
@ -725,7 +670,7 @@ Log a static string, without any context or `printf`-style templating:
|
|||
|
||||
| Library | Time | Bytes Allocated | Objects Allocated |
|
||||
| :--- | :---: | :---: | :---: |
|
||||
| zlog | 50 ns/op | 0 B/op | 0 allocs/op |
|
||||
| zerolog | 50 ns/op | 0 B/op | 0 allocs/op |
|
||||
| :zap: zap | 236 ns/op | 0 B/op | 0 allocs/op |
|
||||
| standard library | 453 ns/op | 80 B/op | 2 allocs/op |
|
||||
| :zap: zap (sugared) | 337 ns/op | 80 B/op | 2 allocs/op |
|
||||
|
@ -737,10 +682,10 @@ Log a static string, without any context or `printf`-style templating:
|
|||
|
||||
## Caveats
|
||||
|
||||
Note that zlog does no de-duplication of fields. Using the same key multiple times creates multiple keys in final JSON:
|
||||
Note that zerolog does no de-duplication of fields. Using the same key multiple times creates multiple keys in final JSON:
|
||||
|
||||
```go
|
||||
logger := zlog.New(os.Stderr).With().Timestamp().Logger()
|
||||
logger := zerolog.New(os.Stderr).With().Timestamp().Logger()
|
||||
logger.Info().
|
||||
Timestamp().
|
||||
Msg("dup")
|
||||
|
|
42
array.go
42
array.go
|
@ -1,4 +1,4 @@
|
|||
package zlog
|
||||
package zerolog
|
||||
|
||||
import (
|
||||
"net"
|
||||
|
@ -57,7 +57,7 @@ func (a *Array) write(dst []byte) []byte {
|
|||
}
|
||||
|
||||
// Object marshals an object that implement the LogObjectMarshaler
|
||||
// interface and appends it to the array.
|
||||
// interface and append append it to the array.
|
||||
func (a *Array) Object(obj LogObjectMarshaler) *Array {
|
||||
e := Dict()
|
||||
obj.MarshalZerologObject(e)
|
||||
|
@ -67,19 +67,19 @@ func (a *Array) Object(obj LogObjectMarshaler) *Array {
|
|||
return a
|
||||
}
|
||||
|
||||
// Str appends the val as a string to the array.
|
||||
// Str append append the val as a string to the array.
|
||||
func (a *Array) Str(val string) *Array {
|
||||
a.buf = enc.AppendString(enc.AppendArrayDelim(a.buf), val)
|
||||
return a
|
||||
}
|
||||
|
||||
// Bytes appends the val as a string to the array.
|
||||
// Bytes append append the val as a string to the array.
|
||||
func (a *Array) Bytes(val []byte) *Array {
|
||||
a.buf = enc.AppendBytes(enc.AppendArrayDelim(a.buf), val)
|
||||
return a
|
||||
}
|
||||
|
||||
// Hex appends the val as a hex string to the array.
|
||||
// Hex append append the val as a hex string to the array.
|
||||
func (a *Array) Hex(val []byte) *Array {
|
||||
a.buf = enc.AppendHex(enc.AppendArrayDelim(a.buf), val)
|
||||
return a
|
||||
|
@ -115,97 +115,97 @@ func (a *Array) Err(err error) *Array {
|
|||
return a
|
||||
}
|
||||
|
||||
// Bool appends the val as a bool to the array.
|
||||
// Bool append append the val as a bool to the array.
|
||||
func (a *Array) Bool(b bool) *Array {
|
||||
a.buf = enc.AppendBool(enc.AppendArrayDelim(a.buf), b)
|
||||
return a
|
||||
}
|
||||
|
||||
// Int appends i as a int to the array.
|
||||
// Int append append i as a int to the array.
|
||||
func (a *Array) Int(i int) *Array {
|
||||
a.buf = enc.AppendInt(enc.AppendArrayDelim(a.buf), i)
|
||||
return a
|
||||
}
|
||||
|
||||
// Int8 appends i as a int8 to the array.
|
||||
// Int8 append append i as a int8 to the array.
|
||||
func (a *Array) Int8(i int8) *Array {
|
||||
a.buf = enc.AppendInt8(enc.AppendArrayDelim(a.buf), i)
|
||||
return a
|
||||
}
|
||||
|
||||
// Int16 appends i as a int16 to the array.
|
||||
// Int16 append append i as a int16 to the array.
|
||||
func (a *Array) Int16(i int16) *Array {
|
||||
a.buf = enc.AppendInt16(enc.AppendArrayDelim(a.buf), i)
|
||||
return a
|
||||
}
|
||||
|
||||
// Int32 appends i as a int32 to the array.
|
||||
// Int32 append append i as a int32 to the array.
|
||||
func (a *Array) Int32(i int32) *Array {
|
||||
a.buf = enc.AppendInt32(enc.AppendArrayDelim(a.buf), i)
|
||||
return a
|
||||
}
|
||||
|
||||
// Int64 appends i as a int64 to the array.
|
||||
// Int64 append append i as a int64 to the array.
|
||||
func (a *Array) Int64(i int64) *Array {
|
||||
a.buf = enc.AppendInt64(enc.AppendArrayDelim(a.buf), i)
|
||||
return a
|
||||
}
|
||||
|
||||
// Uint appends i as a uint to the array.
|
||||
// Uint append append i as a uint to the array.
|
||||
func (a *Array) Uint(i uint) *Array {
|
||||
a.buf = enc.AppendUint(enc.AppendArrayDelim(a.buf), i)
|
||||
return a
|
||||
}
|
||||
|
||||
// Uint8 appends i as a uint8 to the array.
|
||||
// Uint8 append append i as a uint8 to the array.
|
||||
func (a *Array) Uint8(i uint8) *Array {
|
||||
a.buf = enc.AppendUint8(enc.AppendArrayDelim(a.buf), i)
|
||||
return a
|
||||
}
|
||||
|
||||
// Uint16 appends i as a uint16 to the array.
|
||||
// Uint16 append append i as a uint16 to the array.
|
||||
func (a *Array) Uint16(i uint16) *Array {
|
||||
a.buf = enc.AppendUint16(enc.AppendArrayDelim(a.buf), i)
|
||||
return a
|
||||
}
|
||||
|
||||
// Uint32 appends i as a uint32 to the array.
|
||||
// Uint32 append append i as a uint32 to the array.
|
||||
func (a *Array) Uint32(i uint32) *Array {
|
||||
a.buf = enc.AppendUint32(enc.AppendArrayDelim(a.buf), i)
|
||||
return a
|
||||
}
|
||||
|
||||
// Uint64 appends i as a uint64 to the array.
|
||||
// Uint64 append append i as a uint64 to the array.
|
||||
func (a *Array) Uint64(i uint64) *Array {
|
||||
a.buf = enc.AppendUint64(enc.AppendArrayDelim(a.buf), i)
|
||||
return a
|
||||
}
|
||||
|
||||
// Float32 appends f as a float32 to the array.
|
||||
// Float32 append append f as a float32 to the array.
|
||||
func (a *Array) Float32(f float32) *Array {
|
||||
a.buf = enc.AppendFloat32(enc.AppendArrayDelim(a.buf), f)
|
||||
return a
|
||||
}
|
||||
|
||||
// Float64 appends f as a float64 to the array.
|
||||
// Float64 append append f as a float64 to the array.
|
||||
func (a *Array) Float64(f float64) *Array {
|
||||
a.buf = enc.AppendFloat64(enc.AppendArrayDelim(a.buf), f)
|
||||
return a
|
||||
}
|
||||
|
||||
// Time appends t formatted as string using zlog.TimeFieldFormat.
|
||||
// Time append append t formatted as string using zerolog.TimeFieldFormat.
|
||||
func (a *Array) Time(t time.Time) *Array {
|
||||
a.buf = enc.AppendTime(enc.AppendArrayDelim(a.buf), t, TimeFieldFormat)
|
||||
return a
|
||||
}
|
||||
|
||||
// Dur appends d to the array.
|
||||
// Dur append append d to the array.
|
||||
func (a *Array) Dur(d time.Duration) *Array {
|
||||
a.buf = enc.AppendDuration(enc.AppendArrayDelim(a.buf), d, DurationFieldUnit, DurationFieldInteger)
|
||||
return a
|
||||
}
|
||||
|
||||
// Interface appends i marshaled using reflection.
|
||||
// Interface append append i marshaled using reflection.
|
||||
func (a *Array) Interface(i interface{}) *Array {
|
||||
if obj, ok := i.(LogObjectMarshaler); ok {
|
||||
return a.Object(obj)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package zlog
|
||||
package zerolog
|
||||
|
||||
import (
|
||||
"net"
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package zlog
|
||||
package zerolog
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// +build binary_log
|
||||
|
||||
package zlog
|
||||
package zerolog
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
|
|
@ -4,13 +4,13 @@ This is a basic linter that checks for missing log event finishers. Finds errors
|
|||
|
||||
## Problem
|
||||
|
||||
When using zlog it's easy to forget to finish the log event chain by calling a finisher - the `Msg` or `Msgf` function that will schedule the event for writing. The problem with this is that it doesn't warn/panic during compilation and it's not easily found by grep or other general tools. It's even prominently mentioned in the project's readme, that:
|
||||
When using zerolog it's easy to forget to finish the log event chain by calling a finisher - the `Msg` or `Msgf` function that will schedule the event for writing. The problem with this is that it doesn't warn/panic during compilation and it's not easily found by grep or other general tools. It's even prominently mentioned in the project's readme, that:
|
||||
|
||||
> It is very important to note that when using the **zlog** chaining API, as shown above (`log.Info().Msg("hello world"`), the chain must have either the `Msg` or `Msgf` method call. If you forget to add either of these, the log will not occur and there is no compile time error to alert you of this.
|
||||
> It is very important to note that when using the **zerolog** chaining API, as shown above (`log.Info().Msg("hello world"`), the chain must have either the `Msg` or `Msgf` method call. If you forget to add either of these, the log will not occur and there is no compile time error to alert you of this.
|
||||
|
||||
## Solution
|
||||
|
||||
A basic linter like this one here that looks for method invocations on `zlog.Event` can examine the last call in a method call chain and check if it is a finisher, thus pointing out these errors.
|
||||
A basic linter like this one here that looks for method invocations on `zerolog.Event` can examine the last call in a method call chain and check if it is a finisher, thus pointing out these errors.
|
||||
|
||||
## Usage
|
||||
|
||||
|
@ -33,5 +33,5 @@ The command accepts only one argument - the package to be inspected - and 4 opti
|
|||
|
||||
## Drawbacks
|
||||
|
||||
As it is, linter can generate a false positives in a specific case. These false positives come from the fact that if you have a method that returns a `zlog.Event` the linter will flag it because you are obviously not finishing the event. This will be solved in later release.
|
||||
As it is, linter can generate a false positives in a specific case. These false positives come from the fact that if you have a method that returns a `zerolog.Event` the linter will flag it because you are obviously not finishing the event. This will be solved in later release.
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
module tuxpa.in/a/zlog/cmd/lint
|
||||
module github.com/rs/zerolog/cmd/lint
|
||||
|
||||
go 1.15
|
||||
|
||||
|
|
|
@ -29,8 +29,8 @@ func init() {
|
|||
flag.Var(&allowedFinishers, "finisher", "allowed finisher for the event chain")
|
||||
flag.Parse()
|
||||
|
||||
// add zlog to recursively ignored packages
|
||||
recursivelyIgnoredPkgs = append(recursivelyIgnoredPkgs, "tuxpa.in/a/zlog")
|
||||
// add zerolog to recursively ignored packages
|
||||
recursivelyIgnoredPkgs = append(recursivelyIgnoredPkgs, "github.com/rs/zerolog")
|
||||
args := flag.Args()
|
||||
if len(args) != 1 {
|
||||
fmt.Fprintln(os.Stderr, "you must provide exactly one package path")
|
||||
|
@ -49,14 +49,14 @@ func main() {
|
|||
os.Exit(1)
|
||||
}
|
||||
|
||||
// get the tuxpa.in/a/zlog.Event type
|
||||
// get the github.com/rs/zerolog.Event type
|
||||
event := getEvent(p)
|
||||
if event == nil {
|
||||
fmt.Fprintln(os.Stderr, "Error: tuxpa.in/a/zlog.Event declaration not found, maybe zlog is not imported in the scanned package?")
|
||||
fmt.Fprintln(os.Stderr, "Error: github.com/rs/zerolog.Event declaration not found, maybe zerolog is not imported in the scanned package?")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// get all selections (function calls) with the tuxpa.in/a/zlog.Event (or pointer) receiver
|
||||
// get all selections (function calls) with the github.com/rs/zerolog.Event (or pointer) receiver
|
||||
selections := getSelectionsWithReceiverType(p, event)
|
||||
|
||||
// print the violations (if any)
|
||||
|
@ -80,7 +80,7 @@ func main() {
|
|||
|
||||
func getEvent(p *loader.Program) types.Type {
|
||||
for _, pkg := range p.AllPackages {
|
||||
if strings.HasSuffix(pkg.Pkg.Path(), "tuxpa.in/a/zlog") {
|
||||
if strings.HasSuffix(pkg.Pkg.Path(), "github.com/rs/zerolog") {
|
||||
for _, d := range pkg.Defs {
|
||||
if d != nil && d.Name() == "Event" {
|
||||
return d.Type()
|
||||
|
|
|
@ -1,40 +0,0 @@
|
|||
# Zerolog PrettyLog
|
||||
|
||||
This is a basic CLI utility that will colorize and pretty print your structured JSON logs.
|
||||
|
||||
## Usage
|
||||
|
||||
You can compile it or run it directly. The only issue is that by default Zerolog does not output to `stdout`
|
||||
but rather to `stderr` so we must pipe `stderr` stream to this CLI tool.
|
||||
|
||||
### Linux
|
||||
|
||||
These commands will redirect `stderr` to our `prettylog` tool and `stdout` will remain unaffected.
|
||||
|
||||
1. Compiled version
|
||||
|
||||
```shell
|
||||
some_program_with_zerolog 2> >(prettylog)
|
||||
```
|
||||
|
||||
2. Run it directly with `go run`
|
||||
|
||||
```shell
|
||||
some_program_with_zerolog 2> >(go run cmd/prettylog/prettylog.go)
|
||||
```
|
||||
|
||||
### Windows
|
||||
|
||||
These commands will redirect `stderr` to `stdout` and then pipe it to our `prettylog` tool.
|
||||
|
||||
1. Compiled version
|
||||
|
||||
```shell
|
||||
some_program_with_zerolog 2>&1 | prettylog
|
||||
```
|
||||
|
||||
2. Run it directly with `go run`
|
||||
|
||||
```shell
|
||||
some_program_with_zerolog 2>&1 | go run cmd/prettylog/prettylog.go
|
||||
```
|
|
@ -1,26 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
|
||||
"tuxpa.in/a/zlog"
|
||||
)
|
||||
|
||||
func isInputFromPipe() bool {
|
||||
fileInfo, _ := os.Stdin.Stat()
|
||||
return fileInfo.Mode()&os.ModeCharDevice == 0
|
||||
}
|
||||
|
||||
func main() {
|
||||
if !isInputFromPipe() {
|
||||
fmt.Println("The command is intended to work with pipes.")
|
||||
fmt.Println("Usage: app_with_zerolog | 2> >(prettylog)")
|
||||
os.Exit(1)
|
||||
return
|
||||
}
|
||||
|
||||
writer := zlog.NewConsoleWriter()
|
||||
_, _ = io.Copy(writer, os.Stdin)
|
||||
}
|
38
console.go
38
console.go
|
@ -1,4 +1,4 @@
|
|||
package zlog
|
||||
package zerolog
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
@ -74,8 +74,6 @@ type ConsoleWriter struct {
|
|||
FormatFieldValue Formatter
|
||||
FormatErrFieldName Formatter
|
||||
FormatErrFieldValue Formatter
|
||||
|
||||
FormatExtra func(map[string]interface{}, *bytes.Buffer) error
|
||||
}
|
||||
|
||||
// NewConsoleWriter creates and initializes a new ConsoleWriter.
|
||||
|
@ -130,18 +128,10 @@ func (w ConsoleWriter) Write(p []byte) (n int, err error) {
|
|||
|
||||
w.writeFields(evt, buf)
|
||||
|
||||
if w.FormatExtra != nil {
|
||||
err = w.FormatExtra(evt, buf)
|
||||
if err != nil {
|
||||
return n, err
|
||||
}
|
||||
}
|
||||
|
||||
err = buf.WriteByte('\n')
|
||||
if err != nil {
|
||||
return n, err
|
||||
}
|
||||
|
||||
_, err = buf.WriteTo(w.Out)
|
||||
return len(p), err
|
||||
}
|
||||
|
@ -231,7 +221,7 @@ func (w ConsoleWriter) writeFields(evt map[string]interface{}, buf *bytes.Buffer
|
|||
case json.Number:
|
||||
buf.WriteString(fv(fValue))
|
||||
default:
|
||||
b, err := InterfaceMarshalFunc(fValue)
|
||||
b, err := json.Marshal(fValue)
|
||||
if err != nil {
|
||||
fmt.Fprintf(buf, colorize("[error: %v]", colorRed, w.NoColor), err)
|
||||
} else {
|
||||
|
@ -337,31 +327,27 @@ func consoleDefaultFormatTimestamp(timeFormat string, noColor bool) Formatter {
|
|||
t := "<nil>"
|
||||
switch tt := i.(type) {
|
||||
case string:
|
||||
ts, err := time.ParseInLocation(TimeFieldFormat, tt, time.Local)
|
||||
ts, err := time.Parse(TimeFieldFormat, tt)
|
||||
if err != nil {
|
||||
t = tt
|
||||
} else {
|
||||
t = ts.Local().Format(timeFormat)
|
||||
t = ts.Format(timeFormat)
|
||||
}
|
||||
case json.Number:
|
||||
i, err := tt.Int64()
|
||||
if err != nil {
|
||||
t = tt.String()
|
||||
} else {
|
||||
var sec, nsec int64
|
||||
|
||||
var sec, nsec int64 = i, 0
|
||||
switch TimeFieldFormat {
|
||||
case TimeFormatUnixNano:
|
||||
sec, nsec = 0, i
|
||||
case TimeFormatUnixMicro:
|
||||
sec, nsec = 0, int64(time.Duration(i)*time.Microsecond)
|
||||
case TimeFormatUnixMs:
|
||||
sec, nsec = 0, int64(time.Duration(i)*time.Millisecond)
|
||||
default:
|
||||
sec, nsec = i, 0
|
||||
nsec = int64(time.Duration(i) * time.Millisecond)
|
||||
sec = 0
|
||||
case TimeFormatUnixMicro:
|
||||
nsec = int64(time.Duration(i) * time.Microsecond)
|
||||
sec = 0
|
||||
}
|
||||
|
||||
ts := time.Unix(sec, nsec)
|
||||
ts := time.Unix(sec, nsec).UTC()
|
||||
t = ts.Format(timeFormat)
|
||||
}
|
||||
}
|
||||
|
@ -389,7 +375,7 @@ func consoleDefaultFormatLevel(noColor bool) Formatter {
|
|||
case LevelPanicValue:
|
||||
l = colorize(colorize("PNC", colorRed, noColor), colorBold, noColor)
|
||||
default:
|
||||
l = colorize(ll, colorBold, noColor)
|
||||
l = colorize("???", colorBold, noColor)
|
||||
}
|
||||
} else {
|
||||
if i == nil {
|
||||
|
|
149
console_test.go
149
console_test.go
|
@ -1,4 +1,4 @@
|
|||
package zlog_test
|
||||
package zerolog_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
@ -9,39 +9,39 @@ import (
|
|||
"testing"
|
||||
"time"
|
||||
|
||||
"tuxpa.in/a/zlog"
|
||||
"github.com/rs/zerolog"
|
||||
)
|
||||
|
||||
func ExampleConsoleWriter() {
|
||||
log := zlog.New(zlog.ConsoleWriter{Out: os.Stdout, NoColor: true})
|
||||
log := zerolog.New(zerolog.ConsoleWriter{Out: os.Stdout, NoColor: true})
|
||||
|
||||
log.Info().Str("foo", "bar").Msg("Hello World")
|
||||
// Output: <nil> INF Hello World foo=bar
|
||||
}
|
||||
|
||||
func ExampleConsoleWriter_customFormatters() {
|
||||
out := zlog.ConsoleWriter{Out: os.Stdout, NoColor: true}
|
||||
out := zerolog.ConsoleWriter{Out: os.Stdout, NoColor: true}
|
||||
out.FormatLevel = func(i interface{}) string { return strings.ToUpper(fmt.Sprintf("%-6s|", i)) }
|
||||
out.FormatFieldName = func(i interface{}) string { return fmt.Sprintf("%s:", i) }
|
||||
out.FormatFieldValue = func(i interface{}) string { return strings.ToUpper(fmt.Sprintf("%s", i)) }
|
||||
log := zlog.New(out)
|
||||
log := zerolog.New(out)
|
||||
|
||||
log.Info().Str("foo", "bar").Msg("Hello World")
|
||||
// Output: <nil> INFO | Hello World foo:BAR
|
||||
}
|
||||
|
||||
func ExampleNewConsoleWriter() {
|
||||
out := zlog.NewConsoleWriter()
|
||||
out := zerolog.NewConsoleWriter()
|
||||
out.NoColor = true // For testing purposes only
|
||||
log := zlog.New(out)
|
||||
log := zerolog.New(out)
|
||||
|
||||
log.Debug().Str("foo", "bar").Msg("Hello World")
|
||||
// Output: <nil> DBG Hello World foo=bar
|
||||
}
|
||||
|
||||
func ExampleNewConsoleWriter_customFormatters() {
|
||||
out := zlog.NewConsoleWriter(
|
||||
func(w *zlog.ConsoleWriter) {
|
||||
out := zerolog.NewConsoleWriter(
|
||||
func(w *zerolog.ConsoleWriter) {
|
||||
// Customize time format
|
||||
w.TimeFormat = time.RFC822
|
||||
// Customize level formatting
|
||||
|
@ -50,7 +50,7 @@ func ExampleNewConsoleWriter_customFormatters() {
|
|||
)
|
||||
out.NoColor = true // For testing purposes only
|
||||
|
||||
log := zlog.New(out)
|
||||
log := zerolog.New(out)
|
||||
|
||||
log.Info().Str("foo", "bar").Msg("Hello World")
|
||||
// Output: <nil> [INFO ] Hello World foo=bar
|
||||
|
@ -59,7 +59,7 @@ func ExampleNewConsoleWriter_customFormatters() {
|
|||
func TestConsoleLogger(t *testing.T) {
|
||||
t.Run("Numbers", func(t *testing.T) {
|
||||
buf := &bytes.Buffer{}
|
||||
log := zlog.New(zlog.ConsoleWriter{Out: buf, NoColor: true})
|
||||
log := zerolog.New(zerolog.ConsoleWriter{Out: buf, NoColor: true})
|
||||
log.Info().
|
||||
Float64("float", 1.23).
|
||||
Uint64("small", 123).
|
||||
|
@ -74,7 +74,7 @@ func TestConsoleLogger(t *testing.T) {
|
|||
func TestConsoleWriter(t *testing.T) {
|
||||
t.Run("Default field formatter", func(t *testing.T) {
|
||||
buf := &bytes.Buffer{}
|
||||
w := zlog.ConsoleWriter{Out: buf, NoColor: true, PartsOrder: []string{"foo"}}
|
||||
w := zerolog.ConsoleWriter{Out: buf, NoColor: true, PartsOrder: []string{"foo"}}
|
||||
|
||||
_, err := w.Write([]byte(`{"foo": "DEFAULT"}`))
|
||||
if err != nil {
|
||||
|
@ -90,7 +90,7 @@ func TestConsoleWriter(t *testing.T) {
|
|||
|
||||
t.Run("Write colorized", func(t *testing.T) {
|
||||
buf := &bytes.Buffer{}
|
||||
w := zlog.ConsoleWriter{Out: buf, NoColor: false}
|
||||
w := zerolog.ConsoleWriter{Out: buf, NoColor: false}
|
||||
|
||||
_, err := w.Write([]byte(`{"level": "warn", "message": "Foobar"}`))
|
||||
if err != nil {
|
||||
|
@ -106,16 +106,15 @@ func TestConsoleWriter(t *testing.T) {
|
|||
|
||||
t.Run("Write fields", func(t *testing.T) {
|
||||
buf := &bytes.Buffer{}
|
||||
w := zlog.ConsoleWriter{Out: buf, NoColor: true}
|
||||
w := zerolog.ConsoleWriter{Out: buf, NoColor: true}
|
||||
|
||||
ts := time.Unix(0, 0)
|
||||
d := ts.UTC().Format(time.RFC3339)
|
||||
d := time.Unix(0, 0).UTC().Format(time.RFC3339)
|
||||
_, err := w.Write([]byte(`{"time": "` + d + `", "level": "debug", "message": "Foobar", "foo": "bar"}`))
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error when writing output: %s", err)
|
||||
}
|
||||
|
||||
expectedOutput := ts.Format(time.Kitchen) + " DBG Foobar foo=bar\n"
|
||||
expectedOutput := "12:00AM DBG Foobar foo=bar\n"
|
||||
actualOutput := buf.String()
|
||||
if actualOutput != expectedOutput {
|
||||
t.Errorf("Unexpected output %q, want: %q", actualOutput, expectedOutput)
|
||||
|
@ -123,21 +122,21 @@ func TestConsoleWriter(t *testing.T) {
|
|||
})
|
||||
|
||||
t.Run("Unix timestamp input format", func(t *testing.T) {
|
||||
of := zlog.TimeFieldFormat
|
||||
of := zerolog.TimeFieldFormat
|
||||
defer func() {
|
||||
zlog.TimeFieldFormat = of
|
||||
zerolog.TimeFieldFormat = of
|
||||
}()
|
||||
zlog.TimeFieldFormat = zlog.TimeFormatUnix
|
||||
zerolog.TimeFieldFormat = zerolog.TimeFormatUnix
|
||||
|
||||
buf := &bytes.Buffer{}
|
||||
w := zlog.ConsoleWriter{Out: buf, TimeFormat: time.StampMilli, NoColor: true}
|
||||
w := zerolog.ConsoleWriter{Out: buf, TimeFormat: time.StampMilli, NoColor: true}
|
||||
|
||||
_, err := w.Write([]byte(`{"time": 1234, "level": "debug", "message": "Foobar", "foo": "bar"}`))
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error when writing output: %s", err)
|
||||
}
|
||||
|
||||
expectedOutput := time.Unix(1234, 0).Format(time.StampMilli) + " DBG Foobar foo=bar\n"
|
||||
expectedOutput := "Jan 1 00:20:34.000 DBG Foobar foo=bar\n"
|
||||
actualOutput := buf.String()
|
||||
if actualOutput != expectedOutput {
|
||||
t.Errorf("Unexpected output %q, want: %q", actualOutput, expectedOutput)
|
||||
|
@ -145,21 +144,21 @@ func TestConsoleWriter(t *testing.T) {
|
|||
})
|
||||
|
||||
t.Run("Unix timestamp ms input format", func(t *testing.T) {
|
||||
of := zlog.TimeFieldFormat
|
||||
of := zerolog.TimeFieldFormat
|
||||
defer func() {
|
||||
zlog.TimeFieldFormat = of
|
||||
zerolog.TimeFieldFormat = of
|
||||
}()
|
||||
zlog.TimeFieldFormat = zlog.TimeFormatUnixMs
|
||||
zerolog.TimeFieldFormat = zerolog.TimeFormatUnixMs
|
||||
|
||||
buf := &bytes.Buffer{}
|
||||
w := zlog.ConsoleWriter{Out: buf, TimeFormat: time.StampMilli, NoColor: true}
|
||||
w := zerolog.ConsoleWriter{Out: buf, TimeFormat: time.StampMilli, NoColor: true}
|
||||
|
||||
_, err := w.Write([]byte(`{"time": 1234567, "level": "debug", "message": "Foobar", "foo": "bar"}`))
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error when writing output: %s", err)
|
||||
}
|
||||
|
||||
expectedOutput := time.Unix(1234, 567000000).Format(time.StampMilli) + " DBG Foobar foo=bar\n"
|
||||
expectedOutput := "Jan 1 00:20:34.567 DBG Foobar foo=bar\n"
|
||||
actualOutput := buf.String()
|
||||
if actualOutput != expectedOutput {
|
||||
t.Errorf("Unexpected output %q, want: %q", actualOutput, expectedOutput)
|
||||
|
@ -167,21 +166,21 @@ func TestConsoleWriter(t *testing.T) {
|
|||
})
|
||||
|
||||
t.Run("Unix timestamp us input format", func(t *testing.T) {
|
||||
of := zlog.TimeFieldFormat
|
||||
of := zerolog.TimeFieldFormat
|
||||
defer func() {
|
||||
zlog.TimeFieldFormat = of
|
||||
zerolog.TimeFieldFormat = of
|
||||
}()
|
||||
zlog.TimeFieldFormat = zlog.TimeFormatUnixMicro
|
||||
zerolog.TimeFieldFormat = zerolog.TimeFormatUnixMicro
|
||||
|
||||
buf := &bytes.Buffer{}
|
||||
w := zlog.ConsoleWriter{Out: buf, TimeFormat: time.StampMicro, NoColor: true}
|
||||
w := zerolog.ConsoleWriter{Out: buf, TimeFormat: time.StampMicro, NoColor: true}
|
||||
|
||||
_, err := w.Write([]byte(`{"time": 1234567891, "level": "debug", "message": "Foobar", "foo": "bar"}`))
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error when writing output: %s", err)
|
||||
}
|
||||
|
||||
expectedOutput := time.Unix(1234, 567891000).Format(time.StampMicro) + " DBG Foobar foo=bar\n"
|
||||
expectedOutput := "Jan 1 00:20:34.567891 DBG Foobar foo=bar\n"
|
||||
actualOutput := buf.String()
|
||||
if actualOutput != expectedOutput {
|
||||
t.Errorf("Unexpected output %q, want: %q", actualOutput, expectedOutput)
|
||||
|
@ -190,7 +189,7 @@ func TestConsoleWriter(t *testing.T) {
|
|||
|
||||
t.Run("No message field", func(t *testing.T) {
|
||||
buf := &bytes.Buffer{}
|
||||
w := zlog.ConsoleWriter{Out: buf, NoColor: true}
|
||||
w := zerolog.ConsoleWriter{Out: buf, NoColor: true}
|
||||
|
||||
_, err := w.Write([]byte(`{"level": "debug", "foo": "bar"}`))
|
||||
if err != nil {
|
||||
|
@ -206,7 +205,7 @@ func TestConsoleWriter(t *testing.T) {
|
|||
|
||||
t.Run("No level field", func(t *testing.T) {
|
||||
buf := &bytes.Buffer{}
|
||||
w := zlog.ConsoleWriter{Out: buf, NoColor: true}
|
||||
w := zerolog.ConsoleWriter{Out: buf, NoColor: true}
|
||||
|
||||
_, err := w.Write([]byte(`{"message": "Foobar", "foo": "bar"}`))
|
||||
if err != nil {
|
||||
|
@ -222,7 +221,7 @@ func TestConsoleWriter(t *testing.T) {
|
|||
|
||||
t.Run("Write colorized fields", func(t *testing.T) {
|
||||
buf := &bytes.Buffer{}
|
||||
w := zlog.ConsoleWriter{Out: buf, NoColor: false}
|
||||
w := zerolog.ConsoleWriter{Out: buf, NoColor: false}
|
||||
|
||||
_, err := w.Write([]byte(`{"level": "warn", "message": "Foobar", "foo": "bar"}`))
|
||||
if err != nil {
|
||||
|
@ -238,10 +237,9 @@ func TestConsoleWriter(t *testing.T) {
|
|||
|
||||
t.Run("Write error field", func(t *testing.T) {
|
||||
buf := &bytes.Buffer{}
|
||||
w := zlog.ConsoleWriter{Out: buf, NoColor: true}
|
||||
w := zerolog.ConsoleWriter{Out: buf, NoColor: true}
|
||||
|
||||
ts := time.Unix(0, 0)
|
||||
d := ts.UTC().Format(time.RFC3339)
|
||||
d := time.Unix(0, 0).UTC().Format(time.RFC3339)
|
||||
evt := `{"time": "` + d + `", "level": "error", "message": "Foobar", "aaa": "bbb", "error": "Error"}`
|
||||
// t.Log(evt)
|
||||
|
||||
|
@ -250,7 +248,7 @@ func TestConsoleWriter(t *testing.T) {
|
|||
t.Errorf("Unexpected error when writing output: %s", err)
|
||||
}
|
||||
|
||||
expectedOutput := ts.Format(time.Kitchen) + " ERR Foobar error=Error aaa=bbb\n"
|
||||
expectedOutput := "12:00AM ERR Foobar error=Error aaa=bbb\n"
|
||||
actualOutput := buf.String()
|
||||
if actualOutput != expectedOutput {
|
||||
t.Errorf("Unexpected output %q, want: %q", actualOutput, expectedOutput)
|
||||
|
@ -259,15 +257,14 @@ func TestConsoleWriter(t *testing.T) {
|
|||
|
||||
t.Run("Write caller field", func(t *testing.T) {
|
||||
buf := &bytes.Buffer{}
|
||||
w := zlog.ConsoleWriter{Out: buf, NoColor: true}
|
||||
w := zerolog.ConsoleWriter{Out: buf, NoColor: true}
|
||||
|
||||
cwd, err := os.Getwd()
|
||||
if err != nil {
|
||||
t.Fatalf("Cannot get working directory: %s", err)
|
||||
}
|
||||
|
||||
ts := time.Unix(0, 0)
|
||||
d := ts.UTC().Format(time.RFC3339)
|
||||
d := time.Unix(0, 0).UTC().Format(time.RFC3339)
|
||||
evt := `{"time": "` + d + `", "level": "debug", "message": "Foobar", "foo": "bar", "caller": "` + cwd + `/foo/bar.go"}`
|
||||
// t.Log(evt)
|
||||
|
||||
|
@ -276,7 +273,7 @@ func TestConsoleWriter(t *testing.T) {
|
|||
t.Errorf("Unexpected error when writing output: %s", err)
|
||||
}
|
||||
|
||||
expectedOutput := ts.Format(time.Kitchen) + " DBG foo/bar.go > Foobar foo=bar\n"
|
||||
expectedOutput := "12:00AM DBG foo/bar.go > Foobar foo=bar\n"
|
||||
actualOutput := buf.String()
|
||||
if actualOutput != expectedOutput {
|
||||
t.Errorf("Unexpected output %q, want: %q", actualOutput, expectedOutput)
|
||||
|
@ -285,7 +282,7 @@ func TestConsoleWriter(t *testing.T) {
|
|||
|
||||
t.Run("Write JSON field", func(t *testing.T) {
|
||||
buf := &bytes.Buffer{}
|
||||
w := zlog.ConsoleWriter{Out: buf, NoColor: true}
|
||||
w := zerolog.ConsoleWriter{Out: buf, NoColor: true}
|
||||
|
||||
evt := `{"level": "debug", "message": "Foobar", "foo": [1, 2, 3], "bar": true}`
|
||||
// t.Log(evt)
|
||||
|
@ -306,10 +303,9 @@ func TestConsoleWriter(t *testing.T) {
|
|||
func TestConsoleWriterConfiguration(t *testing.T) {
|
||||
t.Run("Sets TimeFormat", func(t *testing.T) {
|
||||
buf := &bytes.Buffer{}
|
||||
w := zlog.ConsoleWriter{Out: buf, NoColor: true, TimeFormat: time.RFC3339}
|
||||
w := zerolog.ConsoleWriter{Out: buf, NoColor: true, TimeFormat: time.RFC3339}
|
||||
|
||||
ts := time.Unix(0, 0)
|
||||
d := ts.UTC().Format(time.RFC3339)
|
||||
d := time.Unix(0, 0).UTC().Format(time.RFC3339)
|
||||
evt := `{"time": "` + d + `", "level": "info", "message": "Foobar"}`
|
||||
|
||||
_, err := w.Write([]byte(evt))
|
||||
|
@ -317,7 +313,7 @@ func TestConsoleWriterConfiguration(t *testing.T) {
|
|||
t.Errorf("Unexpected error when writing output: %s", err)
|
||||
}
|
||||
|
||||
expectedOutput := ts.Format(time.RFC3339) + " INF Foobar\n"
|
||||
expectedOutput := "1970-01-01T00:00:00Z INF Foobar\n"
|
||||
actualOutput := buf.String()
|
||||
if actualOutput != expectedOutput {
|
||||
t.Errorf("Unexpected output %q, want: %q", actualOutput, expectedOutput)
|
||||
|
@ -326,7 +322,7 @@ func TestConsoleWriterConfiguration(t *testing.T) {
|
|||
|
||||
t.Run("Sets PartsOrder", func(t *testing.T) {
|
||||
buf := &bytes.Buffer{}
|
||||
w := zlog.ConsoleWriter{Out: buf, NoColor: true, PartsOrder: []string{"message", "level"}}
|
||||
w := zerolog.ConsoleWriter{Out: buf, NoColor: true, PartsOrder: []string{"message", "level"}}
|
||||
|
||||
evt := `{"level": "info", "message": "Foobar"}`
|
||||
_, err := w.Write([]byte(evt))
|
||||
|
@ -343,7 +339,7 @@ func TestConsoleWriterConfiguration(t *testing.T) {
|
|||
|
||||
t.Run("Sets PartsExclude", func(t *testing.T) {
|
||||
buf := &bytes.Buffer{}
|
||||
w := zlog.ConsoleWriter{Out: buf, NoColor: true, PartsExclude: []string{"time"}}
|
||||
w := zerolog.ConsoleWriter{Out: buf, NoColor: true, PartsExclude: []string{"time"}}
|
||||
|
||||
d := time.Unix(0, 0).UTC().Format(time.RFC3339)
|
||||
evt := `{"time": "` + d + `", "level": "info", "message": "Foobar"}`
|
||||
|
@ -361,7 +357,7 @@ func TestConsoleWriterConfiguration(t *testing.T) {
|
|||
|
||||
t.Run("Sets FieldsExclude", func(t *testing.T) {
|
||||
buf := &bytes.Buffer{}
|
||||
w := zlog.ConsoleWriter{Out: buf, NoColor: true, FieldsExclude: []string{"foo"}}
|
||||
w := zerolog.ConsoleWriter{Out: buf, NoColor: true, FieldsExclude: []string{"foo"}}
|
||||
|
||||
evt := `{"level": "info", "message": "Foobar", "foo":"bar", "baz":"quux"}`
|
||||
_, err := w.Write([]byte(evt))
|
||||
|
@ -375,55 +371,6 @@ func TestConsoleWriterConfiguration(t *testing.T) {
|
|||
t.Errorf("Unexpected output %q, want: %q", actualOutput, expectedOutput)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Sets FormatExtra", func(t *testing.T) {
|
||||
buf := &bytes.Buffer{}
|
||||
w := zlog.ConsoleWriter{
|
||||
Out: buf, NoColor: true, PartsOrder: []string{"level", "message"},
|
||||
FormatExtra: func(evt map[string]interface{}, buf *bytes.Buffer) error {
|
||||
buf.WriteString("\nAdditional stacktrace")
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
evt := `{"level": "info", "message": "Foobar"}`
|
||||
_, err := w.Write([]byte(evt))
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error when writing output: %s", err)
|
||||
}
|
||||
|
||||
expectedOutput := "INF Foobar\nAdditional stacktrace\n"
|
||||
actualOutput := buf.String()
|
||||
if actualOutput != expectedOutput {
|
||||
t.Errorf("Unexpected output %q, want: %q", actualOutput, expectedOutput)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Uses local time for console writer without time zone", func(t *testing.T) {
|
||||
// Regression test for issue #483 (check there for more details)
|
||||
|
||||
timeFormat := "2006-01-02 15:04:05"
|
||||
expectedOutput := "2022-10-20 20:24:50 INF Foobar\n"
|
||||
evt := `{"time": "2022-10-20 20:24:50", "level": "info", "message": "Foobar"}`
|
||||
|
||||
of := zlog.TimeFieldFormat
|
||||
defer func() {
|
||||
zlog.TimeFieldFormat = of
|
||||
}()
|
||||
zlog.TimeFieldFormat = timeFormat
|
||||
|
||||
buf := &bytes.Buffer{}
|
||||
w := zlog.ConsoleWriter{Out: buf, NoColor: true, TimeFormat: timeFormat}
|
||||
_, err := w.Write([]byte(evt))
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error when writing output: %s", err)
|
||||
}
|
||||
|
||||
actualOutput := buf.String()
|
||||
if actualOutput != expectedOutput {
|
||||
t.Errorf("Unexpected output %q, want: %q", actualOutput, expectedOutput)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func BenchmarkConsoleWriter(b *testing.B) {
|
||||
|
@ -432,7 +379,7 @@ func BenchmarkConsoleWriter(b *testing.B) {
|
|||
|
||||
var msg = []byte(`{"level": "info", "foo": "bar", "message": "HELLO", "time": "1990-01-01"}`)
|
||||
|
||||
w := zlog.ConsoleWriter{Out: ioutil.Discard, NoColor: false}
|
||||
w := zerolog.ConsoleWriter{Out: ioutil.Discard, NoColor: false}
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
w.Write(msg)
|
||||
|
|
17
context.go
17
context.go
|
@ -1,4 +1,4 @@
|
|||
package zlog
|
||||
package zerolog
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
@ -35,7 +35,7 @@ func (c Context) Dict(key string, dict *Event) Context {
|
|||
}
|
||||
|
||||
// Array adds the field key with an array to the event context.
|
||||
// Use zlog.Arr() to create the array or pass a type that
|
||||
// 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 = enc.AppendKey(c.l.context, key)
|
||||
|
@ -329,9 +329,8 @@ func (ts timestampHook) Run(e *Event, level Level, msg string) {
|
|||
|
||||
var th = timestampHook{}
|
||||
|
||||
// Timestamp adds the current local time to the logger context with the "time" key, formatted using zlog.TimeFieldFormat.
|
||||
// To customize the key name, change zlog.TimestampFieldName.
|
||||
// To customize the time format, change zlog.TimeFieldFormat.
|
||||
// Timestamp adds the current local time as UNIX timestamp to the logger context with the "time" key.
|
||||
// To customize the key name, change zerolog.TimestampFieldName.
|
||||
//
|
||||
// NOTE: It won't dedupe the "time" key if the *Context has one already.
|
||||
func (c Context) Timestamp() Context {
|
||||
|
@ -339,13 +338,13 @@ func (c Context) Timestamp() Context {
|
|||
return c
|
||||
}
|
||||
|
||||
// Time adds the field key with t formated as string using zlog.TimeFieldFormat.
|
||||
// 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 = enc.AppendTime(enc.AppendKey(c.l.context, key), t, TimeFieldFormat)
|
||||
return c
|
||||
}
|
||||
|
||||
// Times adds the field key with t formated as string using zlog.TimeFieldFormat.
|
||||
// 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 = enc.AppendTimes(enc.AppendKey(c.l.context, key), t, TimeFieldFormat)
|
||||
return c
|
||||
|
@ -395,13 +394,13 @@ const useGlobalSkipFrameCount = math.MinInt32
|
|||
// ch is the default caller hook using the global CallerSkipFrameCount.
|
||||
var ch = newCallerHook(useGlobalSkipFrameCount)
|
||||
|
||||
// Caller adds the file:line of the caller with the zlog.CallerFieldName key.
|
||||
// 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
|
||||
}
|
||||
|
||||
// CallerWithSkipFrameCount adds the file:line of the caller with the zlog.CallerFieldName key.
|
||||
// CallerWithSkipFrameCount adds the file:line of the caller with the zerolog.CallerFieldName key.
|
||||
// The specified skipFrameCount int will override the global CallerSkipFrameCount for this context's respective logger.
|
||||
// If set to -1 the global CallerSkipFrameCount will be used.
|
||||
func (c Context) CallerWithSkipFrameCount(skipFrameCount int) Context {
|
||||
|
|
23
ctx.go
23
ctx.go
|
@ -1,4 +1,4 @@
|
|||
package zlog
|
||||
package zerolog
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
@ -14,25 +14,24 @@ func init() {
|
|||
|
||||
type ctxKey struct{}
|
||||
|
||||
// WithContext returns a copy of ctx with the receiver attached. The Logger
|
||||
// attached to the provided Context (if any) will not be effected. If the
|
||||
// receiver's log level is Disabled it will only be attached to the returned
|
||||
// Context if the provided Context has a previously attached Logger. If the
|
||||
// provided Context has no attached Logger, a Disabled Logger will not be
|
||||
// attached.
|
||||
// WithContext returns a copy of ctx with l associated. If an instance of Logger
|
||||
// is already in the context, the context is not updated.
|
||||
//
|
||||
// Note: to modify the existing Logger attached to a Context (instead of
|
||||
// replacing it in a new Context), use UpdateContext with the following
|
||||
// For instance, to add a field to an existing logger in the context, use this
|
||||
// notation:
|
||||
//
|
||||
// ctx := r.Context()
|
||||
// l := zlog.Ctx(ctx)
|
||||
// l := zerolog.Ctx(ctx)
|
||||
// l.UpdateContext(func(c Context) Context {
|
||||
// return c.Str("bar", "baz")
|
||||
// })
|
||||
//
|
||||
func (l Logger) WithContext(ctx context.Context) context.Context {
|
||||
if _, ok := ctx.Value(ctxKey{}).(*Logger); !ok && l.level == Disabled {
|
||||
if lp, ok := ctx.Value(ctxKey{}).(*Logger); ok {
|
||||
if lp == &l {
|
||||
// Do not store same logger.
|
||||
return ctx
|
||||
}
|
||||
} else if l.level == Disabled {
|
||||
// Do not store disabled logger.
|
||||
return ctx
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package zlog
|
||||
package zerolog
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
|
|
@ -8,7 +8,7 @@ import (
|
|||
"sync"
|
||||
"time"
|
||||
|
||||
"tuxpa.in/a/zlog/diode/internal/diodes"
|
||||
"github.com/rs/zerolog/diode/internal/diodes"
|
||||
)
|
||||
|
||||
var bufPool = &sync.Pool{
|
||||
|
@ -42,7 +42,7 @@ type Writer struct {
|
|||
// wr := diode.NewWriter(w, 1000, 0, func(missed int) {
|
||||
// log.Printf("Dropped %d messages", missed)
|
||||
// })
|
||||
// log := zlog.New(wr)
|
||||
// log := zerolog.New(wr)
|
||||
//
|
||||
// If pollInterval is greater than 0, a poller is used otherwise a waiter is
|
||||
// used.
|
||||
|
@ -72,7 +72,7 @@ func NewWriter(w io.Writer, size int, pollInterval time.Duration, f Alerter) Wri
|
|||
}
|
||||
|
||||
func (dw Writer) Write(p []byte) (n int, err error) {
|
||||
// p is pooled in zlog so we can't hold it passed this call, hence the
|
||||
// p is pooled in zerolog so we can't hold it passed this call, hence the
|
||||
// copy.
|
||||
p = append(bufPool.Get().([]byte), p...)
|
||||
dw.d.Set(diodes.GenericDataType(&p))
|
||||
|
|
|
@ -6,15 +6,15 @@ import (
|
|||
"fmt"
|
||||
"os"
|
||||
|
||||
"tuxpa.in/a/zlog"
|
||||
"tuxpa.in/a/zlog/diode"
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/rs/zerolog/diode"
|
||||
)
|
||||
|
||||
func ExampleNewWriter() {
|
||||
w := diode.NewWriter(os.Stdout, 1000, 0, func(missed int) {
|
||||
fmt.Printf("Dropped %d messages\n", missed)
|
||||
})
|
||||
log := zlog.New(w)
|
||||
log := zerolog.New(w)
|
||||
log.Print("test")
|
||||
|
||||
w.Close()
|
||||
|
|
|
@ -9,9 +9,9 @@ import (
|
|||
"testing"
|
||||
"time"
|
||||
|
||||
"tuxpa.in/a/zlog"
|
||||
"tuxpa.in/a/zlog/diode"
|
||||
"tuxpa.in/a/zlog/internal/cbor"
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/rs/zerolog/diode"
|
||||
"github.com/rs/zerolog/internal/cbor"
|
||||
)
|
||||
|
||||
func TestNewWriter(t *testing.T) {
|
||||
|
@ -19,7 +19,7 @@ func TestNewWriter(t *testing.T) {
|
|||
w := diode.NewWriter(&buf, 1000, 0, func(missed int) {
|
||||
fmt.Printf("Dropped %d messages\n", missed)
|
||||
})
|
||||
log := zlog.New(w)
|
||||
log := zerolog.New(w)
|
||||
log.Print("test")
|
||||
|
||||
w.Close()
|
||||
|
@ -30,14 +30,6 @@ func TestNewWriter(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestClose(t *testing.T) {
|
||||
buf := bytes.Buffer{}
|
||||
w := diode.NewWriter(&buf, 1000, 0, func(missed int) {})
|
||||
log := zlog.New(w)
|
||||
log.Print("test")
|
||||
w.Close()
|
||||
}
|
||||
|
||||
func Benchmark(b *testing.B) {
|
||||
log.SetOutput(ioutil.Discard)
|
||||
defer log.SetOutput(os.Stderr)
|
||||
|
@ -48,7 +40,7 @@ func Benchmark(b *testing.B) {
|
|||
for name, interval := range benchs {
|
||||
b.Run(name, func(b *testing.B) {
|
||||
w := diode.NewWriter(ioutil.Discard, 100000, interval, nil)
|
||||
log := zlog.New(w)
|
||||
log := zerolog.New(w)
|
||||
defer w.Close()
|
||||
|
||||
b.SetParallelism(1000)
|
||||
|
|
|
@ -39,12 +39,7 @@ func NewWaiter(d Diode, opts ...WaiterConfigOption) *Waiter {
|
|||
|
||||
go func() {
|
||||
<-w.ctx.Done()
|
||||
|
||||
// Mutex is strictly necessary here to avoid a race in Next() (between
|
||||
// w.isDone() and w.c.Wait()) and w.c.Broadcast() here.
|
||||
w.mu.Lock()
|
||||
w.c.Broadcast()
|
||||
w.mu.Unlock()
|
||||
}()
|
||||
|
||||
return w
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package zlog
|
||||
package zerolog
|
||||
|
||||
import (
|
||||
"net"
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
// +build binary_log
|
||||
|
||||
package zlog
|
||||
package zerolog
|
||||
|
||||
// This file contains bindings to do binary encoding.
|
||||
|
||||
import (
|
||||
"tuxpa.in/a/zlog/internal/cbor"
|
||||
"github.com/rs/zerolog/internal/cbor"
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -24,9 +24,6 @@ func init() {
|
|||
func appendJSON(dst []byte, j []byte) []byte {
|
||||
return cbor.AppendEmbeddedJSON(dst, j)
|
||||
}
|
||||
func appendCBOR(dst []byte, c []byte) []byte {
|
||||
return cbor.AppendEmbeddedCBOR(dst, c)
|
||||
}
|
||||
|
||||
// decodeIfBinaryToString - converts a binary formatted log msg to a
|
||||
// JSON formatted String Log message.
|
||||
|
|
|
@ -1,14 +1,12 @@
|
|||
//go:build !binary_log
|
||||
// +build !binary_log
|
||||
|
||||
package zlog
|
||||
package zerolog
|
||||
|
||||
// encoder_json.go file contains bindings to generate
|
||||
// JSON encoded byte stream.
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"tuxpa.in/a/zlog/internal/json"
|
||||
"github.com/rs/zerolog/internal/json"
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -27,17 +25,6 @@ func init() {
|
|||
func appendJSON(dst []byte, j []byte) []byte {
|
||||
return append(dst, j...)
|
||||
}
|
||||
func appendCBOR(dst []byte, cbor []byte) []byte {
|
||||
dst = append(dst, []byte("\"data:application/cbor;base64,")...)
|
||||
l := len(dst)
|
||||
enc := base64.StdEncoding
|
||||
n := enc.EncodedLen(len(cbor))
|
||||
for i := 0; i < n; i++ {
|
||||
dst = append(dst, '.')
|
||||
}
|
||||
enc.Encode(dst[l:], cbor)
|
||||
return append(dst, '"')
|
||||
}
|
||||
|
||||
func decodeIfBinaryToString(in []byte) string {
|
||||
return string(in)
|
||||
|
|
60
event.go
60
event.go
|
@ -1,4 +1,4 @@
|
|||
package zlog
|
||||
package zerolog
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
@ -150,7 +150,7 @@ func (e *Event) msg(msg string) {
|
|||
if ErrorHandler != nil {
|
||||
ErrorHandler(err)
|
||||
} else {
|
||||
fmt.Fprintf(os.Stderr, "zlog: could not write event: %v\n", err)
|
||||
fmt.Fprintf(os.Stderr, "zerolog: could not write event: %v\n", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -167,7 +167,7 @@ func (e *Event) Fields(fields interface{}) *Event {
|
|||
}
|
||||
|
||||
// Dict adds the field key with a dict to the event context.
|
||||
// Use zlog.Dict() to create the dictionary.
|
||||
// Use zerolog.Dict() to create the dictionary.
|
||||
func (e *Event) Dict(key string, dict *Event) *Event {
|
||||
if e == nil {
|
||||
return e
|
||||
|
@ -186,7 +186,7 @@ func Dict() *Event {
|
|||
}
|
||||
|
||||
// Array adds the field key with an array to the event context.
|
||||
// Use zlog.Arr() to create the array or pass a type that
|
||||
// Use zerolog.Arr() to create the array or pass a type that
|
||||
// implement the LogArrayMarshaler interface.
|
||||
func (e *Event) Array(key string, arr LogArrayMarshaler) *Event {
|
||||
if e == nil {
|
||||
|
@ -318,18 +318,6 @@ func (e *Event) RawJSON(key string, b []byte) *Event {
|
|||
return e
|
||||
}
|
||||
|
||||
// RawCBOR adds already encoded CBOR to the log line under key.
|
||||
//
|
||||
// No sanity check is performed on b
|
||||
// Note: The full featureset of CBOR is supported as data will not be mapped to json but stored as data-url
|
||||
func (e *Event) RawCBOR(key string, b []byte) *Event {
|
||||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = appendCBOR(enc.AppendKey(e.buf, key), b)
|
||||
return e
|
||||
}
|
||||
|
||||
// AnErr adds the field key with serialized err to the *Event context.
|
||||
// If err is nil, no field is added.
|
||||
func (e *Event) AnErr(key string, err error) *Event {
|
||||
|
@ -380,11 +368,11 @@ func (e *Event) Errs(key string, errs []error) *Event {
|
|||
// Err adds the field "error" with serialized err to the *Event context.
|
||||
// If err is nil, no field is added.
|
||||
//
|
||||
// To customize the key name, change zlog.ErrorFieldName.
|
||||
// To customize the key name, change zerolog.ErrorFieldName.
|
||||
//
|
||||
// If Stack() has been called before and zlog.ErrorStackMarshaler is defined,
|
||||
// If Stack() has been called before and zerolog.ErrorStackMarshaler is defined,
|
||||
// the err is passed to ErrorStackMarshaler and the result is appended to the
|
||||
// zlog.ErrorStackFieldName.
|
||||
// zerolog.ErrorStackFieldName.
|
||||
func (e *Event) Err(err error) *Event {
|
||||
if e == nil {
|
||||
return e
|
||||
|
@ -652,7 +640,7 @@ func (e *Event) Floats64(key string, f []float64) *Event {
|
|||
}
|
||||
|
||||
// Timestamp adds the current local time as UNIX timestamp to the *Event context with the "time" key.
|
||||
// To customize the key name, change zlog.TimestampFieldName.
|
||||
// To customize the key name, change zerolog.TimestampFieldName.
|
||||
//
|
||||
// NOTE: It won't dedupe the "time" key if the *Event (or *Context) has one
|
||||
// already.
|
||||
|
@ -664,7 +652,7 @@ func (e *Event) Timestamp() *Event {
|
|||
return e
|
||||
}
|
||||
|
||||
// Time adds the field key with t formatted as string using zlog.TimeFieldFormat.
|
||||
// Time adds the field key with t formatted as string using zerolog.TimeFieldFormat.
|
||||
func (e *Event) Time(key string, t time.Time) *Event {
|
||||
if e == nil {
|
||||
return e
|
||||
|
@ -673,7 +661,7 @@ func (e *Event) Time(key string, t time.Time) *Event {
|
|||
return e
|
||||
}
|
||||
|
||||
// Times adds the field key with t formatted as string using zlog.TimeFieldFormat.
|
||||
// Times adds the field key with t formatted as string using zerolog.TimeFieldFormat.
|
||||
func (e *Event) Times(key string, t []time.Time) *Event {
|
||||
if e == nil {
|
||||
return e
|
||||
|
@ -682,8 +670,8 @@ func (e *Event) Times(key string, t []time.Time) *Event {
|
|||
return e
|
||||
}
|
||||
|
||||
// Dur adds the field key with duration d stored as zlog.DurationFieldUnit.
|
||||
// If zlog.DurationFieldInteger is true, durations are rendered as integer
|
||||
// Dur adds the field key with duration d stored as zerolog.DurationFieldUnit.
|
||||
// If zerolog.DurationFieldInteger is true, durations are rendered as integer
|
||||
// instead of float.
|
||||
func (e *Event) Dur(key string, d time.Duration) *Event {
|
||||
if e == nil {
|
||||
|
@ -693,8 +681,8 @@ func (e *Event) Dur(key string, d time.Duration) *Event {
|
|||
return e
|
||||
}
|
||||
|
||||
// Durs adds the field key with duration d stored as zlog.DurationFieldUnit.
|
||||
// If zlog.DurationFieldInteger is true, durations are rendered as integer
|
||||
// Durs adds the field key with duration d stored as zerolog.DurationFieldUnit.
|
||||
// If zerolog.DurationFieldInteger is true, durations are rendered as integer
|
||||
// instead of float.
|
||||
func (e *Event) Durs(key string, d []time.Duration) *Event {
|
||||
if e == nil {
|
||||
|
@ -719,11 +707,6 @@ func (e *Event) TimeDiff(key string, t time.Time, start time.Time) *Event {
|
|||
return e
|
||||
}
|
||||
|
||||
// Any is a wrapper around Event.Interface.
|
||||
func (e *Event) Any(key string, i interface{}) *Event {
|
||||
return e.Interface(key, i)
|
||||
}
|
||||
|
||||
// Interface adds the field key with i marshaled using reflection.
|
||||
func (e *Event) Interface(key string, i interface{}) *Event {
|
||||
if e == nil {
|
||||
|
@ -736,15 +719,6 @@ func (e *Event) Interface(key string, i interface{}) *Event {
|
|||
return e
|
||||
}
|
||||
|
||||
// Type adds the field key with val's type using reflection.
|
||||
func (e *Event) Type(key string, val interface{}) *Event {
|
||||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = enc.AppendType(enc.AppendKey(e.buf, key), val)
|
||||
return e
|
||||
}
|
||||
|
||||
// CallerSkipFrame instructs any future Caller calls to skip the specified number of frames.
|
||||
// This includes those added via hooks from the context.
|
||||
func (e *Event) CallerSkipFrame(skip int) *Event {
|
||||
|
@ -755,7 +729,7 @@ func (e *Event) CallerSkipFrame(skip int) *Event {
|
|||
return e
|
||||
}
|
||||
|
||||
// Caller adds the file:line of the caller with the zlog.CallerFieldName key.
|
||||
// Caller adds the file:line of the caller with the zerolog.CallerFieldName key.
|
||||
// The argument skip is the number of stack frames to ascend
|
||||
// Skip If not passed, use the global variable CallerSkipFrameCount
|
||||
func (e *Event) Caller(skip ...int) *Event {
|
||||
|
@ -770,11 +744,11 @@ func (e *Event) caller(skip int) *Event {
|
|||
if e == nil {
|
||||
return e
|
||||
}
|
||||
pc, file, line, ok := runtime.Caller(skip + e.skipFrame)
|
||||
_, file, line, ok := runtime.Caller(skip + e.skipFrame)
|
||||
if !ok {
|
||||
return e
|
||||
}
|
||||
e.buf = enc.AppendString(enc.AppendKey(e.buf, CallerFieldName), CallerMarshalFunc(pc, file, line))
|
||||
e.buf = enc.AppendString(enc.AppendKey(e.buf, CallerFieldName), CallerMarshalFunc(file, line))
|
||||
return e
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// +build !binary_log
|
||||
|
||||
package zlog
|
||||
package zerolog
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
|
12
globals.go
12
globals.go
|
@ -1,4 +1,4 @@
|
|||
package zlog
|
||||
package zerolog
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
@ -19,10 +19,6 @@ const (
|
|||
// TimeFormatUnixMicro defines a time format that makes time fields to be
|
||||
// serialized as Unix timestamp integers in microseconds.
|
||||
TimeFormatUnixMicro = "UNIXMICRO"
|
||||
|
||||
// TimeFormatUnixNano defines a time format that makes time fields to be
|
||||
// serialized as Unix timestamp integers in nanoseconds.
|
||||
TimeFormatUnixNano = "UNIXNANO"
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -65,7 +61,7 @@ var (
|
|||
CallerSkipFrameCount = 2
|
||||
|
||||
// CallerMarshalFunc allows customization of global caller marshaling
|
||||
CallerMarshalFunc = func(pc uintptr, file string, line int) string {
|
||||
CallerMarshalFunc = func(file string, line int) string {
|
||||
return file + ":" + strconv.Itoa(line)
|
||||
}
|
||||
|
||||
|
@ -85,7 +81,7 @@ var (
|
|||
InterfaceMarshalFunc = json.Marshal
|
||||
|
||||
// TimeFieldFormat defines the time format of the Time field type. If set to
|
||||
// TimeFormatUnix, TimeFormatUnixMs, TimeFormatUnixMicro or TimeFormatUnixNano, the time is formatted as a UNIX
|
||||
// TimeFormatUnix, TimeFormatUnixMs or TimeFormatUnixMicro, the time is formatted as a UNIX
|
||||
// timestamp as integer.
|
||||
TimeFieldFormat = time.RFC3339
|
||||
|
||||
|
@ -100,7 +96,7 @@ var (
|
|||
// set to true.
|
||||
DurationFieldInteger = false
|
||||
|
||||
// ErrorHandler is called whenever zlog fails to write an event on its
|
||||
// ErrorHandler is called whenever zerolog fails to write an event on its
|
||||
// output. If not set, an error is printed on the stderr. This handler must
|
||||
// be thread safe and non-blocking.
|
||||
ErrorHandler func(err error)
|
||||
|
|
8
go.mod
8
go.mod
|
@ -1,12 +1,10 @@
|
|||
module tuxpa.in/a/zlog
|
||||
module github.com/rs/zerolog
|
||||
|
||||
go 1.15
|
||||
|
||||
require (
|
||||
github.com/coreos/go-systemd/v22 v22.5.0
|
||||
github.com/coreos/go-systemd/v22 v22.3.3-0.20220203105225-a9a7ef127534
|
||||
github.com/mattn/go-colorable v0.1.12
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/rs/xid v1.5.0
|
||||
github.com/rs/zerolog v1.28.0
|
||||
golang.org/x/sys v0.0.0-20220915200043-7b5979e65e41 // indirect
|
||||
github.com/rs/xid v1.3.0
|
||||
)
|
||||
|
|
15
go.sum
15
go.sum
|
@ -1,6 +1,7 @@
|
|||
github.com/coreos/go-systemd/v22 v22.3.2 h1:D9/bQk5vlXQFZ6Kwuu6zaiXJ9oTPe68++AzAJc1DzSI=
|
||||
github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
||||
github.com/coreos/go-systemd/v22 v22.3.3-0.20220203105225-a9a7ef127534 h1:rtAn27wIbmOGUs7RIbVgPEjb31ehTVniDwPGXyMxm5U=
|
||||
github.com/coreos/go-systemd/v22 v22.3.3-0.20220203105225-a9a7ef127534/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
||||
github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs=
|
||||
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
||||
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40=
|
||||
github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
|
||||
|
@ -8,12 +9,8 @@ github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9
|
|||
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/rs/xid v1.4.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
|
||||
github.com/rs/xid v1.5.0 h1:mKX4bl4iPYJtEIxp6CYiUuLQ/8DYMoz0PUdtGgMFRVc=
|
||||
github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
|
||||
github.com/rs/zerolog v1.28.0 h1:MirSo27VyNi7RJYP3078AA1+Cyzd2GB66qy3aUHvsWY=
|
||||
github.com/rs/zerolog v1.28.0/go.mod h1:NILgTygv/Uej1ra5XxGf82ZFSLk58MFGAUS2o6usyD0=
|
||||
github.com/rs/xid v1.3.0 h1:6NjYksEUlhurdVehpc7S7dk6DAmcKv8V9gG0FsVN2U4=
|
||||
github.com/rs/xid v1.3.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
|
||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6 h1:foEbQz/B0Oz6YIqu/69kfXPYeFQAuuMYFkjaqXzl5Wo=
|
||||
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220915200043-7b5979e65e41 h1:ohgcoMbSofXygzo6AD2I1kz3BFmW1QArPYTtwEM3UXc=
|
||||
golang.org/x/sys v0.0.0-20220915200043-7b5979e65e41/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
|
|
2
go112.go
2
go112.go
|
@ -1,6 +1,6 @@
|
|||
// +build go1.12
|
||||
|
||||
package zlog
|
||||
package zerolog
|
||||
|
||||
// Since go 1.12, some auto generated init functions are hidden from
|
||||
// runtime.Caller.
|
||||
|
|
58
hlog/hlog.go
58
hlog/hlog.go
|
@ -1,4 +1,4 @@
|
|||
// Package hlog provides a set of http.Handler helpers for zlog.
|
||||
// Package hlog provides a set of http.Handler helpers for zerolog.
|
||||
package hlog
|
||||
|
||||
import (
|
||||
|
@ -7,19 +7,19 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/rs/xid"
|
||||
"tuxpa.in/a/zlog"
|
||||
"tuxpa.in/a/zlog/hlog/internal/mutil"
|
||||
"tuxpa.in/a/zlog/log"
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/rs/zerolog/hlog/internal/mutil"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
// FromRequest gets the logger in the request's context.
|
||||
// This is a shortcut for log.Ctx(r.Context())
|
||||
func FromRequest(r *http.Request) *zlog.Logger {
|
||||
func FromRequest(r *http.Request) *zerolog.Logger {
|
||||
return log.Ctx(r.Context())
|
||||
}
|
||||
|
||||
// NewHandler injects log into requests context.
|
||||
func NewHandler(log zlog.Logger) func(http.Handler) http.Handler {
|
||||
func NewHandler(log zerolog.Logger) func(http.Handler) http.Handler {
|
||||
return func(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
// Create a copy of the logger (including internal context slice)
|
||||
|
@ -36,8 +36,8 @@ func NewHandler(log zlog.Logger) func(http.Handler) http.Handler {
|
|||
func URLHandler(fieldKey string) func(next http.Handler) http.Handler {
|
||||
return func(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
log := zlog.Ctx(r.Context())
|
||||
log.UpdateContext(func(c zlog.Context) zlog.Context {
|
||||
log := zerolog.Ctx(r.Context())
|
||||
log.UpdateContext(func(c zerolog.Context) zerolog.Context {
|
||||
return c.Str(fieldKey, r.URL.String())
|
||||
})
|
||||
next.ServeHTTP(w, r)
|
||||
|
@ -50,8 +50,8 @@ func URLHandler(fieldKey string) func(next http.Handler) http.Handler {
|
|||
func MethodHandler(fieldKey string) func(next http.Handler) http.Handler {
|
||||
return func(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
log := zlog.Ctx(r.Context())
|
||||
log.UpdateContext(func(c zlog.Context) zlog.Context {
|
||||
log := zerolog.Ctx(r.Context())
|
||||
log.UpdateContext(func(c zerolog.Context) zerolog.Context {
|
||||
return c.Str(fieldKey, r.Method)
|
||||
})
|
||||
next.ServeHTTP(w, r)
|
||||
|
@ -64,8 +64,8 @@ func MethodHandler(fieldKey string) func(next http.Handler) http.Handler {
|
|||
func RequestHandler(fieldKey string) func(next http.Handler) http.Handler {
|
||||
return func(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
log := zlog.Ctx(r.Context())
|
||||
log.UpdateContext(func(c zlog.Context) zlog.Context {
|
||||
log := zerolog.Ctx(r.Context())
|
||||
log.UpdateContext(func(c zerolog.Context) zerolog.Context {
|
||||
return c.Str(fieldKey, r.Method+" "+r.URL.String())
|
||||
})
|
||||
next.ServeHTTP(w, r)
|
||||
|
@ -79,8 +79,8 @@ func RemoteAddrHandler(fieldKey string) func(next http.Handler) http.Handler {
|
|||
return func(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.RemoteAddr != "" {
|
||||
log := zlog.Ctx(r.Context())
|
||||
log.UpdateContext(func(c zlog.Context) zlog.Context {
|
||||
log := zerolog.Ctx(r.Context())
|
||||
log.UpdateContext(func(c zerolog.Context) zerolog.Context {
|
||||
return c.Str(fieldKey, r.RemoteAddr)
|
||||
})
|
||||
}
|
||||
|
@ -95,8 +95,8 @@ func UserAgentHandler(fieldKey string) func(next http.Handler) http.Handler {
|
|||
return func(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if ua := r.Header.Get("User-Agent"); ua != "" {
|
||||
log := zlog.Ctx(r.Context())
|
||||
log.UpdateContext(func(c zlog.Context) zlog.Context {
|
||||
log := zerolog.Ctx(r.Context())
|
||||
log.UpdateContext(func(c zerolog.Context) zerolog.Context {
|
||||
return c.Str(fieldKey, ua)
|
||||
})
|
||||
}
|
||||
|
@ -111,8 +111,8 @@ func RefererHandler(fieldKey string) func(next http.Handler) http.Handler {
|
|||
return func(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if ref := r.Header.Get("Referer"); ref != "" {
|
||||
log := zlog.Ctx(r.Context())
|
||||
log.UpdateContext(func(c zlog.Context) zlog.Context {
|
||||
log := zerolog.Ctx(r.Context())
|
||||
log.UpdateContext(func(c zerolog.Context) zerolog.Context {
|
||||
return c.Str(fieldKey, ref)
|
||||
})
|
||||
}
|
||||
|
@ -121,20 +121,6 @@ func RefererHandler(fieldKey string) func(next http.Handler) http.Handler {
|
|||
}
|
||||
}
|
||||
|
||||
// ProtoHandler adds the requests protocol version as a field to the context logger
|
||||
// using fieldKey as field Key.
|
||||
func ProtoHandler(fieldKey string) func(next http.Handler) http.Handler {
|
||||
return func(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
log := zlog.Ctx(r.Context())
|
||||
log.UpdateContext(func(c zlog.Context) zlog.Context {
|
||||
return c.Str(fieldKey, r.Proto)
|
||||
})
|
||||
next.ServeHTTP(w, r)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
type idKey struct{}
|
||||
|
||||
// IDFromRequest returns the unique id associated to the request if any.
|
||||
|
@ -176,8 +162,8 @@ func RequestIDHandler(fieldKey, headerName string) func(next http.Handler) http.
|
|||
r = r.WithContext(ctx)
|
||||
}
|
||||
if fieldKey != "" {
|
||||
log := zlog.Ctx(ctx)
|
||||
log.UpdateContext(func(c zlog.Context) zlog.Context {
|
||||
log := zerolog.Ctx(ctx)
|
||||
log.UpdateContext(func(c zerolog.Context) zerolog.Context {
|
||||
return c.Str(fieldKey, id.String())
|
||||
})
|
||||
}
|
||||
|
@ -195,8 +181,8 @@ func CustomHeaderHandler(fieldKey, header string) func(next http.Handler) http.H
|
|||
return func(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if val := r.Header.Get(header); val != "" {
|
||||
log := zlog.Ctx(r.Context())
|
||||
log.UpdateContext(func(c zlog.Context) zlog.Context {
|
||||
log := zerolog.Ctx(r.Context())
|
||||
log.UpdateContext(func(c zerolog.Context) zerolog.Context {
|
||||
return c.Str(fieldKey, val)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -9,8 +9,8 @@ import (
|
|||
|
||||
"net/http/httptest"
|
||||
|
||||
"tuxpa.in/a/zlog"
|
||||
"tuxpa.in/a/zlog/hlog"
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/rs/zerolog/hlog"
|
||||
)
|
||||
|
||||
// fake alice to avoid dep
|
||||
|
@ -31,13 +31,13 @@ func (a alice) Then(h http.Handler) http.Handler {
|
|||
}
|
||||
|
||||
func init() {
|
||||
zlog.TimestampFunc = func() time.Time {
|
||||
zerolog.TimestampFunc = func() time.Time {
|
||||
return time.Date(2001, time.February, 3, 4, 5, 6, 7, time.UTC)
|
||||
}
|
||||
}
|
||||
|
||||
func Example_handler() {
|
||||
log := zlog.New(os.Stdout).With().
|
||||
log := zerolog.New(os.Stdout).With().
|
||||
Timestamp().
|
||||
Str("role", "my-service").
|
||||
Str("host", "local-hostname").
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
//go:build go1.7
|
||||
// +build go1.7
|
||||
|
||||
package hlog
|
||||
|
@ -15,8 +14,8 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/rs/xid"
|
||||
"tuxpa.in/a/zlog"
|
||||
"tuxpa.in/a/zlog/internal/cbor"
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/rs/zerolog/internal/cbor"
|
||||
)
|
||||
|
||||
func decodeIfBinary(out *bytes.Buffer) string {
|
||||
|
@ -28,7 +27,7 @@ func decodeIfBinary(out *bytes.Buffer) string {
|
|||
}
|
||||
|
||||
func TestNewHandler(t *testing.T) {
|
||||
log := zlog.New(nil).With().
|
||||
log := zerolog.New(nil).With().
|
||||
Str("foo", "bar").
|
||||
Logger()
|
||||
lh := NewHandler(log)
|
||||
|
@ -50,7 +49,7 @@ func TestURLHandler(t *testing.T) {
|
|||
l := FromRequest(r)
|
||||
l.Log().Msg("")
|
||||
}))
|
||||
h = NewHandler(zlog.New(out))(h)
|
||||
h = NewHandler(zerolog.New(out))(h)
|
||||
h.ServeHTTP(nil, r)
|
||||
if want, got := `{"url":"/path?foo=bar"}`+"\n", decodeIfBinary(out); want != got {
|
||||
t.Errorf("Invalid log output, got: %s, want: %s", got, want)
|
||||
|
@ -66,7 +65,7 @@ func TestMethodHandler(t *testing.T) {
|
|||
l := FromRequest(r)
|
||||
l.Log().Msg("")
|
||||
}))
|
||||
h = NewHandler(zlog.New(out))(h)
|
||||
h = NewHandler(zerolog.New(out))(h)
|
||||
h.ServeHTTP(nil, r)
|
||||
if want, got := `{"method":"POST"}`+"\n", decodeIfBinary(out); want != got {
|
||||
t.Errorf("Invalid log output, got: %s, want: %s", got, want)
|
||||
|
@ -83,7 +82,7 @@ func TestRequestHandler(t *testing.T) {
|
|||
l := FromRequest(r)
|
||||
l.Log().Msg("")
|
||||
}))
|
||||
h = NewHandler(zlog.New(out))(h)
|
||||
h = NewHandler(zerolog.New(out))(h)
|
||||
h.ServeHTTP(nil, r)
|
||||
if want, got := `{"request":"POST /path?foo=bar"}`+"\n", decodeIfBinary(out); want != got {
|
||||
t.Errorf("Invalid log output, got: %s, want: %s", got, want)
|
||||
|
@ -99,7 +98,7 @@ func TestRemoteAddrHandler(t *testing.T) {
|
|||
l := FromRequest(r)
|
||||
l.Log().Msg("")
|
||||
}))
|
||||
h = NewHandler(zlog.New(out))(h)
|
||||
h = NewHandler(zerolog.New(out))(h)
|
||||
h.ServeHTTP(nil, r)
|
||||
if want, got := `{"ip":"1.2.3.4:1234"}`+"\n", decodeIfBinary(out); want != got {
|
||||
t.Errorf("Invalid log output, got: %s, want: %s", got, want)
|
||||
|
@ -115,7 +114,7 @@ func TestRemoteAddrHandlerIPv6(t *testing.T) {
|
|||
l := FromRequest(r)
|
||||
l.Log().Msg("")
|
||||
}))
|
||||
h = NewHandler(zlog.New(out))(h)
|
||||
h = NewHandler(zerolog.New(out))(h)
|
||||
h.ServeHTTP(nil, r)
|
||||
if want, got := `{"ip":"[2001:db8:a0b:12f0::1]:1234"}`+"\n", decodeIfBinary(out); want != got {
|
||||
t.Errorf("Invalid log output, got: %s, want: %s", got, want)
|
||||
|
@ -133,7 +132,7 @@ func TestUserAgentHandler(t *testing.T) {
|
|||
l := FromRequest(r)
|
||||
l.Log().Msg("")
|
||||
}))
|
||||
h = NewHandler(zlog.New(out))(h)
|
||||
h = NewHandler(zerolog.New(out))(h)
|
||||
h.ServeHTTP(nil, r)
|
||||
if want, got := `{"ua":"some user agent string"}`+"\n", decodeIfBinary(out); want != got {
|
||||
t.Errorf("Invalid log output, got: %s, want: %s", got, want)
|
||||
|
@ -151,7 +150,7 @@ func TestRefererHandler(t *testing.T) {
|
|||
l := FromRequest(r)
|
||||
l.Log().Msg("")
|
||||
}))
|
||||
h = NewHandler(zlog.New(out))(h)
|
||||
h = NewHandler(zerolog.New(out))(h)
|
||||
h.ServeHTTP(nil, r)
|
||||
if want, got := `{"referer":"http://foo.com/bar"}`+"\n", decodeIfBinary(out); want != got {
|
||||
t.Errorf("Invalid log output, got: %s, want: %s", got, want)
|
||||
|
@ -179,7 +178,7 @@ func TestRequestIDHandler(t *testing.T) {
|
|||
t.Errorf("Invalid log output, got: %s, want: %s", got, want)
|
||||
}
|
||||
}))
|
||||
h = NewHandler(zlog.New(out))(h)
|
||||
h = NewHandler(zerolog.New(out))(h)
|
||||
h.ServeHTTP(httptest.NewRecorder(), r)
|
||||
}
|
||||
|
||||
|
@ -194,29 +193,13 @@ func TestCustomHeaderHandler(t *testing.T) {
|
|||
l := FromRequest(r)
|
||||
l.Log().Msg("")
|
||||
}))
|
||||
h = NewHandler(zlog.New(out))(h)
|
||||
h = NewHandler(zerolog.New(out))(h)
|
||||
h.ServeHTTP(nil, r)
|
||||
if want, got := `{"reqID":"514bbe5bb5251c92bd07a9846f4a1ab6"}`+"\n", decodeIfBinary(out); want != got {
|
||||
t.Errorf("Invalid log output, got: %s, want: %s", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestProtoHandler(t *testing.T) {
|
||||
out := &bytes.Buffer{}
|
||||
r := &http.Request{
|
||||
Proto: "test",
|
||||
}
|
||||
h := ProtoHandler("proto")(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
l := FromRequest(r)
|
||||
l.Log().Msg("")
|
||||
}))
|
||||
h = NewHandler(zlog.New(out))(h)
|
||||
h.ServeHTTP(nil, r)
|
||||
if want, got := `{"proto":"test"}`+"\n", decodeIfBinary(out); want != got {
|
||||
t.Errorf("Invalid log output, got: %s, want: %s", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCombinedHandlers(t *testing.T) {
|
||||
out := &bytes.Buffer{}
|
||||
r := &http.Request{
|
||||
|
@ -227,7 +210,7 @@ func TestCombinedHandlers(t *testing.T) {
|
|||
l := FromRequest(r)
|
||||
l.Log().Msg("")
|
||||
}))))
|
||||
h = NewHandler(zlog.New(out))(h)
|
||||
h = NewHandler(zerolog.New(out))(h)
|
||||
h.ServeHTTP(nil, r)
|
||||
if want, got := `{"method":"POST","request":"POST /path?foo=bar","url":"/path?foo=bar"}`+"\n", decodeIfBinary(out); want != got {
|
||||
t.Errorf("Invalid log output, got: %s, want: %s", got, want)
|
||||
|
@ -245,10 +228,10 @@ func BenchmarkHandlers(b *testing.B) {
|
|||
}))
|
||||
h2 := MethodHandler("method")(RequestHandler("request")(h1))
|
||||
handlers := map[string]http.Handler{
|
||||
"Single": NewHandler(zlog.New(ioutil.Discard))(h1),
|
||||
"Combined": NewHandler(zlog.New(ioutil.Discard))(h2),
|
||||
"SingleDisabled": NewHandler(zlog.New(ioutil.Discard).Level(zlog.Disabled))(h1),
|
||||
"CombinedDisabled": NewHandler(zlog.New(ioutil.Discard).Level(zlog.Disabled))(h2),
|
||||
"Single": NewHandler(zerolog.New(ioutil.Discard))(h1),
|
||||
"Combined": NewHandler(zerolog.New(ioutil.Discard))(h2),
|
||||
"SingleDisabled": NewHandler(zerolog.New(ioutil.Discard).Level(zerolog.Disabled))(h1),
|
||||
"CombinedDisabled": NewHandler(zerolog.New(ioutil.Discard).Level(zerolog.Disabled))(h2),
|
||||
}
|
||||
for name := range handlers {
|
||||
h := handlers[name]
|
||||
|
@ -261,13 +244,13 @@ func BenchmarkHandlers(b *testing.B) {
|
|||
}
|
||||
|
||||
func BenchmarkDataRace(b *testing.B) {
|
||||
log := zlog.New(nil).With().
|
||||
log := zerolog.New(nil).With().
|
||||
Str("foo", "bar").
|
||||
Logger()
|
||||
lh := NewHandler(log)
|
||||
h := lh(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
l := FromRequest(r)
|
||||
l.UpdateContext(func(c zlog.Context) zlog.Context {
|
||||
l.UpdateContext(func(c zerolog.Context) zerolog.Context {
|
||||
return c.Str("bar", "baz")
|
||||
})
|
||||
l.Log().Msg("")
|
||||
|
|
2
hook.go
2
hook.go
|
@ -1,4 +1,4 @@
|
|||
package zlog
|
||||
package zerolog
|
||||
|
||||
// Hook defines an interface to a log hook.
|
||||
type Hook interface {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package zlog
|
||||
package zerolog
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
|
|
@ -26,8 +26,7 @@ const (
|
|||
additionalTypeBreak byte = 31
|
||||
|
||||
// Tag Sub-types.
|
||||
additionalTypeTimestamp byte = 01
|
||||
additionalTypeEmbeddedCBOR byte = 63
|
||||
additionalTypeTimestamp byte = 01
|
||||
|
||||
// Extended Tags - from https://www.iana.org/assignments/cbor-tags/cbor-tags.xhtml
|
||||
additionalTypeTagNetworkAddr uint16 = 260
|
||||
|
|
|
@ -5,7 +5,6 @@ package cbor
|
|||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"io"
|
||||
"math"
|
||||
|
@ -214,31 +213,6 @@ func decodeString(src *bufio.Reader, noQuotes bool) []byte {
|
|||
}
|
||||
return append(result, '"')
|
||||
}
|
||||
func decodeStringToDataUrl(src *bufio.Reader, mimeType string) []byte {
|
||||
pb := readByte(src)
|
||||
major := pb & maskOutAdditionalType
|
||||
minor := pb & maskOutMajorType
|
||||
if major != majorTypeByteString {
|
||||
panic(fmt.Errorf("Major type is: %d in decodeString", major))
|
||||
}
|
||||
length := decodeIntAdditionalType(src, minor)
|
||||
l := int(length)
|
||||
enc := base64.StdEncoding
|
||||
lEnc := enc.EncodedLen(l)
|
||||
result := make([]byte, len("\"data:;base64,\"")+len(mimeType)+lEnc)
|
||||
dest := result
|
||||
u := copy(dest, "\"data:")
|
||||
dest = dest[u:]
|
||||
u = copy(dest, mimeType)
|
||||
dest = dest[u:]
|
||||
u = copy(dest, ";base64,")
|
||||
dest = dest[u:]
|
||||
pbs := readNBytes(src, l)
|
||||
enc.Encode(dest, pbs)
|
||||
dest = dest[lEnc:]
|
||||
dest[0] = '"'
|
||||
return result
|
||||
}
|
||||
|
||||
func decodeUTF8String(src *bufio.Reader) []byte {
|
||||
pb := readByte(src)
|
||||
|
@ -375,20 +349,6 @@ func decodeTagData(src *bufio.Reader) []byte {
|
|||
switch minor {
|
||||
case additionalTypeTimestamp:
|
||||
return decodeTimeStamp(src)
|
||||
case additionalTypeIntUint8:
|
||||
val := decodeIntAdditionalType(src, minor)
|
||||
switch byte(val) {
|
||||
case additionalTypeEmbeddedCBOR:
|
||||
pb := readByte(src)
|
||||
dataMajor := pb & maskOutAdditionalType
|
||||
if dataMajor != majorTypeByteString {
|
||||
panic(fmt.Errorf("Unsupported embedded Type: %d in decodeEmbeddedCBOR", dataMajor))
|
||||
}
|
||||
src.UnreadByte()
|
||||
return decodeStringToDataUrl(src, "application/cbor")
|
||||
default:
|
||||
panic(fmt.Errorf("Unsupported Additional Tag Type: %d in decodeTagData", val))
|
||||
}
|
||||
|
||||
// Tag value is larger than 256 (so uint16).
|
||||
case additionalTypeIntUint16:
|
||||
|
|
|
@ -8,7 +8,7 @@ import (
|
|||
"os"
|
||||
"time"
|
||||
|
||||
"tuxpa.in/a/zlog"
|
||||
"github.com/rs/zerolog"
|
||||
)
|
||||
|
||||
func writeLog(fname string, count int, useCompress bool) {
|
||||
|
@ -34,8 +34,8 @@ func writeLog(fname string, count int, useCompress bool) {
|
|||
|
||||
}
|
||||
|
||||
zlog.TimestampFunc = func() time.Time { return time.Now().Round(time.Second) }
|
||||
log := zlog.New(f).With().
|
||||
zerolog.TimestampFunc = func() time.Time { return time.Now().Round(time.Second) }
|
||||
log := zerolog.New(f).With().
|
||||
Timestamp().
|
||||
Logger()
|
||||
for i := 0; i < count; i++ {
|
||||
|
|
|
@ -93,25 +93,3 @@ func AppendEmbeddedJSON(dst, s []byte) []byte {
|
|||
}
|
||||
return append(dst, s...)
|
||||
}
|
||||
|
||||
// AppendEmbeddedCBOR adds a tag and embeds input CBOR as such.
|
||||
func AppendEmbeddedCBOR(dst, s []byte) []byte {
|
||||
major := majorTypeTags
|
||||
minor := additionalTypeEmbeddedCBOR
|
||||
|
||||
// Append the TAG to indicate this is Embedded JSON.
|
||||
dst = append(dst, major|additionalTypeIntUint8)
|
||||
dst = append(dst, minor)
|
||||
|
||||
// Append the CBOR Object as Byte String.
|
||||
major = majorTypeByteString
|
||||
|
||||
l := len(s)
|
||||
if l <= additionalMax {
|
||||
lb := byte(l)
|
||||
dst = append(dst, major|lb)
|
||||
} else {
|
||||
dst = appendCborTypePrefix(dst, major, uint64(l))
|
||||
}
|
||||
return append(dst, s...)
|
||||
}
|
||||
|
|
|
@ -4,7 +4,6 @@ import (
|
|||
"fmt"
|
||||
"math"
|
||||
"net"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
// AppendNil inserts a 'Nil' object into the dst byte array.
|
||||
|
@ -439,14 +438,6 @@ func (e Encoder) AppendInterface(dst []byte, i interface{}) []byte {
|
|||
return AppendEmbeddedJSON(dst, marshaled)
|
||||
}
|
||||
|
||||
// AppendType appends the parameter type (as a string) to the input byte slice.
|
||||
func (e Encoder) AppendType(dst []byte, i interface{}) []byte {
|
||||
if i == nil {
|
||||
return e.AppendString(dst, "<nil>")
|
||||
}
|
||||
return e.AppendString(dst, reflect.TypeOf(i).String())
|
||||
}
|
||||
|
||||
// AppendIPAddr encodes and inserts an IP Address (IPv4 or IPv6).
|
||||
func (e Encoder) AppendIPAddr(dst []byte, ip net.IP) []byte {
|
||||
dst = append(dst, majorTypeTags|additionalTypeIntUint16)
|
||||
|
|
|
@ -6,11 +6,10 @@ import (
|
|||
)
|
||||
|
||||
const (
|
||||
// Import from zlog/global.go
|
||||
timeFormatUnix = ""
|
||||
timeFormatUnixMs = "UNIXMS"
|
||||
// Import from zerolog/global.go
|
||||
timeFormatUnix = ""
|
||||
timeFormatUnixMs = "UNIXMS"
|
||||
timeFormatUnixMicro = "UNIXMICRO"
|
||||
timeFormatUnixNano = "UNIXNANO"
|
||||
)
|
||||
|
||||
// AppendTime formats the input time with the given format
|
||||
|
@ -23,8 +22,6 @@ func (e Encoder) AppendTime(dst []byte, t time.Time, format string) []byte {
|
|||
return e.AppendInt64(dst, t.UnixNano()/1000000)
|
||||
case timeFormatUnixMicro:
|
||||
return e.AppendInt64(dst, t.UnixNano()/1000)
|
||||
case timeFormatUnixNano:
|
||||
return e.AppendInt64(dst, t.UnixNano())
|
||||
}
|
||||
return append(t.AppendFormat(append(dst, '"'), format), '"')
|
||||
}
|
||||
|
@ -36,11 +33,7 @@ func (Encoder) AppendTimes(dst []byte, vals []time.Time, format string) []byte {
|
|||
case timeFormatUnix:
|
||||
return appendUnixTimes(dst, vals)
|
||||
case timeFormatUnixMs:
|
||||
return appendUnixNanoTimes(dst, vals, 1000000)
|
||||
case timeFormatUnixMicro:
|
||||
return appendUnixNanoTimes(dst, vals, 1000)
|
||||
case timeFormatUnixNano:
|
||||
return appendUnixNanoTimes(dst, vals, 1)
|
||||
return appendUnixMsTimes(dst, vals)
|
||||
}
|
||||
if len(vals) == 0 {
|
||||
return append(dst, '[', ']')
|
||||
|
@ -71,15 +64,15 @@ func appendUnixTimes(dst []byte, vals []time.Time) []byte {
|
|||
return dst
|
||||
}
|
||||
|
||||
func appendUnixNanoTimes(dst []byte, vals []time.Time, div int64) []byte {
|
||||
func appendUnixMsTimes(dst []byte, vals []time.Time) []byte {
|
||||
if len(vals) == 0 {
|
||||
return append(dst, '[', ']')
|
||||
}
|
||||
dst = append(dst, '[')
|
||||
dst = strconv.AppendInt(dst, vals[0].UnixNano()/div, 10)
|
||||
dst = strconv.AppendInt(dst, vals[0].UnixNano()/1000000, 10)
|
||||
if len(vals) > 1 {
|
||||
for _, t := range vals[1:] {
|
||||
dst = strconv.AppendInt(append(dst, ','), t.UnixNano()/div, 10)
|
||||
dst = strconv.AppendInt(append(dst, ','), t.UnixNano()/1000000, 10)
|
||||
}
|
||||
}
|
||||
dst = append(dst, ']')
|
||||
|
|
|
@ -4,7 +4,6 @@ import (
|
|||
"fmt"
|
||||
"math"
|
||||
"net"
|
||||
"reflect"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
|
@ -370,14 +369,6 @@ func (e Encoder) AppendInterface(dst []byte, i interface{}) []byte {
|
|||
return append(dst, marshaled...)
|
||||
}
|
||||
|
||||
// AppendType appends the parameter type (as a string) to the input byte slice.
|
||||
func (e Encoder) AppendType(dst []byte, i interface{}) []byte {
|
||||
if i == nil {
|
||||
return e.AppendString(dst, "<nil>")
|
||||
}
|
||||
return e.AppendString(dst, reflect.TypeOf(i).String())
|
||||
}
|
||||
|
||||
// AppendObjectData takes in an object that is already in a byte array
|
||||
// and adds it to the dst.
|
||||
func (Encoder) AppendObjectData(dst []byte, o []byte) []byte {
|
||||
|
|
|
@ -166,28 +166,6 @@ func Test_appendMac(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func Test_appendType(t *testing.T) {
|
||||
typeTests := []struct {
|
||||
label string
|
||||
input interface{}
|
||||
want []byte
|
||||
}{
|
||||
{"int", 42, []byte(`"int"`)},
|
||||
{"MAC", net.HardwareAddr{0x12, 0x34, 0x00, 0x00, 0x90, 0xab}, []byte(`"net.HardwareAddr"`)},
|
||||
{"float64", float64(2.50), []byte(`"float64"`)},
|
||||
{"nil", nil, []byte(`"<nil>"`)},
|
||||
{"bool", true, []byte(`"bool"`)},
|
||||
}
|
||||
|
||||
for _, tt := range typeTests {
|
||||
t.Run(tt.label, func(t *testing.T) {
|
||||
if got := enc.AppendType([]byte{}, tt.input); !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("appendType() = %s, want %s", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_appendObjectData(t *testing.T) {
|
||||
tests := []struct {
|
||||
dst []byte
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
|
||||
package journald
|
||||
|
||||
// This file provides a zlog writer so that logs printed
|
||||
// using zlog library can be sent to a journalD.
|
||||
// This file provides a zerolog writer so that logs printed
|
||||
// using zerolog library can be sent to a journalD.
|
||||
|
||||
// Zerolog's Top level key/Value Pairs are translated to
|
||||
// journald's args - all Values are sent to journald as strings.
|
||||
|
@ -25,13 +25,13 @@ import (
|
|||
"strings"
|
||||
|
||||
"github.com/coreos/go-systemd/v22/journal"
|
||||
"tuxpa.in/a/zlog"
|
||||
"tuxpa.in/a/zlog/internal/cbor"
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/rs/zerolog/internal/cbor"
|
||||
)
|
||||
|
||||
const defaultJournalDPrio = journal.PriNotice
|
||||
|
||||
// NewJournalDWriter returns a zlog log destination
|
||||
// NewJournalDWriter returns a zerolog log destination
|
||||
// to be used as parameter to New() calls. Writing logs
|
||||
// to this writer will send the log messages to journalD
|
||||
// running in this system.
|
||||
|
@ -42,28 +42,28 @@ func NewJournalDWriter() io.Writer {
|
|||
type journalWriter struct {
|
||||
}
|
||||
|
||||
// levelToJPrio converts zlog Level string into
|
||||
// levelToJPrio converts zerolog Level string into
|
||||
// journalD's priority values. JournalD has more
|
||||
// priorities than zlog.
|
||||
// priorities than zerolog.
|
||||
func levelToJPrio(zLevel string) journal.Priority {
|
||||
lvl, _ := zlog.ParseLevel(zLevel)
|
||||
lvl, _ := zerolog.ParseLevel(zLevel)
|
||||
|
||||
switch lvl {
|
||||
case zlog.TraceLevel:
|
||||
case zerolog.TraceLevel:
|
||||
return journal.PriDebug
|
||||
case zlog.DebugLevel:
|
||||
case zerolog.DebugLevel:
|
||||
return journal.PriDebug
|
||||
case zlog.InfoLevel:
|
||||
case zerolog.InfoLevel:
|
||||
return journal.PriInfo
|
||||
case zlog.WarnLevel:
|
||||
case zerolog.WarnLevel:
|
||||
return journal.PriWarning
|
||||
case zlog.ErrorLevel:
|
||||
case zerolog.ErrorLevel:
|
||||
return journal.PriErr
|
||||
case zlog.FatalLevel:
|
||||
case zerolog.FatalLevel:
|
||||
return journal.PriCrit
|
||||
case zlog.PanicLevel:
|
||||
case zerolog.PanicLevel:
|
||||
return journal.PriEmerg
|
||||
case zlog.NoLevel:
|
||||
case zerolog.NoLevel:
|
||||
return journal.PriNotice
|
||||
}
|
||||
return defaultJournalDPrio
|
||||
|
@ -81,7 +81,7 @@ func (w journalWriter) Write(p []byte) (n int, err error) {
|
|||
if err != nil {
|
||||
return
|
||||
}
|
||||
if l, ok := event[zlog.LevelFieldName].(string); ok {
|
||||
if l, ok := event[zerolog.LevelFieldName].(string); ok {
|
||||
jPrio = levelToJPrio(l)
|
||||
}
|
||||
|
||||
|
@ -89,9 +89,9 @@ func (w journalWriter) Write(p []byte) (n int, err error) {
|
|||
for key, value := range event {
|
||||
jKey := strings.ToUpper(key)
|
||||
switch key {
|
||||
case zlog.LevelFieldName, zlog.TimestampFieldName:
|
||||
case zerolog.LevelFieldName, zerolog.TimestampFieldName:
|
||||
continue
|
||||
case zlog.MessageFieldName:
|
||||
case zerolog.MessageFieldName:
|
||||
msg, _ = value.(string)
|
||||
continue
|
||||
}
|
||||
|
@ -102,7 +102,7 @@ func (w journalWriter) Write(p []byte) (n int, err error) {
|
|||
case json.Number:
|
||||
args[jKey] = fmt.Sprint(value)
|
||||
default:
|
||||
b, err := zlog.InterfaceMarshalFunc(value)
|
||||
b, err := json.Marshal(value)
|
||||
if err != nil {
|
||||
args[jKey] = fmt.Sprintf("[error: %v]", err)
|
||||
} else {
|
||||
|
|
|
@ -7,12 +7,12 @@ import (
|
|||
"io"
|
||||
"testing"
|
||||
|
||||
"tuxpa.in/a/zlog"
|
||||
"tuxpa.in/a/zlog/journald"
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/rs/zerolog/journald"
|
||||
)
|
||||
|
||||
func ExampleNewJournalDWriter() {
|
||||
log := zlog.New(journald.NewJournalDWriter())
|
||||
log := zerolog.New(journald.NewJournalDWriter())
|
||||
log.Info().Str("foo", "bar").Uint64("small", 123).Float64("float", 3.14).Uint64("big", 1152921504606846976).Msg("Journal Test")
|
||||
// Output:
|
||||
}
|
||||
|
@ -71,14 +71,14 @@ func TestMultiWrite(t *testing.T) {
|
|||
w3 = journald.NewJournalDWriter()
|
||||
)
|
||||
|
||||
zlog.ErrorHandler = func(err error) {
|
||||
zerolog.ErrorHandler = func(err error) {
|
||||
if err == io.ErrShortWrite {
|
||||
t.Errorf("Unexpected ShortWriteError")
|
||||
t.FailNow()
|
||||
}
|
||||
}
|
||||
|
||||
log := zlog.New(io.MultiWriter(w1, w2, w3)).With().Logger()
|
||||
log := zerolog.New(io.MultiWriter(w1, w2, w3)).With().Logger()
|
||||
|
||||
for i := 0; i < 10; i++ {
|
||||
log.Info().Msg("Tick!")
|
||||
|
|
150
log.go
150
log.go
|
@ -1,110 +1,109 @@
|
|||
// Package zlog provides a lightweight logging library dedicated to JSON logging.
|
||||
// Package zerolog provides a lightweight logging library dedicated to JSON logging.
|
||||
//
|
||||
// A global Logger can be use for simple logging:
|
||||
//
|
||||
// import "tuxpa.in/a/zlog/log"
|
||||
// import "github.com/rs/zerolog/log"
|
||||
//
|
||||
// log.Info().Msg("hello world")
|
||||
// // Output: {"time":1494567715,"level":"info","message":"hello world"}
|
||||
// log.Info().Msg("hello world")
|
||||
// // Output: {"time":1494567715,"level":"info","message":"hello world"}
|
||||
//
|
||||
// NOTE: To import the global logger, import the "log" subpackage "tuxpa.in/a/zlog/log".
|
||||
// NOTE: To import the global logger, import the "log" subpackage "github.com/rs/zerolog/log".
|
||||
//
|
||||
// Fields can be added to log messages:
|
||||
//
|
||||
// log.Info().Str("foo", "bar").Msg("hello world")
|
||||
// // Output: {"time":1494567715,"level":"info","message":"hello world","foo":"bar"}
|
||||
// log.Info().Str("foo", "bar").Msg("hello world")
|
||||
// // Output: {"time":1494567715,"level":"info","message":"hello world","foo":"bar"}
|
||||
//
|
||||
// Create logger instance to manage different outputs:
|
||||
//
|
||||
// logger := zlog.New(os.Stderr).With().Timestamp().Logger()
|
||||
// logger.Info().
|
||||
// Str("foo", "bar").
|
||||
// Msg("hello world")
|
||||
// // Output: {"time":1494567715,"level":"info","message":"hello world","foo":"bar"}
|
||||
// logger := zerolog.New(os.Stderr).With().Timestamp().Logger()
|
||||
// logger.Info().
|
||||
// Str("foo", "bar").
|
||||
// Msg("hello world")
|
||||
// // Output: {"time":1494567715,"level":"info","message":"hello world","foo":"bar"}
|
||||
//
|
||||
// Sub-loggers let you chain loggers with additional context:
|
||||
//
|
||||
// sublogger := log.With().Str("component": "foo").Logger()
|
||||
// sublogger.Info().Msg("hello world")
|
||||
// // Output: {"time":1494567715,"level":"info","message":"hello world","component":"foo"}
|
||||
// sublogger := log.With().Str("component": "foo").Logger()
|
||||
// sublogger.Info().Msg("hello world")
|
||||
// // Output: {"time":1494567715,"level":"info","message":"hello world","component":"foo"}
|
||||
//
|
||||
// Level logging
|
||||
//
|
||||
// zlog.SetGlobalLevel(zlog.InfoLevel)
|
||||
// zerolog.SetGlobalLevel(zerolog.InfoLevel)
|
||||
//
|
||||
// log.Debug().Msg("filtered out message")
|
||||
// log.Info().Msg("routed message")
|
||||
// log.Debug().Msg("filtered out message")
|
||||
// log.Info().Msg("routed message")
|
||||
//
|
||||
// if e := log.Debug(); e.Enabled() {
|
||||
// // Compute log output only if enabled.
|
||||
// value := compute()
|
||||
// e.Str("foo": value).Msg("some debug message")
|
||||
// }
|
||||
// // Output: {"level":"info","time":1494567715,"routed message"}
|
||||
// if e := log.Debug(); e.Enabled() {
|
||||
// // Compute log output only if enabled.
|
||||
// value := compute()
|
||||
// e.Str("foo": value).Msg("some debug message")
|
||||
// }
|
||||
// // Output: {"level":"info","time":1494567715,"routed message"}
|
||||
//
|
||||
// Customize automatic field names:
|
||||
//
|
||||
// log.TimestampFieldName = "t"
|
||||
// log.LevelFieldName = "p"
|
||||
// log.MessageFieldName = "m"
|
||||
// log.TimestampFieldName = "t"
|
||||
// log.LevelFieldName = "p"
|
||||
// log.MessageFieldName = "m"
|
||||
//
|
||||
// log.Info().Msg("hello world")
|
||||
// // Output: {"t":1494567715,"p":"info","m":"hello world"}
|
||||
// log.Info().Msg("hello world")
|
||||
// // Output: {"t":1494567715,"p":"info","m":"hello world"}
|
||||
//
|
||||
// Log with no level and message:
|
||||
//
|
||||
// log.Log().Str("foo","bar").Msg("")
|
||||
// // Output: {"time":1494567715,"foo":"bar"}
|
||||
// log.Log().Str("foo","bar").Msg("")
|
||||
// // Output: {"time":1494567715,"foo":"bar"}
|
||||
//
|
||||
// Add contextual fields to global Logger:
|
||||
//
|
||||
// log.Logger = log.With().Str("foo", "bar").Logger()
|
||||
// log.Logger = log.With().Str("foo", "bar").Logger()
|
||||
//
|
||||
// Sample logs:
|
||||
//
|
||||
// sampled := log.Sample(&zlog.BasicSampler{N: 10})
|
||||
// sampled.Info().Msg("will be logged every 10 messages")
|
||||
// sampled := log.Sample(&zerolog.BasicSampler{N: 10})
|
||||
// sampled.Info().Msg("will be logged every 10 messages")
|
||||
//
|
||||
// Log with contextual hooks:
|
||||
//
|
||||
// // Create the hook:
|
||||
// type SeverityHook struct{}
|
||||
// // Create the hook:
|
||||
// type SeverityHook struct{}
|
||||
//
|
||||
// func (h SeverityHook) Run(e *zlog.Event, level zlog.Level, msg string) {
|
||||
// if level != zlog.NoLevel {
|
||||
// e.Str("severity", level.String())
|
||||
// }
|
||||
// }
|
||||
// func (h SeverityHook) Run(e *zerolog.Event, level zerolog.Level, msg string) {
|
||||
// if level != zerolog.NoLevel {
|
||||
// e.Str("severity", level.String())
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // And use it:
|
||||
// var h SeverityHook
|
||||
// log := zlog.New(os.Stdout).Hook(h)
|
||||
// log.Warn().Msg("")
|
||||
// // Output: {"level":"warn","severity":"warn"}
|
||||
// // And use it:
|
||||
// var h SeverityHook
|
||||
// log := zerolog.New(os.Stdout).Hook(h)
|
||||
// log.Warn().Msg("")
|
||||
// // Output: {"level":"warn","severity":"warn"}
|
||||
//
|
||||
// # Caveats
|
||||
//
|
||||
// Caveats
|
||||
//
|
||||
// There is no fields deduplication out-of-the-box.
|
||||
// Using the same key multiple times creates new key in final JSON each time.
|
||||
//
|
||||
// logger := zlog.New(os.Stderr).With().Timestamp().Logger()
|
||||
// logger.Info().
|
||||
// Timestamp().
|
||||
// Msg("dup")
|
||||
// // Output: {"level":"info","time":1494567715,"time":1494567715,"message":"dup"}
|
||||
// logger := zerolog.New(os.Stderr).With().Timestamp().Logger()
|
||||
// logger.Info().
|
||||
// Timestamp().
|
||||
// Msg("dup")
|
||||
// // Output: {"level":"info","time":1494567715,"time":1494567715,"message":"dup"}
|
||||
//
|
||||
// In this case, many consumers will take the last value,
|
||||
// but this is not guaranteed; check yours if in doubt.
|
||||
package zlog
|
||||
package zerolog
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Level defines log levels.
|
||||
|
@ -157,27 +156,27 @@ func (l Level) String() string {
|
|||
return strconv.Itoa(int(l))
|
||||
}
|
||||
|
||||
// ParseLevel converts a level string into a zlog Level value.
|
||||
// ParseLevel converts a level string into a zerolog Level value.
|
||||
// returns an error if the input string does not match known values.
|
||||
func ParseLevel(levelStr string) (Level, error) {
|
||||
switch {
|
||||
case strings.EqualFold(levelStr, LevelFieldMarshalFunc(TraceLevel)):
|
||||
switch levelStr {
|
||||
case LevelFieldMarshalFunc(TraceLevel):
|
||||
return TraceLevel, nil
|
||||
case strings.EqualFold(levelStr, LevelFieldMarshalFunc(DebugLevel)):
|
||||
case LevelFieldMarshalFunc(DebugLevel):
|
||||
return DebugLevel, nil
|
||||
case strings.EqualFold(levelStr, LevelFieldMarshalFunc(InfoLevel)):
|
||||
case LevelFieldMarshalFunc(InfoLevel):
|
||||
return InfoLevel, nil
|
||||
case strings.EqualFold(levelStr, LevelFieldMarshalFunc(WarnLevel)):
|
||||
case LevelFieldMarshalFunc(WarnLevel):
|
||||
return WarnLevel, nil
|
||||
case strings.EqualFold(levelStr, LevelFieldMarshalFunc(ErrorLevel)):
|
||||
case LevelFieldMarshalFunc(ErrorLevel):
|
||||
return ErrorLevel, nil
|
||||
case strings.EqualFold(levelStr, LevelFieldMarshalFunc(FatalLevel)):
|
||||
case LevelFieldMarshalFunc(FatalLevel):
|
||||
return FatalLevel, nil
|
||||
case strings.EqualFold(levelStr, LevelFieldMarshalFunc(PanicLevel)):
|
||||
case LevelFieldMarshalFunc(PanicLevel):
|
||||
return PanicLevel, nil
|
||||
case strings.EqualFold(levelStr, LevelFieldMarshalFunc(Disabled)):
|
||||
case LevelFieldMarshalFunc(Disabled):
|
||||
return Disabled, nil
|
||||
case strings.EqualFold(levelStr, LevelFieldMarshalFunc(NoLevel)):
|
||||
case LevelFieldMarshalFunc(NoLevel):
|
||||
return NoLevel, nil
|
||||
}
|
||||
i, err := strconv.Atoi(levelStr)
|
||||
|
@ -190,21 +189,6 @@ func ParseLevel(levelStr string) (Level, error) {
|
|||
return Level(i), nil
|
||||
}
|
||||
|
||||
// UnmarshalText implements encoding.TextUnmarshaler to allow for easy reading from toml/yaml/json formats
|
||||
func (l *Level) UnmarshalText(text []byte) error {
|
||||
if l == nil {
|
||||
return errors.New("can't unmarshal a nil *Level")
|
||||
}
|
||||
var err error
|
||||
*l, err = ParseLevel(string(text))
|
||||
return err
|
||||
}
|
||||
|
||||
// MarshalText implements encoding.TextMarshaler to allow for easy writing into toml/yaml/json formats
|
||||
func (l Level) MarshalText() ([]byte, error) {
|
||||
return []byte(LevelFieldMarshalFunc(l)), nil
|
||||
}
|
||||
|
||||
// A Logger represents an active logging object that generates lines
|
||||
// of JSON output to an io.Writer. Each logging operation makes a single
|
||||
// call to the Writer's Write method. There is no guarantee on access
|
||||
|
@ -308,9 +292,7 @@ func (l Logger) Sample(s Sampler) Logger {
|
|||
|
||||
// Hook returns a logger with the h Hook.
|
||||
func (l Logger) Hook(h Hook) Logger {
|
||||
newHooks := make([]Hook, len(l.hooks), len(l.hooks)+1)
|
||||
copy(newHooks, l.hooks)
|
||||
l.hooks = append(newHooks, h)
|
||||
l.hooks = append(l.hooks, h)
|
||||
return l
|
||||
}
|
||||
|
||||
|
|
79
log/log.go
79
log/log.go
|
@ -1,4 +1,4 @@
|
|||
// Package log provides a global logger for zlog.
|
||||
// Package log provides a global logger for zerolog.
|
||||
package log
|
||||
|
||||
import (
|
||||
|
@ -6,42 +6,35 @@ import (
|
|||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/rs/zerolog"
|
||||
"tuxpa.in/a/zlog"
|
||||
)
|
||||
|
||||
// Logger is the global logger.
|
||||
var Logger = zlog.New(nil).Output(
|
||||
zerolog.ConsoleWriter{
|
||||
Out: os.Stderr,
|
||||
TimeFormat: time.RFC3339,
|
||||
},
|
||||
).With().Timestamp().Logger()
|
||||
var Logger = zerolog.New(os.Stderr).With().Timestamp().Logger()
|
||||
|
||||
// Output duplicates the global logger and sets w as its output.
|
||||
func Output(w io.Writer) zlog.Logger {
|
||||
func Output(w io.Writer) zerolog.Logger {
|
||||
return Logger.Output(w)
|
||||
}
|
||||
|
||||
// With creates a child logger with the field added to its context.
|
||||
func With() zlog.Context {
|
||||
func With() zerolog.Context {
|
||||
return Logger.With()
|
||||
}
|
||||
|
||||
// Level creates a child logger with the minimum accepted level set to level.
|
||||
func Level(level zlog.Level) zlog.Logger {
|
||||
func Level(level zerolog.Level) zerolog.Logger {
|
||||
return Logger.Level(level)
|
||||
}
|
||||
|
||||
// Sample returns a logger with the s sampler.
|
||||
func Sample(s zlog.Sampler) zlog.Logger {
|
||||
func Sample(s zerolog.Sampler) zerolog.Logger {
|
||||
return Logger.Sample(s)
|
||||
}
|
||||
|
||||
// Hook returns a logger with the h Hook.
|
||||
func Hook(h zlog.Hook) zlog.Logger {
|
||||
func Hook(h zerolog.Hook) zerolog.Logger {
|
||||
return Logger.Hook(h)
|
||||
}
|
||||
|
||||
|
@ -49,99 +42,73 @@ func Hook(h zlog.Hook) zlog.Logger {
|
|||
// with info level if err is nil.
|
||||
//
|
||||
// You must call Msg on the returned event in order to send the event.
|
||||
func Err(err error) *zlog.Event {
|
||||
func Err(err error) *zerolog.Event {
|
||||
return Logger.Err(err)
|
||||
}
|
||||
|
||||
// Trace starts a new message with trace level.
|
||||
//
|
||||
// You must call Msg on the returned event in order to send the event.
|
||||
func Trace() *zlog.Event {
|
||||
func Trace() *zerolog.Event {
|
||||
return Logger.Trace()
|
||||
}
|
||||
|
||||
// Debug starts a new message with debug level.
|
||||
//
|
||||
// You must call Msg on the returned event in order to send the event.
|
||||
func Debug() *zlog.Event {
|
||||
func Debug() *zerolog.Event {
|
||||
return Logger.Debug()
|
||||
}
|
||||
|
||||
// Info starts a new message with info level.
|
||||
//
|
||||
// You must call Msg on the returned event in order to send the event.
|
||||
func Info() *zlog.Event {
|
||||
func Info() *zerolog.Event {
|
||||
return Logger.Info()
|
||||
}
|
||||
|
||||
// Warn starts a new message with warn level.
|
||||
//
|
||||
// You must call Msg on the returned event in order to send the event.
|
||||
func Warn() *zlog.Event {
|
||||
func Warn() *zerolog.Event {
|
||||
return Logger.Warn()
|
||||
}
|
||||
|
||||
// Error starts a new message with error level.
|
||||
//
|
||||
// You must call Msg on the returned event in order to send the event.
|
||||
func Error() *zlog.Event {
|
||||
func Error() *zerolog.Event {
|
||||
return Logger.Error()
|
||||
}
|
||||
|
||||
// Errorf sends a log event using debug level and no extra field.
|
||||
// Arguments are handled in the manner of fmt.Errorf.
|
||||
func Errorf(format string, v ...interface{}) {
|
||||
Logger.Error().CallerSkipFrame(1).Msgf(format, v...)
|
||||
}
|
||||
|
||||
func Errorln(args ...interface{}) {
|
||||
Logger.Error().Msg(fmt.Sprintln(args...))
|
||||
}
|
||||
|
||||
// Fatal starts a new message with fatal level. The os.Exit(1) function
|
||||
// is called by the Msg method.
|
||||
//
|
||||
// You must call Msg on the returned event in order to send the event.
|
||||
func Fatal() *zlog.Event {
|
||||
func Fatal() *zerolog.Event {
|
||||
return Logger.Fatal()
|
||||
}
|
||||
|
||||
func Fatalf(format string, args ...interface{}) {
|
||||
Logger.Fatal().Msgf(format, args...)
|
||||
}
|
||||
|
||||
func Fatalln(args ...interface{}) {
|
||||
Logger.Fatal().Msg(fmt.Sprintln(args...))
|
||||
}
|
||||
|
||||
// Panic starts a new message with panic level. The message is also sent
|
||||
// to the panic function.
|
||||
//
|
||||
// You must call Msg on the returned event in order to send the event.
|
||||
func Panic() *zlog.Event {
|
||||
func Panic() *zerolog.Event {
|
||||
return Logger.Panic()
|
||||
}
|
||||
|
||||
func Panicf(format string, args ...interface{}) {
|
||||
Logger.Panic().Msgf(format, args...)
|
||||
}
|
||||
|
||||
func Panicln(args ...interface{}) {
|
||||
Logger.Panic().Msg(fmt.Sprintln(args...))
|
||||
}
|
||||
|
||||
// WithLevel starts a new message with level.
|
||||
//
|
||||
// You must call Msg on the returned event in order to send the event.
|
||||
func WithLevel(level zlog.Level) *zlog.Event {
|
||||
func WithLevel(level zerolog.Level) *zerolog.Event {
|
||||
return Logger.WithLevel(level)
|
||||
}
|
||||
|
||||
// Log starts a new message with no level. Setting zlog.GlobalLevel to
|
||||
// zlog.Disabled will still disable events produced by this method.
|
||||
// Log starts a new message with no level. Setting zerolog.GlobalLevel to
|
||||
// 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() *zlog.Event {
|
||||
func Log() *zerolog.Event {
|
||||
return Logger.Log()
|
||||
}
|
||||
|
||||
|
@ -157,12 +124,8 @@ func Printf(format string, v ...interface{}) {
|
|||
Logger.Debug().CallerSkipFrame(1).Msgf(format, v...)
|
||||
}
|
||||
|
||||
func Println(args ...interface{}) {
|
||||
Logger.Debug().Msg(fmt.Sprintln(args...))
|
||||
}
|
||||
|
||||
// Ctx returns the Logger associated with the ctx. If no logger
|
||||
// is associated, a disabled logger is returned.
|
||||
func Ctx(ctx context.Context) *zlog.Logger {
|
||||
return zlog.Ctx(ctx)
|
||||
func Ctx(ctx context.Context) *zerolog.Logger {
|
||||
return zerolog.Ctx(ctx)
|
||||
}
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
//go:build !binary_log
|
||||
// +build !binary_log
|
||||
|
||||
package log_test
|
||||
|
@ -9,8 +8,8 @@ import (
|
|||
"os"
|
||||
"time"
|
||||
|
||||
"tuxpa.in/a/zlog"
|
||||
"tuxpa.in/a/zlog/log"
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
// setup would normally be an init() function, however, there seems
|
||||
|
@ -18,16 +17,16 @@ import (
|
|||
// global Logger from an init()
|
||||
func setup() {
|
||||
// UNIX Time is faster and smaller than most timestamps
|
||||
// If you set zlog.TimeFieldFormat to an empty string,
|
||||
// If you set zerolog.TimeFieldFormat to an empty string,
|
||||
// logs will write with UNIX time
|
||||
zlog.TimeFieldFormat = ""
|
||||
zerolog.TimeFieldFormat = ""
|
||||
// In order to always output a static time to stdout for these
|
||||
// examples to pass, we need to override zlog.TimestampFunc
|
||||
// examples to pass, we need to override zerolog.TimestampFunc
|
||||
// and log.Logger globals -- you would not normally need to do this
|
||||
zlog.TimestampFunc = func() time.Time {
|
||||
zerolog.TimestampFunc = func() time.Time {
|
||||
return time.Date(2008, 1, 8, 17, 5, 05, 0, time.UTC)
|
||||
}
|
||||
log.Logger = zlog.New(os.Stdout).With().Timestamp().Logger()
|
||||
log.Logger = zerolog.New(os.Stdout).With().Timestamp().Logger()
|
||||
}
|
||||
|
||||
// Simple logging example using the Print function in the log package
|
||||
|
@ -131,9 +130,9 @@ func Example() {
|
|||
flag.Parse()
|
||||
|
||||
// Default level for this example is info, unless debug flag is present
|
||||
zlog.SetGlobalLevel(zlog.InfoLevel)
|
||||
zerolog.SetGlobalLevel(zerolog.InfoLevel)
|
||||
if *debug {
|
||||
zlog.SetGlobalLevel(zlog.DebugLevel)
|
||||
zerolog.SetGlobalLevel(zerolog.DebugLevel)
|
||||
}
|
||||
|
||||
log.Debug().Msg("This message appears only when log level set to Debug")
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// +build !binary_log
|
||||
|
||||
package zlog_test
|
||||
package zerolog_test
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
@ -10,18 +10,18 @@ import (
|
|||
"os"
|
||||
"time"
|
||||
|
||||
"tuxpa.in/a/zlog"
|
||||
"github.com/rs/zerolog"
|
||||
)
|
||||
|
||||
func ExampleNew() {
|
||||
log := zlog.New(os.Stdout)
|
||||
log := zerolog.New(os.Stdout)
|
||||
|
||||
log.Info().Msg("hello world")
|
||||
// Output: {"level":"info","message":"hello world"}
|
||||
}
|
||||
|
||||
func ExampleLogger_With() {
|
||||
log := zlog.New(os.Stdout).
|
||||
log := zerolog.New(os.Stdout).
|
||||
With().
|
||||
Str("foo", "bar").
|
||||
Logger()
|
||||
|
@ -32,7 +32,7 @@ func ExampleLogger_With() {
|
|||
}
|
||||
|
||||
func ExampleLogger_Level() {
|
||||
log := zlog.New(os.Stdout).Level(zlog.WarnLevel)
|
||||
log := zerolog.New(os.Stdout).Level(zerolog.WarnLevel)
|
||||
|
||||
log.Info().Msg("filtered out message")
|
||||
log.Error().Msg("kept message")
|
||||
|
@ -41,7 +41,7 @@ func ExampleLogger_Level() {
|
|||
}
|
||||
|
||||
func ExampleLogger_Sample() {
|
||||
log := zlog.New(os.Stdout).Sample(&zlog.BasicSampler{N: 2})
|
||||
log := zerolog.New(os.Stdout).Sample(&zerolog.BasicSampler{N: 2})
|
||||
|
||||
log.Info().Msg("message 1")
|
||||
log.Info().Msg("message 2")
|
||||
|
@ -54,8 +54,8 @@ func ExampleLogger_Sample() {
|
|||
|
||||
type LevelNameHook struct{}
|
||||
|
||||
func (h LevelNameHook) Run(e *zlog.Event, l zlog.Level, msg string) {
|
||||
if l != zlog.NoLevel {
|
||||
func (h LevelNameHook) Run(e *zerolog.Event, l zerolog.Level, msg string) {
|
||||
if l != zerolog.NoLevel {
|
||||
e.Str("level_name", l.String())
|
||||
} else {
|
||||
e.Str("level_name", "NoLevel")
|
||||
|
@ -64,7 +64,7 @@ func (h LevelNameHook) Run(e *zlog.Event, l zlog.Level, msg string) {
|
|||
|
||||
type MessageHook string
|
||||
|
||||
func (h MessageHook) Run(e *zlog.Event, l zlog.Level, msg string) {
|
||||
func (h MessageHook) Run(e *zerolog.Event, l zerolog.Level, msg string) {
|
||||
e.Str("the_message", msg)
|
||||
}
|
||||
|
||||
|
@ -72,7 +72,7 @@ func ExampleLogger_Hook() {
|
|||
var levelNameHook LevelNameHook
|
||||
var messageHook MessageHook = "The message"
|
||||
|
||||
log := zlog.New(os.Stdout).Hook(levelNameHook).Hook(messageHook)
|
||||
log := zerolog.New(os.Stdout).Hook(levelNameHook).Hook(messageHook)
|
||||
|
||||
log.Info().Msg("hello world")
|
||||
|
||||
|
@ -80,7 +80,7 @@ func ExampleLogger_Hook() {
|
|||
}
|
||||
|
||||
func ExampleLogger_Print() {
|
||||
log := zlog.New(os.Stdout)
|
||||
log := zerolog.New(os.Stdout)
|
||||
|
||||
log.Print("hello world")
|
||||
|
||||
|
@ -88,7 +88,7 @@ func ExampleLogger_Print() {
|
|||
}
|
||||
|
||||
func ExampleLogger_Printf() {
|
||||
log := zlog.New(os.Stdout)
|
||||
log := zerolog.New(os.Stdout)
|
||||
|
||||
log.Printf("hello %s", "world")
|
||||
|
||||
|
@ -96,7 +96,7 @@ func ExampleLogger_Printf() {
|
|||
}
|
||||
|
||||
func ExampleLogger_Trace() {
|
||||
log := zlog.New(os.Stdout)
|
||||
log := zerolog.New(os.Stdout)
|
||||
|
||||
log.Trace().
|
||||
Str("foo", "bar").
|
||||
|
@ -107,7 +107,7 @@ func ExampleLogger_Trace() {
|
|||
}
|
||||
|
||||
func ExampleLogger_Debug() {
|
||||
log := zlog.New(os.Stdout)
|
||||
log := zerolog.New(os.Stdout)
|
||||
|
||||
log.Debug().
|
||||
Str("foo", "bar").
|
||||
|
@ -118,7 +118,7 @@ func ExampleLogger_Debug() {
|
|||
}
|
||||
|
||||
func ExampleLogger_Info() {
|
||||
log := zlog.New(os.Stdout)
|
||||
log := zerolog.New(os.Stdout)
|
||||
|
||||
log.Info().
|
||||
Str("foo", "bar").
|
||||
|
@ -129,7 +129,7 @@ func ExampleLogger_Info() {
|
|||
}
|
||||
|
||||
func ExampleLogger_Warn() {
|
||||
log := zlog.New(os.Stdout)
|
||||
log := zerolog.New(os.Stdout)
|
||||
|
||||
log.Warn().
|
||||
Str("foo", "bar").
|
||||
|
@ -139,7 +139,7 @@ func ExampleLogger_Warn() {
|
|||
}
|
||||
|
||||
func ExampleLogger_Error() {
|
||||
log := zlog.New(os.Stdout)
|
||||
log := zerolog.New(os.Stdout)
|
||||
|
||||
log.Error().
|
||||
Err(errors.New("some error")).
|
||||
|
@ -149,16 +149,16 @@ func ExampleLogger_Error() {
|
|||
}
|
||||
|
||||
func ExampleLogger_WithLevel() {
|
||||
log := zlog.New(os.Stdout)
|
||||
log := zerolog.New(os.Stdout)
|
||||
|
||||
log.WithLevel(zlog.InfoLevel).
|
||||
log.WithLevel(zerolog.InfoLevel).
|
||||
Msg("hello world")
|
||||
|
||||
// Output: {"level":"info","message":"hello world"}
|
||||
}
|
||||
|
||||
func ExampleLogger_Write() {
|
||||
log := zlog.New(os.Stdout).With().
|
||||
log := zerolog.New(os.Stdout).With().
|
||||
Str("foo", "bar").
|
||||
Logger()
|
||||
|
||||
|
@ -171,7 +171,7 @@ func ExampleLogger_Write() {
|
|||
}
|
||||
|
||||
func ExampleLogger_Log() {
|
||||
log := zlog.New(os.Stdout)
|
||||
log := zerolog.New(os.Stdout)
|
||||
|
||||
log.Log().
|
||||
Str("foo", "bar").
|
||||
|
@ -182,11 +182,11 @@ func ExampleLogger_Log() {
|
|||
}
|
||||
|
||||
func ExampleEvent_Dict() {
|
||||
log := zlog.New(os.Stdout)
|
||||
log := zerolog.New(os.Stdout)
|
||||
|
||||
log.Log().
|
||||
Str("foo", "bar").
|
||||
Dict("dict", zlog.Dict().
|
||||
Dict("dict", zerolog.Dict().
|
||||
Str("bar", "baz").
|
||||
Int("n", 1),
|
||||
).
|
||||
|
@ -201,7 +201,7 @@ type User struct {
|
|||
Created time.Time
|
||||
}
|
||||
|
||||
func (u User) MarshalZerologObject(e *zlog.Event) {
|
||||
func (u User) MarshalZerologObject(e *zerolog.Event) {
|
||||
e.Str("name", u.Name).
|
||||
Int("age", u.Age).
|
||||
Time("created", u.Created)
|
||||
|
@ -213,7 +213,7 @@ type Price struct {
|
|||
unit string
|
||||
}
|
||||
|
||||
func (p Price) MarshalZerologObject(e *zlog.Event) {
|
||||
func (p Price) MarshalZerologObject(e *zerolog.Event) {
|
||||
denom := uint64(1)
|
||||
for i := 0; i < p.prec; i++ {
|
||||
denom *= 10
|
||||
|
@ -225,21 +225,21 @@ func (p Price) MarshalZerologObject(e *zlog.Event) {
|
|||
|
||||
type Users []User
|
||||
|
||||
func (uu Users) MarshalZerologArray(a *zlog.Array) {
|
||||
func (uu Users) MarshalZerologArray(a *zerolog.Array) {
|
||||
for _, u := range uu {
|
||||
a.Object(u)
|
||||
}
|
||||
}
|
||||
|
||||
func ExampleEvent_Array() {
|
||||
log := zlog.New(os.Stdout)
|
||||
log := zerolog.New(os.Stdout)
|
||||
|
||||
log.Log().
|
||||
Str("foo", "bar").
|
||||
Array("array", zlog.Arr().
|
||||
Array("array", zerolog.Arr().
|
||||
Str("baz").
|
||||
Int(1).
|
||||
Dict(zlog.Dict().
|
||||
Dict(zerolog.Dict().
|
||||
Str("bar", "baz").
|
||||
Int("n", 1),
|
||||
),
|
||||
|
@ -250,9 +250,9 @@ func ExampleEvent_Array() {
|
|||
}
|
||||
|
||||
func ExampleEvent_Array_object() {
|
||||
log := zlog.New(os.Stdout)
|
||||
log := zerolog.New(os.Stdout)
|
||||
|
||||
// Users implements zlog.LogArrayMarshaler
|
||||
// Users implements zerolog.LogArrayMarshaler
|
||||
u := Users{
|
||||
User{"John", 35, time.Time{}},
|
||||
User{"Bob", 55, time.Time{}},
|
||||
|
@ -267,9 +267,9 @@ func ExampleEvent_Array_object() {
|
|||
}
|
||||
|
||||
func ExampleEvent_Object() {
|
||||
log := zlog.New(os.Stdout)
|
||||
log := zerolog.New(os.Stdout)
|
||||
|
||||
// User implements zlog.LogObjectMarshaler
|
||||
// User implements zerolog.LogObjectMarshaler
|
||||
u := User{"John", 35, time.Time{}}
|
||||
|
||||
log.Log().
|
||||
|
@ -281,7 +281,7 @@ func ExampleEvent_Object() {
|
|||
}
|
||||
|
||||
func ExampleEvent_EmbedObject() {
|
||||
log := zlog.New(os.Stdout)
|
||||
log := zerolog.New(os.Stdout)
|
||||
|
||||
price := Price{val: 6449, prec: 2, unit: "$"}
|
||||
|
||||
|
@ -294,7 +294,7 @@ func ExampleEvent_EmbedObject() {
|
|||
}
|
||||
|
||||
func ExampleEvent_Interface() {
|
||||
log := zlog.New(os.Stdout)
|
||||
log := zerolog.New(os.Stdout)
|
||||
|
||||
obj := struct {
|
||||
Name string `json:"name"`
|
||||
|
@ -313,7 +313,7 @@ func ExampleEvent_Interface() {
|
|||
func ExampleEvent_Dur() {
|
||||
d := 10 * time.Second
|
||||
|
||||
log := zlog.New(os.Stdout)
|
||||
log := zerolog.New(os.Stdout)
|
||||
|
||||
log.Log().
|
||||
Str("foo", "bar").
|
||||
|
@ -329,7 +329,7 @@ func ExampleEvent_Durs() {
|
|||
20 * time.Second,
|
||||
}
|
||||
|
||||
log := zlog.New(os.Stdout)
|
||||
log := zerolog.New(os.Stdout)
|
||||
|
||||
log.Log().
|
||||
Str("foo", "bar").
|
||||
|
@ -345,7 +345,7 @@ func ExampleEvent_Fields_map() {
|
|||
"n": 1,
|
||||
}
|
||||
|
||||
log := zlog.New(os.Stdout)
|
||||
log := zerolog.New(os.Stdout)
|
||||
|
||||
log.Log().
|
||||
Str("foo", "bar").
|
||||
|
@ -361,7 +361,7 @@ func ExampleEvent_Fields_slice() {
|
|||
"n", 1,
|
||||
}
|
||||
|
||||
log := zlog.New(os.Stdout)
|
||||
log := zerolog.New(os.Stdout)
|
||||
|
||||
log.Log().
|
||||
Str("foo", "bar").
|
||||
|
@ -372,9 +372,9 @@ func ExampleEvent_Fields_slice() {
|
|||
}
|
||||
|
||||
func ExampleContext_Dict() {
|
||||
log := zlog.New(os.Stdout).With().
|
||||
log := zerolog.New(os.Stdout).With().
|
||||
Str("foo", "bar").
|
||||
Dict("dict", zlog.Dict().
|
||||
Dict("dict", zerolog.Dict().
|
||||
Str("bar", "baz").
|
||||
Int("n", 1),
|
||||
).Logger()
|
||||
|
@ -385,9 +385,9 @@ func ExampleContext_Dict() {
|
|||
}
|
||||
|
||||
func ExampleContext_Array() {
|
||||
log := zlog.New(os.Stdout).With().
|
||||
log := zerolog.New(os.Stdout).With().
|
||||
Str("foo", "bar").
|
||||
Array("array", zlog.Arr().
|
||||
Array("array", zerolog.Arr().
|
||||
Str("baz").
|
||||
Int(1),
|
||||
).Logger()
|
||||
|
@ -398,13 +398,13 @@ func ExampleContext_Array() {
|
|||
}
|
||||
|
||||
func ExampleContext_Array_object() {
|
||||
// Users implements zlog.LogArrayMarshaler
|
||||
// Users implements zerolog.LogArrayMarshaler
|
||||
u := Users{
|
||||
User{"John", 35, time.Time{}},
|
||||
User{"Bob", 55, time.Time{}},
|
||||
}
|
||||
|
||||
log := zlog.New(os.Stdout).With().
|
||||
log := zerolog.New(os.Stdout).With().
|
||||
Str("foo", "bar").
|
||||
Array("users", u).
|
||||
Logger()
|
||||
|
@ -415,10 +415,10 @@ func ExampleContext_Array_object() {
|
|||
}
|
||||
|
||||
func ExampleContext_Object() {
|
||||
// User implements zlog.LogObjectMarshaler
|
||||
// User implements zerolog.LogObjectMarshaler
|
||||
u := User{"John", 35, time.Time{}}
|
||||
|
||||
log := zlog.New(os.Stdout).With().
|
||||
log := zerolog.New(os.Stdout).With().
|
||||
Str("foo", "bar").
|
||||
Object("user", u).
|
||||
Logger()
|
||||
|
@ -432,7 +432,7 @@ func ExampleContext_EmbedObject() {
|
|||
|
||||
price := Price{val: 6449, prec: 2, unit: "$"}
|
||||
|
||||
log := zlog.New(os.Stdout).With().
|
||||
log := zerolog.New(os.Stdout).With().
|
||||
Str("foo", "bar").
|
||||
EmbedObject(price).
|
||||
Logger()
|
||||
|
@ -449,7 +449,7 @@ func ExampleContext_Interface() {
|
|||
Name: "john",
|
||||
}
|
||||
|
||||
log := zlog.New(os.Stdout).With().
|
||||
log := zerolog.New(os.Stdout).With().
|
||||
Str("foo", "bar").
|
||||
Interface("obj", obj).
|
||||
Logger()
|
||||
|
@ -462,7 +462,7 @@ func ExampleContext_Interface() {
|
|||
func ExampleContext_Dur() {
|
||||
d := 10 * time.Second
|
||||
|
||||
log := zlog.New(os.Stdout).With().
|
||||
log := zerolog.New(os.Stdout).With().
|
||||
Str("foo", "bar").
|
||||
Dur("dur", d).
|
||||
Logger()
|
||||
|
@ -478,7 +478,7 @@ func ExampleContext_Durs() {
|
|||
20 * time.Second,
|
||||
}
|
||||
|
||||
log := zlog.New(os.Stdout).With().
|
||||
log := zerolog.New(os.Stdout).With().
|
||||
Str("foo", "bar").
|
||||
Durs("durs", d).
|
||||
Logger()
|
||||
|
@ -490,7 +490,7 @@ func ExampleContext_Durs() {
|
|||
|
||||
func ExampleContext_IPAddr() {
|
||||
hostIP := net.IP{192, 168, 0, 100}
|
||||
log := zlog.New(os.Stdout).With().
|
||||
log := zerolog.New(os.Stdout).With().
|
||||
IPAddr("HostIP", hostIP).
|
||||
Logger()
|
||||
|
||||
|
@ -501,7 +501,7 @@ func ExampleContext_IPAddr() {
|
|||
|
||||
func ExampleContext_IPPrefix() {
|
||||
route := net.IPNet{IP: net.IP{192, 168, 0, 0}, Mask: net.CIDRMask(24, 32)}
|
||||
log := zlog.New(os.Stdout).With().
|
||||
log := zerolog.New(os.Stdout).With().
|
||||
IPPrefix("Route", route).
|
||||
Logger()
|
||||
|
||||
|
@ -512,7 +512,7 @@ func ExampleContext_IPPrefix() {
|
|||
|
||||
func ExampleContext_MACAddr() {
|
||||
mac := net.HardwareAddr{0x00, 0x14, 0x22, 0x01, 0x23, 0x45}
|
||||
log := zlog.New(os.Stdout).With().
|
||||
log := zerolog.New(os.Stdout).With().
|
||||
MACAddr("hostMAC", mac).
|
||||
Logger()
|
||||
|
||||
|
@ -527,7 +527,7 @@ func ExampleContext_Fields_map() {
|
|||
"n": 1,
|
||||
}
|
||||
|
||||
log := zlog.New(os.Stdout).With().
|
||||
log := zerolog.New(os.Stdout).With().
|
||||
Str("foo", "bar").
|
||||
Fields(fields).
|
||||
Logger()
|
||||
|
@ -543,7 +543,7 @@ func ExampleContext_Fields_slice() {
|
|||
"n", 1,
|
||||
}
|
||||
|
||||
log := zlog.New(os.Stdout).With().
|
||||
log := zerolog.New(os.Stdout).With().
|
||||
Str("foo", "bar").
|
||||
Fields(fields).
|
||||
Logger()
|
||||
|
|
80
log_test.go
80
log_test.go
|
@ -1,4 +1,4 @@
|
|||
package zlog
|
||||
package zerolog
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
@ -320,7 +320,6 @@ func TestFields(t *testing.T) {
|
|||
Bytes("bytes", []byte("bar")).
|
||||
Hex("hex", []byte{0x12, 0xef}).
|
||||
RawJSON("json", []byte(`{"some":"json"}`)).
|
||||
RawCBOR("cbor", []byte{0x83, 0x01, 0x82, 0x02, 0x03, 0x82, 0x04, 0x05}).
|
||||
Func(func(e *Event) { e.Str("func", "func_output") }).
|
||||
AnErr("some_err", nil).
|
||||
Err(errors.New("some error")).
|
||||
|
@ -345,7 +344,7 @@ func TestFields(t *testing.T) {
|
|||
Time("time", time.Time{}).
|
||||
TimeDiff("diff", now, now.Add(-10*time.Second)).
|
||||
Msg("")
|
||||
if got, want := decodeIfBinaryToString(out.Bytes()), `{"caller":"`+caller+`","string":"foo","stringer":"127.0.0.1","stringer_nil":null,"bytes":"bar","hex":"12ef","json":{"some":"json"},"cbor":"data:application/cbor;base64,gwGCAgOCBAU=","func":"func_output","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,"IPv4":"192.168.0.100","IPv6":"2001:db8:85a3::8a2e:370:7334","Mac":"00:14:22:01:23:45","Prefix":"192.168.0.100/24","float32":11.1234,"float64":12.321321321,"dur":1000,"time":"0001-01-01T00:00:00Z","diff":10000}`+"\n"; got != want {
|
||||
if got, want := decodeIfBinaryToString(out.Bytes()), `{"caller":"`+caller+`","string":"foo","stringer":"127.0.0.1","stringer_nil":null,"bytes":"bar","hex":"12ef","json":{"some":"json"},"func":"func_output","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,"IPv4":"192.168.0.100","IPv6":"2001:db8:85a3::8a2e:370:7334","Mac":"00:14:22:01:23:45","Prefix":"192.168.0.100/24","float32":11.1234,"float64":12.321321321,"dur":1000,"time":"0001-01-01T00:00:00Z","diff":10000}`+"\n"; got != want {
|
||||
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
|
||||
}
|
||||
}
|
||||
|
@ -783,7 +782,7 @@ func TestCallerMarshalFunc(t *testing.T) {
|
|||
|
||||
// test default behaviour this is really brittle due to the line numbers
|
||||
// actually mattering for validation
|
||||
pc, file, line, _ := runtime.Caller(0)
|
||||
_, file, line, _ := runtime.Caller(0)
|
||||
caller := fmt.Sprintf("%s:%d", file, line+2)
|
||||
log.Log().Caller().Msg("msg")
|
||||
if got, want := decodeIfBinaryToString(out.Bytes()), `{"caller":"`+caller+`","message":"msg"}`+"\n"; got != want {
|
||||
|
@ -794,16 +793,16 @@ func TestCallerMarshalFunc(t *testing.T) {
|
|||
// test custom behavior. In this case we'll take just the last directory
|
||||
origCallerMarshalFunc := CallerMarshalFunc
|
||||
defer func() { CallerMarshalFunc = origCallerMarshalFunc }()
|
||||
CallerMarshalFunc = func(pc uintptr, file string, line int) string {
|
||||
CallerMarshalFunc = func(file string, line int) string {
|
||||
parts := strings.Split(file, "/")
|
||||
if len(parts) > 1 {
|
||||
return strings.Join(parts[len(parts)-2:], "/") + ":" + strconv.Itoa(line)
|
||||
}
|
||||
|
||||
return runtime.FuncForPC(pc).Name() + ":" + file + ":" + strconv.Itoa(line)
|
||||
return file + ":" + strconv.Itoa(line)
|
||||
}
|
||||
pc, file, line, _ = runtime.Caller(0)
|
||||
caller = CallerMarshalFunc(pc, file, line+2)
|
||||
_, file, line, _ = runtime.Caller(0)
|
||||
caller = CallerMarshalFunc(file, line+2)
|
||||
log.Log().Caller().Msg("msg")
|
||||
if got, want := decodeIfBinaryToString(out.Bytes()), `{"caller":"`+caller+`","message":"msg"}`+"\n"; got != want {
|
||||
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
|
||||
|
@ -908,33 +907,6 @@ func TestLevel_String(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestLevel_MarshalText(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
l Level
|
||||
want string
|
||||
}{
|
||||
{"trace", TraceLevel, "trace"},
|
||||
{"debug", DebugLevel, "debug"},
|
||||
{"info", InfoLevel, "info"},
|
||||
{"warn", WarnLevel, "warn"},
|
||||
{"error", ErrorLevel, "error"},
|
||||
{"fatal", FatalLevel, "fatal"},
|
||||
{"panic", PanicLevel, "panic"},
|
||||
{"disabled", Disabled, "disabled"},
|
||||
{"nolevel", NoLevel, ""},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got, err := tt.l.MarshalText(); err != nil {
|
||||
t.Errorf("MarshalText couldn't marshal: %v", tt.l)
|
||||
} else if string(got) != tt.want {
|
||||
t.Errorf("String() = %v, want %v", string(got), tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseLevel(t *testing.T) {
|
||||
type args struct {
|
||||
levelStr string
|
||||
|
@ -971,41 +943,3 @@ func TestParseLevel(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestUnmarshalTextLevel(t *testing.T) {
|
||||
type args struct {
|
||||
levelStr string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want Level
|
||||
wantErr bool
|
||||
}{
|
||||
{"trace", args{"trace"}, TraceLevel, false},
|
||||
{"debug", args{"debug"}, DebugLevel, false},
|
||||
{"info", args{"info"}, InfoLevel, false},
|
||||
{"warn", args{"warn"}, WarnLevel, false},
|
||||
{"error", args{"error"}, ErrorLevel, false},
|
||||
{"fatal", args{"fatal"}, FatalLevel, false},
|
||||
{"panic", args{"panic"}, PanicLevel, false},
|
||||
{"disabled", args{"disabled"}, Disabled, false},
|
||||
{"nolevel", args{""}, NoLevel, false},
|
||||
{"-1", args{"-1"}, TraceLevel, false},
|
||||
{"-2", args{"-2"}, Level(-2), false},
|
||||
{"-3", args{"-3"}, Level(-3), false},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
var l Level
|
||||
err := l.UnmarshalText([]byte(tt.args.levelStr))
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("UnmarshalText() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
if l != tt.want {
|
||||
t.Errorf("UnmarshalText() got = %v, want %v", l, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// +build !go1.12
|
||||
|
||||
package zlog
|
||||
package zerolog
|
||||
|
||||
const contextCallerSkipFrameCount = 3
|
||||
|
|
|
@ -42,32 +42,15 @@ func frameField(f errors.Frame, s *state, c rune) string {
|
|||
|
||||
// MarshalStack implements pkg/errors stack trace marshaling.
|
||||
//
|
||||
// zlog.ErrorStackMarshaler = MarshalStack
|
||||
// zerolog.ErrorStackMarshaler = MarshalStack
|
||||
func MarshalStack(err error) interface{} {
|
||||
type stackTracer interface {
|
||||
StackTrace() errors.StackTrace
|
||||
}
|
||||
var sterr stackTracer
|
||||
var ok bool
|
||||
for err != nil {
|
||||
sterr, ok = err.(stackTracer)
|
||||
if ok {
|
||||
break
|
||||
}
|
||||
|
||||
u, ok := err.(interface {
|
||||
Unwrap() error
|
||||
})
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
|
||||
err = u.Unwrap()
|
||||
}
|
||||
if sterr == nil {
|
||||
sterr, ok := err.(stackTracer)
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
|
||||
st := sterr.StackTrace()
|
||||
s := &state{}
|
||||
out := make([]map[string]string, 0, len(st))
|
||||
|
|
|
@ -4,50 +4,49 @@ package pkgerrors
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"testing"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"tuxpa.in/a/zlog"
|
||||
"github.com/rs/zerolog"
|
||||
)
|
||||
|
||||
func TestLogStack(t *testing.T) {
|
||||
zlog.ErrorStackMarshaler = MarshalStack
|
||||
zerolog.ErrorStackMarshaler = MarshalStack
|
||||
|
||||
out := &bytes.Buffer{}
|
||||
log := zlog.New(out)
|
||||
log := zerolog.New(out)
|
||||
|
||||
err := fmt.Errorf("from error: %w", errors.New("error message"))
|
||||
err := errors.Wrap(errors.New("error message"), "from error")
|
||||
log.Log().Stack().Err(err).Msg("")
|
||||
|
||||
got := out.String()
|
||||
want := `\{"stack":\[\{"func":"TestLogStack","line":"21","source":"stacktrace_test.go"\},.*\],"error":"from error: error message"\}\n`
|
||||
want := `\{"stack":\[\{"func":"TestLogStack","line":"20","source":"stacktrace_test.go"\},.*\],"error":"from error: error message"\}\n`
|
||||
if ok, _ := regexp.MatchString(want, got); !ok {
|
||||
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLogStackFromContext(t *testing.T) {
|
||||
zlog.ErrorStackMarshaler = MarshalStack
|
||||
zerolog.ErrorStackMarshaler = MarshalStack
|
||||
|
||||
out := &bytes.Buffer{}
|
||||
log := zlog.New(out).With().Stack().Logger() // calling Stack() on log context instead of event
|
||||
log := zerolog.New(out).With().Stack().Logger() // calling Stack() on log context instead of event
|
||||
|
||||
err := fmt.Errorf("from error: %w", errors.New("error message"))
|
||||
err := errors.Wrap(errors.New("error message"), "from error")
|
||||
log.Log().Err(err).Msg("") // not explicitly calling Stack()
|
||||
|
||||
got := out.String()
|
||||
want := `\{"stack":\[\{"func":"TestLogStackFromContext","line":"37","source":"stacktrace_test.go"\},.*\],"error":"from error: error message"\}\n`
|
||||
want := `\{"stack":\[\{"func":"TestLogStackFromContext","line":"36","source":"stacktrace_test.go"\},.*\],"error":"from error: error message"\}\n`
|
||||
if ok, _ := regexp.MatchString(want, got); !ok {
|
||||
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkLogStack(b *testing.B) {
|
||||
zlog.ErrorStackMarshaler = MarshalStack
|
||||
zerolog.ErrorStackMarshaler = MarshalStack
|
||||
out := &bytes.Buffer{}
|
||||
log := zlog.New(out)
|
||||
log := zerolog.New(out)
|
||||
err := errors.Wrap(errors.New("error message"), "from error")
|
||||
b.ReportAllocs()
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package zlog
|
||||
package zerolog
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// +build !binary_log
|
||||
|
||||
package zlog
|
||||
package zerolog
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// +build !windows
|
||||
// +build !binary_log
|
||||
|
||||
package zlog
|
||||
package zerolog
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
@ -28,7 +28,7 @@ type syslogWriter struct {
|
|||
}
|
||||
|
||||
// SyslogLevelWriter wraps a SyslogWriter and call the right syslog level
|
||||
// method matching the zlog level.
|
||||
// method matching the zerolog level.
|
||||
func SyslogLevelWriter(w SyslogWriter) LevelWriter {
|
||||
return syslogWriter{w, ""}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// +build !binary_log
|
||||
// +build !windows
|
||||
|
||||
package zlog
|
||||
package zerolog
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
//go:build !binary_log && !windows
|
||||
// +build !binary_log,!windows
|
||||
|
||||
package zlog
|
||||
package zerolog
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
|
Loading…
Reference in New Issue