...

Source file src/github.com/Microsoft/hcsshim/internal/oc/exporter.go

Documentation: github.com/Microsoft/hcsshim/internal/oc

     1  package oc
     2  
     3  import (
     4  	"github.com/sirupsen/logrus"
     5  	"go.opencensus.io/trace"
     6  	"google.golang.org/grpc/codes"
     7  
     8  	"github.com/Microsoft/hcsshim/internal/log"
     9  	"github.com/Microsoft/hcsshim/internal/logfields"
    10  )
    11  
    12  const spanMessage = "Span"
    13  
    14  var _errorCodeKey = logrus.ErrorKey + "Code"
    15  
    16  // LogrusExporter is an OpenCensus `trace.Exporter` that exports
    17  // `trace.SpanData` to logrus output.
    18  type LogrusExporter struct{}
    19  
    20  var _ trace.Exporter = &LogrusExporter{}
    21  
    22  // ExportSpan exports `s` based on the the following rules:
    23  //
    24  // 1. All output will contain `s.Attributes`, `s.SpanKind`, `s.TraceID`,
    25  // `s.SpanID`, and `s.ParentSpanID` for correlation
    26  //
    27  // 2. Any calls to .Annotate will not be supported.
    28  //
    29  // 3. The span itself will be written at `logrus.InfoLevel` unless
    30  // `s.Status.Code != 0` in which case it will be written at `logrus.ErrorLevel`
    31  // providing `s.Status.Message` as the error value.
    32  func (le *LogrusExporter) ExportSpan(s *trace.SpanData) {
    33  	if s.DroppedAnnotationCount > 0 {
    34  		logrus.WithFields(logrus.Fields{
    35  			"name":            s.Name,
    36  			logfields.TraceID: s.TraceID.String(),
    37  			logfields.SpanID:  s.SpanID.String(),
    38  			"dropped":         s.DroppedAttributeCount,
    39  			"maxAttributes":   len(s.Attributes),
    40  		}).Warning("span had dropped attributes")
    41  	}
    42  
    43  	entry := log.L.Dup()
    44  	// Combine all span annotations with span data (eg, trace ID, span ID, parent span ID,
    45  	// error, status code)
    46  	// (OC) Span attributes are guaranteed to be  strings, bools, or int64s, so we can
    47  	// can skip overhead in entry.WithFields() and add them directly to entry.Data.
    48  	// Preallocate ahead of time, since we should add, at most, 10 additional entries
    49  	data := make(logrus.Fields, len(entry.Data)+len(s.Attributes)+10)
    50  
    51  	// Default log entry may have prexisting/application-wide data
    52  	for k, v := range entry.Data {
    53  		data[k] = v
    54  	}
    55  	for k, v := range s.Attributes {
    56  		data[k] = v
    57  	}
    58  
    59  	data[logfields.Name] = s.Name
    60  	data[logfields.TraceID] = s.TraceID.String()
    61  	data[logfields.SpanID] = s.SpanID.String()
    62  	data[logfields.ParentSpanID] = s.ParentSpanID.String()
    63  	data[logfields.StartTime] = s.StartTime
    64  	data[logfields.EndTime] = s.EndTime
    65  	data[logfields.Duration] = s.EndTime.Sub(s.StartTime)
    66  	if sk := spanKindToString(s.SpanKind); sk != "" {
    67  		data["spanKind"] = sk
    68  	}
    69  
    70  	level := logrus.InfoLevel
    71  	if s.Status.Code != 0 {
    72  		level = logrus.ErrorLevel
    73  
    74  		// don't overwrite an existing "error" or "errorCode" attributes
    75  		if _, ok := data[logrus.ErrorKey]; !ok {
    76  			data[logrus.ErrorKey] = s.Status.Message
    77  		}
    78  		if _, ok := data[_errorCodeKey]; !ok {
    79  			data[_errorCodeKey] = codes.Code(s.Status.Code).String()
    80  		}
    81  	}
    82  
    83  	entry.Data = data
    84  	entry.Time = s.StartTime
    85  	entry.Log(level, spanMessage)
    86  }
    87  

View as plain text