diff --git a/receiver/kafkareceiver/zipkin_unmarshaler.go b/receiver/kafkareceiver/zipkin_unmarshaler.go index 895e5552bd0..0d36276dd82 100644 --- a/receiver/kafkareceiver/zipkin_unmarshaler.go +++ b/receiver/kafkareceiver/zipkin_unmarshaler.go @@ -15,19 +15,18 @@ package kafkareceiver import ( - "context" "encoding/json" - "github.com/apache/thrift/lib/go/thrift" - "github.com/jaegertracing/jaeger/thrift-gen/zipkincore" zipkinmodel "github.com/openzipkin/zipkin-go/model" "github.com/openzipkin/zipkin-go/proto/zipkin_proto3" "go.opentelemetry.io/collector/consumer/pdata" - zipkintranslator "go.opentelemetry.io/collector/translator/trace/zipkin" + "go.opentelemetry.io/collector/translator/trace/zipkinv1" "go.opentelemetry.io/collector/translator/trace/zipkinv2" ) +var v1ThriftUnmarshaler = zipkinv1.NewThriftTracesUnmarshaler() + type zipkinProtoSpanUnmarshaler struct { } @@ -71,41 +70,9 @@ type zipkinThriftSpanUnmarshaler struct { var _ TracesUnmarshaler = (*zipkinThriftSpanUnmarshaler)(nil) func (z zipkinThriftSpanUnmarshaler) Unmarshal(bytes []byte) (pdata.Traces, error) { - spans, err := deserializeZipkinThrift(bytes) - if err != nil { - return pdata.NewTraces(), err - } - return zipkintranslator.V1ThriftBatchToInternalTraces(spans) - + return v1ThriftUnmarshaler.Unmarshal(bytes) } func (z zipkinThriftSpanUnmarshaler) Encoding() string { return "zipkin_thrift" } - -// deserializeThrift decodes Thrift bytes to a list of spans. -// This code comes from jaegertracing/jaeger, ideally we should have imported -// it but this was creating many conflicts so brought the code to here. -// https://github.com/jaegertracing/jaeger/blob/6bc0c122bfca8e737a747826ae60a22a306d7019/model/converter/thrift/zipkin/deserialize.go#L36 -func deserializeZipkinThrift(b []byte) ([]*zipkincore.Span, error) { - buffer := thrift.NewTMemoryBuffer() - buffer.Write(b) - - transport := thrift.NewTBinaryProtocolConf(buffer, nil) - _, size, err := transport.ReadListBegin(context.Background()) // Ignore the returned element type - if err != nil { - return nil, err - } - - // We don't depend on the size returned by ReadListBegin to preallocate the array because it - // sometimes returns a nil error on bad input and provides an unreasonably large int for size - var spans []*zipkincore.Span - for i := 0; i < size; i++ { - zs := &zipkincore.Span{} - if err = zs.Read(context.Background(), transport); err != nil { - return nil, err - } - spans = append(spans, zs) - } - return spans, nil -} diff --git a/receiver/kafkareceiver/zipkin_unmarshaler_test.go b/receiver/kafkareceiver/zipkin_unmarshaler_test.go index 58469532b24..8c4248be3ca 100644 --- a/receiver/kafkareceiver/zipkin_unmarshaler_test.go +++ b/receiver/kafkareceiver/zipkin_unmarshaler_test.go @@ -28,11 +28,10 @@ import ( "go.opentelemetry.io/collector/consumer/pdata" "go.opentelemetry.io/collector/translator/conventions" - zipkintranslator "go.opentelemetry.io/collector/translator/trace/zipkin" "go.opentelemetry.io/collector/translator/trace/zipkinv2" ) -var fromTranslator zipkinv2.FromTranslator +var v2FromTranslator zipkinv2.FromTranslator func TestUnmarshalZipkin(t *testing.T) { td := pdata.NewTraces() @@ -46,7 +45,7 @@ func TestUnmarshalZipkin(t *testing.T) { span.SetTraceID(pdata.NewTraceID([16]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16})) span.SetSpanID(pdata.NewSpanID([8]byte{1, 2, 3, 4, 5, 6, 7, 8})) span.SetParentSpanID(pdata.NewSpanID([8]byte{0, 0, 0, 0, 0, 0, 0, 0})) - ret, err := fromTranslator.FromTraces(td) + ret, err := v2FromTranslator.FromTraces(td) require.NoError(t, err) spans := ret.([]*zipkinmodel.SpanModel) @@ -62,7 +61,7 @@ func TestUnmarshalZipkin(t *testing.T) { require.NoError(t, err) require.NoError(t, protocolTransport.WriteListEnd(context.Background())) - tdThrift, err := zipkintranslator.V1ThriftBatchToInternalTraces([]*zipkincore.Span{tSpan}) + tdThrift, err := v1ThriftUnmarshaler.Unmarshal(thriftTransport.Buffer.Bytes()) require.NoError(t, err) protoBytes, err := new(zipkin_proto3.SpanSerializer).Serialize(spans) @@ -106,7 +105,7 @@ func TestUnmarshalZipkin(t *testing.T) { func TestUnmarshalZipkinThrift_error(t *testing.T) { p := zipkinThriftSpanUnmarshaler{} got, err := p.Unmarshal([]byte("+$%")) - assert.Equal(t, pdata.NewTraces(), got) + assert.Equal(t, pdata.Traces{}, got) assert.Error(t, err) } diff --git a/receiver/zipkinreceiver/trace_receiver.go b/receiver/zipkinreceiver/trace_receiver.go index 6b3381e493c..488715424b5 100644 --- a/receiver/zipkinreceiver/trace_receiver.go +++ b/receiver/zipkinreceiver/trace_receiver.go @@ -27,7 +27,6 @@ import ( "strings" "sync" - jaegerzipkin "github.com/jaegertracing/jaeger/model/converter/thrift/zipkin" zipkinmodel "github.com/openzipkin/zipkin-go/model" "github.com/openzipkin/zipkin-go/proto/zipkin_proto3" @@ -39,7 +38,7 @@ import ( "go.opentelemetry.io/collector/consumer/pdata" "go.opentelemetry.io/collector/internal/model" "go.opentelemetry.io/collector/obsreport" - "go.opentelemetry.io/collector/translator/trace/zipkin" + "go.opentelemetry.io/collector/translator/trace/zipkinv1" "go.opentelemetry.io/collector/translator/trace/zipkinv2" ) @@ -66,6 +65,9 @@ type ZipkinReceiver struct { server *http.Server config *Config translator model.ToTracesTranslator + + v1ThriftUnmarshaler model.TracesUnmarshaler + v1JSONUnmarshaler model.TracesUnmarshaler } var _ http.Handler = (*ZipkinReceiver)(nil) @@ -77,10 +79,12 @@ func New(config *Config, nextConsumer consumer.Traces) (*ZipkinReceiver, error) } zr := &ZipkinReceiver{ - nextConsumer: nextConsumer, - id: config.ID(), - config: config, - translator: zipkinv2.ToTranslator{ParseStringTags: config.ParseStringTags}, + nextConsumer: nextConsumer, + id: config.ID(), + config: config, + translator: zipkinv2.ToTranslator{ParseStringTags: config.ParseStringTags}, + v1ThriftUnmarshaler: zipkinv1.NewThriftTracesUnmarshaler(), + v1JSONUnmarshaler: zipkinv1.NewJSONTracesUnmarshaler(config.ParseStringTags), } return zr, nil } @@ -116,14 +120,9 @@ func (zr *ZipkinReceiver) Start(_ context.Context, host component.Host) error { // v1ToTraceSpans parses Zipkin v1 JSON traces and converts them to OpenCensus Proto spans. func (zr *ZipkinReceiver) v1ToTraceSpans(blob []byte, hdr http.Header) (reqs pdata.Traces, err error) { if hdr.Get("Content-Type") == "application/x-thrift" { - zSpans, err := jaegerzipkin.DeserializeThrift(blob) - if err != nil { - return pdata.NewTraces(), err - } - - return zipkin.V1ThriftBatchToInternalTraces(zSpans) + return zr.v1ThriftUnmarshaler.Unmarshal(blob) } - return zipkin.V1JSONBatchToInternalTraces(blob, zr.config.ParseStringTags) + return zr.v1JSONUnmarshaler.Unmarshal(blob) } // v2ToTraceSpans parses Zipkin v2 JSON or Protobuf traces and converts them to OpenCensus Proto spans. diff --git a/receiver/zipkinreceiver/trace_receiver_test.go b/receiver/zipkinreceiver/trace_receiver_test.go index 8fad5f1835b..3b439a587d7 100644 --- a/receiver/zipkinreceiver/trace_receiver_test.go +++ b/receiver/zipkinreceiver/trace_receiver_test.go @@ -51,7 +51,7 @@ import ( const ( zipkinV2Single = "../../translator/trace/zipkinv2/testdata/zipkin_v2_single.json" zipkinV2NoTimestamp = "../../translator/trace/zipkinv2/testdata/zipkin_v2_notimestamp.json" - zipkinV1SingleBatch = "../../translator/trace/zipkin/testdata/zipkin_v1_single_batch.json" + zipkinV1SingleBatch = "../../translator/trace/zipkinv1/testdata/zipkin_v1_single_batch.json" ) var zipkinReceiverID = config.NewIDWithName(typeStr, "receiver_test") diff --git a/translator/trace/zipkin/zipkinv1_thrift_to_traces.go b/translator/trace/zipkin/zipkinv1_thrift_to_traces.go deleted file mode 100644 index 0eee057a9df..00000000000 --- a/translator/trace/zipkin/zipkinv1_thrift_to_traces.go +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright The 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 zipkin - -import ( - "github.com/jaegertracing/jaeger/thrift-gen/zipkincore" - - "go.opentelemetry.io/collector/consumer/pdata" - "go.opentelemetry.io/collector/translator/internaldata" -) - -// V1ThriftBatchToInternalTraces transforms Zipkin v1 spans into pdata.Traces. -func V1ThriftBatchToInternalTraces(zSpans []*zipkincore.Span) (pdata.Traces, error) { - traces := pdata.NewTraces() - ocTraces, _ := v1ThriftBatchToOCProto(zSpans) - - for _, td := range ocTraces { - tmp := internaldata.OCToTraces(td.Node, td.Resource, td.Spans) - tmp.ResourceSpans().MoveAndAppendTo(traces.ResourceSpans()) - } - return traces, nil -} diff --git a/translator/trace/zipkin/zipkinv1_thrift_to_traces_test.go b/translator/trace/zipkin/zipkinv1_thrift_to_traces_test.go deleted file mode 100644 index c019ee7c8cb..00000000000 --- a/translator/trace/zipkin/zipkinv1_thrift_to_traces_test.go +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright The 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 zipkin - -import ( - "encoding/json" - "io/ioutil" - "testing" - - "github.com/jaegertracing/jaeger/thrift-gen/zipkincore" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func TestV1ThriftToTraces(t *testing.T) { - blob, err := ioutil.ReadFile("./testdata/zipkin_v1_thrift_single_batch.json") - require.NoError(t, err, "Failed to load test data") - - var ztSpans []*zipkincore.Span - err = json.Unmarshal(blob, &ztSpans) - require.NoError(t, err, "Failed to unmarshal json into zipkin v1 thrift") - - got, err := V1ThriftBatchToInternalTraces(ztSpans) - require.NoError(t, err, "Failed to translate zipkinv1 thrift to OC proto") - - assert.Equal(t, 5, got.SpanCount()) -} diff --git a/translator/trace/zipkin/zipkinv1_to_traces_test.go b/translator/trace/zipkin/zipkinv1_to_traces_test.go deleted file mode 100644 index e91d2b1c734..00000000000 --- a/translator/trace/zipkin/zipkinv1_to_traces_test.go +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright The 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 zipkin - -import ( - "io/ioutil" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func TestSingleJSONV1BatchToTraces(t *testing.T) { - blob, err := ioutil.ReadFile("./testdata/zipkin_v1_single_batch.json") - require.NoError(t, err, "Failed to load test data") - - got, err := V1JSONBatchToInternalTraces(blob, false) - require.NoError(t, err, "Failed to translate zipkinv1 to OC proto") - - assert.Equal(t, 5, got.SpanCount()) -} - -func TestErrorSpanToTraces(t *testing.T) { - blob, err := ioutil.ReadFile("./testdata/zipkin_v1_error_batch.json") - require.NoError(t, err, "Failed to load test data") - - td, err := V1JSONBatchToInternalTraces(blob, false) - assert.Error(t, err, "Should have generated error") - assert.NotNil(t, td) -} diff --git a/translator/trace/zipkin/consumerdata.go b/translator/trace/zipkinv1/consumerdata.go similarity index 98% rename from translator/trace/zipkin/consumerdata.go rename to translator/trace/zipkinv1/consumerdata.go index 6495ca93f28..65fdd62d770 100644 --- a/translator/trace/zipkin/consumerdata.go +++ b/translator/trace/zipkinv1/consumerdata.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package zipkin +package zipkinv1 import ( commonpb "github.com/census-instrumentation/opencensus-proto/gen-go/agent/common/v1" diff --git a/translator/trace/zipkin/grpc_http_mapper.go b/translator/trace/zipkinv1/grpc_http_mapper.go similarity index 99% rename from translator/trace/zipkin/grpc_http_mapper.go rename to translator/trace/zipkinv1/grpc_http_mapper.go index 52d75b9f3ed..e3a1beb6428 100644 --- a/translator/trace/zipkin/grpc_http_mapper.go +++ b/translator/trace/zipkinv1/grpc_http_mapper.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package zipkin +package zipkinv1 // https://github.com/googleapis/googleapis/blob/bee79fbe03254a35db125dc6d2f1e9b752b390fe/google/rpc/code.proto#L33-L186 const ( diff --git a/translator/trace/zipkin/grpc_http_mapper_test.go b/translator/trace/zipkinv1/grpc_http_mapper_test.go similarity index 98% rename from translator/trace/zipkin/grpc_http_mapper_test.go rename to translator/trace/zipkinv1/grpc_http_mapper_test.go index 874ac1a6d2e..3b5fdde1beb 100644 --- a/translator/trace/zipkin/grpc_http_mapper_test.go +++ b/translator/trace/zipkinv1/grpc_http_mapper_test.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package zipkin +package zipkinv1 import ( "testing" diff --git a/translator/trace/zipkin/zipkinv1_to_protospan.go b/translator/trace/zipkinv1/json.go similarity index 91% rename from translator/trace/zipkin/zipkinv1_to_protospan.go rename to translator/trace/zipkinv1/json.go index d61ae268696..6c2700e8f4c 100644 --- a/translator/trace/zipkin/zipkinv1_to_protospan.go +++ b/translator/trace/zipkinv1/json.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package zipkin +package zipkinv1 import ( "encoding/json" @@ -28,8 +28,10 @@ import ( "google.golang.org/protobuf/types/known/timestamppb" "go.opentelemetry.io/collector/consumer/pdata" - idutils "go.opentelemetry.io/collector/internal/idutils" + "go.opentelemetry.io/collector/internal/idutils" + "go.opentelemetry.io/collector/internal/model" tracetranslator "go.opentelemetry.io/collector/translator/trace" + "go.opentelemetry.io/collector/translator/trace/zipkin" ) var ( @@ -39,14 +41,30 @@ var ( msgZipkinV1SpanIDError = "zipkinV1 span id" msgZipkinV1ParentIDError = "zipkinV1 span parentId" // Generic hex to ID conversion errors - errHexTraceIDWrongLen = errors.New("hex traceId span has wrong length (expected 16 or 32)") - errHexTraceIDParsing = errors.New("failed to parse hex traceId") - errHexTraceIDZero = errors.New("traceId is zero") - errHexIDWrongLen = errors.New("hex Id has wrong length (expected 16)") - errHexIDParsing = errors.New("failed to parse hex Id") - errHexIDZero = errors.New("ID is zero") + errHexTraceIDWrongLen = errors.New("hex traceId span has wrong length (expected 16 or 32)") + errHexTraceIDParsing = errors.New("failed to parse hex traceId") + errHexTraceIDZero = errors.New("traceId is zero") + errHexIDWrongLen = errors.New("hex Id has wrong length (expected 16)") + errHexIDParsing = errors.New("failed to parse hex Id") + errHexIDZero = errors.New("ID is zero") + _ model.TracesDecoder = (*jsonDecoder)(nil) ) +type jsonDecoder struct { + // ParseStringTags should be set to true if tags should be converted to numbers when possible. + ParseStringTags bool +} + +// DecodeTraces from JSON bytes. +func (j jsonDecoder) DecodeTraces(buf []byte) (interface{}, error) { + return v1JSONBatchToOCProto(buf, j.ParseStringTags) +} + +// NewJSONTracesUnmarshaler returns an unmarshaler for Zipkin JSON. +func NewJSONTracesUnmarshaler(parseStringTags bool) model.TracesUnmarshaler { + return model.NewTracesUnmarshaler(jsonDecoder{ParseStringTags: parseStringTags}, toTranslator{}) +} + // Trace translation from Zipkin V1 is a bit of special case since there is no model // defined in golang for Zipkin V1 spans and there is no need to define one here, given // that the zipkinV1Span defined below is as defined at: @@ -254,7 +272,7 @@ func parseAnnotationValue(value string, parseStringTags bool) *tracepb.Attribute pbAttrib := &tracepb.AttributeValue{} if parseStringTags { - switch DetermineValueType(value) { + switch zipkin.DetermineValueType(value) { case pdata.AttributeValueTypeInt: iValue, _ := strconv.ParseInt(value, 10, 64) pbAttrib.Value = &tracepb.AttributeValue_IntValue{IntValue: iValue} @@ -509,7 +527,7 @@ func setTimestampsIfUnset(span *tracepb.Span) { if span.Attributes.AttributeMap == nil { span.Attributes.AttributeMap = make(map[string]*tracepb.AttributeValue, 1) } - span.Attributes.AttributeMap[StartTimeAbsent] = &tracepb.AttributeValue{ + span.Attributes.AttributeMap[zipkin.StartTimeAbsent] = &tracepb.AttributeValue{ Value: &tracepb.AttributeValue_BoolValue{ BoolValue: true, }} diff --git a/translator/trace/zipkin/zipkinv1_to_protospan_test.go b/translator/trace/zipkinv1/json_test.go similarity index 95% rename from translator/trace/zipkin/zipkinv1_to_protospan_test.go rename to translator/trace/zipkinv1/json_test.go index 1125cdf09c9..accb45b69c6 100644 --- a/translator/trace/zipkin/zipkinv1_to_protospan_test.go +++ b/translator/trace/zipkinv1/json_test.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package zipkin +package zipkinv1 import ( "encoding/json" @@ -24,17 +24,42 @@ import ( commonpb "github.com/census-instrumentation/opencensus-proto/gen-go/agent/common/v1" tracepb "github.com/census-instrumentation/opencensus-proto/gen-go/trace/v1" - "github.com/google/go-cmp/cmp" zipkinmodel "github.com/openzipkin/zipkin-go/model" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "google.golang.org/protobuf/testing/protocmp" "google.golang.org/protobuf/types/known/timestamppb" "go.opentelemetry.io/collector/translator/conventions" tracetranslator "go.opentelemetry.io/collector/translator/trace" + "go.opentelemetry.io/collector/translator/trace/zipkin" ) +func TestSingleJSONV1BatchToTraces(t *testing.T) { + blob, err := ioutil.ReadFile("./testdata/zipkin_v1_single_batch.json") + require.NoError(t, err, "Failed to load test data") + + got, err := jsonDecoder{ParseStringTags: false}.DecodeTraces(blob) + require.NoError(t, err, "Failed to translate zipkinv1 to OC proto") + + td := got.([]traceData) + spanCount := 0 + + for _, data := range td { + spanCount += len(data.Spans) + } + + assert.Equal(t, 5, spanCount) +} + +func TestErrorSpanToTraces(t *testing.T) { + blob, err := ioutil.ReadFile("./testdata/zipkin_v1_error_batch.json") + require.NoError(t, err, "Failed to load test data") + + got, err := jsonDecoder{ParseStringTags: false}.DecodeTraces(blob) + assert.Error(t, err, "Should have generated error") + assert.Nil(t, got) +} + func Test_hexIDToOCID(t *testing.T) { tests := []struct { name string @@ -159,11 +184,7 @@ func TestSingleJSONV1BatchToOCProto(t *testing.T) { got, err := v1JSONBatchToOCProto(blob, parseStringTags) require.NoError(t, err, "Failed to translate zipkinv1 to OC proto") - want := ocBatchesFromZipkinV1 - sortTraceByNodeName(want) - sortTraceByNodeName(got) - - assert.EqualValues(t, got, want) + compareTraceData(t, got, ocBatchesFromZipkinV1) } func TestMultipleJSONV1BatchesToOCProto(t *testing.T) { @@ -200,13 +221,7 @@ func TestMultipleJSONV1BatchesToOCProto(t *testing.T) { got = append(got, *tsr) } - want := ocBatchesFromZipkinV1 - sortTraceByNodeName(want) - sortTraceByNodeName(got) - - if diff := cmp.Diff(want, got, protocmp.Transform()); diff != "" { - t.Errorf("Unexpected difference:\n%v", diff) - } + compareTraceData(t, got, ocBatchesFromZipkinV1) } func sortTraceByNodeName(trace []traceData) { @@ -538,7 +553,7 @@ func TestSpanWithoutTimestampGetsTag(t *testing.T) { wantAttributes := &tracepb.Span_Attributes{ AttributeMap: map[string]*tracepb.AttributeValue{ - StartTimeAbsent: { + zipkin.StartTimeAbsent: { Value: &tracepb.AttributeValue_BoolValue{ BoolValue: true, }, diff --git a/translator/trace/zipkin/status_code.go b/translator/trace/zipkinv1/status_code.go similarity index 99% rename from translator/trace/zipkin/status_code.go rename to translator/trace/zipkinv1/status_code.go index 62f0fff9bb5..9cb611a6424 100644 --- a/translator/trace/zipkin/status_code.go +++ b/translator/trace/zipkinv1/status_code.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package zipkin +package zipkinv1 import ( "fmt" diff --git a/translator/trace/zipkin/status_code_test.go b/translator/trace/zipkinv1/status_code_test.go similarity index 99% rename from translator/trace/zipkin/status_code_test.go rename to translator/trace/zipkinv1/status_code_test.go index c568dd34b1d..3b84f2687b5 100644 --- a/translator/trace/zipkin/status_code_test.go +++ b/translator/trace/zipkinv1/status_code_test.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package zipkin +package zipkinv1 import ( "fmt" diff --git a/translator/trace/zipkin/testdata/zipkin_v1_error_batch.json b/translator/trace/zipkinv1/testdata/zipkin_v1_error_batch.json similarity index 100% rename from translator/trace/zipkin/testdata/zipkin_v1_error_batch.json rename to translator/trace/zipkinv1/testdata/zipkin_v1_error_batch.json diff --git a/translator/trace/zipkin/testdata/zipkin_v1_local_component.json b/translator/trace/zipkinv1/testdata/zipkin_v1_local_component.json similarity index 100% rename from translator/trace/zipkin/testdata/zipkin_v1_local_component.json rename to translator/trace/zipkinv1/testdata/zipkin_v1_local_component.json diff --git a/translator/trace/zipkin/testdata/zipkin_v1_multiple_batches.json b/translator/trace/zipkinv1/testdata/zipkin_v1_multiple_batches.json similarity index 100% rename from translator/trace/zipkin/testdata/zipkin_v1_multiple_batches.json rename to translator/trace/zipkinv1/testdata/zipkin_v1_multiple_batches.json diff --git a/translator/trace/zipkin/testdata/zipkin_v1_single_batch.json b/translator/trace/zipkinv1/testdata/zipkin_v1_single_batch.json similarity index 100% rename from translator/trace/zipkin/testdata/zipkin_v1_single_batch.json rename to translator/trace/zipkinv1/testdata/zipkin_v1_single_batch.json diff --git a/translator/trace/zipkin/testdata/zipkin_v1_thrift_local_component.json b/translator/trace/zipkinv1/testdata/zipkin_v1_thrift_local_component.json similarity index 100% rename from translator/trace/zipkin/testdata/zipkin_v1_thrift_local_component.json rename to translator/trace/zipkinv1/testdata/zipkin_v1_thrift_local_component.json diff --git a/translator/trace/zipkin/testdata/zipkin_v1_thrift_single_batch.json b/translator/trace/zipkinv1/testdata/zipkin_v1_thrift_single_batch.json similarity index 100% rename from translator/trace/zipkin/testdata/zipkin_v1_thrift_single_batch.json rename to translator/trace/zipkinv1/testdata/zipkin_v1_thrift_single_batch.json diff --git a/translator/trace/zipkin/zipkinv1_thrift_to_protospan.go b/translator/trace/zipkinv1/thrift.go similarity index 92% rename from translator/trace/zipkin/zipkinv1_thrift_to_protospan.go rename to translator/trace/zipkinv1/thrift.go index 2e588560bbd..73dff84642a 100644 --- a/translator/trace/zipkin/zipkinv1_thrift_to_protospan.go +++ b/translator/trace/zipkinv1/thrift.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package zipkin +package zipkinv1 import ( "bytes" @@ -24,12 +24,32 @@ import ( "net" tracepb "github.com/census-instrumentation/opencensus-proto/gen-go/trace/v1" + jaegerzipkin "github.com/jaegertracing/jaeger/model/converter/thrift/zipkin" "github.com/jaegertracing/jaeger/thrift-gen/zipkincore" "google.golang.org/protobuf/types/known/timestamppb" - idutils "go.opentelemetry.io/collector/internal/idutils" + "go.opentelemetry.io/collector/internal/idutils" + "go.opentelemetry.io/collector/internal/model" ) +var _ model.TracesDecoder = (*thriftDecoder)(nil) + +type thriftDecoder struct{} + +// DecodeTraces from Thrift bytes. +func (t thriftDecoder) DecodeTraces(buf []byte) (interface{}, error) { + spans, err := jaegerzipkin.DeserializeThrift(buf) + if err != nil { + return nil, err + } + return v1ThriftBatchToOCProto(spans) +} + +// NewThriftTracesUnmarshaler returns an unmarshaler for Zipkin Thrift. +func NewThriftTracesUnmarshaler() model.TracesUnmarshaler { + return model.NewTracesUnmarshaler(thriftDecoder{}, toTranslator{}) +} + // v1ThriftBatchToOCProto converts Zipkin v1 spans to OC Proto. func v1ThriftBatchToOCProto(zSpans []*zipkincore.Span) ([]traceData, error) { ocSpansAndParsedAnnotations := make([]ocSpanAndParsedAnnotations, 0, len(zSpans)) diff --git a/translator/trace/zipkin/zipkinv1_thrift_to_protospan_test.go b/translator/trace/zipkinv1/thrift_test.go similarity index 93% rename from translator/trace/zipkin/zipkinv1_thrift_to_protospan_test.go rename to translator/trace/zipkinv1/thrift_test.go index 39715f996a2..8747827fab4 100644 --- a/translator/trace/zipkin/zipkinv1_thrift_to_protospan_test.go +++ b/translator/trace/zipkinv1/thrift_test.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package zipkin +package zipkinv1 import ( "encoding/binary" @@ -23,14 +23,47 @@ import ( "testing" tracepb "github.com/census-instrumentation/opencensus-proto/gen-go/trace/v1" + "github.com/google/go-cmp/cmp" + "github.com/jaegertracing/jaeger/model/converter/thrift/zipkin" "github.com/jaegertracing/jaeger/thrift-gen/zipkincore" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "google.golang.org/protobuf/testing/protocmp" "go.opentelemetry.io/collector/translator/conventions" tracetranslator "go.opentelemetry.io/collector/translator/trace" ) +// compareTraceData compares got to want while ignoring order. Both are modified in place. +func compareTraceData(t *testing.T, got []traceData, want []traceData) { + sortTraceByNodeName(want) + sortTraceByNodeName(got) + if diff := cmp.Diff(want, got, protocmp.Transform()); diff != "" { + t.Errorf("Unexpected difference:\n%v", diff) + } +} + +func TestV1ThriftToTraces(t *testing.T) { + blob, err := ioutil.ReadFile("./testdata/zipkin_v1_thrift_single_batch.json") + require.NoError(t, err, "Failed to load test data") + + var zSpans []*zipkincore.Span + require.NoError(t, json.Unmarshal(blob, &zSpans), "failed to unmarshal json test file") + thriftBytes := zipkin.SerializeThrift(zSpans) + + got, err := thriftDecoder{}.DecodeTraces(thriftBytes) + require.NoError(t, err, "Failed to translate zipkinv1 thrift to OC proto") + + td := got.([]traceData) + spanCount := 0 + + for _, data := range td { + spanCount += len(data.Spans) + } + + assert.Equal(t, 5, spanCount) +} + func TestZipkinThriftFallbackToLocalComponent(t *testing.T) { blob, err := ioutil.ReadFile("./testdata/zipkin_v1_thrift_local_component.json") require.NoError(t, err, "Failed to load test data") @@ -68,11 +101,7 @@ func TestV1ThriftToOCProto(t *testing.T) { got, err := v1ThriftBatchToOCProto(ztSpans) require.NoError(t, err, "Failed to translate zipkinv1 thrift to OC proto") - want := ocBatchesFromZipkinV1 - sortTraceByNodeName(want) - sortTraceByNodeName(got) - - assert.EqualValues(t, want, got) + compareTraceData(t, got, ocBatchesFromZipkinV1) } func BenchmarkV1ThriftToOCProto(b *testing.B) { diff --git a/translator/trace/zipkin/zipkinv1_to_traces.go b/translator/trace/zipkinv1/to_translator.go similarity index 54% rename from translator/trace/zipkin/zipkinv1_to_traces.go rename to translator/trace/zipkinv1/to_translator.go index 997edb16d8d..0819510201e 100644 --- a/translator/trace/zipkin/zipkinv1_to_traces.go +++ b/translator/trace/zipkinv1/to_translator.go @@ -12,25 +12,31 @@ // See the License for the specific language governing permissions and // limitations under the License. -package zipkin +package zipkinv1 import ( "go.opentelemetry.io/collector/consumer/pdata" + "go.opentelemetry.io/collector/internal/model" "go.opentelemetry.io/collector/translator/internaldata" ) -// V1JSONBatchToInternalTraces transforms a JSON blob with a list of Zipkin v1 spans into pdata.Traces. -func V1JSONBatchToInternalTraces(blob []byte, parseStringTags bool) (pdata.Traces, error) { - traces := pdata.NewTraces() +var _ model.ToTracesTranslator = (*toTranslator)(nil) - ocTraces, err := v1JSONBatchToOCProto(blob, parseStringTags) - if err != nil { - return traces, err +type toTranslator struct{} + +// ToTraces converts converts traceData to pdata.Traces. +func (t toTranslator) ToTraces(src interface{}) (pdata.Traces, error) { + ocTraces, ok := src.([]traceData) + if !ok { + return pdata.Traces{}, model.NewErrIncompatibleType([]traceData{}, src) } - for _, td := range ocTraces { - tmp := internaldata.OCToTraces(td.Node, td.Resource, td.Spans) - tmp.ResourceSpans().MoveAndAppendTo(traces.ResourceSpans()) + td := pdata.NewTraces() + + for _, trace := range ocTraces { + tmp := internaldata.OCToTraces(trace.Node, trace.Resource, trace.Spans) + tmp.ResourceSpans().MoveAndAppendTo(td.ResourceSpans()) } - return traces, nil + + return td, nil }