Skip to content

Commit

Permalink
Deprecate Array attribute in favor of *Slice types (#2162)
Browse files Browse the repository at this point in the history
* Deprecate Array attribute in favor of *Slice types

* Use new attr types in Jaeger exporter

* Use slice attr types in otlpmetric

* Use slice attr types in otlptrace

* Use slice attr types in zipkin exporter

* Remove array attr test from deprectated oteltest func

* Use StringSlice for cmd arg resource attr

* Add changes to the changelog

* Remove use of deprecated Array func
  • Loading branch information
MrAlias committed Aug 12, 2021
1 parent df384a9 commit 87d09df
Show file tree
Hide file tree
Showing 17 changed files with 580 additions and 192 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
### Added

- Added `ErrorHandlerFunc` to use a function as an `"go.opentelemetry.io/otel".ErrorHandler`. (#2149)
- Added typed slice attribute types and functionality to the `go.opentelemetry.io/otel/attribute` package to replace the existing array type and functions. (#2162)
- `BoolSlice`, `IntSlice`, `Int64Slice`, `Float64Slice`, and `StringSlice` replace the use of the `Array` function in the package.

### Changed

Expand All @@ -21,6 +23,8 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
- The `go.opentelemetry.io/otel/bridge/opencensus/utils` package is deprecated.
All functionality from this package now exists in the `go.opentelemetry.io/otel/bridge/opencensus` package.
The functions from that package should be used instead. (#2166)
- The `"go.opentelemetry.io/otel/attribute".Array` function and the related `ARRAY` value type is deprecated.
Use the typed `*Slice` functions and types added to the package instead. (#2162)

### Removed

Expand Down
142 changes: 132 additions & 10 deletions attribute/benchmark_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,14 @@ var (
outV attribute.Value
outKV attribute.KeyValue

outBool bool
outInt64 int64
outFloat64 float64
outStr string
outBool bool
outBoolSlice []bool
outInt64 int64
outInt64Slice []int64
outFloat64 float64
outFloat64Slice []float64
outStr string
outStrSlice []string
)

func benchmarkAny(k string, v interface{}) func(*testing.B) {
Expand Down Expand Up @@ -91,6 +95,32 @@ func BenchmarkBool(b *testing.B) {
b.Run("Array", benchmarkArray(k, array))
}

func BenchmarkBoolSlice(b *testing.B) {
k, v := "bool slice", []bool{true, false, true}
kv := attribute.BoolSlice(k, v)

b.Run("Value", func(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
outV = attribute.BoolSliceValue(v)
}
})
b.Run("KeyValue", func(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
outKV = attribute.BoolSlice(k, v)
}
})
b.Run("AsBoolSlice", func(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
outBoolSlice = kv.Value.AsBoolSlice()
}
})
b.Run("Any", benchmarkAny(k, v))
b.Run("Emit", benchmarkEmit(kv))
}

func BenchmarkInt(b *testing.B) {
k, v := "int", int(42)
kv := attribute.Int(k, v)
Expand All @@ -113,6 +143,26 @@ func BenchmarkInt(b *testing.B) {
b.Run("Array", benchmarkArray(k, array))
}

func BenchmarkIntSlice(b *testing.B) {
k, v := "int slice", []int{42, -3, 12}
kv := attribute.IntSlice(k, v)

b.Run("Value", func(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
outV = attribute.IntSliceValue(v)
}
})
b.Run("KeyValue", func(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
outKV = attribute.IntSlice(k, v)
}
})
b.Run("Any", benchmarkAny(k, v))
b.Run("Emit", benchmarkEmit(kv))
}

func BenchmarkInt8(b *testing.B) {
b.Run("Any", benchmarkAny("int8", int8(42)))
}
Expand Down Expand Up @@ -153,6 +203,32 @@ func BenchmarkInt64(b *testing.B) {
b.Run("Array", benchmarkArray(k, array))
}

func BenchmarkInt64Slice(b *testing.B) {
k, v := "int64 slice", []int64{42, -3, 12}
kv := attribute.Int64Slice(k, v)

b.Run("Value", func(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
outV = attribute.Int64SliceValue(v)
}
})
b.Run("KeyValue", func(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
outKV = attribute.Int64Slice(k, v)
}
})
b.Run("AsInt64Slice", func(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
outInt64Slice = kv.Value.AsInt64Slice()
}
})
b.Run("Any", benchmarkAny(k, v))
b.Run("Emit", benchmarkEmit(kv))
}

func BenchmarkFloat64(b *testing.B) {
k, v := "float64", float64(42)
kv := attribute.Float64(k, v)
Expand Down Expand Up @@ -181,6 +257,32 @@ func BenchmarkFloat64(b *testing.B) {
b.Run("Array", benchmarkArray(k, array))
}

func BenchmarkFloat64Slice(b *testing.B) {
k, v := "float64 slice", []float64{42, -3, 12}
kv := attribute.Float64Slice(k, v)

b.Run("Value", func(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
outV = attribute.Float64SliceValue(v)
}
})
b.Run("KeyValue", func(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
outKV = attribute.Float64Slice(k, v)
}
})
b.Run("AsFloat64Slice", func(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
outFloat64Slice = kv.Value.AsFloat64Slice()
}
})
b.Run("Any", benchmarkAny(k, v))
b.Run("Emit", benchmarkEmit(kv))
}

func BenchmarkString(b *testing.B) {
k, v := "string", "42"
kv := attribute.String(k, v)
Expand Down Expand Up @@ -209,12 +311,32 @@ func BenchmarkString(b *testing.B) {
b.Run("Array", benchmarkArray(k, array))
}

func BenchmarkBytes(b *testing.B) {
b.Run("Any", benchmarkAny("bytes", []byte("bytes")))
}
func BenchmarkStringSlice(b *testing.B) {
k, v := "float64 slice", []string{"forty-two", "negative three", "twelve"}
kv := attribute.StringSlice(k, v)

type test struct{}
b.Run("Value", func(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
outV = attribute.StringSliceValue(v)
}
})
b.Run("KeyValue", func(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
outKV = attribute.StringSlice(k, v)
}
})
b.Run("AsStringSlice", func(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
outStrSlice = kv.Value.AsStringSlice()
}
})
b.Run("Any", benchmarkAny(k, v))
b.Run("Emit", benchmarkEmit(kv))
}

func BenchmarkStruct(b *testing.B) {
b.Run("Any", benchmarkAny("struct", test{}))
func BenchmarkBytes(b *testing.B) {
b.Run("Any", benchmarkAny("bytes", []byte("bytes")))
}
57 changes: 57 additions & 0 deletions attribute/key.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,17 @@ func (k Key) Bool(v bool) KeyValue {
}
}

// BoolSlice creates a KeyValue instance with a BOOLSLICE Value.
//
// If creating both a key and value at the same time, use the provided
// convenience function instead -- BoolSlice(name, value).
func (k Key) BoolSlice(v []bool) KeyValue {
return KeyValue{
Key: k,
Value: BoolSliceValue(v),
}
}

// Int creates a KeyValue instance with an INT64 Value.
//
// If creating both a key and value at the same time, use the provided
Expand All @@ -40,6 +51,17 @@ func (k Key) Int(v int) KeyValue {
}
}

// IntSlice creates a KeyValue instance with an INT64SLICE Value.
//
// If creating both a key and value at the same time, use the provided
// convenience function instead -- IntSlice(name, value).
func (k Key) IntSlice(v []int) KeyValue {
return KeyValue{
Key: k,
Value: IntSliceValue(v),
}
}

// Int64 creates a KeyValue instance with an INT64 Value.
//
// If creating both a key and value at the same time, use the provided
Expand All @@ -51,6 +73,17 @@ func (k Key) Int64(v int64) KeyValue {
}
}

// Int64Slice creates a KeyValue instance with an INT64SLICE Value.
//
// If creating both a key and value at the same time, use the provided
// convenience function instead -- Int64Slice(name, value).
func (k Key) Int64Slice(v []int64) KeyValue {
return KeyValue{
Key: k,
Value: Int64SliceValue(v),
}
}

// Float64 creates a KeyValue instance with a FLOAT64 Value.
//
// If creating both a key and value at the same time, use the provided
Expand All @@ -62,6 +95,17 @@ func (k Key) Float64(v float64) KeyValue {
}
}

// Float64Slice creates a KeyValue instance with a FLOAT64SLICE Value.
//
// If creating both a key and value at the same time, use the provided
// convenience function instead -- Float64(name, value).
func (k Key) Float64Slice(v []float64) KeyValue {
return KeyValue{
Key: k,
Value: Float64SliceValue(v),
}
}

// String creates a KeyValue instance with a STRING Value.
//
// If creating both a key and value at the same time, use the provided
Expand All @@ -73,10 +117,23 @@ func (k Key) String(v string) KeyValue {
}
}

// StringSlice creates a KeyValue instance with a STRINGSLICE Value.
//
// If creating both a key and value at the same time, use the provided
// convenience function instead -- StringSlice(name, value).
func (k Key) StringSlice(v []string) KeyValue {
return KeyValue{
Key: k,
Value: StringSliceValue(v),
}
}

// Array creates a KeyValue instance with an ARRAY Value.
//
// If creating both a key and value at the same time, use the provided
// convenience function instead -- Array(name, value).
//
// Deprecated: Use the typed *Slice methods instead.
func (k Key) Array(v interface{}) KeyValue {
return KeyValue{
Key: k,
Expand Down
49 changes: 46 additions & 3 deletions attribute/kv.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,26 +36,51 @@ func Bool(k string, v bool) KeyValue {
return Key(k).Bool(v)
}

// BoolSlice creates a KeyValue with a BOOLSLICE Value type.
func BoolSlice(k string, v []bool) KeyValue {
return Key(k).BoolSlice(v)
}

// Int creates a KeyValue with an INT64 Value type.
func Int(k string, v int) KeyValue {
return Key(k).Int(v)
}

// Int64 creates a KeyValue with a INT64 Value type.
// IntSlice creates a KeyValue with an INT64SLICE Value type.
func IntSlice(k string, v []int) KeyValue {
return Key(k).IntSlice(v)
}

// Int64 creates a KeyValue with an INT64 Value type.
func Int64(k string, v int64) KeyValue {
return Key(k).Int64(v)
}

// Int64Slice creates a KeyValue with an INT64SLICE Value type.
func Int64Slice(k string, v []int64) KeyValue {
return Key(k).Int64Slice(v)
}

// Float64 creates a KeyValue with a FLOAT64 Value type.
func Float64(k string, v float64) KeyValue {
return Key(k).Float64(v)
}

// Float64Slice creates a KeyValue with a FLOAT64SLICE Value type.
func Float64Slice(k string, v []float64) KeyValue {
return Key(k).Float64Slice(v)
}

// String creates a KeyValue with a STRING Value type.
func String(k, v string) KeyValue {
return Key(k).String(v)
}

// StringSlice creates a KeyValue with a STRINGSLICE Value type.
func StringSlice(k string, v []string) KeyValue {
return Key(k).StringSlice(v)
}

// Stringer creates a new key-value pair with a passed name and a string
// value generated by the passed Stringer interface.
func Stringer(k string, v fmt.Stringer) KeyValue {
Expand All @@ -64,6 +89,8 @@ func Stringer(k string, v fmt.Stringer) KeyValue {

// Array creates a new key-value pair with a passed name and a array.
// Only arrays of primitive type are supported.
//
// Deprecated: Use the typed *Slice functions instead.
func Array(k string, v interface{}) KeyValue {
return Key(k).Array(v)
}
Expand All @@ -82,8 +109,24 @@ func Any(k string, value interface{}) KeyValue {
rv := reflect.ValueOf(value)

switch rv.Kind() {
case reflect.Array, reflect.Slice:
return Array(k, value)
case reflect.Array:
rv = rv.Slice(0, rv.Len())
fallthrough
case reflect.Slice:
switch reflect.TypeOf(value).Elem().Kind() {
case reflect.Bool:
return BoolSlice(k, rv.Interface().([]bool))
case reflect.Int:
return IntSlice(k, rv.Interface().([]int))
case reflect.Int64:
return Int64Slice(k, rv.Interface().([]int64))
case reflect.Float64:
return Float64Slice(k, rv.Interface().([]float64))
case reflect.String:
return StringSlice(k, rv.Interface().([]string))
default:
return KeyValue{Key: Key(k), Value: Value{vtype: INVALID}}
}
case reflect.Bool:
return Bool(k, rv.Bool())
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
Expand Down

0 comments on commit 87d09df

Please sign in to comment.