Skip to content

Commit 3dd4e81

Browse files
fix wrong representation of status value in zipkin exporter (open-telemetry#3340)
* export status codes to upper case in zipkin exporter * add test cases for status UNSET and ERROR * Update exporters/zipkin/model.go correct the usage of case-sensitive terms Co-authored-by: Tyler Yahn <MrAlias@users.noreply.github.com> * change unit test cases to test exact behavior * move this PR to unrelease section in the CHANGELOG.md Co-authored-by: Tyler Yahn <MrAlias@users.noreply.github.com>
1 parent 94ae231 commit 3dd4e81

File tree

4 files changed

+215
-15
lines changed

4 files changed

+215
-15
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
1313
- The `go.opentelemetry.io/otel/exporters/prometheus` exporter fixes duplicated `_total` suffixes. (#3369)
1414
- Cumulative metrics from the OpenCensus bridge (`go.opentelemetry.io/otel/bridge/opencensus`) are defined as monotonic sums, instead of non-monotonic. (#3389)
1515
- Asynchronous counters (`Counter` and `UpDownCounter`) from the metric SDK now produce delta sums when configured with delta temporality. (#3398)
16+
- Exported `Status` codes in the `go.opentelemetry.io/otel/exporters/zipkin` exporter are now exported as all upper case values. (#3340)
1617

1718
## [1.11.1/0.33.0] 2022-10-19
1819

exporters/zipkin/model.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
"fmt"
2121
"net"
2222
"strconv"
23+
"strings"
2324

2425
zkmodel "github.com/openzipkin/zipkin-go/model"
2526

@@ -209,7 +210,9 @@ func toZipkinTags(data tracesdk.ReadOnlySpan) map[string]string {
209210
}
210211

211212
if data.Status().Code != codes.Unset {
212-
m["otel.status_code"] = data.Status().Code.String()
213+
// Zipkin expect to receive uppercase status values
214+
// rather than default capitalized ones.
215+
m["otel.status_code"] = strings.ToUpper(data.Status().Code.String())
213216
}
214217

215218
if data.Status().Code == codes.Error {

exporters/zipkin/model_test.go

Lines changed: 208 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,85 @@ func TestModelConversion(t *testing.T) {
4545
)
4646

4747
inputBatch := tracetest.SpanStubs{
48-
// typical span data
48+
// typical span data with UNSET status
49+
{
50+
SpanContext: trace.NewSpanContext(trace.SpanContextConfig{
51+
TraceID: trace.TraceID{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F},
52+
SpanID: trace.SpanID{0xFF, 0xFE, 0xFD, 0xFC, 0xFB, 0xFA, 0xF9, 0xF8},
53+
}),
54+
Parent: trace.NewSpanContext(trace.SpanContextConfig{
55+
TraceID: trace.TraceID{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F},
56+
SpanID: trace.SpanID{0x3F, 0x3E, 0x3D, 0x3C, 0x3B, 0x3A, 0x39, 0x38},
57+
}),
58+
SpanKind: trace.SpanKindServer,
59+
Name: "foo",
60+
StartTime: time.Date(2020, time.March, 11, 19, 24, 0, 0, time.UTC),
61+
EndTime: time.Date(2020, time.March, 11, 19, 25, 0, 0, time.UTC),
62+
Attributes: []attribute.KeyValue{
63+
attribute.Int64("attr1", 42),
64+
attribute.String("attr2", "bar"),
65+
attribute.IntSlice("attr3", []int{0, 1, 2}),
66+
},
67+
Events: []tracesdk.Event{
68+
{
69+
Time: time.Date(2020, time.March, 11, 19, 24, 30, 0, time.UTC),
70+
Name: "ev1",
71+
Attributes: []attribute.KeyValue{
72+
attribute.Int64("eventattr1", 123),
73+
},
74+
},
75+
{
76+
Time: time.Date(2020, time.March, 11, 19, 24, 45, 0, time.UTC),
77+
Name: "ev2",
78+
Attributes: nil,
79+
},
80+
},
81+
Status: tracesdk.Status{
82+
Code: codes.Unset,
83+
Description: "",
84+
},
85+
Resource: res,
86+
},
87+
// typical span data with OK status
88+
{
89+
SpanContext: trace.NewSpanContext(trace.SpanContextConfig{
90+
TraceID: trace.TraceID{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F},
91+
SpanID: trace.SpanID{0xFF, 0xFE, 0xFD, 0xFC, 0xFB, 0xFA, 0xF9, 0xF8},
92+
}),
93+
Parent: trace.NewSpanContext(trace.SpanContextConfig{
94+
TraceID: trace.TraceID{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F},
95+
SpanID: trace.SpanID{0x3F, 0x3E, 0x3D, 0x3C, 0x3B, 0x3A, 0x39, 0x38},
96+
}),
97+
SpanKind: trace.SpanKindServer,
98+
Name: "foo",
99+
StartTime: time.Date(2020, time.March, 11, 19, 24, 0, 0, time.UTC),
100+
EndTime: time.Date(2020, time.March, 11, 19, 25, 0, 0, time.UTC),
101+
Attributes: []attribute.KeyValue{
102+
attribute.Int64("attr1", 42),
103+
attribute.String("attr2", "bar"),
104+
attribute.IntSlice("attr3", []int{0, 1, 2}),
105+
},
106+
Events: []tracesdk.Event{
107+
{
108+
Time: time.Date(2020, time.March, 11, 19, 24, 30, 0, time.UTC),
109+
Name: "ev1",
110+
Attributes: []attribute.KeyValue{
111+
attribute.Int64("eventattr1", 123),
112+
},
113+
},
114+
{
115+
Time: time.Date(2020, time.March, 11, 19, 24, 45, 0, time.UTC),
116+
Name: "ev2",
117+
Attributes: nil,
118+
},
119+
},
120+
Status: tracesdk.Status{
121+
Code: codes.Ok,
122+
Description: "",
123+
},
124+
Resource: res,
125+
},
126+
// typical span data with ERROR status
49127
{
50128
SpanContext: trace.NewSpanContext(trace.SpanContextConfig{
51129
TraceID: trace.TraceID{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F},
@@ -373,7 +451,49 @@ func TestModelConversion(t *testing.T) {
373451
}.Snapshots()
374452

375453
expectedOutputBatch := []zkmodel.SpanModel{
376-
// model for typical span data
454+
// model for typical span data with UNSET status
455+
{
456+
SpanContext: zkmodel.SpanContext{
457+
TraceID: zkmodel.TraceID{
458+
High: 0x001020304050607,
459+
Low: 0x8090a0b0c0d0e0f,
460+
},
461+
ID: zkmodel.ID(0xfffefdfcfbfaf9f8),
462+
ParentID: zkmodelIDPtr(0x3f3e3d3c3b3a3938),
463+
Debug: false,
464+
Sampled: nil,
465+
Err: nil,
466+
},
467+
Name: "foo",
468+
Kind: "SERVER",
469+
Timestamp: time.Date(2020, time.March, 11, 19, 24, 0, 0, time.UTC),
470+
Duration: time.Minute,
471+
Shared: false,
472+
LocalEndpoint: &zkmodel.Endpoint{
473+
ServiceName: "model-test",
474+
},
475+
RemoteEndpoint: nil,
476+
Annotations: []zkmodel.Annotation{
477+
{
478+
Timestamp: time.Date(2020, time.March, 11, 19, 24, 30, 0, time.UTC),
479+
Value: `ev1: {"eventattr1":123}`,
480+
},
481+
{
482+
Timestamp: time.Date(2020, time.March, 11, 19, 24, 45, 0, time.UTC),
483+
Value: "ev2",
484+
},
485+
},
486+
Tags: map[string]string{
487+
"attr1": "42",
488+
"attr2": "bar",
489+
"attr3": "[0,1,2]",
490+
"service.name": "model-test",
491+
"service.version": "0.1.0",
492+
"resource-attr1": "42",
493+
"resource-attr2": "[0,1,2]",
494+
},
495+
},
496+
// model for typical span data with OK status
377497
{
378498
SpanContext: zkmodel.SpanContext{
379499
TraceID: zkmodel.TraceID{
@@ -409,7 +529,50 @@ func TestModelConversion(t *testing.T) {
409529
"attr1": "42",
410530
"attr2": "bar",
411531
"attr3": "[0,1,2]",
412-
"otel.status_code": "Error",
532+
"otel.status_code": "OK",
533+
"service.name": "model-test",
534+
"service.version": "0.1.0",
535+
"resource-attr1": "42",
536+
"resource-attr2": "[0,1,2]",
537+
},
538+
},
539+
// model for typical span data with ERROR status
540+
{
541+
SpanContext: zkmodel.SpanContext{
542+
TraceID: zkmodel.TraceID{
543+
High: 0x001020304050607,
544+
Low: 0x8090a0b0c0d0e0f,
545+
},
546+
ID: zkmodel.ID(0xfffefdfcfbfaf9f8),
547+
ParentID: zkmodelIDPtr(0x3f3e3d3c3b3a3938),
548+
Debug: false,
549+
Sampled: nil,
550+
Err: nil,
551+
},
552+
Name: "foo",
553+
Kind: "SERVER",
554+
Timestamp: time.Date(2020, time.March, 11, 19, 24, 0, 0, time.UTC),
555+
Duration: time.Minute,
556+
Shared: false,
557+
LocalEndpoint: &zkmodel.Endpoint{
558+
ServiceName: "model-test",
559+
},
560+
RemoteEndpoint: nil,
561+
Annotations: []zkmodel.Annotation{
562+
{
563+
Timestamp: time.Date(2020, time.March, 11, 19, 24, 30, 0, time.UTC),
564+
Value: `ev1: {"eventattr1":123}`,
565+
},
566+
{
567+
Timestamp: time.Date(2020, time.March, 11, 19, 24, 45, 0, time.UTC),
568+
Value: "ev2",
569+
},
570+
},
571+
Tags: map[string]string{
572+
"attr1": "42",
573+
"attr2": "bar",
574+
"attr3": "[0,1,2]",
575+
"otel.status_code": "ERROR",
413576
"error": "404, file not found",
414577
"service.name": "model-test",
415578
"service.version": "0.1.0",
@@ -452,7 +615,7 @@ func TestModelConversion(t *testing.T) {
452615
Tags: map[string]string{
453616
"attr1": "42",
454617
"attr2": "bar",
455-
"otel.status_code": "Error",
618+
"otel.status_code": "ERROR",
456619
"error": "404, file not found",
457620
"service.name": "model-test",
458621
"service.version": "0.1.0",
@@ -495,7 +658,7 @@ func TestModelConversion(t *testing.T) {
495658
Tags: map[string]string{
496659
"attr1": "42",
497660
"attr2": "bar",
498-
"otel.status_code": "Error",
661+
"otel.status_code": "ERROR",
499662
"error": "404, file not found",
500663
"service.name": "model-test",
501664
"service.version": "0.1.0",
@@ -538,7 +701,7 @@ func TestModelConversion(t *testing.T) {
538701
Tags: map[string]string{
539702
"attr1": "42",
540703
"attr2": "bar",
541-
"otel.status_code": "Error",
704+
"otel.status_code": "ERROR",
542705
"error": "404, file not found",
543706
"service.name": "model-test",
544707
"service.version": "0.1.0",
@@ -587,7 +750,7 @@ func TestModelConversion(t *testing.T) {
587750
"net.peer.ip": "1.2.3.4",
588751
"net.peer.port": "9876",
589752
"peer.hostname": "test-peer-hostname",
590-
"otel.status_code": "Error",
753+
"otel.status_code": "ERROR",
591754
"error": "404, file not found",
592755
"service.name": "model-test",
593756
"service.version": "0.1.0",
@@ -630,7 +793,7 @@ func TestModelConversion(t *testing.T) {
630793
Tags: map[string]string{
631794
"attr1": "42",
632795
"attr2": "bar",
633-
"otel.status_code": "Error",
796+
"otel.status_code": "ERROR",
634797
"error": "404, file not found",
635798
"service.name": "model-test",
636799
"service.version": "0.1.0",
@@ -673,7 +836,7 @@ func TestModelConversion(t *testing.T) {
673836
Tags: map[string]string{
674837
"attr1": "42",
675838
"attr2": "bar",
676-
"otel.status_code": "Error",
839+
"otel.status_code": "ERROR",
677840
"error": "404, file not found",
678841
"service.name": "model-test",
679842
"service.version": "0.1.0",
@@ -707,7 +870,7 @@ func TestModelConversion(t *testing.T) {
707870
Tags: map[string]string{
708871
"attr1": "42",
709872
"attr2": "bar",
710-
"otel.status_code": "Error",
873+
"otel.status_code": "ERROR",
711874
"error": "404, file not found",
712875
"service.name": "model-test",
713876
"service.version": "0.1.0",
@@ -809,7 +972,40 @@ func TestTagsTransformation(t *testing.T) {
809972
want: nil,
810973
},
811974
{
812-
name: "statusCode",
975+
name: "statusCode UNSET",
976+
data: tracetest.SpanStub{
977+
Attributes: []attribute.KeyValue{
978+
attribute.String("key", keyValue),
979+
},
980+
Status: tracesdk.Status{
981+
Code: codes.Unset,
982+
Description: "",
983+
},
984+
},
985+
want: map[string]string{
986+
"key": keyValue,
987+
},
988+
},
989+
{
990+
name: "statusCode OK",
991+
data: tracetest.SpanStub{
992+
Attributes: []attribute.KeyValue{
993+
attribute.String("key", keyValue),
994+
attribute.Bool("ok", true),
995+
},
996+
Status: tracesdk.Status{
997+
Code: codes.Ok,
998+
Description: "",
999+
},
1000+
},
1001+
want: map[string]string{
1002+
"key": keyValue,
1003+
"ok": "true",
1004+
"otel.status_code": "OK",
1005+
},
1006+
},
1007+
{
1008+
name: "statusCode ERROR",
8131009
data: tracetest.SpanStub{
8141010
Attributes: []attribute.KeyValue{
8151011
attribute.String("key", keyValue),
@@ -823,7 +1019,7 @@ func TestTagsTransformation(t *testing.T) {
8231019
want: map[string]string{
8241020
"error": statusMessage,
8251021
"key": keyValue,
826-
"otel.status_code": codes.Error.String(),
1022+
"otel.status_code": "ERROR",
8271023
},
8281024
},
8291025
{

exporters/zipkin/zipkin_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -270,7 +270,7 @@ func TestExportSpans(t *testing.T) {
270270
RemoteEndpoint: nil,
271271
Annotations: nil,
272272
Tags: map[string]string{
273-
"otel.status_code": "Error",
273+
"otel.status_code": "ERROR",
274274
"error": "404, file not found",
275275
"service.name": "exporter-test",
276276
"service.version": "0.1.0",
@@ -300,7 +300,7 @@ func TestExportSpans(t *testing.T) {
300300
RemoteEndpoint: nil,
301301
Annotations: nil,
302302
Tags: map[string]string{
303-
"otel.status_code": "Error",
303+
"otel.status_code": "ERROR",
304304
"error": "403, forbidden",
305305
"service.name": "exporter-test",
306306
"service.version": "0.1.0",

0 commit comments

Comments
 (0)