123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458 |
- package log
- import (
- "context"
- "fmt"
- "time"
- )
- const (
- // DefaultErrorFieldName is the default field name used for errors
- DefaultErrorFieldName = "error"
- )
- // FieldType is a type of data Field can represent
- type FieldType int
- const (
- // FieldTypeNil is for a pure nil
- FieldTypeNil FieldType = iota
- // FieldTypeString is for a string
- FieldTypeString
- // FieldTypeBinary is for a binary array
- FieldTypeBinary
- // FieldTypeBoolean is for boolean
- FieldTypeBoolean
- // FieldTypeSigned is for signed integers
- FieldTypeSigned
- // FieldTypeUnsigned is for unsigned integers
- FieldTypeUnsigned
- // FieldTypeFloat is for float
- FieldTypeFloat
- // FieldTypeTime is for time.Time
- FieldTypeTime
- // FieldTypeDuration is for time.Duration
- FieldTypeDuration
- // FieldTypeError is for an error
- FieldTypeError
- // FieldTypeArray is for an array of any type
- FieldTypeArray
- // FieldTypeAny is for any type
- FieldTypeAny
- // FieldTypeReflect is for unknown types
- FieldTypeReflect
- // FieldTypeByteString is for a bytes that can be represented as UTF-8 string
- FieldTypeByteString
- // FieldTypeContext wraps context for lazy context fields evaluation if possible
- FieldTypeContext
- )
- // Field stores one structured logging field
- type Field struct {
- key string
- ftype FieldType
- string string
- signed int64
- unsigned uint64
- float float64
- iface interface{}
- }
- // Key returns field key
- func (f Field) Key() string {
- return f.key
- }
- // Type returns field type
- func (f Field) Type() FieldType {
- return f.ftype
- }
- // String returns field string
- func (f Field) String() string {
- return f.string
- }
- // Binary constructs field of []byte
- func (f Field) Binary() []byte {
- if f.iface == nil {
- return nil
- }
- return f.iface.([]byte)
- }
- // Bool returns field bool
- func (f Field) Bool() bool {
- return f.Signed() != 0
- }
- // Signed returns field int64
- func (f Field) Signed() int64 {
- return f.signed
- }
- // Unsigned returns field uint64
- func (f Field) Unsigned() uint64 {
- return f.unsigned
- }
- // Float returns field float64
- func (f Field) Float() float64 {
- return f.float
- }
- // Time returns field time.Time
- func (f Field) Time() time.Time {
- return time.Unix(0, f.signed)
- }
- // Duration returns field time.Duration
- func (f Field) Duration() time.Duration {
- return time.Nanosecond * time.Duration(f.signed)
- }
- // Error constructs field of error type
- func (f Field) Error() error {
- if f.iface == nil {
- return nil
- }
- return f.iface.(error)
- }
- // Interface returns field interface
- func (f Field) Interface() interface{} {
- return f.iface
- }
- // Any returns contained data as interface{}
- // nolint: gocyclo
- func (f Field) Any() interface{} {
- switch f.Type() {
- case FieldTypeNil:
- return nil
- case FieldTypeString:
- return f.String()
- case FieldTypeBinary:
- return f.Interface()
- case FieldTypeBoolean:
- return f.Bool()
- case FieldTypeSigned:
- return f.Signed()
- case FieldTypeUnsigned:
- return f.Unsigned()
- case FieldTypeFloat:
- return f.Float()
- case FieldTypeTime:
- return f.Time()
- case FieldTypeDuration:
- return f.Duration()
- case FieldTypeError:
- return f.Error()
- case FieldTypeArray:
- return f.Interface()
- case FieldTypeAny:
- return f.Interface()
- case FieldTypeReflect:
- return f.Interface()
- case FieldTypeByteString:
- return f.Interface()
- case FieldTypeContext:
- return f.Interface()
- default:
- // For when new field type is not added to this func
- panic(fmt.Sprintf("unknown field type: %d", f.Type()))
- }
- }
- // Nil constructs field of nil type
- func Nil(key string) Field {
- return Field{key: key, ftype: FieldTypeNil}
- }
- // String constructs field of string type
- func String(key, value string) Field {
- return Field{key: key, ftype: FieldTypeString, string: value}
- }
- // Sprintf constructs field of string type with formatting
- func Sprintf(key, format string, args ...interface{}) Field {
- return Field{key: key, ftype: FieldTypeString, string: fmt.Sprintf(format, args...)}
- }
- // Strings constructs Field from []string
- func Strings(key string, value []string) Field {
- return Array(key, value)
- }
- // Binary constructs field of []byte type
- func Binary(key string, value []byte) Field {
- return Field{key: key, ftype: FieldTypeBinary, iface: value}
- }
- // Bool constructs field of bool type
- func Bool(key string, value bool) Field {
- field := Field{key: key, ftype: FieldTypeBoolean}
- if value {
- field.signed = 1
- } else {
- field.signed = 0
- }
- return field
- }
- // Bools constructs Field from []bool
- func Bools(key string, value []bool) Field {
- return Array(key, value)
- }
- // Int constructs Field from int
- func Int(key string, value int) Field {
- return Int64(key, int64(value))
- }
- // Ints constructs Field from []int
- func Ints(key string, value []int) Field {
- return Array(key, value)
- }
- // Int8 constructs Field from int8
- func Int8(key string, value int8) Field {
- return Int64(key, int64(value))
- }
- // Int8s constructs Field from []int8
- func Int8s(key string, value []int8) Field {
- return Array(key, value)
- }
- // Int16 constructs Field from int16
- func Int16(key string, value int16) Field {
- return Int64(key, int64(value))
- }
- // Int16s constructs Field from []int16
- func Int16s(key string, value []int16) Field {
- return Array(key, value)
- }
- // Int32 constructs Field from int32
- func Int32(key string, value int32) Field {
- return Int64(key, int64(value))
- }
- // Int32s constructs Field from []int32
- func Int32s(key string, value []int32) Field {
- return Array(key, value)
- }
- // Int64 constructs Field from int64
- func Int64(key string, value int64) Field {
- return Field{key: key, ftype: FieldTypeSigned, signed: value}
- }
- // Int64s constructs Field from []int64
- func Int64s(key string, value []int64) Field {
- return Array(key, value)
- }
- // UInt constructs Field from uint
- func UInt(key string, value uint) Field {
- return UInt64(key, uint64(value))
- }
- // UInts constructs Field from []uint
- func UInts(key string, value []uint) Field {
- return Array(key, value)
- }
- // UInt8 constructs Field from uint8
- func UInt8(key string, value uint8) Field {
- return UInt64(key, uint64(value))
- }
- // UInt8s constructs Field from []uint8
- func UInt8s(key string, value []uint8) Field {
- return Array(key, value)
- }
- // UInt16 constructs Field from uint16
- func UInt16(key string, value uint16) Field {
- return UInt64(key, uint64(value))
- }
- // UInt16s constructs Field from []uint16
- func UInt16s(key string, value []uint16) Field {
- return Array(key, value)
- }
- // UInt32 constructs Field from uint32
- func UInt32(key string, value uint32) Field {
- return UInt64(key, uint64(value))
- }
- // UInt32s constructs Field from []uint32
- func UInt32s(key string, value []uint32) Field {
- return Array(key, value)
- }
- // UInt64 constructs Field from uint64
- func UInt64(key string, value uint64) Field {
- return Field{key: key, ftype: FieldTypeUnsigned, unsigned: value}
- }
- // UInt64s constructs Field from []uint64
- func UInt64s(key string, value []uint64) Field {
- return Array(key, value)
- }
- // Float32 constructs Field from float32
- func Float32(key string, value float32) Field {
- return Float64(key, float64(value))
- }
- // Float32s constructs Field from []float32
- func Float32s(key string, value []float32) Field {
- return Array(key, value)
- }
- // Float64 constructs Field from float64
- func Float64(key string, value float64) Field {
- return Field{key: key, ftype: FieldTypeFloat, float: value}
- }
- // Float64s constructs Field from []float64
- func Float64s(key string, value []float64) Field {
- return Array(key, value)
- }
- // Time constructs field of time.Time type
- func Time(key string, value time.Time) Field {
- return Field{key: key, ftype: FieldTypeTime, signed: value.UnixNano()}
- }
- // Times constructs Field from []time.Time
- func Times(key string, value []time.Time) Field {
- return Array(key, value)
- }
- // Duration constructs field of time.Duration type
- func Duration(key string, value time.Duration) Field {
- return Field{key: key, ftype: FieldTypeDuration, signed: value.Nanoseconds()}
- }
- // Durations constructs Field from []time.Duration
- func Durations(key string, value []time.Duration) Field {
- return Array(key, value)
- }
- // NamedError constructs field of error type
- func NamedError(key string, value error) Field {
- return Field{key: key, ftype: FieldTypeError, iface: value}
- }
- // Error constructs field of error type with default field name
- func Error(value error) Field {
- return NamedError(DefaultErrorFieldName, value)
- }
- // Errors constructs Field from []error
- func Errors(key string, value []error) Field {
- return Array(key, value)
- }
- // Array constructs field of array type
- func Array(key string, value interface{}) Field {
- return Field{key: key, ftype: FieldTypeArray, iface: value}
- }
- // Reflect constructs field of unknown type
- func Reflect(key string, value interface{}) Field {
- return Field{key: key, ftype: FieldTypeReflect, iface: value}
- }
- // ByteString constructs field of bytes that could represent UTF-8 string
- func ByteString(key string, value []byte) Field {
- return Field{key: key, ftype: FieldTypeByteString, iface: value}
- }
- // Context constructs field for lazy context fields evaluation if possible
- func Context(ctx context.Context) Field {
- return Field{ftype: FieldTypeContext, iface: ctx}
- }
- // Any tries to deduce interface{} underlying type and constructs Field from it.
- // Use of this function is ok only for the sole purpose of not repeating its entire code
- // or parts of it in user's code (when you need to log interface{} types with unknown content).
- // Otherwise please use specialized functions.
- // nolint: gocyclo
- func Any(key string, value interface{}) Field {
- switch val := value.(type) {
- case bool:
- return Bool(key, val)
- case float64:
- return Float64(key, val)
- case float32:
- return Float32(key, val)
- case int:
- return Int(key, val)
- case []int:
- return Ints(key, val)
- case int64:
- return Int64(key, val)
- case []int64:
- return Int64s(key, val)
- case int32:
- return Int32(key, val)
- case []int32:
- return Int32s(key, val)
- case int16:
- return Int16(key, val)
- case []int16:
- return Int16s(key, val)
- case int8:
- return Int8(key, val)
- case []int8:
- return Int8s(key, val)
- case string:
- return String(key, val)
- case []string:
- return Strings(key, val)
- case uint:
- return UInt(key, val)
- case []uint:
- return UInts(key, val)
- case uint64:
- return UInt64(key, val)
- case []uint64:
- return UInt64s(key, val)
- case uint32:
- return UInt32(key, val)
- case []uint32:
- return UInt32s(key, val)
- case uint16:
- return UInt16(key, val)
- case []uint16:
- return UInt16s(key, val)
- case uint8:
- return UInt8(key, val)
- case []byte:
- return Binary(key, val)
- case time.Time:
- return Time(key, val)
- case []time.Time:
- return Times(key, val)
- case time.Duration:
- return Duration(key, val)
- case []time.Duration:
- return Durations(key, val)
- case error:
- return NamedError(key, val)
- case []error:
- return Errors(key, val)
- case context.Context:
- return Context(val)
- default:
- return Field{key: key, ftype: FieldTypeAny, iface: value}
- }
- }
|