Permalink
Browse files

Flesh out the LogFields and LogKV changes

  • Loading branch information...
1 parent 5ffc1aa commit 44d840f4fbf65723100efa6fe0fff2e5162101f5 @bensigelman bensigelman committed Aug 30, 2016
Showing with 270 additions and 47 deletions.
  1. +20 −18 log/field.go
  2. +84 −0 mocktracer/mocklogrecord.go
  3. +53 −15 mocktracer/mockspan.go
  4. +78 −8 mocktracer/mocktracer_test.go
  5. +6 −2 noop.go
  6. +22 −1 span.go
  7. +7 −3 testtracer_test.go
View
@@ -1,7 +1,9 @@
-package opentracing
+package log
import "math"
+type fieldType int
+
const (
stringType fieldType = iota
boolType
@@ -10,7 +12,7 @@ const (
uint32Type
int64Type
uint64Type
- float324Type
+ float32Type
float64Type
errorType
objectType
@@ -25,7 +27,7 @@ const (
// https://github.com/uber-go/zap
type Field struct {
key string
- valType valType
+ fieldType fieldType
numericVal int64
stringVal string
interfaceVal interface{}
@@ -34,7 +36,7 @@ type Field struct {
func String(key, val string) Field {
return Field{
key: key,
- valType: stringType,
+ fieldType: stringType,
stringVal: val,
}
}
@@ -46,79 +48,79 @@ func Bool(key string, val bool) Field {
}
return Field{
key: key,
- valType: boolType,
+ fieldType: boolType,
numericVal: numericVal,
}
}
func Int(key string, val int) Field {
return Field{
key: key,
- valType: intType,
+ fieldType: intType,
numericVal: int64(val),
}
}
func Int32(key string, val int32) Field {
return Field{
key: key,
- valType: int32Type,
+ fieldType: int32Type,
numericVal: int64(val),
}
}
func Int64(key string, val int64) Field {
return Field{
key: key,
- valType: int64Type,
+ fieldType: int64Type,
numericVal: val,
}
}
func Uint32(key string, val uint32) Field {
return Field{
key: key,
- valType: uint32Type,
+ fieldType: uint32Type,
numericVal: int64(val),
}
}
func Uint64(key string, val uint64) Field {
return Field{
key: key,
- valType: int64Type,
+ fieldType: int64Type,
numericVal: int64(val),
}
}
func Float32(key string, val float32) Field {
return Field{
key: key,
- valType: float32Type,
+ fieldType: float32Type,
numericVal: int64(math.Float32bits(val)),
}
}
func Float64(key string, val float64) Field {
return Field{
key: key,
- valType: float64Type,
+ fieldType: float64Type,
numericVal: int64(math.Float64bits(val)),
}
}
func Error(err error) Field {
return Field{
key: "error",
- valType: errorType,
+ fieldType: errorType,
interfaceVal: err,
}
}
func Object(key string, obj interface{}) Field {
return Field{
key: key,
- valType: objectType,
+ fieldType: objectType,
interfaceVal: obj,
}
}
@@ -128,7 +130,7 @@ type LazyLogger func(fv FieldVisitor)
func Lazy(key string, ll LazyLogger) Field {
return Field{
key: key,
- valType: lazyLoggerType,
+ fieldType: lazyLoggerType,
interfaceVal: ll,
}
}
@@ -156,7 +158,7 @@ type FieldVisitor interface {
// Visit passes a Field instance through to the appropriate field-type-specific
// method of a FieldVisitor.
func (lf Field) Visit(visitor FieldVisitor) {
- switch lf.valType {
+ switch lf.fieldType {
case stringType:
visitor.AddString(lf.key, lf.stringVal)
case boolType:
@@ -172,11 +174,11 @@ func (lf Field) Visit(visitor FieldVisitor) {
case uint64Type:
visitor.AddUint64(lf.key, uint64(lf.numericVal))
case float32Type:
- visitor.AddFloat32(lf.key, math.Float32frombits(uint64(lf.numericVal)))
+ visitor.AddFloat32(lf.key, math.Float32frombits(uint32(lf.numericVal)))
case float64Type:
visitor.AddFloat64(lf.key, math.Float64frombits(uint64(lf.numericVal)))
case errorType:
- visitor.AddString(lf.key, lf.obj.(error).Error())
+ visitor.AddString(lf.key, lf.interfaceVal.(error).Error())
case objectType:
visitor.AddObject(lf.key, lf.interfaceVal)
case lazyLoggerType:
@@ -0,0 +1,84 @@
+package mocktracer
+
+import (
+ "fmt"
+ "reflect"
+ "time"
+
+ "github.com/opentracing/opentracing-go/log"
+)
+
+// MockLogRecord represents data logged to a Span via Span.LogFields or
+// Span.LogKV.
+type MockLogRecord struct {
+ Timestamp time.Time
+ Fields []MockKeyValue
+}
+
+// MockKeyValue represents a single key:value pair.
+type MockKeyValue struct {
+ Key string
+
+ // All MockLogRecord values are coerced to strings via fmt.Sprint(), though
+ // we retain their type separately.
+ ValueKind reflect.Kind
+ ValueString string
+}
+
+func (m *MockKeyValue) AddString(key, value string) {
+ m.Key = key
+ m.ValueKind = reflect.TypeOf(value).Kind()
+ m.ValueString = fmt.Sprint(value)
+}
+func (m *MockKeyValue) AddBool(key string, value bool) {
+ m.Key = key
+ m.ValueKind = reflect.TypeOf(value).Kind()
+ m.ValueString = fmt.Sprint(value)
+}
+func (m *MockKeyValue) AddInt(key string, value int) {
+ m.Key = key
+ m.ValueKind = reflect.TypeOf(value).Kind()
+ m.ValueString = fmt.Sprint(value)
+}
+func (m *MockKeyValue) AddInt32(key string, value int32) {
+ m.Key = key
+ m.ValueKind = reflect.TypeOf(value).Kind()
+ m.ValueString = fmt.Sprint(value)
+}
+func (m *MockKeyValue) AddInt64(key string, value int64) {
+ m.Key = key
+ m.ValueKind = reflect.TypeOf(value).Kind()
+ m.ValueString = fmt.Sprint(value)
+}
+func (m *MockKeyValue) AddUint32(key string, value uint32) {
+ m.Key = key
+ m.ValueKind = reflect.TypeOf(value).Kind()
+ m.ValueString = fmt.Sprint(value)
+}
+func (m *MockKeyValue) AddUint64(key string, value uint64) {
+ m.Key = key
+ m.ValueKind = reflect.TypeOf(value).Kind()
+ m.ValueString = fmt.Sprint(value)
+}
+func (m *MockKeyValue) AddFloat32(key string, value float32) {
+ m.Key = key
+ m.ValueKind = reflect.TypeOf(value).Kind()
+ m.ValueString = fmt.Sprint(value)
+}
+func (m *MockKeyValue) AddFloat64(key string, value float64) {
+ m.Key = key
+ m.ValueKind = reflect.TypeOf(value).Kind()
+ m.ValueString = fmt.Sprint(value)
+}
+func (m *MockKeyValue) AddObject(key string, value interface{}) {
+ m.Key = key
+ m.ValueKind = reflect.TypeOf(value).Kind()
+ m.ValueString = fmt.Sprint(value)
+}
+func (m *MockKeyValue) AddLazyLogger(key string, value log.LazyLogger) {
+ var meta MockKeyValue
+ value(&meta)
+ m.Key = meta.Key
+ m.ValueKind = meta.ValueKind
+ m.ValueString = meta.ValueString
+}
@@ -8,6 +8,7 @@ import (
"github.com/opentracing/opentracing-go"
"github.com/opentracing/opentracing-go/ext"
+ "github.com/opentracing/opentracing-go/log"
)
// MockSpanContext is an opentracing.SpanContext implementation.
@@ -70,7 +71,7 @@ type MockSpan struct {
// All of the below are protected by the embedded RWMutex.
SpanContext MockSpanContext
tags map[string]interface{}
- logs []opentracing.LogData
+ logs []MockLogRecord
tracer *MockTracer
}
@@ -99,7 +100,7 @@ func newMockSpan(t *MockTracer, name string, opts opentracing.StartSpanOptions)
OperationName: name,
StartTime: startTime,
tags: tags,
- logs: []opentracing.LogData{},
+ logs: []MockLogRecord{},
SpanContext: spanContext,
tracer: t,
@@ -125,10 +126,10 @@ func (s *MockSpan) Tag(k string) interface{} {
}
// Logs returns a copy of logs accumulated in the span so far
-func (s *MockSpan) Logs() []opentracing.LogData {
+func (s *MockSpan) Logs() []MockLogRecord {
s.RLock()
defer s.RUnlock()
- logs := make([]opentracing.LogData, len(s.logs))
+ logs := make([]MockLogRecord, len(s.logs))
copy(logs, s.logs)
return logs
}
@@ -183,8 +184,26 @@ func (s *MockSpan) Finish() {
func (s *MockSpan) FinishWithOptions(opts opentracing.FinishOptions) {
s.Lock()
s.FinishTime = opts.FinishTime
- s.logs = append(s.logs, opts.BulkLogData...)
s.Unlock()
+
+ // Handle any late-bound LogRecords.
+ for _, lr := range opts.LogRecords {
+ s.logFieldsWithTimestamp(lr.Timestamp, lr.Fields...)
+ }
+ // Handle (deprecated) BulkLogData.
+ for _, ld := range opts.BulkLogData {
+ if ld.Payload != nil {
+ s.logFieldsWithTimestamp(
+ ld.Timestamp,
+ log.String("event", ld.Event),
+ log.Object("payload", ld.Payload))
+ } else {
+ s.logFieldsWithTimestamp(
+ ld.Timestamp,
+ log.String("event", ld.Event))
+ }
+ }
+
s.tracer.recordSpan(s)
}
@@ -196,26 +215,45 @@ func (s *MockSpan) String() string {
s.SpanContext.Sampled, s.OperationName)
}
+// LogFields belongs to the Span interface
+func (s *MockSpan) LogFields(fields ...log.Field) {
+ s.logFieldsWithTimestamp(time.Now(), fields...)
+}
+
+// The caller MUST NOT hold s.Lock
+func (s *MockSpan) logFieldsWithTimestamp(ts time.Time, fields ...log.Field) {
+ lr := MockLogRecord{
+ Timestamp: ts,
+ Fields: make([]MockKeyValue, len(fields)),
+ }
+ for i, f := range fields {
+ outField := &(lr.Fields[i])
+ f.Visit(outField)
+ }
+
+ s.Lock()
+ defer s.Unlock()
+ s.logs = append(s.logs, lr)
+}
+
+// LogKV belongs to the Span interface
+func (s *MockSpan) LogKV(keyValues ...interface{}) {
+ // XXX
+}
+
// LogEvent belongs to the Span interface
func (s *MockSpan) LogEvent(event string) {
- s.Log(opentracing.LogData{
- Event: event,
- })
+ s.LogFields(log.String("event", event))
}
// LogEventWithPayload belongs to the Span interface
func (s *MockSpan) LogEventWithPayload(event string, payload interface{}) {
- s.Log(opentracing.LogData{
- Event: event,
- Payload: payload,
- })
+ s.LogFields(log.String("event", event), log.Object("payload", payload))
}
// Log belongs to the Span interface
func (s *MockSpan) Log(data opentracing.LogData) {
- s.Lock()
- defer s.Unlock()
- s.logs = append(s.logs, data)
+ panic("MockSpan.Log() no longer supported")
}
// SetOperationName belongs to the Span interface
Oops, something went wrong.

0 comments on commit 44d840f

Please sign in to comment.