Skip to content

Commit

Permalink
fix wrong representation of status value in zipkin exporter (#3340)
Browse files Browse the repository at this point in the history
* 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>
  • Loading branch information
NewReStarter and MrAlias committed Oct 28, 2022
1 parent 94ae231 commit 3dd4e81
Show file tree
Hide file tree
Showing 4 changed files with 215 additions and 15 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -13,6 +13,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
- The `go.opentelemetry.io/otel/exporters/prometheus` exporter fixes duplicated `_total` suffixes. (#3369)
- Cumulative metrics from the OpenCensus bridge (`go.opentelemetry.io/otel/bridge/opencensus`) are defined as monotonic sums, instead of non-monotonic. (#3389)
- Asynchronous counters (`Counter` and `UpDownCounter`) from the metric SDK now produce delta sums when configured with delta temporality. (#3398)
- Exported `Status` codes in the `go.opentelemetry.io/otel/exporters/zipkin` exporter are now exported as all upper case values. (#3340)

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

Expand Down
5 changes: 4 additions & 1 deletion exporters/zipkin/model.go
Expand Up @@ -20,6 +20,7 @@ import (
"fmt"
"net"
"strconv"
"strings"

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

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

if data.Status().Code != codes.Unset {
m["otel.status_code"] = data.Status().Code.String()
// Zipkin expect to receive uppercase status values
// rather than default capitalized ones.
m["otel.status_code"] = strings.ToUpper(data.Status().Code.String())
}

if data.Status().Code == codes.Error {
Expand Down
220 changes: 208 additions & 12 deletions exporters/zipkin/model_test.go
Expand Up @@ -45,7 +45,85 @@ func TestModelConversion(t *testing.T) {
)

inputBatch := tracetest.SpanStubs{
// typical span data
// typical span data with UNSET status
{
SpanContext: trace.NewSpanContext(trace.SpanContextConfig{
TraceID: trace.TraceID{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F},
SpanID: trace.SpanID{0xFF, 0xFE, 0xFD, 0xFC, 0xFB, 0xFA, 0xF9, 0xF8},
}),
Parent: trace.NewSpanContext(trace.SpanContextConfig{
TraceID: trace.TraceID{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F},
SpanID: trace.SpanID{0x3F, 0x3E, 0x3D, 0x3C, 0x3B, 0x3A, 0x39, 0x38},
}),
SpanKind: trace.SpanKindServer,
Name: "foo",
StartTime: time.Date(2020, time.March, 11, 19, 24, 0, 0, time.UTC),
EndTime: time.Date(2020, time.March, 11, 19, 25, 0, 0, time.UTC),
Attributes: []attribute.KeyValue{
attribute.Int64("attr1", 42),
attribute.String("attr2", "bar"),
attribute.IntSlice("attr3", []int{0, 1, 2}),
},
Events: []tracesdk.Event{
{
Time: time.Date(2020, time.March, 11, 19, 24, 30, 0, time.UTC),
Name: "ev1",
Attributes: []attribute.KeyValue{
attribute.Int64("eventattr1", 123),
},
},
{
Time: time.Date(2020, time.March, 11, 19, 24, 45, 0, time.UTC),
Name: "ev2",
Attributes: nil,
},
},
Status: tracesdk.Status{
Code: codes.Unset,
Description: "",
},
Resource: res,
},
// typical span data with OK status
{
SpanContext: trace.NewSpanContext(trace.SpanContextConfig{
TraceID: trace.TraceID{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F},
SpanID: trace.SpanID{0xFF, 0xFE, 0xFD, 0xFC, 0xFB, 0xFA, 0xF9, 0xF8},
}),
Parent: trace.NewSpanContext(trace.SpanContextConfig{
TraceID: trace.TraceID{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F},
SpanID: trace.SpanID{0x3F, 0x3E, 0x3D, 0x3C, 0x3B, 0x3A, 0x39, 0x38},
}),
SpanKind: trace.SpanKindServer,
Name: "foo",
StartTime: time.Date(2020, time.March, 11, 19, 24, 0, 0, time.UTC),
EndTime: time.Date(2020, time.March, 11, 19, 25, 0, 0, time.UTC),
Attributes: []attribute.KeyValue{
attribute.Int64("attr1", 42),
attribute.String("attr2", "bar"),
attribute.IntSlice("attr3", []int{0, 1, 2}),
},
Events: []tracesdk.Event{
{
Time: time.Date(2020, time.March, 11, 19, 24, 30, 0, time.UTC),
Name: "ev1",
Attributes: []attribute.KeyValue{
attribute.Int64("eventattr1", 123),
},
},
{
Time: time.Date(2020, time.March, 11, 19, 24, 45, 0, time.UTC),
Name: "ev2",
Attributes: nil,
},
},
Status: tracesdk.Status{
Code: codes.Ok,
Description: "",
},
Resource: res,
},
// typical span data with ERROR status
{
SpanContext: trace.NewSpanContext(trace.SpanContextConfig{
TraceID: trace.TraceID{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F},
Expand Down Expand Up @@ -373,7 +451,49 @@ func TestModelConversion(t *testing.T) {
}.Snapshots()

expectedOutputBatch := []zkmodel.SpanModel{
// model for typical span data
// model for typical span data with UNSET status
{
SpanContext: zkmodel.SpanContext{
TraceID: zkmodel.TraceID{
High: 0x001020304050607,
Low: 0x8090a0b0c0d0e0f,
},
ID: zkmodel.ID(0xfffefdfcfbfaf9f8),
ParentID: zkmodelIDPtr(0x3f3e3d3c3b3a3938),
Debug: false,
Sampled: nil,
Err: nil,
},
Name: "foo",
Kind: "SERVER",
Timestamp: time.Date(2020, time.March, 11, 19, 24, 0, 0, time.UTC),
Duration: time.Minute,
Shared: false,
LocalEndpoint: &zkmodel.Endpoint{
ServiceName: "model-test",
},
RemoteEndpoint: nil,
Annotations: []zkmodel.Annotation{
{
Timestamp: time.Date(2020, time.March, 11, 19, 24, 30, 0, time.UTC),
Value: `ev1: {"eventattr1":123}`,
},
{
Timestamp: time.Date(2020, time.March, 11, 19, 24, 45, 0, time.UTC),
Value: "ev2",
},
},
Tags: map[string]string{
"attr1": "42",
"attr2": "bar",
"attr3": "[0,1,2]",
"service.name": "model-test",
"service.version": "0.1.0",
"resource-attr1": "42",
"resource-attr2": "[0,1,2]",
},
},
// model for typical span data with OK status
{
SpanContext: zkmodel.SpanContext{
TraceID: zkmodel.TraceID{
Expand Down Expand Up @@ -409,7 +529,50 @@ func TestModelConversion(t *testing.T) {
"attr1": "42",
"attr2": "bar",
"attr3": "[0,1,2]",
"otel.status_code": "Error",
"otel.status_code": "OK",
"service.name": "model-test",
"service.version": "0.1.0",
"resource-attr1": "42",
"resource-attr2": "[0,1,2]",
},
},
// model for typical span data with ERROR status
{
SpanContext: zkmodel.SpanContext{
TraceID: zkmodel.TraceID{
High: 0x001020304050607,
Low: 0x8090a0b0c0d0e0f,
},
ID: zkmodel.ID(0xfffefdfcfbfaf9f8),
ParentID: zkmodelIDPtr(0x3f3e3d3c3b3a3938),
Debug: false,
Sampled: nil,
Err: nil,
},
Name: "foo",
Kind: "SERVER",
Timestamp: time.Date(2020, time.March, 11, 19, 24, 0, 0, time.UTC),
Duration: time.Minute,
Shared: false,
LocalEndpoint: &zkmodel.Endpoint{
ServiceName: "model-test",
},
RemoteEndpoint: nil,
Annotations: []zkmodel.Annotation{
{
Timestamp: time.Date(2020, time.March, 11, 19, 24, 30, 0, time.UTC),
Value: `ev1: {"eventattr1":123}`,
},
{
Timestamp: time.Date(2020, time.March, 11, 19, 24, 45, 0, time.UTC),
Value: "ev2",
},
},
Tags: map[string]string{
"attr1": "42",
"attr2": "bar",
"attr3": "[0,1,2]",
"otel.status_code": "ERROR",
"error": "404, file not found",
"service.name": "model-test",
"service.version": "0.1.0",
Expand Down Expand Up @@ -452,7 +615,7 @@ func TestModelConversion(t *testing.T) {
Tags: map[string]string{
"attr1": "42",
"attr2": "bar",
"otel.status_code": "Error",
"otel.status_code": "ERROR",
"error": "404, file not found",
"service.name": "model-test",
"service.version": "0.1.0",
Expand Down Expand Up @@ -495,7 +658,7 @@ func TestModelConversion(t *testing.T) {
Tags: map[string]string{
"attr1": "42",
"attr2": "bar",
"otel.status_code": "Error",
"otel.status_code": "ERROR",
"error": "404, file not found",
"service.name": "model-test",
"service.version": "0.1.0",
Expand Down Expand Up @@ -538,7 +701,7 @@ func TestModelConversion(t *testing.T) {
Tags: map[string]string{
"attr1": "42",
"attr2": "bar",
"otel.status_code": "Error",
"otel.status_code": "ERROR",
"error": "404, file not found",
"service.name": "model-test",
"service.version": "0.1.0",
Expand Down Expand Up @@ -587,7 +750,7 @@ func TestModelConversion(t *testing.T) {
"net.peer.ip": "1.2.3.4",
"net.peer.port": "9876",
"peer.hostname": "test-peer-hostname",
"otel.status_code": "Error",
"otel.status_code": "ERROR",
"error": "404, file not found",
"service.name": "model-test",
"service.version": "0.1.0",
Expand Down Expand Up @@ -630,7 +793,7 @@ func TestModelConversion(t *testing.T) {
Tags: map[string]string{
"attr1": "42",
"attr2": "bar",
"otel.status_code": "Error",
"otel.status_code": "ERROR",
"error": "404, file not found",
"service.name": "model-test",
"service.version": "0.1.0",
Expand Down Expand Up @@ -673,7 +836,7 @@ func TestModelConversion(t *testing.T) {
Tags: map[string]string{
"attr1": "42",
"attr2": "bar",
"otel.status_code": "Error",
"otel.status_code": "ERROR",
"error": "404, file not found",
"service.name": "model-test",
"service.version": "0.1.0",
Expand Down Expand Up @@ -707,7 +870,7 @@ func TestModelConversion(t *testing.T) {
Tags: map[string]string{
"attr1": "42",
"attr2": "bar",
"otel.status_code": "Error",
"otel.status_code": "ERROR",
"error": "404, file not found",
"service.name": "model-test",
"service.version": "0.1.0",
Expand Down Expand Up @@ -809,7 +972,40 @@ func TestTagsTransformation(t *testing.T) {
want: nil,
},
{
name: "statusCode",
name: "statusCode UNSET",
data: tracetest.SpanStub{
Attributes: []attribute.KeyValue{
attribute.String("key", keyValue),
},
Status: tracesdk.Status{
Code: codes.Unset,
Description: "",
},
},
want: map[string]string{
"key": keyValue,
},
},
{
name: "statusCode OK",
data: tracetest.SpanStub{
Attributes: []attribute.KeyValue{
attribute.String("key", keyValue),
attribute.Bool("ok", true),
},
Status: tracesdk.Status{
Code: codes.Ok,
Description: "",
},
},
want: map[string]string{
"key": keyValue,
"ok": "true",
"otel.status_code": "OK",
},
},
{
name: "statusCode ERROR",
data: tracetest.SpanStub{
Attributes: []attribute.KeyValue{
attribute.String("key", keyValue),
Expand All @@ -823,7 +1019,7 @@ func TestTagsTransformation(t *testing.T) {
want: map[string]string{
"error": statusMessage,
"key": keyValue,
"otel.status_code": codes.Error.String(),
"otel.status_code": "ERROR",
},
},
{
Expand Down
4 changes: 2 additions & 2 deletions exporters/zipkin/zipkin_test.go
Expand Up @@ -270,7 +270,7 @@ func TestExportSpans(t *testing.T) {
RemoteEndpoint: nil,
Annotations: nil,
Tags: map[string]string{
"otel.status_code": "Error",
"otel.status_code": "ERROR",
"error": "404, file not found",
"service.name": "exporter-test",
"service.version": "0.1.0",
Expand Down Expand Up @@ -300,7 +300,7 @@ func TestExportSpans(t *testing.T) {
RemoteEndpoint: nil,
Annotations: nil,
Tags: map[string]string{
"otel.status_code": "Error",
"otel.status_code": "ERROR",
"error": "403, forbidden",
"service.name": "exporter-test",
"service.version": "0.1.0",
Expand Down

0 comments on commit 3dd4e81

Please sign in to comment.