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

Export resource attributes from zipkin exporter #2589

Merged
merged 5 commits into from Feb 9, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -17,6 +17,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
### Changed

- Jaeger exporter takes into additional 70 bytes overhead into consideration when sending UDP packets (#2489, #2512)
- Zipkin exporter exports `Resource` attributes as the `Tags` field.
tttanikawa marked this conversation as resolved.
Show resolved Hide resolved

### Deprecated

Expand Down
22 changes: 21 additions & 1 deletion exporters/zipkin/model.go
Expand Up @@ -177,7 +177,8 @@ var extraZipkinTags = []string{

func toZipkinTags(data tracesdk.ReadOnlySpan) map[string]string {
attr := data.Attributes()
m := make(map[string]string, len(attr)+len(extraZipkinTags))
resourceAttr := data.Resource().Attributes()
m := make(map[string]string, len(attr)+len(resourceAttr)+len(extraZipkinTags))
for _, kv := range attr {
switch kv.Value.Type() {
// For slice attributes, serialize as JSON list string.
Expand All @@ -197,6 +198,25 @@ func toZipkinTags(data tracesdk.ReadOnlySpan) map[string]string {
m[(string)(kv.Key)] = kv.Value.Emit()
}
}
for _, kv := range resourceAttr {
switch kv.Value.Type() {
// For slice attributes, serialize as JSON list string.
case attribute.BOOLSLICE:
json, _ := json.Marshal(kv.Value.AsBoolSlice())
m[(string)(kv.Key)] = (string)(json)
case attribute.INT64SLICE:
json, _ := json.Marshal(kv.Value.AsInt64Slice())
m[(string)(kv.Key)] = (string)(json)
case attribute.FLOAT64SLICE:
json, _ := json.Marshal(kv.Value.AsFloat64Slice())
m[(string)(kv.Key)] = (string)(json)
case attribute.STRINGSLICE:
json, _ := json.Marshal(kv.Value.AsStringSlice())
m[(string)(kv.Key)] = (string)(json)
default:
m[(string)(kv.Key)] = kv.Value.Emit()
}
MrAlias marked this conversation as resolved.
Show resolved Hide resolved
}

if data.Status().Code != codes.Unset {
m["otel.status_code"] = data.Status().Code.String()
Expand Down
42 changes: 41 additions & 1 deletion exporters/zipkin/model_test.go
Expand Up @@ -39,6 +39,9 @@ import (
func TestModelConversion(t *testing.T) {
resource := resource.NewSchemaless(
semconv.ServiceNameKey.String("model-test"),
semconv.ServiceVersionKey.String("0.1.0"),
attribute.Int64("resource-attr1", 42),
attribute.IntSlice("resource-attr2", []int{0, 1, 2}),
)

inputBatch := tracetest.SpanStubs{
Expand Down Expand Up @@ -408,6 +411,10 @@ func TestModelConversion(t *testing.T) {
"attr3": "[0,1,2]",
"otel.status_code": "Error",
"error": "404, file not found",
"service.name": "model-test",
"service.version": "0.1.0",
"resource-attr1": "42",
"resource-attr2": "[0,1,2]",
},
},
// model for span data with no parent
Expand Down Expand Up @@ -447,6 +454,10 @@ func TestModelConversion(t *testing.T) {
"attr2": "bar",
"otel.status_code": "Error",
"error": "404, file not found",
"service.name": "model-test",
"service.version": "0.1.0",
"resource-attr1": "42",
"resource-attr2": "[0,1,2]",
},
},
// model for span data of unspecified kind
Expand Down Expand Up @@ -486,6 +497,10 @@ func TestModelConversion(t *testing.T) {
"attr2": "bar",
"otel.status_code": "Error",
"error": "404, file not found",
"service.name": "model-test",
"service.version": "0.1.0",
"resource-attr1": "42",
"resource-attr2": "[0,1,2]",
},
},
// model for span data of internal kind
Expand Down Expand Up @@ -525,6 +540,10 @@ func TestModelConversion(t *testing.T) {
"attr2": "bar",
"otel.status_code": "Error",
"error": "404, file not found",
"service.name": "model-test",
"service.version": "0.1.0",
"resource-attr1": "42",
"resource-attr2": "[0,1,2]",
},
},
// model for span data of client kind
Expand Down Expand Up @@ -570,6 +589,10 @@ func TestModelConversion(t *testing.T) {
"peer.hostname": "test-peer-hostname",
"otel.status_code": "Error",
"error": "404, file not found",
"service.name": "model-test",
"service.version": "0.1.0",
"resource-attr1": "42",
"resource-attr2": "[0,1,2]",
},
},
// model for span data of producer kind
Expand Down Expand Up @@ -609,6 +632,10 @@ func TestModelConversion(t *testing.T) {
"attr2": "bar",
"otel.status_code": "Error",
"error": "404, file not found",
"service.name": "model-test",
"service.version": "0.1.0",
"resource-attr1": "42",
"resource-attr2": "[0,1,2]",
},
},
// model for span data of consumer kind
Expand Down Expand Up @@ -648,6 +675,10 @@ func TestModelConversion(t *testing.T) {
"attr2": "bar",
"otel.status_code": "Error",
"error": "404, file not found",
"service.name": "model-test",
"service.version": "0.1.0",
"resource-attr1": "42",
"resource-attr2": "[0,1,2]",
},
},
// model for span data with no events
Expand Down Expand Up @@ -678,6 +709,10 @@ func TestModelConversion(t *testing.T) {
"attr2": "bar",
"otel.status_code": "Error",
"error": "404, file not found",
"service.name": "model-test",
"service.version": "0.1.0",
"resource-attr1": "42",
"resource-attr2": "[0,1,2]",
},
},
// model for span data with an "error" attribute set to "false"
Expand Down Expand Up @@ -712,7 +747,12 @@ func TestModelConversion(t *testing.T) {
Value: "ev2",
},
},
Tags: nil, // should be omitted
Tags: map[string]string{
"service.name": "model-test",
"service.version": "0.1.0",
"resource-attr1": "42",
"resource-attr2": "[0,1,2]",
}, // only resource tags should be included
},
}
gottenOutputBatch := SpanModels(inputBatch)
Expand Down
5 changes: 5 additions & 0 deletions exporters/zipkin/zipkin_test.go
Expand Up @@ -200,6 +200,7 @@ func logStoreLogger(s *logStore) *log.Logger {
func TestExportSpans(t *testing.T) {
resource := resource.NewSchemaless(
semconv.ServiceNameKey.String("exporter-test"),
semconv.ServiceVersionKey.String("0.1.0"),
)

spans := tracetest.SpanStubs{
Expand Down Expand Up @@ -271,6 +272,8 @@ func TestExportSpans(t *testing.T) {
Tags: map[string]string{
"otel.status_code": "Error",
"error": "404, file not found",
"service.name": "exporter-test",
"service.version": "0.1.0",
},
},
// model of child
Expand Down Expand Up @@ -299,6 +302,8 @@ func TestExportSpans(t *testing.T) {
Tags: map[string]string{
"otel.status_code": "Error",
"error": "403, forbidden",
"service.name": "exporter-test",
"service.version": "0.1.0",
},
},
}
Expand Down