Skip to content

Commit

Permalink
Update label.ArrayValue to store copies of 1D arrays (open-telemetry#…
Browse files Browse the repository at this point in the history
…1226)

* Update label.ArrayValue to store copies of 1D arrays

* Update OTLP transform of array attributes

* Add changes to CHANGELOG

* Add PR number to changes

* Update value function documentation

* Remove redundant checks

* Add Array test for invalid array types

* Add test to ensure return from AsArray is a type

* Clean up iteration
  • Loading branch information
MrAlias authored Oct 6, 2020
1 parent 577b217 commit 5660b0b
Show file tree
Hide file tree
Showing 5 changed files with 137 additions and 200 deletions.
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

0 comments on commit 5660b0b

Please sign in to comment.