mirror of
https://github.com/open-telemetry/opentelemetry-go.git
synced 2024-12-12 10:04:29 +02:00
Export resource attributes from zipkin exporter (#2589)
* Export resource attributes from zipkin exporter * Update CHANGELOG.md Co-authored-by: Tyler Yahn <MrAlias@users.noreply.github.com> * Refactoring * Refactoring Co-authored-by: Tyler Yahn <MrAlias@users.noreply.github.com>
This commit is contained in:
parent
10b58d631c
commit
9f42a81a5f
@ -17,6 +17,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
|
|||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- Jaeger exporter takes into additional 70 bytes overhead into consideration when sending UDP packets (#2489, #2512)
|
- 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. (#2589)
|
||||||
|
|
||||||
### Deprecated
|
### Deprecated
|
||||||
|
|
||||||
|
@ -168,6 +168,27 @@ func attributesToJSONMapString(attributes []attribute.KeyValue) string {
|
|||||||
return (string)(jsonBytes)
|
return (string)(jsonBytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// attributeToStringPair serializes each attribute to a string pair
|
||||||
|
func attributeToStringPair(kv attribute.KeyValue) (string, string) {
|
||||||
|
switch kv.Value.Type() {
|
||||||
|
// For slice attributes, serialize as JSON list string.
|
||||||
|
case attribute.BOOLSLICE:
|
||||||
|
json, _ := json.Marshal(kv.Value.AsBoolSlice())
|
||||||
|
return (string)(kv.Key), (string)(json)
|
||||||
|
case attribute.INT64SLICE:
|
||||||
|
json, _ := json.Marshal(kv.Value.AsInt64Slice())
|
||||||
|
return (string)(kv.Key), (string)(json)
|
||||||
|
case attribute.FLOAT64SLICE:
|
||||||
|
json, _ := json.Marshal(kv.Value.AsFloat64Slice())
|
||||||
|
return (string)(kv.Key), (string)(json)
|
||||||
|
case attribute.STRINGSLICE:
|
||||||
|
json, _ := json.Marshal(kv.Value.AsStringSlice())
|
||||||
|
return (string)(kv.Key), (string)(json)
|
||||||
|
default:
|
||||||
|
return (string)(kv.Key), kv.Value.Emit()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// extraZipkinTags are those that may be added to every outgoing span
|
// extraZipkinTags are those that may be added to every outgoing span
|
||||||
var extraZipkinTags = []string{
|
var extraZipkinTags = []string{
|
||||||
"otel.status_code",
|
"otel.status_code",
|
||||||
@ -177,25 +198,15 @@ var extraZipkinTags = []string{
|
|||||||
|
|
||||||
func toZipkinTags(data tracesdk.ReadOnlySpan) map[string]string {
|
func toZipkinTags(data tracesdk.ReadOnlySpan) map[string]string {
|
||||||
attr := data.Attributes()
|
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 {
|
for _, kv := range attr {
|
||||||
switch kv.Value.Type() {
|
k, v := attributeToStringPair(kv)
|
||||||
// For slice attributes, serialize as JSON list string.
|
m[k] = v
|
||||||
case attribute.BOOLSLICE:
|
}
|
||||||
json, _ := json.Marshal(kv.Value.AsBoolSlice())
|
for _, kv := range resourceAttr {
|
||||||
m[(string)(kv.Key)] = (string)(json)
|
k, v := attributeToStringPair(kv)
|
||||||
case attribute.INT64SLICE:
|
m[k] = v
|
||||||
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()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if data.Status().Code != codes.Unset {
|
if data.Status().Code != codes.Unset {
|
||||||
|
@ -39,6 +39,9 @@ import (
|
|||||||
func TestModelConversion(t *testing.T) {
|
func TestModelConversion(t *testing.T) {
|
||||||
resource := resource.NewSchemaless(
|
resource := resource.NewSchemaless(
|
||||||
semconv.ServiceNameKey.String("model-test"),
|
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{
|
inputBatch := tracetest.SpanStubs{
|
||||||
@ -408,6 +411,10 @@ func TestModelConversion(t *testing.T) {
|
|||||||
"attr3": "[0,1,2]",
|
"attr3": "[0,1,2]",
|
||||||
"otel.status_code": "Error",
|
"otel.status_code": "Error",
|
||||||
"error": "404, file not found",
|
"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
|
// model for span data with no parent
|
||||||
@ -447,6 +454,10 @@ func TestModelConversion(t *testing.T) {
|
|||||||
"attr2": "bar",
|
"attr2": "bar",
|
||||||
"otel.status_code": "Error",
|
"otel.status_code": "Error",
|
||||||
"error": "404, file not found",
|
"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
|
// model for span data of unspecified kind
|
||||||
@ -486,6 +497,10 @@ func TestModelConversion(t *testing.T) {
|
|||||||
"attr2": "bar",
|
"attr2": "bar",
|
||||||
"otel.status_code": "Error",
|
"otel.status_code": "Error",
|
||||||
"error": "404, file not found",
|
"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
|
// model for span data of internal kind
|
||||||
@ -525,6 +540,10 @@ func TestModelConversion(t *testing.T) {
|
|||||||
"attr2": "bar",
|
"attr2": "bar",
|
||||||
"otel.status_code": "Error",
|
"otel.status_code": "Error",
|
||||||
"error": "404, file not found",
|
"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
|
// model for span data of client kind
|
||||||
@ -570,6 +589,10 @@ func TestModelConversion(t *testing.T) {
|
|||||||
"peer.hostname": "test-peer-hostname",
|
"peer.hostname": "test-peer-hostname",
|
||||||
"otel.status_code": "Error",
|
"otel.status_code": "Error",
|
||||||
"error": "404, file not found",
|
"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
|
// model for span data of producer kind
|
||||||
@ -609,6 +632,10 @@ func TestModelConversion(t *testing.T) {
|
|||||||
"attr2": "bar",
|
"attr2": "bar",
|
||||||
"otel.status_code": "Error",
|
"otel.status_code": "Error",
|
||||||
"error": "404, file not found",
|
"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
|
// model for span data of consumer kind
|
||||||
@ -648,6 +675,10 @@ func TestModelConversion(t *testing.T) {
|
|||||||
"attr2": "bar",
|
"attr2": "bar",
|
||||||
"otel.status_code": "Error",
|
"otel.status_code": "Error",
|
||||||
"error": "404, file not found",
|
"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
|
// model for span data with no events
|
||||||
@ -678,6 +709,10 @@ func TestModelConversion(t *testing.T) {
|
|||||||
"attr2": "bar",
|
"attr2": "bar",
|
||||||
"otel.status_code": "Error",
|
"otel.status_code": "Error",
|
||||||
"error": "404, file not found",
|
"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"
|
// model for span data with an "error" attribute set to "false"
|
||||||
@ -712,7 +747,12 @@ func TestModelConversion(t *testing.T) {
|
|||||||
Value: "ev2",
|
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)
|
gottenOutputBatch := SpanModels(inputBatch)
|
||||||
|
@ -200,6 +200,7 @@ func logStoreLogger(s *logStore) *log.Logger {
|
|||||||
func TestExportSpans(t *testing.T) {
|
func TestExportSpans(t *testing.T) {
|
||||||
resource := resource.NewSchemaless(
|
resource := resource.NewSchemaless(
|
||||||
semconv.ServiceNameKey.String("exporter-test"),
|
semconv.ServiceNameKey.String("exporter-test"),
|
||||||
|
semconv.ServiceVersionKey.String("0.1.0"),
|
||||||
)
|
)
|
||||||
|
|
||||||
spans := tracetest.SpanStubs{
|
spans := tracetest.SpanStubs{
|
||||||
@ -271,6 +272,8 @@ func TestExportSpans(t *testing.T) {
|
|||||||
Tags: map[string]string{
|
Tags: map[string]string{
|
||||||
"otel.status_code": "Error",
|
"otel.status_code": "Error",
|
||||||
"error": "404, file not found",
|
"error": "404, file not found",
|
||||||
|
"service.name": "exporter-test",
|
||||||
|
"service.version": "0.1.0",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
// model of child
|
// model of child
|
||||||
@ -299,6 +302,8 @@ func TestExportSpans(t *testing.T) {
|
|||||||
Tags: map[string]string{
|
Tags: map[string]string{
|
||||||
"otel.status_code": "Error",
|
"otel.status_code": "Error",
|
||||||
"error": "403, forbidden",
|
"error": "403, forbidden",
|
||||||
|
"service.name": "exporter-test",
|
||||||
|
"service.version": "0.1.0",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user