Skip to content
This repository was archived by the owner on Nov 7, 2022. It is now read-only.

Commit d3300a2

Browse files
author
Paulo Janotti
authored
Valid OC proto traceID from 64bit ZipkinV2 traceID (#330)
* Valid OC proto traceID from 64bit ZipkinV2 traceID * Revert go.mod and go.sum changes
1 parent 268822b commit d3300a2

2 files changed

Lines changed: 99 additions & 14 deletions

File tree

receiver/zipkin/trace_receiver.go

Lines changed: 29 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import (
1818
"compress/gzip"
1919
"compress/zlib"
2020
"context"
21-
"encoding/hex"
21+
"encoding/binary"
2222
"encoding/json"
2323
"errors"
2424
"fmt"
@@ -282,28 +282,48 @@ func (zr *ZipkinReceiver) ServeHTTP(w http.ResponseWriter, r *http.Request) {
282282
w.WriteHeader(http.StatusAccepted)
283283
}
284284

285-
var errNilZipkinSpan = errors.New("non-nil Zipkin span expected")
285+
var (
286+
errNilZipkinSpan = errors.New("non-nil Zipkin span expected")
287+
errZeroTraceID = errors.New("trace id is zero")
288+
errZeroID = errors.New("id is zero")
289+
)
286290

287-
var blankIP net.IP
291+
func zTraceIDToOCProtoTraceID(zTraceID zipkinmodel.TraceID) ([]byte, error) {
292+
if zTraceID.High == 0 && zTraceID.Low == 0 {
293+
return nil, errZeroTraceID
294+
}
295+
traceID := make([]byte, 16)
296+
binary.BigEndian.PutUint64(traceID[:8], uint64(zTraceID.High))
297+
binary.BigEndian.PutUint64(traceID[8:], uint64(zTraceID.Low))
298+
return traceID, nil
299+
}
300+
301+
func zSpanIDToOCProtoSpanID(id zipkinmodel.ID) ([]byte, error) {
302+
if id == 0 {
303+
return nil, errZeroID
304+
}
305+
spanID := make([]byte, 8)
306+
binary.BigEndian.PutUint64(spanID, uint64(id))
307+
return spanID, nil
308+
}
288309

289310
func zipkinSpanToTraceSpan(zs *zipkinmodel.SpanModel) (*tracepb.Span, *commonpb.Node, error) {
290311
if zs == nil {
291312
return nil, nil, errNilZipkinSpan
292313
}
293314

294315
node := nodeFromZipkinEndpoints(zs)
295-
296-
traceID, err := hexStrToBytes(zs.TraceID.String())
316+
traceID, err := zTraceIDToOCProtoTraceID(zs.TraceID)
297317
if err != nil {
298318
return nil, node, fmt.Errorf("TraceID: %v", err)
299319
}
300-
spanID, err := hexStrToBytes(zs.ID.String())
320+
spanID, err := zSpanIDToOCProtoSpanID(zs.ID)
301321
if err != nil {
302322
return nil, node, fmt.Errorf("SpanID: %v", err)
303323
}
304324
var parentSpanID []byte
305325
if zs.ParentID != nil {
306-
parentSpanID, err = hexStrToBytes(zs.ParentID.String())
326+
parentSpanID, err = zSpanIDToOCProtoSpanID(*zs.ParentID)
307327
if err != nil {
308328
return nil, node, fmt.Errorf("ParentSpanID: %v", err)
309329
}
@@ -356,6 +376,8 @@ func nodeFromZipkinEndpoints(zs *zipkinmodel.SpanModel) *commonpb.Node {
356376
return node
357377
}
358378

379+
var blankIP net.IP
380+
359381
func zipkinEndpointIntoAttributes(ep *zipkinmodel.Endpoint, into map[string]string, prefixFunc func(string) string) map[string]string {
360382
if into == nil {
361383
into = make(map[string]string)
@@ -420,13 +442,6 @@ var canonicalCodesMap = map[string]int32{
420442
"UNAUTHENTICATED": 16,
421443
}
422444

423-
func hexStrToBytes(hexStr string) ([]byte, error) {
424-
if len(hexStr) == 0 {
425-
return nil, nil
426-
}
427-
return hex.DecodeString(hexStr)
428-
}
429-
430445
func zipkinSpanKindToProtoSpanKind(skind zipkinmodel.Kind) tracepb.Span_SpanKind {
431446
switch strings.ToUpper(string(skind)) {
432447
case "CLIENT":

receiver/zipkin/trace_receiver_test.go

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import (
2727
"time"
2828

2929
openzipkin "github.com/openzipkin/zipkin-go"
30+
zipkinmodel "github.com/openzipkin/zipkin-go/model"
3031
zhttp "github.com/openzipkin/zipkin-go/reporter/http"
3132
"go.opencensus.io/exporter/zipkin"
3233

@@ -40,6 +41,75 @@ import (
4041
"github.com/census-instrumentation/opencensus-service/translator/trace"
4142
)
4243

44+
func TestTraceIDConversion(t *testing.T) {
45+
longID, _ := zipkinmodel.TraceIDFromHex("01020304050607080102030405060708")
46+
shortID, _ := zipkinmodel.TraceIDFromHex("0102030405060708")
47+
zeroID, _ := zipkinmodel.TraceIDFromHex("0000000000000000")
48+
tests := []struct {
49+
name string
50+
id zipkinmodel.TraceID
51+
want []byte
52+
wantErr error
53+
}{
54+
{
55+
name: "128bit traceID",
56+
id: longID,
57+
want: []byte{1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8},
58+
wantErr: nil,
59+
},
60+
{
61+
name: "64bit traceID",
62+
id: shortID,
63+
want: []byte{0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8},
64+
wantErr: nil,
65+
},
66+
{
67+
name: "zero traceID",
68+
id: zeroID,
69+
want: nil,
70+
wantErr: errZeroTraceID,
71+
},
72+
}
73+
74+
for _, tc := range tests {
75+
got, gotErr := zTraceIDToOCProtoTraceID(tc.id)
76+
if tc.wantErr != gotErr {
77+
t.Errorf("gotErr=%v wantErr=%v", gotErr, tc.wantErr)
78+
}
79+
if !reflect.DeepEqual(got, tc.want) {
80+
t.Errorf("got=%v want=%v", got, tc.want)
81+
}
82+
}
83+
}
84+
85+
func TestShortIDSpanConversion(t *testing.T) {
86+
shortID, _ := zipkinmodel.TraceIDFromHex("0102030405060708")
87+
if shortID.High != 0 {
88+
t.Errorf("wanted 64bit traceID, so TraceID.High must be zero")
89+
}
90+
91+
zc := zipkinmodel.SpanContext{
92+
TraceID: shortID,
93+
ID: zipkinmodel.ID(shortID.Low),
94+
}
95+
zs := zipkinmodel.SpanModel{
96+
SpanContext: zc,
97+
}
98+
99+
ocSpan, _, err := zipkinSpanToTraceSpan(&zs)
100+
if err != nil {
101+
t.Fatalf("unexpected error %v", err)
102+
}
103+
if len(ocSpan.TraceId) != 16 {
104+
t.Fatalf("incorrect OC proto trace id length")
105+
}
106+
107+
want := []byte{0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8}
108+
if !reflect.DeepEqual(ocSpan.TraceId, want) {
109+
t.Errorf("got=%v want=%v", ocSpan.TraceId, want)
110+
}
111+
}
112+
43113
func TestConvertSpansToTraceSpans_json(t *testing.T) {
44114
// Using Adrian Cole's sample at https://gist.github.com/adriancole/e8823c19dfed64e2eb71
45115
blob, err := ioutil.ReadFile("./testdata/sample1.json")

0 commit comments

Comments
 (0)