Skip to content

Commit

Permalink
Fix slice-valued attributes when used as map keys
Browse files Browse the repository at this point in the history
Signed-off-by: Anthony J Mirabella <a9@aneurysm9.com>
  • Loading branch information
Aneurysm9 committed Sep 6, 2021
1 parent 4bfa003 commit fe29e9f
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 61 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Expand Up @@ -8,6 +8,10 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm

## [Unreleased]

### Fixed

- Slice-valued attributes can correctly be used as map keys. (#2223)

## [1.0.0-RC3] - 2021-09-02

### Added
Expand Down
117 changes: 57 additions & 60 deletions attribute/value.go
Expand Up @@ -73,12 +73,7 @@ func BoolValue(v bool) Value {

// BoolSliceValue creates a BOOLSLICE Value.
func BoolSliceValue(v []bool) Value {
cp := make([]bool, len(v))
copy(cp, v)
return Value{
vtype: BOOLSLICE,
slice: cp,
}
return sliceValue(v, BOOLSLICE)
}

// IntValue creates an INT64 Value.
Expand All @@ -88,14 +83,7 @@ func IntValue(v int) Value {

// IntSliceValue creates an INTSLICE Value.
func IntSliceValue(v []int) Value {
cp := make([]int64, 0, len(v))
for _, i := range v {
cp = append(cp, int64(i))
}
return Value{
vtype: INT64SLICE,
slice: cp,
}
return sliceValue(v, INT64SLICE)
}

// Int64Value creates an INT64 Value.
Expand All @@ -108,12 +96,7 @@ func Int64Value(v int64) Value {

// Int64SliceValue creates an INT64SLICE Value.
func Int64SliceValue(v []int64) Value {
cp := make([]int64, len(v))
copy(cp, v)
return Value{
vtype: INT64SLICE,
slice: cp,
}
return sliceValue(v, INT64SLICE)
}

// Float64Value creates a FLOAT64 Value.
Expand All @@ -126,12 +109,7 @@ func Float64Value(v float64) Value {

// Float64SliceValue creates a FLOAT64SLICE Value.
func Float64SliceValue(v []float64) Value {
cp := make([]float64, len(v))
copy(cp, v)
return Value{
vtype: FLOAT64SLICE,
slice: cp,
}
return sliceValue(v, FLOAT64SLICE)
}

// StringValue creates a STRING Value.
Expand All @@ -144,11 +122,26 @@ func StringValue(v string) Value {

// StringSliceValue creates a STRINGSLICE Value.
func StringSliceValue(v []string) Value {
cp := make([]string, len(v))
copy(cp, v)
return Value{
vtype: STRINGSLICE,
slice: cp,
return sliceValue(v, STRINGSLICE)
}

func sliceValue(v interface{}, vtype Type) Value {
// get array type regardless of dimensions
typ := reflect.TypeOf(v).Elem()
kind := typ.Kind()
switch kind {
case reflect.Bool, reflect.Int, reflect.Int64,
reflect.Float64, reflect.String:
val := reflect.ValueOf(v)
length := val.Len()
frozen := reflect.Indirect(reflect.New(reflect.ArrayOf(length, typ)))
reflect.Copy(frozen, val)
return Value{
vtype: vtype,
slice: frozen.Interface(),
}
default:
return Value{vtype: INVALID}
}
}

Expand All @@ -162,23 +155,7 @@ func StringSliceValue(v []string) Value {
func ArrayValue(v interface{}) Value {
switch reflect.TypeOf(v).Kind() {
case reflect.Array, reflect.Slice:
// get array type regardless of dimensions
typ := reflect.TypeOf(v).Elem()
kind := typ.Kind()
switch kind {
case reflect.Bool, reflect.Int, reflect.Int64,
reflect.Float64, reflect.String:
val := reflect.ValueOf(v)
length := val.Len()
frozen := reflect.Indirect(reflect.New(reflect.ArrayOf(length, typ)))
reflect.Copy(frozen, val)
return Value{
vtype: ARRAY,
slice: frozen.Interface(),
}
default:
return Value{vtype: INVALID}
}
return sliceValue(v, ARRAY)
}
return Value{vtype: INVALID}
}
Expand All @@ -197,10 +174,15 @@ func (v Value) AsBool() bool {
// AsBoolSlice returns the []bool value. Make sure that the Value's type is
// BOOLSLICE.
func (v Value) AsBoolSlice() []bool {
if s, ok := v.slice.([]bool); ok {
return s
if v.vtype != BOOLSLICE {
return nil
}
return nil
r := []bool{}
s := reflect.ValueOf(v.slice)
for i := 0; i < s.Len(); i++ {
r = append(r, s.Index(i).Bool())
}
return r
}

// AsInt64 returns the int64 value. Make sure that the Value's type is
Expand All @@ -212,10 +194,15 @@ func (v Value) AsInt64() int64 {
// AsInt64Slice returns the []int64 value. Make sure that the Value's type is
// INT64SLICE.
func (v Value) AsInt64Slice() []int64 {
if s, ok := v.slice.([]int64); ok {
return s
if v.vtype != INT64SLICE {
return nil
}
r := []int64{}
s := reflect.ValueOf(v.slice)
for i := 0; i < s.Len(); i++ {
r = append(r, s.Index(i).Int())
}
return nil
return r
}

// AsFloat64 returns the float64 value. Make sure that the Value's
Expand All @@ -227,10 +214,15 @@ func (v Value) AsFloat64() float64 {
// AsFloat64Slice returns the []float64 value. Make sure that the Value's type is
// INT64SLICE.
func (v Value) AsFloat64Slice() []float64 {
if s, ok := v.slice.([]float64); ok {
return s
if v.vtype != FLOAT64SLICE {
return nil
}
return nil
r := []float64{}
s := reflect.ValueOf(v.slice)
for i := 0; i < s.Len(); i++ {
r = append(r, s.Index(i).Float())
}
return r
}

// AsString returns the string value. Make sure that the Value's type
Expand All @@ -242,10 +234,15 @@ func (v Value) AsString() string {
// AsStringSlice returns the []string value. Make sure that the Value's type is
// INT64SLICE.
func (v Value) AsStringSlice() []string {
if s, ok := v.slice.([]string); ok {
return s
if v.vtype != STRINGSLICE {
return nil
}
r := []string{}
s := reflect.ValueOf(v.slice)
for i := 0; i < s.Len(); i++ {
r = append(r, s.Index(i).String())
}
return nil
return r
}

// AsArray returns the array Value as an interface{}.
Expand Down
Expand Up @@ -266,7 +266,7 @@ func TestSpanData(t *testing.T) {
DroppedAttributes: 1,
DroppedEvents: 2,
DroppedLinks: 3,
Resource: resource.NewSchemaless(attribute.String("rk1", "rv1"), attribute.Int64("rk2", 5)),
Resource: resource.NewSchemaless(attribute.String("rk1", "rv1"), attribute.Int64("rk2", 5), attribute.StringSlice("rk3", []string{"sv1", "sv2"})),
InstrumentationLibrary: instrumentation.Library{
Name: "go.opentelemetry.io/test/otel",
Version: "v0.0.1",
Expand Down

0 comments on commit fe29e9f

Please sign in to comment.