Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 12 additions & 8 deletions entry.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,6 @@ import (
"time"
)

// assert interface compliance.
var _ Interface = (*Entry)(nil)

// Now returns the current time.
var Now = time.Now

Expand All @@ -32,7 +29,14 @@ func NewEntry(log *Logger) *Entry {
}

// WithFields returns a new entry with `fields` set.
func (e *Entry) WithFields(fields Fielder) *Entry {
func (e *Entry) WithFields(fields Fielder) Interface {
return e.withFields(fields)
}

// withFields returns a new entry with `fields` set.
// but to satify the interface WithFields casts *Entry
// back into `Interface`
func (e *Entry) withFields(fields Fielder) *Entry {
f := []Fields{}
f = append(f, e.fields...)
f = append(f, fields.Fields())
Expand All @@ -43,15 +47,15 @@ func (e *Entry) WithFields(fields Fielder) *Entry {
}

// WithField returns a new entry with the `key` and `value` set.
func (e *Entry) WithField(key string, value interface{}) *Entry {
func (e *Entry) WithField(key string, value interface{}) Interface {
return e.WithFields(Fields{key: value})
}

// WithError returns a new entry with the "error" set to `err`.
//
// The given error may implement .Fielder, if it does the method
// will add all its `.Fields()` into the returned entry.
func (e *Entry) WithError(err error) *Entry {
func (e *Entry) WithError(err error) Interface {
ctx := e.WithField("error", err.Error())

if s, ok := err.(stackTracer); ok {
Expand Down Expand Up @@ -129,9 +133,9 @@ func (e *Entry) Fatalf(msg string, v ...interface{}) {

// Trace returns a new entry with a Stop method to fire off
// a corresponding completion log, useful with defer.
func (e *Entry) Trace(msg string) *Entry {
func (e *Entry) Trace(msg string) Interface {
e.Info(msg)
v := e.WithFields(e.Fields)
v := e.withFields(e.Fields)
v.Message = msg
v.start = time.Now()
return v
Expand Down
10 changes: 5 additions & 5 deletions entry_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ func TestEntry_WithFields(t *testing.T) {

b := a.WithFields(Fields{"foo": "bar"})
assert.Equal(t, Fields{}, a.mergedFields())
assert.Equal(t, Fields{"foo": "bar"}, b.mergedFields())
assert.Equal(t, Fields{"foo": "bar"}, b.(*Entry).mergedFields())

c := a.WithFields(Fields{"foo": "hello", "bar": "world"})
c := a.WithFields(Fields{"foo": "hello", "bar": "world"}).(*Entry)

e := c.finalize(InfoLevel, "upload")
assert.Equal(t, e.Message, "upload")
Expand All @@ -28,19 +28,19 @@ func TestEntry_WithField(t *testing.T) {
a := NewEntry(nil)
b := a.WithField("foo", "bar")
assert.Equal(t, Fields{}, a.mergedFields())
assert.Equal(t, Fields{"foo": "bar"}, b.mergedFields())
assert.Equal(t, Fields{"foo": "bar"}, b.(*Entry).mergedFields())
}

func TestEntry_WithError(t *testing.T) {
a := NewEntry(nil)
b := a.WithError(fmt.Errorf("boom"))
assert.Equal(t, Fields{}, a.mergedFields())
assert.Equal(t, Fields{"error": "boom"}, b.mergedFields())
assert.Equal(t, Fields{"error": "boom"}, b.(*Entry).mergedFields())
}

func TestEntry_WithErrorFields(t *testing.T) {
a := NewEntry(nil)
b := a.WithError(errFields("boom"))
b := a.WithError(errFields("boom")).(*Entry)
assert.Equal(t, Fields{}, a.mergedFields())
assert.Equal(t, Fields{
"error": "boom",
Expand Down
16 changes: 12 additions & 4 deletions interface.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,18 @@
package log

// Fields represents a map of entry level data used for structured logging.
type Fields map[string]interface{}

// Fielder is an interface for providing fields to custom types.
type Fielder interface {
Fields() Fields
}

// Interface represents the API of both Logger and Entry.
type Interface interface {
WithFields(fields Fielder) *Entry
WithField(key string, value interface{}) *Entry
WithError(err error) *Entry
WithFields(fields Fielder) Interface
WithField(key string, value interface{}) Interface
WithError(err error) Interface
Debug(msg string)
Info(msg string)
Warn(msg string)
Expand All @@ -15,5 +23,5 @@ type Interface interface {
Warnf(msg string, v ...interface{})
Errorf(msg string, v ...interface{})
Fatalf(msg string, v ...interface{})
Trace(msg string) *Entry
Trace(msg string) Interface
}
19 changes: 5 additions & 14 deletions logger.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,7 @@ import (
"sort"
)

// assert interface compliance.
var _ Interface = (*Logger)(nil)

// Fielder is an interface for providing fields to custom types.
type Fielder interface {
Fields() Fields
}

// Fields represents a map of entry level data used for structured logging.
type Fields map[string]interface{}
// note: Fields is defined in `interface.go`

// Fields implements Fielder.
func (f Fields) Fields() Fields {
Expand Down Expand Up @@ -62,20 +53,20 @@ type Logger struct {
}

// WithFields returns a new entry with `fields` set.
func (l *Logger) WithFields(fields Fielder) *Entry {
func (l *Logger) WithFields(fields Fielder) Interface {
return NewEntry(l).WithFields(fields.Fields())
}

// WithField returns a new entry with the `key` and `value` set.
//
// Note that the `key` should not have spaces in it - use camel
// case or underscores
func (l *Logger) WithField(key string, value interface{}) *Entry {
func (l *Logger) WithField(key string, value interface{}) Interface {
return NewEntry(l).WithField(key, value)
}

// WithError returns a new entry with the "error" set to `err`.
func (l *Logger) WithError(err error) *Entry {
func (l *Logger) WithError(err error) Interface {
return NewEntry(l).WithError(err)
}

Expand Down Expand Up @@ -131,7 +122,7 @@ func (l *Logger) Fatalf(msg string, v ...interface{}) {

// Trace returns a new entry with a Stop method to fire off
// a corresponding completion log, useful with defer.
func (l *Logger) Trace(msg string) *Entry {
func (l *Logger) Trace(msg string) Interface {
return NewEntry(l).Trace(msg)
}

Expand Down
20 changes: 10 additions & 10 deletions logger_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ func TestLogger_Trace_info(t *testing.T) {
}

func() (err error) {
defer l.WithField("file", "sloth.png").Trace("upload").Stop(&err)
defer l.WithField("file", "sloth.png").Trace("upload").(*log.Entry).Stop(&err)
return nil
}()

Expand Down Expand Up @@ -124,7 +124,7 @@ func TestLogger_Trace_error(t *testing.T) {
}

func() (err error) {
defer l.WithField("file", "sloth.png").Trace("upload").Stop(&err)
defer l.WithField("file", "sloth.png").Trace("upload").(*log.Entry).Stop(&err)
return fmt.Errorf("boom")
}()

Expand Down Expand Up @@ -156,7 +156,7 @@ func TestLogger_Trace_nil(t *testing.T) {
}

func() {
defer l.WithField("file", "sloth.png").Trace("upload").Stop(nil)
defer l.WithField("file", "sloth.png").Trace("upload").(*log.Entry).Stop(nil)
}()

assert.Equal(t, 2, len(h.Entries))
Expand Down Expand Up @@ -236,13 +236,13 @@ func BenchmarkLogger_large(b *testing.B) {
"size": 1 << 20,
}).
WithFields(log.Fields{
"some": "more",
"data": "here",
"whatever": "blah blah",
"more": "stuff",
"context": "such useful",
"much": "fun",
}).
"some": "more",
"data": "here",
"whatever": "blah blah",
"more": "stuff",
"context": "such useful",
"much": "fun",
}).
WithError(err).Error("upload failed")
}
}
8 changes: 4 additions & 4 deletions pkg.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,17 +29,17 @@ func SetLevelFromString(s string) {
}

// WithFields returns a new entry with `fields` set.
func WithFields(fields Fielder) *Entry {
func WithFields(fields Fielder) Interface {
return Log.WithFields(fields)
}

// WithField returns a new entry with the `key` and `value` set.
func WithField(key string, value interface{}) *Entry {
func WithField(key string, value interface{}) Interface {
return Log.WithField(key, value)
}

// WithError returns a new entry with the "error" set to `err`.
func WithError(err error) *Entry {
func WithError(err error) Interface {
return Log.WithError(err)
}

Expand Down Expand Up @@ -95,6 +95,6 @@ func Fatalf(msg string, v ...interface{}) {

// Trace returns a new entry with a Stop method to fire off
// a corresponding completion log, useful with defer.
func Trace(msg string) *Entry {
func Trace(msg string) Interface {
return Log.Trace(msg)
}
2 changes: 1 addition & 1 deletion pkg_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,6 @@ func Example_multipleFields() {
// Trace can be used to simplify logging of start and completion events,
// for example an upload which may fail.
func Example_trace() (err error) {
defer log.Trace("upload").Stop(&err)
defer log.Trace("upload").(*log.Entry).Stop(&err)
return nil
}