1
0
mirror of https://github.com/open-telemetry/opentelemetry-go.git synced 2025-09-16 09:26:25 +02:00

Added support array attributes (#798)

* Added support array attributes

* Changed function signature for AsArray attribute

* Fixed code comments for array attributes

* Fixed typos in comments in value.go

Co-authored-by: Tyler Yahn <MrAlias@users.noreply.github.com>
This commit is contained in:
Mujtaba Ahmed
2020-06-25 00:58:08 +02:00
committed by GitHub
parent 7d631dbfaa
commit 5be82c0e47
6 changed files with 138 additions and 4 deletions

View File

@@ -158,3 +158,16 @@ func (k Key) Uint(v uint) KeyValue {
func (k Key) Defined() bool {
return len(k) != 0
}
// Array creates a KeyValue instance with a ARRAY Value.
//
// If creating both key and a array value at the same time, then
// instead of calling kv.Key(name).String(value) consider using a
// convenience function provided by the api/key package -
// key.Array(name, value).
func (k Key) Array(v interface{}) KeyValue {
return KeyValue{
Key: k,
Value: value.Array(v),
}
}

View File

@@ -95,6 +95,12 @@ func Uint(k string, v uint) KeyValue {
return Key(k).Uint(v)
}
// Array creates a new key-value pair with a passed name and a array.
// Only arrays of primitive type are supported.
func Array(k string, v interface{}) KeyValue {
return Key(k).Array(v)
}
// Infer creates a new key-value pair instance with a passed name and
// automatic type inference. This is slower, and not type-safe.
func Infer(k string, value interface{}) KeyValue {
@@ -109,6 +115,8 @@ func Infer(k string, value interface{}) KeyValue {
rv := reflect.ValueOf(value)
switch rv.Kind() {
case reflect.Array, reflect.Slice:
return Array(k, value)
case reflect.Bool:
return Bool(k, rv.Bool())
case reflect.Int, reflect.Int8, reflect.Int16:

View File

@@ -17,11 +17,12 @@ func _() {
_ = x[FLOAT32-6]
_ = x[FLOAT64-7]
_ = x[STRING-8]
_ = x[ARRAY-9]
}
const _Type_name = "INVALIDBOOLINT32INT64UINT32UINT64FLOAT32FLOAT64STRING"
const _Type_name = "INVALIDBOOLINT32INT64UINT32UINT64FLOAT32FLOAT64STRINGARRAY"
var _Type_index = [...]uint8{0, 7, 11, 16, 21, 27, 33, 40, 47, 53}
var _Type_index = [...]uint8{0, 7, 11, 16, 21, 27, 33, 40, 47, 53, 58}
func (i Type) String() string {
if i < 0 || i >= Type(len(_Type_index)-1) {

View File

@@ -17,7 +17,9 @@ package value
import (
"encoding/json"
"fmt"
"reflect"
"strconv"
"strings"
"unsafe"
"go.opentelemetry.io/otel/api/internal"
@@ -34,6 +36,8 @@ type Value struct {
numeric uint64
stringly string
// TODO Lazy value type?
array interface{}
}
const (
@@ -46,6 +50,7 @@ const (
FLOAT32 // 32 bit floating point value, use AsFloat32() to get it.
FLOAT64 // 64 bit floating point value, use AsFloat64() to get it.
STRING // String value, use AsString() to get it.
ARRAY // Array value of arbitrary type, use AsArray() to get it.
)
// Bool creates a BOOL Value.
@@ -130,6 +135,32 @@ func Uint(v uint) Value {
return Uint64(uint64(v))
}
// Array creates an ARRAY value.
func Array(array interface{}) Value {
switch reflect.TypeOf(array).Kind() {
case reflect.Array, reflect.Slice:
isValidType := func() bool {
// get array type regardless of dimensions
typeName := reflect.TypeOf(array).String()
typeName = typeName[strings.LastIndex(typeName, "]")+1:]
switch typeName {
case "bool", "int", "int32", "int64",
"float32", "float64", "string",
"uint", "uint32", "uint64":
return true
}
return false
}()
if isValidType {
return Value{
vtype: ARRAY,
array: array,
}
}
}
return Value{vtype: INVALID}
}
// Type returns a type of the Value.
func (v Value) Type() Type {
return v.vtype
@@ -183,11 +214,18 @@ func (v Value) AsString() string {
return v.stringly
}
// AsArray returns the array Value as an interface{}.
func (v Value) AsArray() interface{} {
return v.array
}
type unknownValueType struct{}
// AsInterface returns Value's data as interface{}.
func (v Value) AsInterface() interface{} {
switch v.Type() {
case ARRAY:
return v.AsArray()
case BOOL:
return v.AsBool()
case INT32:
@@ -211,6 +249,8 @@ func (v Value) AsInterface() interface{} {
// Emit returns a string representation of Value's data.
func (v Value) Emit() string {
switch v.Type() {
case ARRAY:
return fmt.Sprint(v.array)
case BOOL:
return strconv.FormatBool(v.AsBool())
case INT32:

View File

@@ -40,6 +40,12 @@ func TestValue(t *testing.T) {
wantType: value.BOOL,
wantValue: true,
},
{
name: "Key.Array([]bool) correctly return key's internal bool values",
value: k.Array([]bool{true, false}).Value,
wantType: value.ARRAY,
wantValue: []bool{true, false},
},
{
name: "Key.Int64() correctly returns keys's internal int64 value",
value: k.Int64(42).Value,
@@ -94,6 +100,66 @@ func TestValue(t *testing.T) {
wantType: bli.unsignedType,
wantValue: bli.unsignedValue,
},
{
name: "Key.Array([]int64) correctly returns keys's internal int64 values",
value: k.Array([]int64{42, 43}).Value,
wantType: value.ARRAY,
wantValue: []int64{42, 43},
},
{
name: "KeyArray([]uint64) correctly returns keys's internal uint64 values",
value: k.Array([]uint64{42, 43}).Value,
wantType: value.ARRAY,
wantValue: []uint64{42, 43},
},
{
name: "Key.Array([]float64) correctly returns keys's internal float64 values",
value: k.Array([]float64{42, 43}).Value,
wantType: value.ARRAY,
wantValue: []float64{42, 43},
},
{
name: "Key.Array([]int32) correctly returns keys's internal int32 values",
value: k.Array([]int32{42, 43}).Value,
wantType: value.ARRAY,
wantValue: []int32{42, 43},
},
{
name: "Key.Array([]uint32) correctly returns keys's internal uint32 values",
value: k.Array([]uint32{42, 43}).Value,
wantType: value.ARRAY,
wantValue: []uint32{42, 43},
},
{
name: "Key.Array([]float32) correctly returns keys's internal float32 values",
value: k.Array([]float32{42, 43}).Value,
wantType: value.ARRAY,
wantValue: []float32{42, 43},
},
{
name: "Key.Array([]string) correctly return key's internal string values",
value: k.Array([]string{"foo", "bar"}).Value,
wantType: value.ARRAY,
wantValue: []string{"foo", "bar"},
},
{
name: "Key.Array([]int) correctly returns keys's internal signed integral values",
value: k.Array([]int{42, 43}).Value,
wantType: value.ARRAY,
wantValue: []int{42, 43},
},
{
name: "Key.Array([]uint) correctly returns keys's internal unsigned integral values",
value: k.Array([]uint{42, 43}).Value,
wantType: value.ARRAY,
wantValue: []uint{42, 43},
},
{
name: "Key.Array([][]int) correctly return key's multi dimensional array",
value: k.Array([][]int{{1, 2}, {3, 4}}).Value,
wantType: value.ARRAY,
wantValue: [][]int{{1, 2}, {3, 4}},
},
} {
t.Logf("Running test case %s", testcase.name)
if testcase.value.Type() != testcase.wantType {

View File

@@ -26,6 +26,7 @@ import (
"go.opentelemetry.io/otel/api/global"
"go.opentelemetry.io/otel/api/kv"
"go.opentelemetry.io/otel/api/kv/value"
apitrace "go.opentelemetry.io/otel/api/trace"
export "go.opentelemetry.io/otel/sdk/export/trace"
"go.opentelemetry.io/otel/sdk/internal"
@@ -103,7 +104,10 @@ func (s *span) SetAttributes(attributes ...kv.KeyValue) {
}
func (s *span) SetAttribute(k string, v interface{}) {
s.SetAttributes(kv.Infer(k, v))
attr := kv.Infer(k, v)
if attr.Value.Type() != value.INVALID {
s.SetAttributes(attr)
}
}
func (s *span) End(options ...apitrace.EndOption) {
@@ -293,7 +297,9 @@ func (s *span) copyToCappedAttributes(attributes ...kv.KeyValue) {
s.mu.Lock()
defer s.mu.Unlock()
for _, a := range attributes {
s.attributes.add(a)
if a.Value.Type() != value.INVALID {
s.attributes.add(a)
}
}
}