From 19cedfb12dee10e818adf3f8a233044a1483e4d5 Mon Sep 17 00:00:00 2001 From: Bogdan Drutu Date: Thu, 26 Mar 2020 19:16:27 -0700 Subject: [PATCH] Remove otlp to/from oc converters and use internal converters (#720) Signed-off-by: Bogdan Drutu --- exporter/otlpexporter/otlp.go | 5 +- receiver/otlpreceiver/otlp_test.go | 3 + receiver/otlpreceiver/trace/otlp.go | 26 +- receiver/otlpreceiver/trace/otlp_test.go | 2 +- .../oc_to_traces.go} | 5 +- .../oc_to_traces_test.go} | 4 +- translator/internaldata/traces_to_oc.go | 2 +- translator/trace/oc_to_otlp.go | 324 ------------- translator/trace/oc_to_otlp_test.go | 437 ------------------ translator/trace/otlp_to_oc.go | 410 ---------------- translator/trace/otlp_to_oc_test.go | 323 ------------- 11 files changed, 26 insertions(+), 1515 deletions(-) rename translator/{opencensus/oc_to_internal.go => internaldata/oc_to_traces.go} (99%) rename translator/{opencensus/oc_to_internal_test.go => internaldata/oc_to_traces_test.go} (99%) delete mode 100644 translator/trace/oc_to_otlp.go delete mode 100644 translator/trace/oc_to_otlp_test.go delete mode 100644 translator/trace/otlp_to_oc.go delete mode 100644 translator/trace/otlp_to_oc_test.go diff --git a/exporter/otlpexporter/otlp.go b/exporter/otlpexporter/otlp.go index b3b8d2c0a0a..8f4aed78917 100644 --- a/exporter/otlpexporter/otlp.go +++ b/exporter/otlpexporter/otlp.go @@ -27,9 +27,10 @@ import ( "github.com/open-telemetry/opentelemetry-collector/config/configmodels" "github.com/open-telemetry/opentelemetry-collector/consumer/consumerdata" "github.com/open-telemetry/opentelemetry-collector/exporter/exporterhelper" + "github.com/open-telemetry/opentelemetry-collector/internal/data" "github.com/open-telemetry/opentelemetry-collector/oterr" + "github.com/open-telemetry/opentelemetry-collector/translator/internaldata" metricstranslator "github.com/open-telemetry/opentelemetry-collector/translator/metrics" - tracetranslator "github.com/open-telemetry/opentelemetry-collector/translator/trace" ) type otlpExporter struct { @@ -169,7 +170,7 @@ func (oce *otlpExporter) pushTraceData(ctx context.Context, td consumerdata.Trac // Perform the request. request := &otlptrace.ExportTraceServiceRequest{ - ResourceSpans: tracetranslator.OCToOTLP(td), + ResourceSpans: data.TraceDataToOtlp(internaldata.OCToTraceData(td)), } err := exporter.exportTrace(ctx, request) diff --git a/receiver/otlpreceiver/otlp_test.go b/receiver/otlpreceiver/otlp_test.go index 3990b7fdef2..e5000cabef9 100644 --- a/receiver/otlpreceiver/otlp_test.go +++ b/receiver/otlpreceiver/otlp_test.go @@ -163,6 +163,9 @@ func TestGrpcGateway_endToEnd(t *testing.T) { }, }, }, + // TODO: Remove this after PR:691 is merged + // https://github.com/open-telemetry/opentelemetry-collector/pull/691 + Status: &octrace.Status{}, }, }, SourceFormat: "otlp_trace", diff --git a/receiver/otlpreceiver/trace/otlp.go b/receiver/otlpreceiver/trace/otlp.go index 36a000f27c4..fc2b0c3bfdf 100644 --- a/receiver/otlpreceiver/trace/otlp.go +++ b/receiver/otlpreceiver/trace/otlp.go @@ -18,14 +18,14 @@ import ( "context" collectortrace "github.com/open-telemetry/opentelemetry-proto/gen/go/collector/trace/v1" - otlptrace "github.com/open-telemetry/opentelemetry-proto/gen/go/trace/v1" "github.com/open-telemetry/opentelemetry-collector/client" "github.com/open-telemetry/opentelemetry-collector/consumer" "github.com/open-telemetry/opentelemetry-collector/consumer/consumerdata" + "github.com/open-telemetry/opentelemetry-collector/internal/data" "github.com/open-telemetry/opentelemetry-collector/obsreport" "github.com/open-telemetry/opentelemetry-collector/oterr" - tracetranslator "github.com/open-telemetry/opentelemetry-collector/translator/trace" + "github.com/open-telemetry/opentelemetry-collector/translator/internaldata" ) const ( @@ -61,8 +61,17 @@ func (r *Receiver) Export(ctx context.Context, req *collectortrace.ExportTraceSe // We need to ensure that it propagates the receiver name as a tag ctxWithReceiverName := obsreport.ReceiverContext(ctx, r.instanceName, receiverTransport, receiverTagValue) - for _, resourceMetrics := range req.ResourceSpans { - err := r.processReceivedSpans(ctxWithReceiverName, resourceMetrics) + td := data.TraceDataFromOtlp(req.ResourceSpans) + rss := td.ResourceSpans() + for i := 0; i < rss.Len(); i++ { + rs := rss.Get(i) + + if rs.InstrumentationLibrarySpans().Len() == 0 { + continue + } + + octd := internaldata.ResourceSpansToOC(rs) + err := r.sendToNextConsumer(ctxWithReceiverName, &octd) if err != nil { return nil, err } @@ -71,15 +80,6 @@ func (r *Receiver) Export(ctx context.Context, req *collectortrace.ExportTraceSe return &collectortrace.ExportTraceServiceResponse{}, nil } -func (r *Receiver) processReceivedSpans(ctx context.Context, resourceSpans *otlptrace.ResourceSpans) error { - if len(resourceSpans.InstrumentationLibrarySpans) == 0 { - return nil - } - - td := tracetranslator.ResourceSpansToTraceData(resourceSpans) - return r.sendToNextConsumer(ctx, &td) -} - func (r *Receiver) sendToNextConsumer(ctx context.Context, td *consumerdata.TraceData) error { if c, ok := client.FromGRPC(ctx); ok { ctx = client.NewContext(ctx, c) diff --git a/receiver/otlpreceiver/trace/otlp_test.go b/receiver/otlpreceiver/trace/otlp_test.go index 1f1a6209856..4d31f480f30 100644 --- a/receiver/otlpreceiver/trace/otlp_test.go +++ b/receiver/otlpreceiver/trace/otlp_test.go @@ -167,7 +167,7 @@ func TestExport(t *testing.T) { }, }, }, - DroppedMessageEventsCount: 2, + DroppedAnnotationsCount: 2, }, Links: &octrace.Span_Links{ Link: []*octrace.Span_Link{ diff --git a/translator/opencensus/oc_to_internal.go b/translator/internaldata/oc_to_traces.go similarity index 99% rename from translator/opencensus/oc_to_internal.go rename to translator/internaldata/oc_to_traces.go index 8791aad3f0c..6d4dee1a208 100644 --- a/translator/opencensus/oc_to_internal.go +++ b/translator/internaldata/oc_to_traces.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package opencensus +package internaldata import ( "strings" @@ -29,7 +29,8 @@ import ( tracetranslator "github.com/open-telemetry/opentelemetry-collector/translator/trace" ) -func ocToInternal(td consumerdata.TraceData) data.TraceData { +// OCToTraceData converts OC data format to TraceData. +func OCToTraceData(td consumerdata.TraceData) data.TraceData { traceData := data.NewTraceData() if td.Node == nil && td.Resource == nil && len(td.Spans) == 0 { return traceData diff --git a/translator/opencensus/oc_to_internal_test.go b/translator/internaldata/oc_to_traces_test.go similarity index 99% rename from translator/opencensus/oc_to_internal_test.go rename to translator/internaldata/oc_to_traces_test.go index 18290366b6b..7227d2356df 100644 --- a/translator/opencensus/oc_to_internal_test.go +++ b/translator/internaldata/oc_to_traces_test.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package opencensus +package internaldata import ( "strings" @@ -431,7 +431,7 @@ func TestOcToInternal(t *testing.T) { for _, test := range tests { t.Run(test.Name, func(t *testing.T) { - got := ocToInternal(test.oc) + got := OCToTraceData(test.oc) assert.EqualValues(t, test.TraceData, got) }) } diff --git a/translator/internaldata/traces_to_oc.go b/translator/internaldata/traces_to_oc.go index fa62446ca59..f588c9037e2 100644 --- a/translator/internaldata/traces_to_oc.go +++ b/translator/internaldata/traces_to_oc.go @@ -27,7 +27,7 @@ import ( tracetranslator "github.com/open-telemetry/opentelemetry-collector/translator/trace" ) -const sourceFormat = "otel_internal_trace" +const sourceFormat = "otlp_trace" var ( defaultProcessID = 0 diff --git a/translator/trace/oc_to_otlp.go b/translator/trace/oc_to_otlp.go deleted file mode 100644 index 913702a3079..00000000000 --- a/translator/trace/oc_to_otlp.go +++ /dev/null @@ -1,324 +0,0 @@ -// Copyright 2019 OpenTelemetry Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package tracetranslator - -import ( - "strings" - - octrace "github.com/census-instrumentation/opencensus-proto/gen-go/trace/v1" - "github.com/golang/protobuf/ptypes/timestamp" - otlpcommon "github.com/open-telemetry/opentelemetry-proto/gen/go/common/v1" - otlptrace "github.com/open-telemetry/opentelemetry-proto/gen/go/trace/v1" - - "github.com/open-telemetry/opentelemetry-collector/consumer/consumerdata" - "github.com/open-telemetry/opentelemetry-collector/internal" - translatorcommon "github.com/open-telemetry/opentelemetry-collector/translator/common" - "github.com/open-telemetry/opentelemetry-collector/translator/conventions" -) - -func OCToOTLP(td consumerdata.TraceData) []*otlptrace.ResourceSpans { - - if td.Node == nil && td.Resource == nil && len(td.Spans) == 0 { - return nil - } - - resource := translatorcommon.OCNodeResourceToOtlp(td.Node, td.Resource) - - resourceSpans := &otlptrace.ResourceSpans{ - Resource: resource, - } - resourceSpanList := []*otlptrace.ResourceSpans{resourceSpans} - - if len(td.Spans) != 0 { - ils := &otlptrace.InstrumentationLibrarySpans{} - resourceSpans.InstrumentationLibrarySpans = []*otlptrace.InstrumentationLibrarySpans{ils} - - ils.Spans = make([]*otlptrace.Span, 0, len(td.Spans)) - - for _, ocSpan := range td.Spans { - if ocSpan == nil { - // Skip nil spans. - continue - } - - otlpSpan := ocSpanToOtlp(ocSpan) - - if ocSpan.Resource != nil { - // Add a separate ResourceSpans item just for this span since it - // has a different Resource. - separateRS := &otlptrace.ResourceSpans{ - Resource: translatorcommon.OCNodeResourceToOtlp(td.Node, ocSpan.Resource), - InstrumentationLibrarySpans: []*otlptrace.InstrumentationLibrarySpans{ - { - Spans: []*otlptrace.Span{otlpSpan}, - }, - }, - } - resourceSpanList = append(resourceSpanList, separateRS) - } else { - // Otherwise add the span to the first ResourceSpans item. - ils.Spans = append(ils.Spans, otlpSpan) - } - } - } - - return resourceSpanList -} - -func timestampToUnixNano(ts *timestamp.Timestamp) uint64 { - return uint64(internal.TimestampToUnixNano(ts)) -} - -func ocSpanToOtlp(ocSpan *octrace.Span) *otlptrace.Span { - attrs, droppedAttrCount := ocAttrsToOtlp(ocSpan.Attributes) - events, droppedEventCount := ocEventsToOtlp(ocSpan.TimeEvents) - links, droppedLinkCount := ocLinksToOtlp(ocSpan.Links) - - childSpanCount := int32(0) - if ocSpan.ChildSpanCount != nil { - childSpanCount = int32(ocSpan.ChildSpanCount.Value) - } - _ = childSpanCount // TODO(nilebox): Handle once OTLP supports it - - otlpSpan := &otlptrace.Span{ - TraceId: ocSpan.TraceId, - SpanId: ocSpan.SpanId, - TraceState: ocTraceStateToOtlp(ocSpan.Tracestate), - ParentSpanId: ocSpan.ParentSpanId, - Name: truncableStringToStr(ocSpan.Name), - Kind: ocSpanKindToOtlp(ocSpan.Kind, ocSpan.Attributes), - StartTimeUnixNano: timestampToUnixNano(ocSpan.StartTime), - EndTimeUnixNano: timestampToUnixNano(ocSpan.EndTime), - Attributes: attrs, - DroppedAttributesCount: droppedAttrCount, - Events: events, - DroppedEventsCount: droppedEventCount, - Links: links, - DroppedLinksCount: droppedLinkCount, - Status: ocStatusToOtlp(ocSpan.Status), - } - - return otlpSpan -} - -func ocStatusToOtlp(ocStatus *octrace.Status) *otlptrace.Status { - if ocStatus == nil { - return nil - } - return &otlptrace.Status{ - Code: otlptrace.Status_StatusCode(ocStatus.Code), - Message: ocStatus.Message, - } -} - -// Convert tracestate to W3C format. See the https://w3c.github.io/trace-context/ -func ocTraceStateToOtlp(ocTracestate *octrace.Span_Tracestate) string { - if ocTracestate == nil { - return "" - } - var sb strings.Builder - for i, entry := range ocTracestate.Entries { - if i > 0 { - sb.WriteString(",") - } - sb.WriteString(strings.Join([]string{entry.Key, entry.Value}, "=")) - } - return sb.String() -} - -func ocAttrsToOtlp(ocAttrs *octrace.Span_Attributes) (otlpAttrs []*otlpcommon.AttributeKeyValue, droppedCount uint32) { - if ocAttrs == nil { - return - } - - otlpAttrs = make([]*otlpcommon.AttributeKeyValue, 0, len(ocAttrs.AttributeMap)) - for key, ocAttr := range ocAttrs.AttributeMap { - - otlpAttr := &otlpcommon.AttributeKeyValue{Key: key} - - switch attribValue := ocAttr.Value.(type) { - case *octrace.AttributeValue_StringValue: - otlpAttr.StringValue = truncableStringToStr(attribValue.StringValue) - otlpAttr.Type = otlpcommon.AttributeKeyValue_STRING - - case *octrace.AttributeValue_IntValue: - otlpAttr.IntValue = attribValue.IntValue - otlpAttr.Type = otlpcommon.AttributeKeyValue_INT - - case *octrace.AttributeValue_BoolValue: - otlpAttr.BoolValue = attribValue.BoolValue - otlpAttr.Type = otlpcommon.AttributeKeyValue_BOOL - - case *octrace.AttributeValue_DoubleValue: - otlpAttr.DoubleValue = attribValue.DoubleValue - otlpAttr.Type = otlpcommon.AttributeKeyValue_DOUBLE - - default: - str := "" - otlpAttr.StringValue = str - otlpAttr.Type = otlpcommon.AttributeKeyValue_STRING - } - otlpAttrs = append(otlpAttrs, otlpAttr) - } - droppedCount = uint32(ocAttrs.DroppedAttributesCount) - return -} - -func ocSpanKindToOtlp(ocKind octrace.Span_SpanKind, ocAttrs *octrace.Span_Attributes) otlptrace.Span_SpanKind { - switch ocKind { - case octrace.Span_SERVER: - return otlptrace.Span_SERVER - - case octrace.Span_CLIENT: - return otlptrace.Span_CLIENT - - case octrace.Span_SPAN_KIND_UNSPECIFIED: - // Span kind field is unspecified, check if TagSpanKind attribute is set. - // This can happen if span kind had no equivalent in OC, so we could represent it in - // the SpanKind. In that case the span kind may be a special attribute TagSpanKind. - if ocAttrs != nil { - kindAttr := ocAttrs.AttributeMap[TagSpanKind] - if kindAttr != nil { - strVal, ok := kindAttr.Value.(*octrace.AttributeValue_StringValue) - if ok && strVal != nil { - var otlpKind otlptrace.Span_SpanKind - switch OpenTracingSpanKind(truncableStringToStr(strVal.StringValue)) { - case OpenTracingSpanKindConsumer: - otlpKind = otlptrace.Span_CONSUMER - case OpenTracingSpanKindProducer: - otlpKind = otlptrace.Span_PRODUCER - default: - return otlptrace.Span_SPAN_KIND_UNSPECIFIED - } - delete(ocAttrs.AttributeMap, TagSpanKind) - return otlpKind - } - } - } - return otlptrace.Span_SPAN_KIND_UNSPECIFIED - - default: - return otlptrace.Span_SPAN_KIND_UNSPECIFIED - } -} - -func ocEventsToOtlp(ocEvents *octrace.Span_TimeEvents) (otlpEvents []*otlptrace.Span_Event, droppedCount uint32) { - if ocEvents == nil { - return - } - - droppedCount = uint32(ocEvents.DroppedMessageEventsCount + ocEvents.DroppedAnnotationsCount) - if len(ocEvents.TimeEvent) == 0 { - return - } - - otlpEvents = make([]*otlptrace.Span_Event, 0, len(ocEvents.TimeEvent)) - - for _, ocEvent := range ocEvents.TimeEvent { - if ocEvent == nil { - continue - } - - otlpEvent := &otlptrace.Span_Event{ - TimeUnixNano: timestampToUnixNano(ocEvent.Time), - } - - switch teValue := ocEvent.Value.(type) { - case *octrace.Span_TimeEvent_Annotation_: - if teValue.Annotation != nil { - otlpEvent.Name = truncableStringToStr(teValue.Annotation.Description) - attrs, droppedCount := ocAttrsToOtlp(teValue.Annotation.Attributes) - otlpEvent.Attributes = attrs - otlpEvent.DroppedAttributesCount = droppedCount - } - - case *octrace.Span_TimeEvent_MessageEvent_: - otlpEvent.Attributes = ocMessageEventToOtlpAttrs(teValue.MessageEvent) - - default: - otlpEvent.Name = "An unknown OpenCensus TimeEvent type was detected when translating to OTLP" - } - - otlpEvents = append(otlpEvents, otlpEvent) - } - return -} - -func ocLinksToOtlp(ocLinks *octrace.Span_Links) (otlpLinks []*otlptrace.Span_Link, droppedCount uint32) { - if ocLinks == nil { - return nil, 0 - } - - droppedCount = uint32(ocLinks.DroppedLinksCount) - if len(ocLinks.Link) == 0 { - return nil, droppedCount - } - - otlpLinks = make([]*otlptrace.Span_Link, 0, len(ocLinks.Link)) - - for _, ocLink := range ocLinks.Link { - if ocLink == nil { - continue - } - - attrs, droppedCount := ocAttrsToOtlp(ocLink.Attributes) - otlpLink := &otlptrace.Span_Link{ - TraceId: ocLink.TraceId, - SpanId: ocLink.SpanId, - TraceState: ocTraceStateToOtlp(ocLink.Tracestate), - Attributes: attrs, - DroppedAttributesCount: droppedCount, - } - - otlpLinks = append(otlpLinks, otlpLink) - } - return otlpLinks, droppedCount -} - -func ocMessageEventToOtlpAttrs(msgEvent *octrace.Span_TimeEvent_MessageEvent) []*otlpcommon.AttributeKeyValue { - if msgEvent == nil { - return nil - } - - return []*otlpcommon.AttributeKeyValue{ - { - Key: conventions.OCTimeEventMessageEventType, - StringValue: msgEvent.Type.String(), - Type: otlpcommon.AttributeKeyValue_STRING, - }, - { - Key: conventions.OCTimeEventMessageEventID, - IntValue: int64(msgEvent.Id), - Type: otlpcommon.AttributeKeyValue_INT, - }, - { - Key: conventions.OCTimeEventMessageEventUSize, - IntValue: int64(msgEvent.UncompressedSize), - Type: otlpcommon.AttributeKeyValue_INT, - }, - { - Key: conventions.OCTimeEventMessageEventCSize, - IntValue: int64(msgEvent.CompressedSize), - Type: otlpcommon.AttributeKeyValue_INT, - }, - } -} - -func truncableStringToStr(ts *octrace.TruncatableString) string { - if ts == nil { - return "" - } - return ts.Value -} diff --git a/translator/trace/oc_to_otlp_test.go b/translator/trace/oc_to_otlp_test.go deleted file mode 100644 index 7f1d25980c9..00000000000 --- a/translator/trace/oc_to_otlp_test.go +++ /dev/null @@ -1,437 +0,0 @@ -// Copyright 2019 OpenTelemetry Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package tracetranslator - -import ( - "testing" - "time" - - occommon "github.com/census-instrumentation/opencensus-proto/gen-go/agent/common/v1" - ocresource "github.com/census-instrumentation/opencensus-proto/gen-go/resource/v1" - octrace "github.com/census-instrumentation/opencensus-proto/gen-go/trace/v1" - "github.com/golang/protobuf/ptypes" - otlpcommon "github.com/open-telemetry/opentelemetry-proto/gen/go/common/v1" - otlpresource "github.com/open-telemetry/opentelemetry-proto/gen/go/resource/v1" - otlptrace "github.com/open-telemetry/opentelemetry-proto/gen/go/trace/v1" - "github.com/stretchr/testify/assert" - - "github.com/open-telemetry/opentelemetry-collector/consumer/consumerdata" -) - -func TestOcTraceStateToOtlp(t *testing.T) { - assert.EqualValues(t, "", ocTraceStateToOtlp(nil)) - - tracestate := &octrace.Span_Tracestate{ - Entries: []*octrace.Span_Tracestate_Entry{ - { - Key: "abc", - Value: "def", - }, - }, - } - assert.EqualValues(t, "abc=def", ocTraceStateToOtlp(tracestate)) - - tracestate.Entries = append(tracestate.Entries, - &octrace.Span_Tracestate_Entry{ - Key: "123", - Value: "4567", - }) - assert.EqualValues(t, "abc=def,123=4567", ocTraceStateToOtlp(tracestate)) -} - -func TestOcAttrsToOtlp(t *testing.T) { - otlpAttrs, droppedCount := ocAttrsToOtlp(nil) - assert.True(t, otlpAttrs == nil) - assert.EqualValues(t, 0, droppedCount) - - ocAttrs := &octrace.Span_Attributes{} - otlpAttrs, droppedCount = ocAttrsToOtlp(ocAttrs) - assert.EqualValues(t, []*otlpcommon.AttributeKeyValue{}, otlpAttrs) - assert.EqualValues(t, 0, droppedCount) - - ocAttrs = &octrace.Span_Attributes{ - DroppedAttributesCount: 123, - } - otlpAttrs, droppedCount = ocAttrsToOtlp(ocAttrs) - assert.EqualValues(t, []*otlpcommon.AttributeKeyValue{}, otlpAttrs) - assert.EqualValues(t, 123, droppedCount) - - ocAttrs = &octrace.Span_Attributes{ - AttributeMap: map[string]*octrace.AttributeValue{}, - DroppedAttributesCount: 234, - } - otlpAttrs, droppedCount = ocAttrsToOtlp(ocAttrs) - assert.EqualValues(t, []*otlpcommon.AttributeKeyValue{}, otlpAttrs) - assert.EqualValues(t, 234, droppedCount) - - ocAttrs = &octrace.Span_Attributes{ - AttributeMap: map[string]*octrace.AttributeValue{ - "abc": { - Value: &octrace.AttributeValue_StringValue{StringValue: &octrace.TruncatableString{Value: "def"}}, - }, - }, - DroppedAttributesCount: 234, - } - otlpAttrs, droppedCount = ocAttrsToOtlp(ocAttrs) - assert.EqualValues(t, []*otlpcommon.AttributeKeyValue{ - { - Key: "abc", - Type: otlpcommon.AttributeKeyValue_STRING, - StringValue: "def", - }, - }, otlpAttrs) - assert.EqualValues(t, 234, droppedCount) - - ocAttrs.AttributeMap["intval"] = &octrace.AttributeValue{ - Value: &octrace.AttributeValue_IntValue{IntValue: 345}, - } - ocAttrs.AttributeMap["boolval"] = &octrace.AttributeValue{ - Value: &octrace.AttributeValue_BoolValue{BoolValue: true}, - } - ocAttrs.AttributeMap["doubleval"] = &octrace.AttributeValue{ - Value: &octrace.AttributeValue_DoubleValue{DoubleValue: 4.5}, - } - otlpAttrs, droppedCount = ocAttrsToOtlp(ocAttrs) - assert.EqualValues(t, 234, droppedCount) - assert.EqualValues(t, 4, len(otlpAttrs)) - assertHasAttrVal(t, otlpAttrs, "abc", &otlpcommon.AttributeKeyValue{ - Key: "abc", - Type: otlpcommon.AttributeKeyValue_STRING, - StringValue: "def", - }) - assertHasAttrVal(t, otlpAttrs, "intval", &otlpcommon.AttributeKeyValue{ - Key: "intval", - Type: otlpcommon.AttributeKeyValue_INT, - IntValue: 345, - }) - assertHasAttrVal(t, otlpAttrs, "boolval", &otlpcommon.AttributeKeyValue{ - Key: "boolval", - Type: otlpcommon.AttributeKeyValue_BOOL, - BoolValue: true, - }) - assertHasAttrVal(t, otlpAttrs, "doubleval", &otlpcommon.AttributeKeyValue{ - Key: "doubleval", - Type: otlpcommon.AttributeKeyValue_DOUBLE, - DoubleValue: 4.5, - }) -} - -func TestOcSpanKindToOtlp(t *testing.T) { - tests := []struct { - ocAttrs *octrace.Span_Attributes - ocKind octrace.Span_SpanKind - otlpKind otlptrace.Span_SpanKind - }{ - { - ocKind: octrace.Span_CLIENT, - otlpKind: otlptrace.Span_CLIENT, - }, - { - ocKind: octrace.Span_SERVER, - otlpKind: otlptrace.Span_SERVER, - }, - { - ocKind: octrace.Span_SPAN_KIND_UNSPECIFIED, - otlpKind: otlptrace.Span_SPAN_KIND_UNSPECIFIED, - }, - { - ocKind: octrace.Span_SPAN_KIND_UNSPECIFIED, - ocAttrs: &octrace.Span_Attributes{ - AttributeMap: map[string]*octrace.AttributeValue{ - "span.kind": {Value: &octrace.AttributeValue_StringValue{ - StringValue: &octrace.TruncatableString{Value: "consumer"}}}, - }, - }, - otlpKind: otlptrace.Span_CONSUMER, - }, - { - ocKind: octrace.Span_SPAN_KIND_UNSPECIFIED, - ocAttrs: &octrace.Span_Attributes{ - AttributeMap: map[string]*octrace.AttributeValue{ - "span.kind": {Value: &octrace.AttributeValue_StringValue{ - StringValue: &octrace.TruncatableString{Value: "producer"}}}, - }, - }, - otlpKind: otlptrace.Span_PRODUCER, - }, - { - ocKind: octrace.Span_SPAN_KIND_UNSPECIFIED, - ocAttrs: &octrace.Span_Attributes{ - AttributeMap: map[string]*octrace.AttributeValue{ - "span.kind": {Value: &octrace.AttributeValue_IntValue{ - IntValue: 123}}, - }, - }, - otlpKind: otlptrace.Span_SPAN_KIND_UNSPECIFIED, - }, - { - ocKind: octrace.Span_CLIENT, - ocAttrs: &octrace.Span_Attributes{ - AttributeMap: map[string]*octrace.AttributeValue{ - "span.kind": {Value: &octrace.AttributeValue_StringValue{ - StringValue: &octrace.TruncatableString{Value: "consumer"}}}, - }, - }, - otlpKind: otlptrace.Span_CLIENT, - }, - } - - for _, test := range tests { - t.Run(test.otlpKind.String(), func(t *testing.T) { - got := ocSpanKindToOtlp(test.ocKind, test.ocAttrs) - assert.EqualValues(t, test.otlpKind, got, "Expected "+test.otlpKind.String()+", got "+got.String()) - }) - } -} - -func TestOcToOtlp(t *testing.T) { - ocNode := &occommon.Node{} - ocResource := &ocresource.Resource{} - - timestampP, err := ptypes.TimestampProto(time.Date(2020, 2, 11, 20, 26, 0, 0, time.UTC)) - assert.NoError(t, err) - - ocSpan1 := &octrace.Span{ - Name: &octrace.TruncatableString{Value: "operationB"}, - StartTime: timestampP, - EndTime: timestampP, - TimeEvents: &octrace.Span_TimeEvents{ - TimeEvent: []*octrace.Span_TimeEvent{ - { - Time: timestampP, - Value: &octrace.Span_TimeEvent_Annotation_{ - Annotation: &octrace.Span_TimeEvent_Annotation{ - Description: &octrace.TruncatableString{Value: "event1"}, - Attributes: &octrace.Span_Attributes{ - AttributeMap: map[string]*octrace.AttributeValue{ - "eventattr1": { - Value: &octrace.AttributeValue_StringValue{ - StringValue: &octrace.TruncatableString{Value: "eventattrval1"}, - }, - }, - }, - DroppedAttributesCount: 4, - }, - }, - }, - }, - nil, - }, - DroppedAnnotationsCount: 1, - DroppedMessageEventsCount: 2, - }, - Status: &octrace.Status{Message: "status-cancelled", Code: 1}, - } - - ocSpan2 := &octrace.Span{ - Name: &octrace.TruncatableString{Value: "operationC"}, - StartTime: timestampP, - EndTime: timestampP, - Links: &octrace.Span_Links{ - Link: []*octrace.Span_Link{{}, nil}, - DroppedLinksCount: 1, - }, - } - - ocSpan3 := &octrace.Span{ - Name: &octrace.TruncatableString{Value: "operationD"}, - StartTime: timestampP, - EndTime: timestampP, - Resource: ocResource, - } - - otlpSpan1 := &otlptrace.Span{ - Name: "operationB", - StartTimeUnixNano: timestampToUnixNano(timestampP), - EndTimeUnixNano: timestampToUnixNano(timestampP), - Events: []*otlptrace.Span_Event{ - { - TimeUnixNano: timestampToUnixNano(timestampP), - Name: "event1", - Attributes: []*otlpcommon.AttributeKeyValue{ - { - Key: "eventattr1", - Type: otlpcommon.AttributeKeyValue_STRING, - StringValue: "eventattrval1", - }, - }, - DroppedAttributesCount: 4, - }, - }, - DroppedEventsCount: 3, - Status: &otlptrace.Status{Message: "status-cancelled", Code: otlptrace.Status_Cancelled}, - } - - otlpSpan2 := &otlptrace.Span{ - Name: "operationC", - StartTimeUnixNano: timestampToUnixNano(timestampP), - EndTimeUnixNano: timestampToUnixNano(timestampP), - Links: []*otlptrace.Span_Link{{}}, - DroppedLinksCount: 1, - } - - otlpSpan3 := &otlptrace.Span{ - Name: "operationD", - StartTimeUnixNano: timestampToUnixNano(timestampP), - EndTimeUnixNano: timestampToUnixNano(timestampP), - } - - tests := []struct { - name string - oc consumerdata.TraceData - otlp []*otlptrace.ResourceSpans - }{ - { - name: "empty", - oc: consumerdata.TraceData{}, - otlp: nil, - }, - - { - name: "nil-resource", - oc: consumerdata.TraceData{Node: ocNode}, - otlp: []*otlptrace.ResourceSpans{ - {Resource: &otlpresource.Resource{}}, - }, - }, - - { - name: "nil-node", - oc: consumerdata.TraceData{Resource: ocResource}, - otlp: []*otlptrace.ResourceSpans{ - {Resource: &otlpresource.Resource{}}, - }, - }, - - { - name: "no-spans", - oc: consumerdata.TraceData{Node: ocNode, Resource: ocResource}, - otlp: []*otlptrace.ResourceSpans{ - {Resource: &otlpresource.Resource{}}, - }, - }, - - { - name: "one-spans", - oc: consumerdata.TraceData{ - Node: ocNode, - Resource: ocResource, - Spans: []*octrace.Span{ocSpan1}, - }, - otlp: []*otlptrace.ResourceSpans{ - { - Resource: &otlpresource.Resource{}, - InstrumentationLibrarySpans: []*otlptrace.InstrumentationLibrarySpans{ - { - Spans: []*otlptrace.Span{otlpSpan1}, - }, - }, - }, - }, - }, - - { - name: "two-spans", - oc: consumerdata.TraceData{ - Node: ocNode, - Resource: ocResource, - Spans: []*octrace.Span{ocSpan1, nil, ocSpan2}, - }, - otlp: []*otlptrace.ResourceSpans{ - { - Resource: &otlpresource.Resource{}, - InstrumentationLibrarySpans: []*otlptrace.InstrumentationLibrarySpans{ - { - Spans: []*otlptrace.Span{otlpSpan1, otlpSpan2}, - }, - }, - }, - }, - }, - - { - name: "two-spans-plus-one-separate", - oc: consumerdata.TraceData{ - Node: ocNode, - Resource: ocResource, - Spans: []*octrace.Span{ocSpan1, ocSpan2, ocSpan3}, - }, - otlp: []*otlptrace.ResourceSpans{ - { - Resource: &otlpresource.Resource{}, - InstrumentationLibrarySpans: []*otlptrace.InstrumentationLibrarySpans{ - { - Spans: []*otlptrace.Span{otlpSpan1, otlpSpan2}, - }, - }, - }, - { - Resource: &otlpresource.Resource{}, - InstrumentationLibrarySpans: []*otlptrace.InstrumentationLibrarySpans{ - { - Spans: []*otlptrace.Span{otlpSpan3}, - }, - }, - }, - }, - }, - - { - name: "two-spans-and-separate-in-the-middle", - oc: consumerdata.TraceData{ - Node: ocNode, - Resource: ocResource, - Spans: []*octrace.Span{ocSpan1, ocSpan3, ocSpan2}, - }, - otlp: []*otlptrace.ResourceSpans{ - { - Resource: &otlpresource.Resource{}, - InstrumentationLibrarySpans: []*otlptrace.InstrumentationLibrarySpans{ - { - Spans: []*otlptrace.Span{otlpSpan1, otlpSpan2}, - }, - }, - }, - { - Resource: &otlpresource.Resource{}, - InstrumentationLibrarySpans: []*otlptrace.InstrumentationLibrarySpans{ - { - Spans: []*otlptrace.Span{otlpSpan3}, - }, - }, - }, - }, - }, - } - - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - got := OCToOTLP(test.oc) - assert.EqualValues(t, test.otlp, got) - }) - } -} - -func assertHasAttrVal(t *testing.T, attrs []*otlpcommon.AttributeKeyValue, key string, val *otlpcommon.AttributeKeyValue) { - found := false - for _, attr := range attrs { - if attr != nil && attr.Key == key { - assert.EqualValues(t, false, found, "Duplicate key "+key) - assert.EqualValues(t, val, attr) - found = true - } - } - assert.EqualValues(t, true, found, "Cannot find key "+key) -} diff --git a/translator/trace/otlp_to_oc.go b/translator/trace/otlp_to_oc.go deleted file mode 100644 index e22c4b56bdc..00000000000 --- a/translator/trace/otlp_to_oc.go +++ /dev/null @@ -1,410 +0,0 @@ -// Copyright 2020 OpenTelemetry Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package tracetranslator - -import ( - "fmt" - "strconv" - "strings" - "time" - - occommon "github.com/census-instrumentation/opencensus-proto/gen-go/agent/common/v1" - ocresource "github.com/census-instrumentation/opencensus-proto/gen-go/resource/v1" - octrace "github.com/census-instrumentation/opencensus-proto/gen-go/trace/v1" - "github.com/golang/protobuf/ptypes" - "github.com/golang/protobuf/ptypes/timestamp" - otlpcommon "github.com/open-telemetry/opentelemetry-proto/gen/go/common/v1" - otlpresource "github.com/open-telemetry/opentelemetry-proto/gen/go/resource/v1" - otlptrace "github.com/open-telemetry/opentelemetry-proto/gen/go/trace/v1" - - "github.com/open-telemetry/opentelemetry-collector/consumer/consumerdata" - "github.com/open-telemetry/opentelemetry-collector/internal" - "github.com/open-telemetry/opentelemetry-collector/internal/data" - "github.com/open-telemetry/opentelemetry-collector/translator/conventions" -) - -const sourceFormat = "otlp_trace" - -var ( - defaultTime = time.Time{} // zero - defaultTimestamp = timestamp.Timestamp{} - defaultProcessID = 0 -) - -// ResourceSpansToTraceData converts spans from OTLP to internal (OpenCensus) format -func ResourceSpansToTraceData(resourceSpans *otlptrace.ResourceSpans) consumerdata.TraceData { - node, resource := resourceToOC(resourceSpans.Resource) - td := consumerdata.TraceData{ - Node: node, - Resource: resource, - SourceFormat: sourceFormat, - } - - if len(resourceSpans.InstrumentationLibrarySpans) == 0 { - return td - } - - // Allocate slice with a capacity approximated for the case when there is only one - // InstrumentationLibrary or the first InstrumentationLibrary contains most of the data. - // This is a best guess only that reduced slice re-allocations. - spans := make([]*octrace.Span, 0, len(resourceSpans.InstrumentationLibrarySpans[0].Spans)) - for _, ils := range resourceSpans.InstrumentationLibrarySpans { - for _, span := range ils.Spans { - spans = append(spans, spanToOC(span)) - } - } - - td.Spans = spans - return td -} - -func spanToOC(span *otlptrace.Span) *octrace.Span { - attributes := attributesToOCSpanAttributes(span.Attributes, span.DroppedAttributesCount) - if kindAttr := kindToAttribute(span.Kind); kindAttr != nil { - if attributes == nil { - attributes = &octrace.Span_Attributes{ - AttributeMap: make(map[string]*octrace.AttributeValue, 1), - DroppedAttributesCount: 0, - } - } - attributes.AttributeMap[TagSpanKind] = kindAttr - } - - return &octrace.Span{ - TraceId: span.TraceId, - SpanId: span.SpanId, - Tracestate: tracestateToOC(span.TraceState), - ParentSpanId: span.ParentSpanId, - Name: &octrace.TruncatableString{ - Value: span.Name, - }, - Kind: kindToOC(span.Kind), - StartTime: internal.UnixNanoToTimestamp(data.TimestampUnixNano(span.StartTimeUnixNano)), - EndTime: internal.UnixNanoToTimestamp(data.TimestampUnixNano(span.EndTimeUnixNano)), - Attributes: attributes, - TimeEvents: eventsToOC(span.Events, span.DroppedEventsCount), - Links: linksToOC(span.Links, span.DroppedLinksCount), - Status: statusToOC(span.Status), - ChildSpanCount: nil, // TODO(nilebox): Handle once OTLP supports it - } -} - -func linksToOC(links []*otlptrace.Span_Link, droppedCount uint32) *octrace.Span_Links { - if len(links) == 0 && droppedCount == 0 { - return nil - } - - return &octrace.Span_Links{ - Link: linksToOCLinks(links), - DroppedLinksCount: int32(droppedCount), - } -} - -func linksToOCLinks(links []*otlptrace.Span_Link) []*octrace.Span_Link { - if len(links) == 0 { - return nil - } - - ocLinks := make([]*octrace.Span_Link, 0, len(links)) - for _, link := range links { - ocLink := &octrace.Span_Link{ - TraceId: link.TraceId, - SpanId: link.SpanId, - Tracestate: tracestateToOC(link.TraceState), - Attributes: attributesToOCSpanAttributes(link.Attributes, link.DroppedAttributesCount), - } - ocLinks = append(ocLinks, ocLink) - } - return ocLinks -} - -func eventsToOC(events []*otlptrace.Span_Event, droppedCount uint32) *octrace.Span_TimeEvents { - if len(events) == 0 && droppedCount == 0 { - return nil - } - - return &octrace.Span_TimeEvents{ - TimeEvent: eventsToOCEvents(events), - DroppedMessageEventsCount: int32(droppedCount), - } -} - -func eventsToOCEvents(events []*otlptrace.Span_Event) []*octrace.Span_TimeEvent { - if len(events) == 0 { - return nil - } - - ocEvents := make([]*octrace.Span_TimeEvent, 0, len(events)) - for _, event := range events { - ocAttributes := attributesToOCSpanAttributes(event.Attributes, event.DroppedAttributesCount) - ocEvent := &octrace.Span_TimeEvent{ - Time: internal.UnixNanoToTimestamp(data.TimestampUnixNano(event.TimeUnixNano)), - Value: &octrace.Span_TimeEvent_Annotation_{ - Annotation: &octrace.Span_TimeEvent_Annotation{ - Description: &octrace.TruncatableString{ - Value: event.Name, - }, - Attributes: ocAttributes, - }, - }, - } - - ocEvents = append(ocEvents, ocEvent) - } - return ocEvents -} - -func statusToOC(status *otlptrace.Status) *octrace.Status { - if status == nil { - return nil - } - return &octrace.Status{ - Code: int32(status.Code), - Message: status.Message, - } -} - -func resourceToOC(resource *otlpresource.Resource) (*occommon.Node, *ocresource.Resource) { - if resource == nil { - return nil, nil - } - - ocNode := occommon.Node{} - ocResource := ocresource.Resource{} - - if len(resource.Attributes) == 0 { - return &ocNode, &ocResource - } - - labels := make(map[string]string, len(resource.Attributes)) - for _, attr := range resource.Attributes { - key := attr.Key - val := attributeValueToString(attr) - - switch key { - case conventions.OCAttributeResourceType: - ocResource.Type = val - case conventions.AttributeServiceName: - if ocNode.ServiceInfo == nil { - ocNode.ServiceInfo = &occommon.ServiceInfo{} - } - ocNode.ServiceInfo.Name = val - case conventions.OCAttributeProcessStartTime: - t, err := time.Parse(time.RFC3339Nano, val) - if err != nil { - t = defaultTime - } - ts, err := ptypes.TimestampProto(t) - if err != nil { - ts = &defaultTimestamp - } - if ocNode.Identifier == nil { - ocNode.Identifier = &occommon.ProcessIdentifier{} - } - ocNode.Identifier.StartTimestamp = ts - case conventions.AttributeHostHostname: - if ocNode.Identifier == nil { - ocNode.Identifier = &occommon.ProcessIdentifier{} - } - ocNode.Identifier.HostName = val - case conventions.OCAttributeProcessID: - pid, err := strconv.Atoi(val) - if err != nil { - pid = defaultProcessID - } - if ocNode.Identifier == nil { - ocNode.Identifier = &occommon.ProcessIdentifier{} - } - ocNode.Identifier.Pid = uint32(pid) - case conventions.AttributeLibraryVersion: - if ocNode.LibraryInfo == nil { - ocNode.LibraryInfo = &occommon.LibraryInfo{} - } - ocNode.LibraryInfo.CoreLibraryVersion = val - case conventions.OCAttributeExporterVersion: - if ocNode.LibraryInfo == nil { - ocNode.LibraryInfo = &occommon.LibraryInfo{} - } - ocNode.LibraryInfo.ExporterVersion = val - case conventions.AttributeLibraryLanguage: - if code, ok := occommon.LibraryInfo_Language_value[val]; ok { - if ocNode.LibraryInfo == nil { - ocNode.LibraryInfo = &occommon.LibraryInfo{} - } - ocNode.LibraryInfo.Language = occommon.LibraryInfo_Language(code) - } - default: - // Not a special attribute, put it into resource labels - labels[key] = val - } - } - ocResource.Labels = labels - - return &ocNode, &ocResource -} - -func attributesToOCSpanAttributes(attributes []*otlpcommon.AttributeKeyValue, droppedCount uint32) *octrace.Span_Attributes { - if len(attributes) == 0 && droppedCount == 0 { - return nil - } - - return &octrace.Span_Attributes{ - AttributeMap: attributesToOCMap(attributes), - DroppedAttributesCount: int32(droppedCount), - } -} - -func attributesToOCMap(attributes []*otlpcommon.AttributeKeyValue) map[string]*octrace.AttributeValue { - if len(attributes) == 0 { - return nil - } - - ocAttributes := make(map[string]*octrace.AttributeValue, len(attributes)) - for _, attr := range attributes { - ocAttributes[attr.Key] = attributeValueToOC(attr) - } - return ocAttributes -} - -func attributeValueToString(attr *otlpcommon.AttributeKeyValue) string { - switch attr.Type { - case otlpcommon.AttributeKeyValue_STRING: - return attr.StringValue - case otlpcommon.AttributeKeyValue_BOOL: - return strconv.FormatBool(attr.BoolValue) - case otlpcommon.AttributeKeyValue_DOUBLE: - return strconv.FormatFloat(attr.DoubleValue, 'f', -1, 64) - case otlpcommon.AttributeKeyValue_INT: - return strconv.FormatInt(attr.IntValue, 10) - default: - return fmt.Sprintf("", attr.Type) - } -} - -func attributeValueToOC(attr *otlpcommon.AttributeKeyValue) *octrace.AttributeValue { - a := &octrace.AttributeValue{} - - switch attr.Type { - case otlpcommon.AttributeKeyValue_STRING: - a.Value = &octrace.AttributeValue_StringValue{ - StringValue: &octrace.TruncatableString{ - Value: attr.StringValue, - }, - } - case otlpcommon.AttributeKeyValue_BOOL: - a.Value = &octrace.AttributeValue_BoolValue{ - BoolValue: attr.BoolValue, - } - case otlpcommon.AttributeKeyValue_DOUBLE: - a.Value = &octrace.AttributeValue_DoubleValue{ - DoubleValue: attr.DoubleValue, - } - case otlpcommon.AttributeKeyValue_INT: - a.Value = &octrace.AttributeValue_IntValue{ - IntValue: attr.IntValue, - } - default: - a.Value = &octrace.AttributeValue_StringValue{ - StringValue: &octrace.TruncatableString{ - Value: fmt.Sprintf("", attr.Type), - }, - } - } - - return a -} - -// OTLP follows the W3C format, e.g. "vendorname1=opaqueValue1,vendorname2=opaqueValue2" -// See https://w3c.github.io/trace-context/#combined-header-value -func tracestateToOC(tracestate string) *octrace.Span_Tracestate { - if tracestate == "" { - return nil - } - - // key-value pairs in the "key1=value1" format - pairs := strings.Split(tracestate, ",") - - entries := make([]*octrace.Span_Tracestate_Entry, 0, len(pairs)) - for _, pair := range pairs { - kv := strings.SplitN(pair, "=", 2) - if len(kv) == 0 { - continue - } - - key := kv[0] - val := "" - if len(kv) >= 2 { - val = kv[1] - } - - entries = append(entries, &octrace.Span_Tracestate_Entry{ - Key: key, - Value: val, - }) - } - - return &octrace.Span_Tracestate{ - Entries: entries, - } -} - -func kindToOC(kind otlptrace.Span_SpanKind) octrace.Span_SpanKind { - switch kind { - case otlptrace.Span_SERVER: - return octrace.Span_SERVER - case otlptrace.Span_CLIENT: - return octrace.Span_CLIENT - // NOTE: see `kindToAttribute` function for custom kinds - case otlptrace.Span_SPAN_KIND_UNSPECIFIED: - case otlptrace.Span_INTERNAL: - case otlptrace.Span_PRODUCER: - case otlptrace.Span_CONSUMER: - default: - } - - return octrace.Span_SPAN_KIND_UNSPECIFIED -} - -func kindToAttribute(kind otlptrace.Span_SpanKind) *octrace.AttributeValue { - var ocKind OpenTracingSpanKind - switch kind { - case otlptrace.Span_CONSUMER: - ocKind = OpenTracingSpanKindConsumer - case otlptrace.Span_PRODUCER: - ocKind = OpenTracingSpanKindProducer - case otlptrace.Span_SPAN_KIND_UNSPECIFIED: - case otlptrace.Span_INTERNAL: - case otlptrace.Span_SERVER: // explicitly handled as SpanKind - case otlptrace.Span_CLIENT: // explicitly handled as SpanKind - default: - } - - if string(ocKind) == "" { - // No matching kind attribute value - return nil - } - - return stringAttributeValue(string(ocKind)) -} - -func stringAttributeValue(val string) *octrace.AttributeValue { - return &octrace.AttributeValue{ - Value: &octrace.AttributeValue_StringValue{ - StringValue: &octrace.TruncatableString{ - Value: val, - }, - }, - } -} diff --git a/translator/trace/otlp_to_oc_test.go b/translator/trace/otlp_to_oc_test.go deleted file mode 100644 index e079a94378d..00000000000 --- a/translator/trace/otlp_to_oc_test.go +++ /dev/null @@ -1,323 +0,0 @@ -// Copyright 2020 OpenTelemetry Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package tracetranslator - -import ( - "encoding/base64" - "testing" - "time" - - occommon "github.com/census-instrumentation/opencensus-proto/gen-go/agent/common/v1" - ocresource "github.com/census-instrumentation/opencensus-proto/gen-go/resource/v1" - octrace "github.com/census-instrumentation/opencensus-proto/gen-go/trace/v1" - "github.com/golang/protobuf/ptypes" - otlpcommon "github.com/open-telemetry/opentelemetry-proto/gen/go/common/v1" - otlpresource "github.com/open-telemetry/opentelemetry-proto/gen/go/resource/v1" - otlptrace "github.com/open-telemetry/opentelemetry-proto/gen/go/trace/v1" - "github.com/stretchr/testify/assert" - - "github.com/open-telemetry/opentelemetry-collector/consumer/consumerdata" - "github.com/open-telemetry/opentelemetry-collector/internal" - "github.com/open-telemetry/opentelemetry-collector/internal/data" - "github.com/open-telemetry/opentelemetry-collector/translator/conventions" -) - -func TestResourceSpansToTraceData(t *testing.T) { - unixnanos := uint64(12578940000000012345) - - traceID, err := base64.StdEncoding.DecodeString("SEhaOVO7YSQ=") - assert.NoError(t, err) - - spanID, err := base64.StdEncoding.DecodeString("QuHicGYRg4U=") - assert.NoError(t, err) - - ts, err := ptypes.TimestampProto(time.Date(2020, 2, 11, 20, 26, 0, 0, time.UTC)) - assert.NoError(t, err) - - otlpSpan1 := &otlptrace.Span{ - TraceId: traceID, - SpanId: spanID, - Name: "operationB", - Kind: otlptrace.Span_SERVER, - StartTimeUnixNano: unixnanos, - EndTimeUnixNano: unixnanos, - Events: []*otlptrace.Span_Event{ - { - TimeUnixNano: unixnanos, - Name: "event1", - Attributes: []*otlpcommon.AttributeKeyValue{ - { - Key: "eventattr1", - Type: otlpcommon.AttributeKeyValue_STRING, - StringValue: "eventattrval1", - }, - }, - DroppedAttributesCount: 4, - }, - }, - Links: []*otlptrace.Span_Link{ - { - TraceId: traceID, - SpanId: spanID, - }, - }, - DroppedAttributesCount: 1, - DroppedEventsCount: 2, - Status: &otlptrace.Status{Message: "status-cancelled", Code: otlptrace.Status_Cancelled}, - TraceState: "a=text,b=123", - } - - otlpSpan2 := &otlptrace.Span{ - Name: "operationC", - StartTimeUnixNano: unixnanos, - EndTimeUnixNano: unixnanos, - Kind: otlptrace.Span_CONSUMER, - Links: []*otlptrace.Span_Link{{}}, - DroppedLinksCount: 1, - } - - otlpAttributes := []*otlpcommon.AttributeKeyValue{ - { - Key: conventions.OCAttributeResourceType, - Type: otlpcommon.AttributeKeyValue_STRING, - StringValue: "good-resource", - }, - { - Key: conventions.OCAttributeProcessStartTime, - Type: otlpcommon.AttributeKeyValue_STRING, - StringValue: "2020-02-11T20:26:00Z", - }, - { - Key: conventions.AttributeHostHostname, - Type: otlpcommon.AttributeKeyValue_STRING, - StringValue: "host1", - }, - { - Key: conventions.OCAttributeProcessID, - Type: otlpcommon.AttributeKeyValue_STRING, - StringValue: "123", - }, - { - Key: conventions.AttributeLibraryVersion, - Type: otlpcommon.AttributeKeyValue_STRING, - StringValue: "v2.0.1", - }, - { - Key: conventions.OCAttributeExporterVersion, - Type: otlpcommon.AttributeKeyValue_STRING, - StringValue: "v1.2.0", - }, - { - Key: conventions.AttributeLibraryLanguage, - Type: otlpcommon.AttributeKeyValue_STRING, - StringValue: "CPP", - }, - { - Key: "str1", - Type: otlpcommon.AttributeKeyValue_STRING, - StringValue: "text", - }, - { - Key: "int2", - Type: otlpcommon.AttributeKeyValue_INT, - IntValue: 123, - }, - } - - ocSpan1 := &octrace.Span{ - TraceId: traceID, - SpanId: spanID, - Name: &octrace.TruncatableString{Value: "operationB"}, - Kind: octrace.Span_SERVER, - StartTime: internal.UnixNanoToTimestamp(data.TimestampUnixNano(unixnanos)), - EndTime: internal.UnixNanoToTimestamp(data.TimestampUnixNano(unixnanos)), - TimeEvents: &octrace.Span_TimeEvents{ - TimeEvent: []*octrace.Span_TimeEvent{ - { - Time: internal.UnixNanoToTimestamp(data.TimestampUnixNano(unixnanos)), - Value: &octrace.Span_TimeEvent_Annotation_{ - Annotation: &octrace.Span_TimeEvent_Annotation{ - Description: &octrace.TruncatableString{Value: "event1"}, - Attributes: &octrace.Span_Attributes{ - AttributeMap: map[string]*octrace.AttributeValue{ - "eventattr1": { - Value: &octrace.AttributeValue_StringValue{ - StringValue: &octrace.TruncatableString{Value: "eventattrval1"}, - }, - }, - }, - DroppedAttributesCount: 4, - }, - }, - }, - }, - }, - DroppedMessageEventsCount: 2, - }, - Links: &octrace.Span_Links{ - Link: []*octrace.Span_Link{ - { - TraceId: traceID, - SpanId: spanID, - }, - }, - }, - Attributes: &octrace.Span_Attributes{ - DroppedAttributesCount: 1, - }, - Status: &octrace.Status{Message: "status-cancelled", Code: 1}, - Tracestate: &octrace.Span_Tracestate{ - Entries: []*octrace.Span_Tracestate_Entry{ - { - Key: "a", - Value: "text", - }, - { - Key: "b", - Value: "123", - }, - }, - }, - } - - ocSpan2 := &octrace.Span{ - Name: &octrace.TruncatableString{Value: "operationC"}, - Kind: octrace.Span_SPAN_KIND_UNSPECIFIED, - StartTime: internal.UnixNanoToTimestamp(data.TimestampUnixNano(unixnanos)), - EndTime: internal.UnixNanoToTimestamp(data.TimestampUnixNano(unixnanos)), - Attributes: &octrace.Span_Attributes{ - AttributeMap: map[string]*octrace.AttributeValue{ - TagSpanKind: { - Value: &octrace.AttributeValue_StringValue{ - StringValue: &octrace.TruncatableString{ - Value: string(OpenTracingSpanKindConsumer), - }, - }, - }, - }, - DroppedAttributesCount: 0, - }, - Links: &octrace.Span_Links{ - Link: []*octrace.Span_Link{{}}, - DroppedLinksCount: 1, - }, - } - - ocAttributes := map[string]string{ - "str1": "text", - "int2": "123", - } - - tests := []struct { - name string - oc consumerdata.TraceData - otlp otlptrace.ResourceSpans - }{ - { - name: "empty", - otlp: otlptrace.ResourceSpans{}, - oc: consumerdata.TraceData{ - Spans: nil, - SourceFormat: sourceFormat, - }, - }, - - { - name: "nil-resource", - otlp: otlptrace.ResourceSpans{ - Resource: nil, - }, - oc: consumerdata.TraceData{ - Node: nil, - Resource: nil, - Spans: nil, - SourceFormat: sourceFormat, - }, - }, - - { - name: "no-spans", - otlp: otlptrace.ResourceSpans{ - Resource: &otlpresource.Resource{}, - InstrumentationLibrarySpans: nil, - }, - oc: consumerdata.TraceData{ - Node: &occommon.Node{}, - Resource: &ocresource.Resource{}, - Spans: nil, - SourceFormat: sourceFormat, - }, - }, - - { - name: "one-span", - otlp: otlptrace.ResourceSpans{ - Resource: &otlpresource.Resource{ - Attributes: otlpAttributes, - }, - InstrumentationLibrarySpans: []*otlptrace.InstrumentationLibrarySpans{ - { - Spans: []*otlptrace.Span{otlpSpan1}, - }, - }, - }, - oc: consumerdata.TraceData{ - Node: &occommon.Node{ - Identifier: &occommon.ProcessIdentifier{ - HostName: "host1", - Pid: 123, - StartTimestamp: ts, - }, - LibraryInfo: &occommon.LibraryInfo{ - Language: occommon.LibraryInfo_CPP, - ExporterVersion: "v1.2.0", - CoreLibraryVersion: "v2.0.1", - }, - }, - Resource: &ocresource.Resource{ - Type: "good-resource", - Labels: ocAttributes, - }, - Spans: []*octrace.Span{ocSpan1}, - SourceFormat: sourceFormat, - }, - }, - - { - name: "two-spans", - otlp: otlptrace.ResourceSpans{ - Resource: &otlpresource.Resource{}, - InstrumentationLibrarySpans: []*otlptrace.InstrumentationLibrarySpans{ - { - Spans: []*otlptrace.Span{otlpSpan1, otlpSpan2}, - }, - }, - }, - oc: consumerdata.TraceData{ - Node: &occommon.Node{}, - Resource: &ocresource.Resource{}, - Spans: []*octrace.Span{ocSpan1, ocSpan2}, - SourceFormat: sourceFormat, - }, - }, - } - - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - got := ResourceSpansToTraceData(&test.otlp) - assert.EqualValues(t, test.oc, got) - }) - } -}