...

Source file src/github.com/opentracing/opentracing-go/log/field.go

Documentation: github.com/opentracing/opentracing-go/log

     1  package log
     2  
     3  import (
     4  	"fmt"
     5  	"math"
     6  )
     7  
     8  type fieldType int
     9  
    10  const (
    11  	stringType fieldType = iota
    12  	boolType
    13  	intType
    14  	int32Type
    15  	uint32Type
    16  	int64Type
    17  	uint64Type
    18  	float32Type
    19  	float64Type
    20  	errorType
    21  	objectType
    22  	lazyLoggerType
    23  	noopType
    24  )
    25  
    26  // Field instances are constructed via LogBool, LogString, and so on.
    27  // Tracing implementations may then handle them via the Field.Marshal
    28  // method.
    29  //
    30  // "heavily influenced by" (i.e., partially stolen from)
    31  // https://github.com/uber-go/zap
    32  type Field struct {
    33  	key          string
    34  	fieldType    fieldType
    35  	numericVal   int64
    36  	stringVal    string
    37  	interfaceVal interface{}
    38  }
    39  
    40  // String adds a string-valued key:value pair to a Span.LogFields() record
    41  func String(key, val string) Field {
    42  	return Field{
    43  		key:       key,
    44  		fieldType: stringType,
    45  		stringVal: val,
    46  	}
    47  }
    48  
    49  // Bool adds a bool-valued key:value pair to a Span.LogFields() record
    50  func Bool(key string, val bool) Field {
    51  	var numericVal int64
    52  	if val {
    53  		numericVal = 1
    54  	}
    55  	return Field{
    56  		key:        key,
    57  		fieldType:  boolType,
    58  		numericVal: numericVal,
    59  	}
    60  }
    61  
    62  // Int adds an int-valued key:value pair to a Span.LogFields() record
    63  func Int(key string, val int) Field {
    64  	return Field{
    65  		key:        key,
    66  		fieldType:  intType,
    67  		numericVal: int64(val),
    68  	}
    69  }
    70  
    71  // Int32 adds an int32-valued key:value pair to a Span.LogFields() record
    72  func Int32(key string, val int32) Field {
    73  	return Field{
    74  		key:        key,
    75  		fieldType:  int32Type,
    76  		numericVal: int64(val),
    77  	}
    78  }
    79  
    80  // Int64 adds an int64-valued key:value pair to a Span.LogFields() record
    81  func Int64(key string, val int64) Field {
    82  	return Field{
    83  		key:        key,
    84  		fieldType:  int64Type,
    85  		numericVal: val,
    86  	}
    87  }
    88  
    89  // Uint32 adds a uint32-valued key:value pair to a Span.LogFields() record
    90  func Uint32(key string, val uint32) Field {
    91  	return Field{
    92  		key:        key,
    93  		fieldType:  uint32Type,
    94  		numericVal: int64(val),
    95  	}
    96  }
    97  
    98  // Uint64 adds a uint64-valued key:value pair to a Span.LogFields() record
    99  func Uint64(key string, val uint64) Field {
   100  	return Field{
   101  		key:        key,
   102  		fieldType:  uint64Type,
   103  		numericVal: int64(val),
   104  	}
   105  }
   106  
   107  // Float32 adds a float32-valued key:value pair to a Span.LogFields() record
   108  func Float32(key string, val float32) Field {
   109  	return Field{
   110  		key:        key,
   111  		fieldType:  float32Type,
   112  		numericVal: int64(math.Float32bits(val)),
   113  	}
   114  }
   115  
   116  // Float64 adds a float64-valued key:value pair to a Span.LogFields() record
   117  func Float64(key string, val float64) Field {
   118  	return Field{
   119  		key:        key,
   120  		fieldType:  float64Type,
   121  		numericVal: int64(math.Float64bits(val)),
   122  	}
   123  }
   124  
   125  // Error adds an error with the key "error.object" to a Span.LogFields() record
   126  func Error(err error) Field {
   127  	return Field{
   128  		key:          "error.object",
   129  		fieldType:    errorType,
   130  		interfaceVal: err,
   131  	}
   132  }
   133  
   134  // Object adds an object-valued key:value pair to a Span.LogFields() record
   135  // Please pass in an immutable object, otherwise there may be concurrency issues.
   136  // Such as passing in the map, log.Object may result in "fatal error: concurrent map iteration and map write".
   137  // Because span is sent asynchronously, it is possible that this map will also be modified.
   138  func Object(key string, obj interface{}) Field {
   139  	return Field{
   140  		key:          key,
   141  		fieldType:    objectType,
   142  		interfaceVal: obj,
   143  	}
   144  }
   145  
   146  // Event creates a string-valued Field for span logs with key="event" and value=val.
   147  func Event(val string) Field {
   148  	return String("event", val)
   149  }
   150  
   151  // Message creates a string-valued Field for span logs with key="message" and value=val.
   152  func Message(val string) Field {
   153  	return String("message", val)
   154  }
   155  
   156  // LazyLogger allows for user-defined, late-bound logging of arbitrary data
   157  type LazyLogger func(fv Encoder)
   158  
   159  // Lazy adds a LazyLogger to a Span.LogFields() record; the tracing
   160  // implementation will call the LazyLogger function at an indefinite time in
   161  // the future (after Lazy() returns).
   162  func Lazy(ll LazyLogger) Field {
   163  	return Field{
   164  		fieldType:    lazyLoggerType,
   165  		interfaceVal: ll,
   166  	}
   167  }
   168  
   169  // Noop creates a no-op log field that should be ignored by the tracer.
   170  // It can be used to capture optional fields, for example those that should
   171  // only be logged in non-production environment:
   172  //
   173  //     func customerField(order *Order) log.Field {
   174  //          if os.Getenv("ENVIRONMENT") == "dev" {
   175  //              return log.String("customer", order.Customer.ID)
   176  //          }
   177  //          return log.Noop()
   178  //     }
   179  //
   180  //     span.LogFields(log.String("event", "purchase"), customerField(order))
   181  //
   182  func Noop() Field {
   183  	return Field{
   184  		fieldType: noopType,
   185  	}
   186  }
   187  
   188  // Encoder allows access to the contents of a Field (via a call to
   189  // Field.Marshal).
   190  //
   191  // Tracer implementations typically provide an implementation of Encoder;
   192  // OpenTracing callers typically do not need to concern themselves with it.
   193  type Encoder interface {
   194  	EmitString(key, value string)
   195  	EmitBool(key string, value bool)
   196  	EmitInt(key string, value int)
   197  	EmitInt32(key string, value int32)
   198  	EmitInt64(key string, value int64)
   199  	EmitUint32(key string, value uint32)
   200  	EmitUint64(key string, value uint64)
   201  	EmitFloat32(key string, value float32)
   202  	EmitFloat64(key string, value float64)
   203  	EmitObject(key string, value interface{})
   204  	EmitLazyLogger(value LazyLogger)
   205  }
   206  
   207  // Marshal passes a Field instance through to the appropriate
   208  // field-type-specific method of an Encoder.
   209  func (lf Field) Marshal(visitor Encoder) {
   210  	switch lf.fieldType {
   211  	case stringType:
   212  		visitor.EmitString(lf.key, lf.stringVal)
   213  	case boolType:
   214  		visitor.EmitBool(lf.key, lf.numericVal != 0)
   215  	case intType:
   216  		visitor.EmitInt(lf.key, int(lf.numericVal))
   217  	case int32Type:
   218  		visitor.EmitInt32(lf.key, int32(lf.numericVal))
   219  	case int64Type:
   220  		visitor.EmitInt64(lf.key, int64(lf.numericVal))
   221  	case uint32Type:
   222  		visitor.EmitUint32(lf.key, uint32(lf.numericVal))
   223  	case uint64Type:
   224  		visitor.EmitUint64(lf.key, uint64(lf.numericVal))
   225  	case float32Type:
   226  		visitor.EmitFloat32(lf.key, math.Float32frombits(uint32(lf.numericVal)))
   227  	case float64Type:
   228  		visitor.EmitFloat64(lf.key, math.Float64frombits(uint64(lf.numericVal)))
   229  	case errorType:
   230  		if err, ok := lf.interfaceVal.(error); ok {
   231  			visitor.EmitString(lf.key, err.Error())
   232  		} else {
   233  			visitor.EmitString(lf.key, "<nil>")
   234  		}
   235  	case objectType:
   236  		visitor.EmitObject(lf.key, lf.interfaceVal)
   237  	case lazyLoggerType:
   238  		visitor.EmitLazyLogger(lf.interfaceVal.(LazyLogger))
   239  	case noopType:
   240  		// intentionally left blank
   241  	}
   242  }
   243  
   244  // Key returns the field's key.
   245  func (lf Field) Key() string {
   246  	return lf.key
   247  }
   248  
   249  // Value returns the field's value as interface{}.
   250  func (lf Field) Value() interface{} {
   251  	switch lf.fieldType {
   252  	case stringType:
   253  		return lf.stringVal
   254  	case boolType:
   255  		return lf.numericVal != 0
   256  	case intType:
   257  		return int(lf.numericVal)
   258  	case int32Type:
   259  		return int32(lf.numericVal)
   260  	case int64Type:
   261  		return int64(lf.numericVal)
   262  	case uint32Type:
   263  		return uint32(lf.numericVal)
   264  	case uint64Type:
   265  		return uint64(lf.numericVal)
   266  	case float32Type:
   267  		return math.Float32frombits(uint32(lf.numericVal))
   268  	case float64Type:
   269  		return math.Float64frombits(uint64(lf.numericVal))
   270  	case errorType, objectType, lazyLoggerType:
   271  		return lf.interfaceVal
   272  	case noopType:
   273  		return nil
   274  	default:
   275  		return nil
   276  	}
   277  }
   278  
   279  // String returns a string representation of the key and value.
   280  func (lf Field) String() string {
   281  	return fmt.Sprint(lf.key, ":", lf.Value())
   282  }
   283  

View as plain text