Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix wrong representation of status value in zipkin exporter #3340

Merged
merged 9 commits into from
Oct 28, 2022
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,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)
- 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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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",
MrAlias marked this conversation as resolved.
Show resolved Hide resolved
"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
Original file line number Diff line number Diff line change
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