Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit bc4df5b

Browse files
Merge pull request go-kit#514 from go-kit/defer-time-format
log: Add TimestampFormat and Timeformat.
2 parents b3c024f + 584a942 commit bc4df5b

File tree

2 files changed

+88
-11
lines changed

2 files changed

+88
-11
lines changed

‎log/value.go‎

Lines changed: 47 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,52 @@ func containsValuer(keyvals []interface{}) bool {
3232
return false
3333
}
3434

35-
// Timestamp returns a Valuer that invokes the underlying function when bound,
36-
// returning a time.Time. Users will probably want to use DefaultTimestamp or
37-
// DefaultTimestampUTC.
35+
// Timestamp returns a timestamp Valuer. It invokes the t function to get the
36+
// time; unless you are doing something tricky, pass time.Now.
37+
//
38+
// Most users will want to use DefaultTimestamp or DefaultTimestampUTC, which
39+
// are TimestampFormats that use the RFC3339Nano format.
3840
func Timestamp(t func() time.Time) Valuer {
3941
return func() interface{} { return t() }
4042
}
4143

44+
// TimestampFormat returns a timestamp Valuer with a custom time format. It
45+
// invokes the t function to get the time to format; unless you are doing
46+
// something tricky, pass time.Now. The layout string is passed to
47+
// Time.Format.
48+
//
49+
// Most users will want to use DefaultTimestamp or DefaultTimestampUTC, which
50+
// are TimestampFormats that use the RFC3339Nano format.
51+
func TimestampFormat(t func() time.Time, layout string) Valuer {
52+
return func() interface{} {
53+
return timeFormat{
54+
time: t(),
55+
layout: layout,
56+
}
57+
}
58+
}
59+
60+
// A timeFormat represents an instant in time and a layout used when
61+
// marshaling to a text format.
62+
type timeFormat struct {
63+
time time.Time
64+
layout string
65+
}
66+
67+
func (tf timeFormat) String() string {
68+
return tf.time.Format(tf.layout)
69+
}
70+
71+
// MarshalText implements encoding.TextMarshaller.
72+
func (tf timeFormat) MarshalText() (text []byte, err error) {
73+
// The following code adapted from the standard library time.Time.Format
74+
// method. Using the same undocumented magic constant to extend the size
75+
// of the buffer as seen there.
76+
b := make([]byte, 0, len(tf.layout)+10)
77+
b = tf.time.AppendFormat(b, tf.layout)
78+
return b, nil
79+
}
80+
4281
// Caller returns a Valuer that returns a file and line from a specified depth
4382
// in the callstack. Users will probably want to use DefaultCaller.
4483
func Caller(depth int) Valuer {
@@ -48,15 +87,14 @@ func Caller(depth int) Valuer {
4887
var (
4988
// DefaultTimestamp is a Valuer that returns the current wallclock time,
5089
// respecting time zones, when bound.
51-
DefaultTimestamp = Valuer(func() interface{} {
52-
return time.Now().Format(time.RFC3339Nano)
53-
})
90+
DefaultTimestamp = TimestampFormat(time.Now, time.RFC3339Nano)
5491

5592
// DefaultTimestampUTC is a Valuer that returns the current time in UTC
5693
// when bound.
57-
DefaultTimestampUTC = Valuer(func() interface{} {
58-
return time.Now().UTC().Format(time.RFC3339Nano)
59-
})
94+
DefaultTimestampUTC = TimestampFormat(
95+
func() time.Time { return time.Now().UTC() },
96+
time.RFC3339Nano,
97+
)
6098

6199
// DefaultCaller is a Valuer that returns the file and line where the Log
62100
// method was invoked. It can only be used with log.With.

‎log/value_test.go‎

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
package log_test
22

33
import (
4+
"encoding"
45
"fmt"
6+
"reflect"
57
"testing"
68
"time"
79

@@ -34,7 +36,7 @@ func TestValueBinding(t *testing.T) {
3436
if want, have := start.Add(time.Second), timestamp; want != have {
3537
t.Errorf("output[1]: want %v, have %v", want, have)
3638
}
37-
if want, have := "value_test.go:29", fmt.Sprint(output[3]); want != have {
39+
if want, have := "value_test.go:31", fmt.Sprint(output[3]); want != have {
3840
t.Errorf("output[3]: want %s, have %s", want, have)
3941
}
4042

@@ -47,7 +49,7 @@ func TestValueBinding(t *testing.T) {
4749
if want, have := start.Add(2*time.Second), timestamp; want != have {
4850
t.Errorf("output[1]: want %v, have %v", want, have)
4951
}
50-
if want, have := "value_test.go:42", fmt.Sprint(output[3]); want != have {
52+
if want, have := "value_test.go:44", fmt.Sprint(output[3]); want != have {
5153
t.Errorf("output[3]: want %s, have %s", want, have)
5254
}
5355
}
@@ -90,6 +92,43 @@ func TestValueBinding_loggingZeroKeyvals(t *testing.T) {
9092
}
9193
}
9294

95+
func TestTimestampFormat(t *testing.T) {
96+
t.Parallel()
97+
98+
start := time.Date(2015, time.April, 25, 0, 0, 0, 0, time.UTC)
99+
now := start
100+
mocktime := func() time.Time {
101+
now = now.Add(time.Second)
102+
return now
103+
}
104+
105+
tv := log.TimestampFormat(mocktime, time.RFC822)
106+
107+
if want, have := now.Add(time.Second).Format(time.RFC822), fmt.Sprint(tv()); want != have {
108+
t.Errorf("wrong time format: want %v, have %v", want, have)
109+
}
110+
111+
if want, have := now.Add(2*time.Second).Format(time.RFC822), fmt.Sprint(tv()); want != have {
112+
t.Errorf("wrong time format: want %v, have %v", want, have)
113+
}
114+
115+
mustMarshal := func(v interface{}) []byte {
116+
b, err := v.(encoding.TextMarshaler).MarshalText()
117+
if err != nil {
118+
t.Fatal("error marshaling text:", err)
119+
}
120+
return b
121+
}
122+
123+
if want, have := now.Add(3*time.Second).AppendFormat(nil, time.RFC822), mustMarshal(tv()); !reflect.DeepEqual(want, have) {
124+
t.Errorf("wrong time format: want %s, have %s", want, have)
125+
}
126+
127+
if want, have := now.Add(4*time.Second).AppendFormat(nil, time.RFC822), mustMarshal(tv()); !reflect.DeepEqual(want, have) {
128+
t.Errorf("wrong time format: want %s, have %s", want, have)
129+
}
130+
}
131+
93132
func BenchmarkValueBindingTimestamp(b *testing.B) {
94133
logger := log.NewNopLogger()
95134
lc := log.With(logger, "ts", log.DefaultTimestamp)

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /