diff --git a/log/field.go b/log/field.go index a340aed..00166dd 100644 --- a/log/field.go +++ b/log/field.go @@ -1,6 +1,9 @@ package log -import "math" +import ( + "fmt" + "math" +) type fieldType int @@ -20,13 +23,13 @@ const ( ) // Field instances are constructed via LogBool, LogString, and so on. -// Tracing implementations may then handle them via the Field.Process +// Tracing implementations may then handle them via the Field.Marshal // method. // // "heavily influenced by" (i.e., partially stolen from) // https://github.com/uber-go/zap type Field struct { - key string + Key string fieldType fieldType numericVal int64 stringVal string @@ -36,7 +39,7 @@ type Field struct { // String adds a string-valued key:value pair to a Span.LogFields() record func String(key, val string) Field { return Field{ - key: key, + Key: key, fieldType: stringType, stringVal: val, } @@ -49,7 +52,7 @@ func Bool(key string, val bool) Field { numericVal = 1 } return Field{ - key: key, + Key: key, fieldType: boolType, numericVal: numericVal, } @@ -58,7 +61,7 @@ func Bool(key string, val bool) Field { // Int adds an int-valued key:value pair to a Span.LogFields() record func Int(key string, val int) Field { return Field{ - key: key, + Key: key, fieldType: intType, numericVal: int64(val), } @@ -67,7 +70,7 @@ func Int(key string, val int) Field { // Int32 adds an int32-valued key:value pair to a Span.LogFields() record func Int32(key string, val int32) Field { return Field{ - key: key, + Key: key, fieldType: int32Type, numericVal: int64(val), } @@ -76,7 +79,7 @@ func Int32(key string, val int32) Field { // Int64 adds an int64-valued key:value pair to a Span.LogFields() record func Int64(key string, val int64) Field { return Field{ - key: key, + Key: key, fieldType: int64Type, numericVal: val, } @@ -85,7 +88,7 @@ func Int64(key string, val int64) Field { // Uint32 adds a uint32-valued key:value pair to a Span.LogFields() record func Uint32(key string, val uint32) Field { return Field{ - key: key, + Key: key, fieldType: uint32Type, numericVal: int64(val), } @@ -94,7 +97,7 @@ func Uint32(key string, val uint32) Field { // Uint64 adds a uint64-valued key:value pair to a Span.LogFields() record func Uint64(key string, val uint64) Field { return Field{ - key: key, + Key: key, fieldType: uint64Type, numericVal: int64(val), } @@ -103,7 +106,7 @@ func Uint64(key string, val uint64) Field { // Float32 adds a float32-valued key:value pair to a Span.LogFields() record func Float32(key string, val float32) Field { return Field{ - key: key, + Key: key, fieldType: float32Type, numericVal: int64(math.Float32bits(val)), } @@ -112,7 +115,7 @@ func Float32(key string, val float32) Field { // Float64 adds a float64-valued key:value pair to a Span.LogFields() record func Float64(key string, val float64) Field { return Field{ - key: key, + Key: key, fieldType: float64Type, numericVal: int64(math.Float64bits(val)), } @@ -121,7 +124,7 @@ func Float64(key string, val float64) Field { // Error adds an error with the key "error" to a Span.LogFields() record func Error(err error) Field { return Field{ - key: "error", + Key: "error", fieldType: errorType, interfaceVal: err, } @@ -130,7 +133,7 @@ func Error(err error) Field { // Object adds an object-valued key:value pair to a Span.LogFields() record func Object(key string, obj interface{}) Field { return Field{ - key: key, + Key: key, fieldType: objectType, interfaceVal: obj, } @@ -173,28 +176,61 @@ type Encoder interface { func (lf Field) Marshal(visitor Encoder) { switch lf.fieldType { case stringType: - visitor.EmitString(lf.key, lf.stringVal) + visitor.EmitString(lf.Key, lf.stringVal) case boolType: - visitor.EmitBool(lf.key, lf.numericVal != 0) + visitor.EmitBool(lf.Key, lf.numericVal != 0) case intType: - visitor.EmitInt(lf.key, int(lf.numericVal)) + visitor.EmitInt(lf.Key, int(lf.numericVal)) case int32Type: - visitor.EmitInt32(lf.key, int32(lf.numericVal)) + visitor.EmitInt32(lf.Key, int32(lf.numericVal)) case int64Type: - visitor.EmitInt64(lf.key, int64(lf.numericVal)) + visitor.EmitInt64(lf.Key, int64(lf.numericVal)) case uint32Type: - visitor.EmitUint32(lf.key, uint32(lf.numericVal)) + visitor.EmitUint32(lf.Key, uint32(lf.numericVal)) case uint64Type: - visitor.EmitUint64(lf.key, uint64(lf.numericVal)) + visitor.EmitUint64(lf.Key, uint64(lf.numericVal)) case float32Type: - visitor.EmitFloat32(lf.key, math.Float32frombits(uint32(lf.numericVal))) + visitor.EmitFloat32(lf.Key, math.Float32frombits(uint32(lf.numericVal))) case float64Type: - visitor.EmitFloat64(lf.key, math.Float64frombits(uint64(lf.numericVal))) + visitor.EmitFloat64(lf.Key, math.Float64frombits(uint64(lf.numericVal))) case errorType: - visitor.EmitString(lf.key, lf.interfaceVal.(error).Error()) + visitor.EmitString(lf.Key, lf.interfaceVal.(error).Error()) case objectType: - visitor.EmitObject(lf.key, lf.interfaceVal) + visitor.EmitObject(lf.Key, lf.interfaceVal) case lazyLoggerType: visitor.EmitLazyLogger(lf.interfaceVal.(LazyLogger)) } } + +// Value returns the field's value as interface{}. +func (lf Field) Value() interface{} { + switch lf.fieldType { + case stringType: + return lf.stringVal + case boolType: + return lf.numericVal != 0 + case intType: + return int(lf.numericVal) + case int32Type: + return int32(lf.numericVal) + case int64Type: + return int64(lf.numericVal) + case uint32Type: + return uint32(lf.numericVal) + case uint64Type: + return uint64(lf.numericVal) + case float32Type: + return math.Float32frombits(uint32(lf.numericVal)) + case float64Type: + return math.Float64frombits(uint64(lf.numericVal)) + case errorType, objectType, lazyLoggerType: + return lf.interfaceVal + default: + return nil + } +} + +// String returns a string representation of the key and value. +func (lf Field) String() string { + return fmt.Sprint(lf.Key, ":", lf.Value()) +} diff --git a/log/field_test.go b/log/field_test.go new file mode 100644 index 0000000..d301e49 --- /dev/null +++ b/log/field_test.go @@ -0,0 +1,35 @@ +package log + +import ( + "fmt" + "testing" +) + +func TestFieldString(t *testing.T) { + testCases := []struct { + field Field + expected string + }{ + { + field: String("key", "value"), + expected: "key:value", + }, + { + field: Bool("key", true), + expected: "key:true", + }, + { + field: Int("key", 5), + expected: "key:5", + }, + { + field: Error(fmt.Errorf("err msg")), + expected: "error:err msg", + }, + } + for i, tc := range testCases { + if str := tc.field.String(); str != tc.expected { + t.Errorf("%d: expected '%s', got '%s'", i, tc.expected, str) + } + } +}