1
0
mirror of https://github.com/open-telemetry/opentelemetry-go.git synced 2025-02-03 13:11:53 +02:00

Unify the OTLP attribute transform (#2170)

* Unify the otlpmetric attribute transform

* Unify attr conversion in otlptrace
This commit is contained in:
Tyler Yahn 2021-08-11 11:30:05 -07:00 committed by GitHub
parent a882ee3792
commit 1cb5cdca6b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 94 additions and 187 deletions

View File

@ -23,71 +23,79 @@ import (
"go.opentelemetry.io/otel/sdk/resource"
)
// Attributes transforms a slice of KeyValues into a slice of OTLP attribute key-values.
func Attributes(attrs []attribute.KeyValue) []*commonpb.KeyValue {
// KeyValues transforms a slice of attribute KeyValues into OTLP key-values.
func KeyValues(attrs []attribute.KeyValue) []*commonpb.KeyValue {
if len(attrs) == 0 {
return nil
}
out := make([]*commonpb.KeyValue, 0, len(attrs))
for _, kv := range attrs {
out = append(out, toAttribute(kv))
out = append(out, KeyValue(kv))
}
return out
}
// ResourceAttributes transforms a Resource into a slice of OTLP attribute key-values.
func ResourceAttributes(resource *resource.Resource) []*commonpb.KeyValue {
if resource.Len() == 0 {
// Iterator transforms an attribute iterator into OTLP key-values.
func Iterator(iter attribute.Iterator) []*commonpb.KeyValue {
l := iter.Len()
if l == 0 {
return nil
}
out := make([]*commonpb.KeyValue, 0, resource.Len())
for iter := resource.Iter(); iter.Next(); {
out = append(out, toAttribute(iter.Attribute()))
out := make([]*commonpb.KeyValue, 0, l)
for iter.Next() {
out = append(out, KeyValue(iter.Attribute()))
}
return out
}
func toAttribute(v attribute.KeyValue) *commonpb.KeyValue {
result := &commonpb.KeyValue{
Key: string(v.Key),
Value: new(commonpb.AnyValue),
}
switch v.Value.Type() {
// ResourceAttributes transforms a Resource OTLP key-values.
func ResourceAttributes(resource *resource.Resource) []*commonpb.KeyValue {
return Iterator(resource.Iter())
}
// KeyValue transforms an attribute KeyValue into an OTLP key-value.
func KeyValue(kv attribute.KeyValue) *commonpb.KeyValue {
return &commonpb.KeyValue{Key: string(kv.Key), Value: Value(kv.Value)}
}
// Value transforms an attribute Value into an OTLP AnyValue.
func Value(v attribute.Value) *commonpb.AnyValue {
av := new(commonpb.AnyValue)
switch v.Type() {
case attribute.BOOL:
result.Value.Value = &commonpb.AnyValue_BoolValue{
BoolValue: v.Value.AsBool(),
av.Value = &commonpb.AnyValue_BoolValue{
BoolValue: v.AsBool(),
}
case attribute.INT64:
result.Value.Value = &commonpb.AnyValue_IntValue{
IntValue: v.Value.AsInt64(),
av.Value = &commonpb.AnyValue_IntValue{
IntValue: v.AsInt64(),
}
case attribute.FLOAT64:
result.Value.Value = &commonpb.AnyValue_DoubleValue{
DoubleValue: v.Value.AsFloat64(),
av.Value = &commonpb.AnyValue_DoubleValue{
DoubleValue: v.AsFloat64(),
}
case attribute.STRING:
result.Value.Value = &commonpb.AnyValue_StringValue{
StringValue: v.Value.AsString(),
av.Value = &commonpb.AnyValue_StringValue{
StringValue: v.AsString(),
}
case attribute.ARRAY:
result.Value.Value = &commonpb.AnyValue_ArrayValue{
av.Value = &commonpb.AnyValue_ArrayValue{
ArrayValue: &commonpb.ArrayValue{
Values: arrayValues(v),
},
}
default:
result.Value.Value = &commonpb.AnyValue_StringValue{
av.Value = &commonpb.AnyValue_StringValue{
StringValue: "INVALID",
}
}
return result
return av
}
func arrayValues(kv attribute.KeyValue) []*commonpb.AnyValue {
a := kv.Value.AsArray()
func arrayValues(v attribute.Value) []*commonpb.AnyValue {
a := v.AsArray()
aType := reflect.TypeOf(a)
var valueFunc func(reflect.Value) *commonpb.AnyValue
switch aType.Elem().Kind() {

View File

@ -83,7 +83,7 @@ func TestAttributes(t *testing.T) {
},
},
} {
got := Attributes(test.attrs)
got := KeyValues(test.attrs)
if !assert.Len(t, got, len(test.expected)) {
continue
}
@ -142,7 +142,7 @@ func TestArrayAttributes(t *testing.T) {
},
},
} {
actualArrayAttributes := Attributes(test.attrs)
actualArrayAttributes := KeyValues(test.attrs)
expectedArrayAttributes := test.expected
if !assert.Len(t, actualArrayAttributes, len(expectedArrayAttributes)) {
continue

View File

@ -318,7 +318,7 @@ func gaugeArray(record export.Record, points []aggregation.Point) (*metricpb.Met
Unit: string(desc.Unit()),
}
pbAttrs := keyValues(labels.Iter())
pbAttrs := Iterator(labels.Iter())
ndp := make([]*metricpb.NumberDataPoint, 0, len(points))
switch nk := desc.NumberKind(); nk {
@ -375,7 +375,7 @@ func gaugePoint(record export.Record, num number.Number, start, end time.Time) (
Value: &metricpb.NumberDataPoint_AsInt{
AsInt: num.CoerceToInt64(n),
},
Attributes: keyValues(labels.Iter()),
Attributes: Iterator(labels.Iter()),
StartTimeUnixNano: toNanos(start),
TimeUnixNano: toNanos(end),
},
@ -390,7 +390,7 @@ func gaugePoint(record export.Record, num number.Number, start, end time.Time) (
Value: &metricpb.NumberDataPoint_AsDouble{
AsDouble: num.CoerceToFloat64(n),
},
Attributes: keyValues(labels.Iter()),
Attributes: Iterator(labels.Iter()),
StartTimeUnixNano: toNanos(start),
TimeUnixNano: toNanos(end),
},
@ -435,7 +435,7 @@ func sumPoint(record export.Record, num number.Number, start, end time.Time, ek
Value: &metricpb.NumberDataPoint_AsInt{
AsInt: num.CoerceToInt64(n),
},
Attributes: keyValues(labels.Iter()),
Attributes: Iterator(labels.Iter()),
StartTimeUnixNano: toNanos(start),
TimeUnixNano: toNanos(end),
},
@ -452,7 +452,7 @@ func sumPoint(record export.Record, num number.Number, start, end time.Time, ek
Value: &metricpb.NumberDataPoint_AsDouble{
AsDouble: num.CoerceToFloat64(n),
},
Attributes: keyValues(labels.Iter()),
Attributes: Iterator(labels.Iter()),
StartTimeUnixNano: toNanos(start),
TimeUnixNano: toNanos(end),
},
@ -502,7 +502,7 @@ func minMaxSumCount(record export.Record, a aggregation.MinMaxSumCount) (*metric
DataPoints: []*metricpb.SummaryDataPoint{
{
Sum: sum.CoerceToFloat64(desc.NumberKind()),
Attributes: keyValues(labels.Iter()),
Attributes: Iterator(labels.Iter()),
StartTimeUnixNano: toNanos(record.StartTime()),
TimeUnixNano: toNanos(record.EndTime()),
Count: uint64(count),
@ -566,7 +566,7 @@ func histogramPoint(record export.Record, ek export.ExportKind, a aggregation.Hi
DataPoints: []*metricpb.HistogramDataPoint{
{
Sum: sum.CoerceToFloat64(desc.NumberKind()),
Attributes: keyValues(labels.Iter()),
Attributes: Iterator(labels.Iter()),
StartTimeUnixNano: toNanos(record.StartTime()),
TimeUnixNano: toNanos(record.EndTime()),
Count: uint64(count),
@ -579,112 +579,3 @@ func histogramPoint(record export.Record, ek export.ExportKind, a aggregation.Hi
}
return m, nil
}
// keyValues transforms an attribute iterator into an OTLP KeyValues.
func keyValues(iter attribute.Iterator) []*commonpb.KeyValue {
l := iter.Len()
if l == 0 {
return nil
}
result := make([]*commonpb.KeyValue, 0, l)
for iter.Next() {
kv := iter.Label()
result = append(result, &commonpb.KeyValue{
Key: string(kv.Key),
Value: value(kv.Value),
})
}
return result
}
// value transforms an attribute Value into an OTLP AnyValue.
func value(v attribute.Value) *commonpb.AnyValue {
switch v.Type() {
case attribute.BOOL:
return &commonpb.AnyValue{
Value: &commonpb.AnyValue_BoolValue{
BoolValue: v.AsBool(),
},
}
case attribute.INT64:
return &commonpb.AnyValue{
Value: &commonpb.AnyValue_IntValue{
IntValue: v.AsInt64(),
},
}
case attribute.FLOAT64:
return &commonpb.AnyValue{
Value: &commonpb.AnyValue_DoubleValue{
DoubleValue: v.AsFloat64(),
},
}
case attribute.ARRAY:
return &commonpb.AnyValue{
Value: &commonpb.AnyValue_ArrayValue{
ArrayValue: &commonpb.ArrayValue{
Values: arrayValue(v.AsArray()),
},
},
}
default:
return &commonpb.AnyValue{
Value: &commonpb.AnyValue_StringValue{
StringValue: v.Emit(),
},
}
}
}
// arrayValue transforms an attribute Value of ARRAY type into an slice of
// OTLP AnyValue.
func arrayValue(arr interface{}) []*commonpb.AnyValue {
var av []*commonpb.AnyValue
switch val := arr.(type) {
case []bool:
av = make([]*commonpb.AnyValue, len(val))
for i, v := range val {
av[i] = &commonpb.AnyValue{
Value: &commonpb.AnyValue_BoolValue{
BoolValue: v,
},
}
}
case []int:
av = make([]*commonpb.AnyValue, len(val))
for i, v := range val {
av[i] = &commonpb.AnyValue{
Value: &commonpb.AnyValue_IntValue{
IntValue: int64(v),
},
}
}
case []int64:
av = make([]*commonpb.AnyValue, len(val))
for i, v := range val {
av[i] = &commonpb.AnyValue{
Value: &commonpb.AnyValue_IntValue{
IntValue: v,
},
}
}
case []float64:
av = make([]*commonpb.AnyValue, len(val))
for i, v := range val {
av[i] = &commonpb.AnyValue{
Value: &commonpb.AnyValue_DoubleValue{
DoubleValue: v,
},
}
}
case []string:
av = make([]*commonpb.AnyValue, len(val))
for i, v := range val {
av[i] = &commonpb.AnyValue{
Value: &commonpb.AnyValue_StringValue{
StringValue: v,
},
}
}
}
return av
}

View File

@ -95,7 +95,7 @@ func TestStringKeyValues(t *testing.T) {
for _, test := range tests {
labels := attribute.NewSet(test.kvs...)
assert.Equal(t, test.expected, keyValues(labels.Iter()))
assert.Equal(t, test.expected, Iterator(labels.Iter()))
}
}

View File

@ -44,5 +44,5 @@ func TestResourceAttributes(t *testing.T) {
if !assert.Len(t, attrs, 2) {
return
}
assert.ElementsMatch(t, Attributes(attrs), got)
assert.ElementsMatch(t, KeyValues(attrs), got)
}

View File

@ -23,71 +23,79 @@ import (
"go.opentelemetry.io/otel/sdk/resource"
)
// Attributes transforms a slice of KeyValues into a slice of OTLP attribute key-values.
func Attributes(attrs []attribute.KeyValue) []*commonpb.KeyValue {
// KeyValues transforms a slice of attribute KeyValues into OTLP key-values.
func KeyValues(attrs []attribute.KeyValue) []*commonpb.KeyValue {
if len(attrs) == 0 {
return nil
}
out := make([]*commonpb.KeyValue, 0, len(attrs))
for _, kv := range attrs {
out = append(out, toAttribute(kv))
out = append(out, KeyValue(kv))
}
return out
}
// ResourceAttributes transforms a Resource into a slice of OTLP attribute key-values.
func ResourceAttributes(resource *resource.Resource) []*commonpb.KeyValue {
if resource.Len() == 0 {
// Iterator transforms an attribute iterator into OTLP key-values.
func Iterator(iter attribute.Iterator) []*commonpb.KeyValue {
l := iter.Len()
if l == 0 {
return nil
}
out := make([]*commonpb.KeyValue, 0, resource.Len())
for iter := resource.Iter(); iter.Next(); {
out = append(out, toAttribute(iter.Attribute()))
out := make([]*commonpb.KeyValue, 0, l)
for iter.Next() {
out = append(out, KeyValue(iter.Attribute()))
}
return out
}
func toAttribute(v attribute.KeyValue) *commonpb.KeyValue {
result := &commonpb.KeyValue{
Key: string(v.Key),
Value: new(commonpb.AnyValue),
}
switch v.Value.Type() {
// ResourceAttributes transforms a Resource OTLP key-values.
func ResourceAttributes(resource *resource.Resource) []*commonpb.KeyValue {
return Iterator(resource.Iter())
}
// KeyValue transforms an attribute KeyValue into an OTLP key-value.
func KeyValue(kv attribute.KeyValue) *commonpb.KeyValue {
return &commonpb.KeyValue{Key: string(kv.Key), Value: Value(kv.Value)}
}
// Value transforms an attribute Value into an OTLP AnyValue.
func Value(v attribute.Value) *commonpb.AnyValue {
av := new(commonpb.AnyValue)
switch v.Type() {
case attribute.BOOL:
result.Value.Value = &commonpb.AnyValue_BoolValue{
BoolValue: v.Value.AsBool(),
av.Value = &commonpb.AnyValue_BoolValue{
BoolValue: v.AsBool(),
}
case attribute.INT64:
result.Value.Value = &commonpb.AnyValue_IntValue{
IntValue: v.Value.AsInt64(),
av.Value = &commonpb.AnyValue_IntValue{
IntValue: v.AsInt64(),
}
case attribute.FLOAT64:
result.Value.Value = &commonpb.AnyValue_DoubleValue{
DoubleValue: v.Value.AsFloat64(),
av.Value = &commonpb.AnyValue_DoubleValue{
DoubleValue: v.AsFloat64(),
}
case attribute.STRING:
result.Value.Value = &commonpb.AnyValue_StringValue{
StringValue: v.Value.AsString(),
av.Value = &commonpb.AnyValue_StringValue{
StringValue: v.AsString(),
}
case attribute.ARRAY:
result.Value.Value = &commonpb.AnyValue_ArrayValue{
av.Value = &commonpb.AnyValue_ArrayValue{
ArrayValue: &commonpb.ArrayValue{
Values: arrayValues(v),
},
}
default:
result.Value.Value = &commonpb.AnyValue_StringValue{
av.Value = &commonpb.AnyValue_StringValue{
StringValue: "INVALID",
}
}
return result
return av
}
func arrayValues(kv attribute.KeyValue) []*commonpb.AnyValue {
a := kv.Value.AsArray()
func arrayValues(v attribute.Value) []*commonpb.AnyValue {
a := v.AsArray()
aType := reflect.TypeOf(a)
var valueFunc func(reflect.Value) *commonpb.AnyValue
switch aType.Elem().Kind() {

View File

@ -83,7 +83,7 @@ func TestAttributes(t *testing.T) {
},
},
} {
got := Attributes(test.attrs)
got := KeyValues(test.attrs)
if !assert.Len(t, got, len(test.expected)) {
continue
}
@ -142,7 +142,7 @@ func TestArrayAttributes(t *testing.T) {
},
},
} {
actualArrayAttributes := Attributes(test.attrs)
actualArrayAttributes := KeyValues(test.attrs)
expectedArrayAttributes := test.expected
if !assert.Len(t, actualArrayAttributes, len(expectedArrayAttributes)) {
continue

View File

@ -44,5 +44,5 @@ func TestResourceAttributes(t *testing.T) {
if !assert.Len(t, attrs, 2) {
return
}
assert.ElementsMatch(t, Attributes(attrs), got)
assert.ElementsMatch(t, KeyValues(attrs), got)
}

View File

@ -114,7 +114,7 @@ func span(sd tracesdk.ReadOnlySpan) *tracepb.Span {
Links: links(sd.Links()),
Kind: spanKind(sd.SpanKind()),
Name: sd.Name(),
Attributes: Attributes(sd.Attributes()),
Attributes: KeyValues(sd.Attributes()),
Events: spanEvents(sd.Events()),
DroppedAttributesCount: uint32(sd.DroppedAttributes()),
DroppedEventsCount: uint32(sd.DroppedEvents()),
@ -163,7 +163,7 @@ func links(links []tracesdk.Link) []*tracepb.Span_Link {
sl = append(sl, &tracepb.Span_Link{
TraceId: tid[:],
SpanId: sid[:],
Attributes: Attributes(otLink.Attributes),
Attributes: KeyValues(otLink.Attributes),
})
}
return sl
@ -192,7 +192,7 @@ func spanEvents(es []tracesdk.Event) []*tracepb.Span_Event {
&tracepb.Span_Event{
Name: e.Name,
TimeUnixNano: uint64(e.Time.UnixNano()),
Attributes: Attributes(e.Attributes),
Attributes: KeyValues(e.Attributes),
// TODO (rghetia) : Add Drop Counts when supported.
},
)

View File

@ -98,7 +98,7 @@ func TestSpanEvent(t *testing.T) {
eventTimestamp := uint64(1589932800 * 1e9)
assert.Equal(t, &tracepb.Span_Event{Name: "test 1", Attributes: nil, TimeUnixNano: eventTimestamp}, got[0])
// Do not test Attributes directly, just that the return value goes to the correct field.
assert.Equal(t, &tracepb.Span_Event{Name: "test 2", Attributes: Attributes(attrs), TimeUnixNano: eventTimestamp}, got[1])
assert.Equal(t, &tracepb.Span_Event{Name: "test 2", Attributes: KeyValues(attrs), TimeUnixNano: eventTimestamp}, got[1])
}
func TestExcessiveSpanEvents(t *testing.T) {
@ -145,7 +145,7 @@ func TestLinks(t *testing.T) {
assert.Equal(t, expected, got[0])
// Do not test Attributes directly, just that the return value goes to the correct field.
expected.Attributes = Attributes(attrs)
expected.Attributes = KeyValues(attrs)
assert.Equal(t, expected, got[1])
// Changes to our links should not change the produced links.
@ -288,7 +288,7 @@ func TestSpanData(t *testing.T) {
Status: status(spanData.Status.Code, spanData.Status.Description),
Events: spanEvents(spanData.Events),
Links: links(spanData.Links),
Attributes: Attributes(spanData.Attributes),
Attributes: KeyValues(spanData.Attributes),
DroppedAttributesCount: 1,
DroppedEventsCount: 2,
DroppedLinksCount: 3,