6 "github.com/go-stack/stack"
9 // A Valuer generates a log value. When passed to With or WithPrefix in a
10 // value element (odd indexes), it represents a dynamic value which is re-
11 // evaluated with each log event.
12 type Valuer func() interface{}
14 // bindValues replaces all value elements (odd indexes) containing a Valuer
15 // with their generated value.
16 func bindValues(keyvals []interface{}) {
17 for i := 1; i < len(keyvals); i += 2 {
18 if v, ok := keyvals[i].(Valuer); ok {
24 // containsValuer returns true if any of the value elements (odd indexes)
26 func containsValuer(keyvals []interface{}) bool {
27 for i := 1; i < len(keyvals); i += 2 {
28 if _, ok := keyvals[i].(Valuer); ok {
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.
38 // Most users will want to use DefaultTimestamp or DefaultTimestampUTC, which
39 // are TimestampFormats that use the RFC3339Nano format.
40 func Timestamp(t func() time.Time) Valuer {
41 return func() interface{} { return t() }
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
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{} {
60 // A timeFormat represents an instant in time and a layout used when
61 // marshaling to a text format.
62 type timeFormat struct {
67 func (tf timeFormat) String() string {
68 return tf.time.Format(tf.layout)
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)
81 // Caller returns a Valuer that returns a file and line from a specified depth
82 // in the callstack. Users will probably want to use DefaultCaller.
83 func Caller(depth int) Valuer {
84 return func() interface{} { return stack.Caller(depth) }
88 // DefaultTimestamp is a Valuer that returns the current wallclock time,
89 // respecting time zones, when bound.
90 DefaultTimestamp = TimestampFormat(time.Now, time.RFC3339Nano)
92 // DefaultTimestampUTC is a Valuer that returns the current time in UTC
94 DefaultTimestampUTC = TimestampFormat(
95 func() time.Time { return time.Now().UTC() },
99 // DefaultCaller is a Valuer that returns the file and line where the Log
100 // method was invoked. It can only be used with log.With.
101 DefaultCaller = Caller(3)