mirror of
https://github.com/VictoriaMetrics/VictoriaMetrics.git
synced 2024-12-22 16:36:27 +01:00
d5c180e680
It is better developing vmctl tool in VictoriaMetrics repository, so it could be released together with the rest of vmutils tools such as vmalert, vmagent, vmbackup, vmrestore and vmauth.
111 lines
3.3 KiB
Go
111 lines
3.3 KiB
Go
package log
|
|
|
|
import (
|
|
"runtime"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
// A Valuer generates a log value. When passed to With or WithPrefix in a
|
|
// value element (odd indexes), it represents a dynamic value which is re-
|
|
// evaluated with each log event.
|
|
type Valuer func() interface{}
|
|
|
|
// bindValues replaces all value elements (odd indexes) containing a Valuer
|
|
// with their generated value.
|
|
func bindValues(keyvals []interface{}) {
|
|
for i := 1; i < len(keyvals); i += 2 {
|
|
if v, ok := keyvals[i].(Valuer); ok {
|
|
keyvals[i] = v()
|
|
}
|
|
}
|
|
}
|
|
|
|
// containsValuer returns true if any of the value elements (odd indexes)
|
|
// contain a Valuer.
|
|
func containsValuer(keyvals []interface{}) bool {
|
|
for i := 1; i < len(keyvals); i += 2 {
|
|
if _, ok := keyvals[i].(Valuer); ok {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
// Timestamp returns a timestamp Valuer. It invokes the t function to get the
|
|
// time; unless you are doing something tricky, pass time.Now.
|
|
//
|
|
// Most users will want to use DefaultTimestamp or DefaultTimestampUTC, which
|
|
// are TimestampFormats that use the RFC3339Nano format.
|
|
func Timestamp(t func() time.Time) Valuer {
|
|
return func() interface{} { return t() }
|
|
}
|
|
|
|
// TimestampFormat returns a timestamp Valuer with a custom time format. It
|
|
// invokes the t function to get the time to format; unless you are doing
|
|
// something tricky, pass time.Now. The layout string is passed to
|
|
// Time.Format.
|
|
//
|
|
// Most users will want to use DefaultTimestamp or DefaultTimestampUTC, which
|
|
// are TimestampFormats that use the RFC3339Nano format.
|
|
func TimestampFormat(t func() time.Time, layout string) Valuer {
|
|
return func() interface{} {
|
|
return timeFormat{
|
|
time: t(),
|
|
layout: layout,
|
|
}
|
|
}
|
|
}
|
|
|
|
// A timeFormat represents an instant in time and a layout used when
|
|
// marshaling to a text format.
|
|
type timeFormat struct {
|
|
time time.Time
|
|
layout string
|
|
}
|
|
|
|
func (tf timeFormat) String() string {
|
|
return tf.time.Format(tf.layout)
|
|
}
|
|
|
|
// MarshalText implements encoding.TextMarshaller.
|
|
func (tf timeFormat) MarshalText() (text []byte, err error) {
|
|
// The following code adapted from the standard library time.Time.Format
|
|
// method. Using the same undocumented magic constant to extend the size
|
|
// of the buffer as seen there.
|
|
b := make([]byte, 0, len(tf.layout)+10)
|
|
b = tf.time.AppendFormat(b, tf.layout)
|
|
return b, nil
|
|
}
|
|
|
|
// Caller returns a Valuer that returns a file and line from a specified depth
|
|
// in the callstack. Users will probably want to use DefaultCaller.
|
|
func Caller(depth int) Valuer {
|
|
return func() interface{} {
|
|
_, file, line, _ := runtime.Caller(depth)
|
|
idx := strings.LastIndexByte(file, '/')
|
|
// using idx+1 below handles both of following cases:
|
|
// idx == -1 because no "/" was found, or
|
|
// idx >= 0 and we want to start at the character after the found "/".
|
|
return file[idx+1:] + ":" + strconv.Itoa(line)
|
|
}
|
|
}
|
|
|
|
var (
|
|
// DefaultTimestamp is a Valuer that returns the current wallclock time,
|
|
// respecting time zones, when bound.
|
|
DefaultTimestamp = TimestampFormat(time.Now, time.RFC3339Nano)
|
|
|
|
// DefaultTimestampUTC is a Valuer that returns the current time in UTC
|
|
// when bound.
|
|
DefaultTimestampUTC = TimestampFormat(
|
|
func() time.Time { return time.Now().UTC() },
|
|
time.RFC3339Nano,
|
|
)
|
|
|
|
// DefaultCaller is a Valuer that returns the file and line where the Log
|
|
// method was invoked. It can only be used with log.With.
|
|
DefaultCaller = Caller(3)
|
|
)
|