diff --git a/api/core/key.go b/api/core/key.go index 5bf8721eddc..456edf7ef91 100644 --- a/api/core/key.go +++ b/api/core/key.go @@ -17,6 +17,7 @@ package core //go:generate stringer -type=ValueType import ( + "encoding/json" "fmt" "strconv" "unsafe" @@ -325,3 +326,14 @@ func (v *Value) Emit() string { return "unknown" } } + +// MarshalJSON returns the JSON encoding of the Value. +func (v *Value) MarshalJSON() ([]byte, error) { + var jsonVal struct { + Type string + Value interface{} + } + jsonVal.Type = v.Type().String() + jsonVal.Value = v.AsInterface() + return json.Marshal(jsonVal) +} diff --git a/exporter/trace/stdout/stdout.go b/exporter/trace/stdout/stdout.go index 9f2c8880255..08b3ffa9b97 100644 --- a/exporter/trace/stdout/stdout.go +++ b/exporter/trace/stdout/stdout.go @@ -19,12 +19,7 @@ import ( "encoding/json" "io" "os" - "time" - "google.golang.org/grpc/codes" - - "go.opentelemetry.io/otel/api/core" - apitrace "go.opentelemetry.io/otel/api/trace" "go.opentelemetry.io/otel/sdk/export" ) @@ -48,72 +43,15 @@ func NewExporter(o Options) (*Exporter, error) { }, nil } -type jsonValue struct { - Type string - Value interface{} -} - -type jsonKeyValue struct { - Key core.Key - Value jsonValue -} - -type jsonSpanData struct { - SpanContext core.SpanContext - ParentSpanID core.SpanID - SpanKind apitrace.SpanKind - Name string - StartTime time.Time - EndTime time.Time - Attributes []jsonKeyValue - MessageEvents []export.Event - Links []apitrace.Link - Status codes.Code - HasRemoteParent bool - DroppedAttributeCount int - DroppedMessageEventCount int - DroppedLinkCount int - ChildSpanCount int -} - -func marshalSpanData(data *export.SpanData, pretty bool) ([]byte, error) { - jsd := jsonSpanData{ - SpanContext: data.SpanContext, - ParentSpanID: data.ParentSpanID, - SpanKind: data.SpanKind, - Name: data.Name, - StartTime: data.StartTime, - EndTime: data.EndTime, - Attributes: toJSONAttributes(data.Attributes), - MessageEvents: data.MessageEvents, - Links: data.Links, - Status: data.Status, - HasRemoteParent: data.HasRemoteParent, - DroppedAttributeCount: data.DroppedAttributeCount, - DroppedMessageEventCount: data.DroppedMessageEventCount, - DroppedLinkCount: data.DroppedLinkCount, - ChildSpanCount: data.ChildSpanCount, - } - - if pretty { - return json.MarshalIndent(jsd, "", "\t") - } - return json.Marshal(jsd) -} - -func toJSONAttributes(attributes []core.KeyValue) []jsonKeyValue { - jsonAttrs := make([]jsonKeyValue, len(attributes)) - for i := 0; i < len(attributes); i++ { - jsonAttrs[i].Key = attributes[i].Key - jsonAttrs[i].Value.Type = attributes[i].Value.Type().String() - jsonAttrs[i].Value.Value = attributes[i].Value.AsInterface() - } - return jsonAttrs -} - // ExportSpan writes a SpanData in json format to stdout. func (e *Exporter) ExportSpan(ctx context.Context, data *export.SpanData) { - jsonSpan, err := marshalSpanData(data, e.pretty) + var jsonSpan []byte + var err error + if e.pretty { + jsonSpan, err = json.MarshalIndent(data, "", "\t") + } else { + jsonSpan, err = json.Marshal(data) + } if err != nil { // ignore writer failures for now _, _ = e.outputWriter.Write([]byte("Error converting spanData to json: " + err.Error())) diff --git a/exporter/trace/stdout/stdout_test.go b/exporter/trace/stdout/stdout_test.go index 24252694cae..d54af337275 100644 --- a/exporter/trace/stdout/stdout_test.go +++ b/exporter/trace/stdout/stdout_test.go @@ -58,6 +58,10 @@ func TestExporter_ExportSpan(t *testing.T) { key.String("key", keyValue), key.Float64("double", doubleValue), }, + MessageEvents: []export.Event{ + {Message: "foo", Attributes: []core.KeyValue{key.String("key", keyValue)}, Time: now}, + {Message: "bar", Attributes: []core.KeyValue{key.Float64("double", doubleValue)}, Time: now}, + }, SpanKind: trace.SpanKindInternal, Status: codes.Unknown, } @@ -84,7 +88,28 @@ func TestExporter_ExportSpan(t *testing.T) { `"Value":{"Type":"FLOAT64","Value":123.456}` + `}` + `],` + - `"MessageEvents":null,` + + `"MessageEvents":[` + + `{` + + `"Message":"foo",` + + `"Attributes":[` + + `{` + + `"Key":"key",` + + `"Value":{"Type":"STRING","Value":"value"}` + + `}` + + `],` + + `"Time":` + string(expectedSerializedNow) + + `},` + + `{` + + `"Message":"bar",` + + `"Attributes":[` + + `{` + + `"Key":"double",` + + `"Value":{"Type":"FLOAT64","Value":123.456}` + + `}` + + `],` + + `"Time":` + string(expectedSerializedNow) + + `}` + + `],` + `"Links":null,` + `"Status":2,` + `"HasRemoteParent":false,` +