Skip to content

Commit

Permalink
feat: major refactor (#17)
Browse files Browse the repository at this point in the history
  • Loading branch information
nrwiersma authored May 14, 2021
1 parent e3e4141 commit 40611a8
Show file tree
Hide file tree
Showing 21 changed files with 1,073 additions and 1,164 deletions.
2 changes: 0 additions & 2 deletions .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,9 @@ run:
linters:
enable-all: true
disable:
- cyclop
- exhaustive
- exhaustivestruct
- forcetypeassert
- funlen
- gochecknoglobals
- gochecknoinits
- gocognit
Expand Down
1 change: 0 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ sudo: false

language: go
go:
- "1.15.x"
- "1.16.x"
- "1.x"

Expand Down
22 changes: 7 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,34 +23,26 @@ go get github.com/hamba/logger
* **Logfmt**
* **Console**

#### Handlers
#### Writers

* **StreamHandler** Write directly to a Writer, usually `os.Stdout`
* **BufferedStreamHandler** A buffered version of `StreamHandler`
* **FilterHandler** Filter log line using a function
* **LevelFilterHandler** Filter log line by level
* **DiscardHandler** Discard everything
* **SyncWriter** Write synchronised to a Writer

## Examples

```go
// Composable handlers
h := logger.LevelFilterHandler(
logger.Info,
logger.StreamHandler(os.Stdout, logger.LogfmtFormat()),
)
log := logger.New(os.Stdout, logger.LogfmtFormat(), logger.Info)

// The logger can have an initial context
l := logger.New(h, "env", "prod")
// Logger can have scoped context
log = log.With(ctx.Str("env", "prod"))

// All messages can have a context
l.Warn("connection error", "redis", conn.Name(), "timeout", conn.Timeout())
log.Warn("connection error", ctx.Str("redis", "dsn_1"), ctx.Int("timeout", conn.Timeout()))
```

Will log the message

```
lvl=warn msg="connection error" redis=dsn_1 timeout=0.500
lvl=warn msg="connection error" env=prod redis=dsn_1 timeout=0.500
```

More examples can be found in the [godocs](https://godoc.org/github.com/hamba/logger).
95 changes: 52 additions & 43 deletions bench_test.go
Original file line number Diff line number Diff line change
@@ -1,77 +1,86 @@
package logger_test

import (
"io/ioutil"
"io"
"os"
"testing"

"github.com/hamba/logger"
"github.com/hamba/logger/ctx"
)

func BenchmarkLogged_Logfmt(b *testing.B) {
l := logger.New(logger.StreamHandler(ioutil.Discard, logger.LogfmtFormat()))
func BenchmarkLogger_Logfmt(b *testing.B) {
log := logger.New(io.Discard, logger.LogfmtFormat(), logger.Debug)

b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
l.Error("some message")
}
b.StopTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
log.Error("some message")
}
})
}

func BenchmarkLogged_Json(b *testing.B) {
l := logger.New(logger.StreamHandler(ioutil.Discard, logger.JSONFormat()))
func BenchmarkLogger_Json(b *testing.B) {
log := logger.New(io.Discard, logger.JSONFormat(), logger.Debug)

b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
l.Error("some message")
}
b.StopTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
log.Error("some message")
}
})
}

func BenchmarkLogged_LogfmtCtx(b *testing.B) {
l := logger.New(logger.StreamHandler(ioutil.Discard, logger.LogfmtFormat()), "_n", "bench", "_p", 1)
func BenchmarkLogger_LogfmtCtx(b *testing.B) {
log := logger.New(io.Discard, logger.LogfmtFormat(), logger.Debug).With(ctx.Str("_n", "bench"), ctx.Int("_p", 1))

b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
l.Error("some message", "key", 1, "key2", 3.141592, "key3", "string", "key4", false)
}
b.StopTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
log.Error("some message", ctx.Int("key", 1), ctx.Float64("key2", 3.141592), ctx.Str("key3", "string"), ctx.Bool("key4", false))
}
})
}

func BenchmarkLogged_JsonCtx(b *testing.B) {
l := logger.New(logger.StreamHandler(ioutil.Discard, logger.JSONFormat()), "_n", "bench", "_p", 1)
func BenchmarkLogger_JsonCtx(b *testing.B) {
log := logger.New(io.Discard, logger.JSONFormat(), logger.Debug).With(ctx.Str("_n", "bench"), ctx.Int("_p", 1))

b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
l.Error("some message", "key", 1, "key2", 3.141592, "key3", "string", "key4", false)
}
b.StopTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
log.Error("some message", ctx.Int("key", 1), ctx.Float64("key2", 3.141592), ctx.Str("key3", "string"), ctx.Bool("key4", false))
}
})
}

func BenchmarkLevelLogged_Logfmt(b *testing.B) {
func BenchmarkLevelLogger_Logfmt(b *testing.B) {
log := logger.New(io.Discard, logger.LogfmtFormat(), logger.Debug).With(ctx.Str("_n", "bench"), ctx.Int("_p", os.Getpid()))

b.ResetTimer()
l := logger.New(logger.StreamHandler(ioutil.Discard, logger.LogfmtFormat()), "_n", "bench", "_p", os.Getpid())
for i := 0; i < b.N; i++ {
l.Debug("debug", "key", 1, "key2", 3.141592, "key3", "string", "key4", false)
l.Info("info", "key", 1, "key2", 3.141592, "key3", "string", "key4", false)
l.Warn("warn", "key", 1, "key2", 3.141592, "key3", "string", "key4", false)
l.Error("error", "key", 1, "key2", 3.141592, "key3", "string", "key4", false)
}
b.StopTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
log.Debug("debug", ctx.Int("key", 1), ctx.Float64("key2", 3.141592), ctx.Str("key3", "string"), ctx.Bool("key4", false))
log.Info("info", ctx.Int("key", 1), ctx.Float64("key2", 3.141592), ctx.Str("key3", "string"), ctx.Bool("key4", false))
log.Warn("warn", ctx.Int("key", 1), ctx.Float64("key2", 3.141592), ctx.Str("key3", "string"), ctx.Bool("key4", false))
log.Error("error", ctx.Int("key", 1), ctx.Float64("key2", 3.141592), ctx.Str("key3", "string"), ctx.Bool("key4", false))
}
})
}

func BenchmarkLevelLogged_Json(b *testing.B) {
func BenchmarkLevelLogger_Json(b *testing.B) {
log := logger.New(io.Discard, logger.LogfmtFormat(), logger.Debug).With(ctx.Str("_n", "bench"), ctx.Int("_p", os.Getpid()))

b.ResetTimer()
l := logger.New(logger.StreamHandler(ioutil.Discard, logger.JSONFormat()), "_n", "bench", "_p", os.Getpid())
for i := 0; i < b.N; i++ {
l.Debug("debug", "key", 1, "key2", 3.141592, "key3", "string", "key4", false)
l.Info("info", "key", 1, "key2", 3.141592, "key3", "string", "key4", false)
l.Warn("warn", "key", 1, "key2", 3.141592, "key3", "string", "key4", false)
l.Error("error", "key", 1, "key2", 3.141592, "key3", "string", "key4", false)
}
b.StopTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
log.Debug("debug", ctx.Int("key", 1), ctx.Float64("key2", 3.141592), ctx.Str("key3", "string"), ctx.Bool("key4", false))
log.Info("info", ctx.Int("key", 1), ctx.Float64("key2", 3.141592), ctx.Str("key3", "string"), ctx.Bool("key4", false))
log.Warn("warn", ctx.Int("key", 1), ctx.Float64("key2", 3.141592), ctx.Str("key3", "string"), ctx.Bool("key4", false))
log.Error("error", ctx.Int("key", 1), ctx.Float64("key2", 3.141592), ctx.Str("key3", "string"), ctx.Bool("key4", false))
}
})
}
154 changes: 154 additions & 0 deletions ctx/ctx.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
package ctx

import (
"time"

"github.com/hamba/logger"
)

// Str returns a string context field.
func Str(k, s string) logger.Field {
return func(e *logger.Event) {
e.AppendString(k, s)
}
}

// Strs returns a string slice context field.
func Strs(k string, s []string) logger.Field {
return func(e *logger.Event) {
e.AppendStrings(k, s)
}
}

// Bytes returns a byte slice context field.
func Bytes(k string, p []byte) logger.Field {
return func(e *logger.Event) {
e.AppendBytes(k, p)
}
}

// Bool returns a boolean context field.
func Bool(k string, b bool) logger.Field {
return func(e *logger.Event) {
e.AppendBool(k, b)
}
}

// Int returns an int context field.
func Int(k string, i int) logger.Field {
return func(e *logger.Event) {
e.AppendInt(k, int64(i))
}
}

// Ints returns an int slice context field.
func Ints(k string, a []int) logger.Field {
return func(e *logger.Event) {
e.AppendInts(k, a)
}
}

// Int8 returns an int8 context field.
func Int8(k string, i int8) logger.Field {
return func(e *logger.Event) {
e.AppendInt(k, int64(i))
}
}

// Int16 returns an int16 context field.
func Int16(k string, i int16) logger.Field {
return func(e *logger.Event) {
e.AppendInt(k, int64(i))
}
}

// Int32 returns an int32 context field.
func Int32(k string, i int32) logger.Field {
return func(e *logger.Event) {
e.AppendInt(k, int64(i))
}
}

// Int64 returns an int64 context field.
func Int64(k string, i int64) logger.Field {
return func(e *logger.Event) {
e.AppendInt(k, i)
}
}

// Uint returns a uint context field.
func Uint(k string, i uint) logger.Field {
return func(e *logger.Event) {
e.AppendUint(k, uint64(i))
}
}

// Uint8 returns a uint8 context field.
func Uint8(k string, i uint8) logger.Field {
return func(e *logger.Event) {
e.AppendUint(k, uint64(i))
}
}

// Uint16 returns a uint16 context field.
func Uint16(k string, i uint16) logger.Field {
return func(e *logger.Event) {
e.AppendUint(k, uint64(i))
}
}

// Uint32 returns a uint32 context field.
func Uint32(k string, i uint32) logger.Field {
return func(e *logger.Event) {
e.AppendUint(k, uint64(i))
}
}

// Uint64 returns a uint64 context field.
func Uint64(k string, i uint64) logger.Field {
return func(e *logger.Event) {
e.AppendUint(k, i)
}
}

// Float32 returns a float32 context field.
func Float32(k string, f float32) logger.Field {
return func(e *logger.Event) {
e.AppendFloat(k, float64(f))
}
}

// Float64 returns a float64 context field.
func Float64(k string, f float64) logger.Field {
return func(e *logger.Event) {
e.AppendFloat(k, f)
}
}

// Error returns an error context field.
func Error(k string, err error) logger.Field {
return func(e *logger.Event) {
e.AppendString(k, err.Error())
}
}

// Time returns a time context field.
func Time(k string, t time.Time) logger.Field {
return func(e *logger.Event) {
e.AppendTime(k, t)
}
}

// Duration returns a duration context field.
func Duration(k string, d time.Duration) logger.Field {
return func(e *logger.Event) {
e.AppendDuration(k, d)
}
}

// Interface returns an interface context field.
func Interface(k string, v interface{}) logger.Field {
return func(e *logger.Event) {
e.AppendInterface(k, v)
}
}
14 changes: 4 additions & 10 deletions doc.go
Original file line number Diff line number Diff line change
@@ -1,19 +1,13 @@
/*
Package logger implements a logging package.
logger implements github.com/hamba/pkg Logger interface.
Example usage:
// Composable handlers
h := logger.LevelFilterHandler(
logger.Info,
logger.StreamHandler(os.Stdout, logger.LogfmtFormat()),
)
log := logger.New(os.Stdout, logger.LogfmtFormat(), logger.Info)
// The logger can have an initial context
l := logger.New(h, "env", "prod")
// Logger can have scoped context
log = log.With(ctx.Str("env", "prod"))
// All messages can have a context
l.Error("connection error", "redis", conn.Name(), "timeout", conn.Timeout())
log.Error("connection error", ctx.Str("redis", conn.Name()), ctx.Int("timeout", conn.Timeout()))
*/
package logger
Loading

0 comments on commit 40611a8

Please sign in to comment.