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

Update label.ArrayValue to store copies of 1D arrays #1226

Merged
merged 10 commits into from
Oct 6, 2020
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
- The `StatusCode` field of the `SpanData` struct in the `go.opentelemetry.io/otel/sdk/export/trace` package now uses the codes package from this package instead of the gRPC project. (#1214)
- Move the `go.opentelemetry.io/otel/api/baggage` package into `go.opentelemetry.io/otel/propagators`. (#1217)

### Fixed

- Copies of data from arrays and slices passed to `go.opentelemetry.io/otel/label.ArrayValue()` are now used in the returned `Value` instead of using the mutable data itself. (#1226)

### Removed

- The `ExtractHTTP` and `InjectHTTP` fuctions from the `go.opentelemetry.io/otel/api/propagation` package were removed. (#1212)
Expand All @@ -33,6 +37,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
- The `SetAttribute` method of the `Span` from the `go.opentelemetry.io/otel/api/trace` package was removed given its redundancy with the `SetAttributes` method. (#1216)
- The internal implementation of Baggage storage is removed in favor of using the new Baggage API functionality. (#1217)
- Remove duplicate hostname key `HostHostNameKey` in Resource semantic conventions. (#1219)
- Nested array/slice support has been removed. (#1226)

## [0.12.0] - 2020-09-24

Expand Down
208 changes: 53 additions & 155 deletions exporters/otlp/internal/transform/attribute.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
package transform

import (
"reflect"

commonpb "go.opentelemetry.io/otel/exporters/otlp/internal/opentelemetry-proto-gen/common/v1"
"go.opentelemetry.io/otel/label"

Expand Down Expand Up @@ -75,7 +77,11 @@ func toAttribute(v label.KeyValue) *commonpb.KeyValue {
StringValue: v.Value.AsString(),
}
case label.ARRAY:
result.Value.Value = toArrayAttribute(v)
result.Value.Value = &commonpb.AnyValue_ArrayValue{
ArrayValue: &commonpb.ArrayValue{
Values: arrayValues(v),
},
}
default:
result.Value.Value = &commonpb.AnyValue_StringValue{
StringValue: "INVALID",
Expand All @@ -84,164 +90,56 @@ func toAttribute(v label.KeyValue) *commonpb.KeyValue {
return result
}

func toArrayAttribute(v label.KeyValue) *commonpb.AnyValue_ArrayValue {
array := v.Value.AsArray()
var resultValues []*commonpb.AnyValue

switch typedArray := array.(type) {
case []bool:
resultValues = getValuesFromBoolArray(typedArray)
case []int:
resultValues = getValuesFromIntArray(typedArray)
case []int32:
resultValues = getValuesFromInt32Array(typedArray)
case []int64:
resultValues = getValuesFromInt64Array(typedArray)
case []uint:
resultValues = getValuesFromUIntArray(typedArray)
case []uint32:
resultValues = getValuesFromUInt32Array(typedArray)
case []uint64:
resultValues = getValuesFromUInt64Array(typedArray)
case []float32:
resultValues = getValuesFromFloat32Array(typedArray)
case []float64:
resultValues = getValuesFromFloat64Array(typedArray)
case []string:
resultValues = getValuesFromStringArray(typedArray)
default:
resultValues = []*commonpb.AnyValue{
{
func arrayValues(kv label.KeyValue) []*commonpb.AnyValue {
a := kv.Value.AsArray()
aType := reflect.TypeOf(a)
var valueFunc func(reflect.Value) *commonpb.AnyValue
switch aType.Elem().Kind() {
case reflect.Bool:
valueFunc = func(v reflect.Value) *commonpb.AnyValue {
return &commonpb.AnyValue{
Value: &commonpb.AnyValue_BoolValue{
BoolValue: v.Bool(),
},
}
}
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
valueFunc = func(v reflect.Value) *commonpb.AnyValue {
return &commonpb.AnyValue{
Value: &commonpb.AnyValue_IntValue{
IntValue: v.Int(),
},
}
}
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
valueFunc = func(v reflect.Value) *commonpb.AnyValue {
return &commonpb.AnyValue{
Value: &commonpb.AnyValue_IntValue{
IntValue: int64(v.Uint()),
},
}
}
case reflect.Float32, reflect.Float64:
valueFunc = func(v reflect.Value) *commonpb.AnyValue {
return &commonpb.AnyValue{
Value: &commonpb.AnyValue_DoubleValue{
DoubleValue: v.Float(),
},
}
}
case reflect.String:
valueFunc = func(v reflect.Value) *commonpb.AnyValue {
return &commonpb.AnyValue{
Value: &commonpb.AnyValue_StringValue{
StringValue: "INVALID",
StringValue: v.String(),
},
},
}
}
}

return &commonpb.AnyValue_ArrayValue{
ArrayValue: &commonpb.ArrayValue{
Values: resultValues,
},
}
}

func getValuesFromBoolArray(boolArray []bool) []*commonpb.AnyValue {
result := []*commonpb.AnyValue{}
for _, b := range boolArray {
result = append(result, &commonpb.AnyValue{
Value: &commonpb.AnyValue_BoolValue{
BoolValue: b,
},
})
}
return result
}

func getValuesFromIntArray(intArray []int) []*commonpb.AnyValue {
result := []*commonpb.AnyValue{}
for _, i := range intArray {
result = append(result, &commonpb.AnyValue{
Value: &commonpb.AnyValue_IntValue{
IntValue: int64(i),
},
})
}
return result
}

func getValuesFromInt32Array(int32Array []int32) []*commonpb.AnyValue {
result := []*commonpb.AnyValue{}
for _, i := range int32Array {
result = append(result, &commonpb.AnyValue{
Value: &commonpb.AnyValue_IntValue{
IntValue: int64(i),
},
})
}
return result
}

func getValuesFromInt64Array(int64Array []int64) []*commonpb.AnyValue {
result := []*commonpb.AnyValue{}
for _, i := range int64Array {
result = append(result, &commonpb.AnyValue{
Value: &commonpb.AnyValue_IntValue{
IntValue: i,
},
})
}
return result
}

func getValuesFromUIntArray(uintArray []uint) []*commonpb.AnyValue {
result := []*commonpb.AnyValue{}
for _, i := range uintArray {
result = append(result, &commonpb.AnyValue{
Value: &commonpb.AnyValue_IntValue{
IntValue: int64(i),
},
})
}
return result
}

func getValuesFromUInt32Array(uint32Array []uint32) []*commonpb.AnyValue {
result := []*commonpb.AnyValue{}
for _, i := range uint32Array {
result = append(result, &commonpb.AnyValue{
Value: &commonpb.AnyValue_IntValue{
IntValue: int64(i),
},
})
}
return result
}

func getValuesFromUInt64Array(uint64Array []uint64) []*commonpb.AnyValue {
result := []*commonpb.AnyValue{}
for _, i := range uint64Array {
result = append(result, &commonpb.AnyValue{
Value: &commonpb.AnyValue_IntValue{
IntValue: int64(i),
},
})
}
return result
}

func getValuesFromFloat32Array(float32Array []float32) []*commonpb.AnyValue {
result := []*commonpb.AnyValue{}
for _, f := range float32Array {
result = append(result, &commonpb.AnyValue{
Value: &commonpb.AnyValue_DoubleValue{
DoubleValue: float64(f),
},
})
}
return result
}

func getValuesFromFloat64Array(float64Array []float64) []*commonpb.AnyValue {
result := []*commonpb.AnyValue{}
for _, f := range float64Array {
result = append(result, &commonpb.AnyValue{
Value: &commonpb.AnyValue_DoubleValue{
DoubleValue: f,
},
})
}
return result
}

func getValuesFromStringArray(stringArray []string) []*commonpb.AnyValue {
result := []*commonpb.AnyValue{}
for _, s := range stringArray {
result = append(result, &commonpb.AnyValue{
Value: &commonpb.AnyValue_StringValue{
StringValue: s,
},
})
results := make([]*commonpb.AnyValue, aType.Len())
for i, aValue := 0, reflect.ValueOf(a); i < aValue.Len(); i++ {
results[i] = valueFunc(aValue.Index(i))
}
return result
return results
}
34 changes: 26 additions & 8 deletions exporters/otlp/internal/transform/attribute_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,21 @@ func TestArrayAttributes(t *testing.T) {
// "uint", "uint32", "uint64"
for _, test := range []attributeTest{
{nil, nil},
{
[]label.KeyValue{
label.Array("invalid", [][]string{{"1", "2"}, {"a"}}),
},
[]*commonpb.KeyValue{
{
Key: "invalid",
Value: &commonpb.AnyValue{
Value: &commonpb.AnyValue_StringValue{
StringValue: "INVALID",
},
},
},
},
},
{
[]label.KeyValue{
label.Array("bool array to bool array", []bool{true, false}),
Expand Down Expand Up @@ -191,17 +206,20 @@ func TestArrayAttributes(t *testing.T) {

for i, actualArrayAttr := range actualArrayAttributes {
expectedArrayAttr := expectedArrayAttributes[i]
if !assert.Equal(t, expectedArrayAttr.Key, actualArrayAttr.Key) {
expectedKey, actualKey := expectedArrayAttr.Key, actualArrayAttr.Key
if !assert.Equal(t, expectedKey, actualKey) {
continue
}

expectedArrayValue := expectedArrayAttr.Value.GetArrayValue()
assert.NotNil(t, expectedArrayValue)

actualArrayValue := actualArrayAttr.Value.GetArrayValue()
assert.NotNil(t, actualArrayValue)

assertExpectedArrayValues(t, expectedArrayValue.Values, actualArrayValue.Values)
expected := expectedArrayAttr.Value.GetArrayValue()
actual := actualArrayAttr.Value.GetArrayValue()
if expected == nil {
assert.Nil(t, actual)
continue
}
if assert.NotNil(t, actual, "expected not nil for %s", actualKey) {
assertExpectedArrayValues(t, expected.Values, actual.Values)
}
}

}
Expand Down
Loading