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
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
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",
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
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