Skip to content

Commit

Permalink
Merge branch 'override-time' of git://github.com/sbrisson2/logrus int…
Browse files Browse the repository at this point in the history
…o sbrisson2-override-time
  • Loading branch information
dgsb committed Jul 12, 2018
2 parents e54a777 + 725f3be commit 9205268
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 2 deletions.
18 changes: 16 additions & 2 deletions entry.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,14 +83,28 @@ func (entry *Entry) WithFields(fields Fields) *Entry {
for k, v := range fields {
data[k] = v
}
return &Entry{Logger: entry.Logger, Data: data}
return &Entry{Logger: entry.Logger, Data: data, Time: entry.Time}
}

// Overrides the time of the Entry.
func (entry *Entry) WithTime(t time.Time) *Entry {
return &Entry{Logger: entry.Logger, Data: entry.Data, Time: t}
}

// This function is not declared with a pointer value because otherwise
// race conditions will occur when using multiple goroutines
func (entry Entry) log(level Level, msg string) {
var buffer *bytes.Buffer
entry.Time = time.Now()

// Default to now, but allow users to override if they want.
//
// We don't have to worry about polluting future calls to Entry#log()
// with this assignment because this function is declared with a
// non-pointer receiver.
if entry.Time.IsZero() {
entry.Time = time.Now()
}

entry.Level = level
entry.Message = msg

Expand Down
10 changes: 10 additions & 0 deletions exported.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package logrus

import (
"io"
"time"
)

var (
Expand Down Expand Up @@ -70,6 +71,15 @@ func WithFields(fields Fields) *Entry {
return std.WithFields(fields)
}

// WithTime creats an entry from the standard logger and overrides the time of
// logs generated with it.
//
// Note that it doesn't log until you call Debug, Print, Info, Warn, Fatal
// or Panic on the Entry it returns.
func WithTime(t time.Time) *Entry {
return std.WithTime(t)
}

// Debug logs a message at level Debug on the standard logger.
func Debug(args ...interface{}) {
std.Debug(args...)
Expand Down
8 changes: 8 additions & 0 deletions logger.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"os"
"sync"
"sync/atomic"
"time"
)

type Logger struct {
Expand Down Expand Up @@ -112,6 +113,13 @@ func (logger *Logger) WithError(err error) *Entry {
return entry.WithError(err)
}

// Overrides the time of the log entry.
func (logger *Logger) WithTime(t time.Time) *Entry {
entry := logger.newEntry()
defer logger.releaseEntry(entry)
return entry.WithTime(t)
}

func (logger *Logger) Debugf(format string, args ...interface{}) {
if logger.level() >= DebugLevel {
entry := logger.newEntry()
Expand Down
60 changes: 60 additions & 0 deletions logrus_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"strings"
"sync"
"testing"
"time"

"github.com/stretchr/testify/assert"
)
Expand Down Expand Up @@ -209,6 +210,65 @@ func TestDefaultFieldsAreNotPrefixed(t *testing.T) {
})
}

func TestWithTimeShouldOverrideTime(t *testing.T) {
now := time.Now().Add(24 * time.Hour)

LogAndAssertJSON(t, func(log *Logger) {
log.WithTime(now).Info("foobar")
}, func(fields Fields) {
assert.Equal(t, fields["time"], now.Format(defaultTimestampFormat))
})
}

func TestWithTimeShouldNotOverrideFields(t *testing.T) {
now := time.Now().Add(24 * time.Hour)

LogAndAssertJSON(t, func(log *Logger) {
log.WithField("herp", "derp").WithTime(now).Info("blah")
}, func(fields Fields) {
assert.Equal(t, fields["time"], now.Format(defaultTimestampFormat))
assert.Equal(t, fields["herp"], "derp")
})
}

func TestWithFieldShouldNotOverrideTime(t *testing.T) {
now := time.Now().Add(24 * time.Hour)

LogAndAssertJSON(t, func(log *Logger) {
log.WithTime(now).WithField("herp", "derp").Info("blah")
}, func(fields Fields) {
assert.Equal(t, fields["time"], now.Format(defaultTimestampFormat))
assert.Equal(t, fields["herp"], "derp")
})
}

func TestTimeOverrideMultipleLogs(t *testing.T) {
var buffer bytes.Buffer
var firstFields, secondFields Fields

logger := New()
logger.Out = &buffer
formatter := new(JSONFormatter)
formatter.TimestampFormat = time.StampMilli
logger.Formatter = formatter

llog := logger.WithField("herp", "derp")
llog.Info("foo")

err := json.Unmarshal(buffer.Bytes(), &firstFields)
assert.NoError(t, err, "should have decoded first message")

buffer.Reset()

time.Sleep(10 * time.Millisecond)
llog.Info("bar")

err = json.Unmarshal(buffer.Bytes(), &secondFields)
assert.NoError(t, err, "should have decoded second message")

assert.NotEqual(t, firstFields["time"], secondFields["time"], "timestamps should not be equal")
}

func TestDoubleLoggingDoesntPrefixPreviousFields(t *testing.T) {

var buffer bytes.Buffer
Expand Down

0 comments on commit 9205268

Please sign in to comment.