Skip to content

Commit

Permalink
adding support for Bytes attribute type (#3756)
Browse files Browse the repository at this point in the history
* adding support for Bytes attribute type

* adding warning comment

* update comments

* update comments
  • Loading branch information
alrex authored Aug 4, 2021
1 parent 999f565 commit 3cfe4f8
Show file tree
Hide file tree
Showing 2 changed files with 142 additions and 1 deletion.
72 changes: 72 additions & 0 deletions model/pdata/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package pdata
// such as timestamps, attributes, etc.

import (
"bytes"
"sort"

otlpcommon "go.opentelemetry.io/collector/model/internal/data/protogen/common/v1"
Expand All @@ -34,6 +35,7 @@ const (
AttributeValueTypeBool
AttributeValueTypeMap
AttributeValueTypeArray
AttributeValueTypeBytes
)

// String returns the string representation of the AttributeValueType.
Expand All @@ -53,6 +55,8 @@ func (avt AttributeValueType) String() string {
return "MAP"
case AttributeValueTypeArray:
return "ARRAY"
case AttributeValueTypeBytes:
return "BYTES"
}
return ""
}
Expand Down Expand Up @@ -116,6 +120,13 @@ func NewAttributeValueArray() AttributeValue {
return AttributeValue{orig: &otlpcommon.AnyValue{Value: &otlpcommon.AnyValue_ArrayValue{ArrayValue: &otlpcommon.ArrayValue{}}}}
}

// NewAttributeValueBytes creates a new AttributeValue with the given []byte value.
// The caller must ensure the []byte passed in is not modified after the call is made, sharing the data
// across multiple attributes is forbidden.
func NewAttributeValueBytes(v []byte) AttributeValue {
return AttributeValue{orig: &otlpcommon.AnyValue{Value: &otlpcommon.AnyValue_BytesValue{BytesValue: v}}}
}

// Type returns the type of the value for this AttributeValue.
// Calling this function on zero-initialized AttributeValue will cause a panic.
func (a AttributeValue) Type() AttributeValueType {
Expand All @@ -135,6 +146,8 @@ func (a AttributeValue) Type() AttributeValueType {
return AttributeValueTypeMap
case *otlpcommon.AnyValue_ArrayValue:
return AttributeValueTypeArray
case *otlpcommon.AnyValue_BytesValue:
return AttributeValueTypeBytes
}
return AttributeValueTypeNull
}
Expand Down Expand Up @@ -193,6 +206,14 @@ func (a AttributeValue) ArrayVal() AnyValueArray {
return newAnyValueArray(&arr.Values)
}

// BytesVal returns the []byte value associated with this AttributeValue.
// If the Type() is not AttributeValueTypeBytes then returns false.
// Calling this function on zero-initialized AttributeValue will cause a panic.
// Modifying the returned []byte in-place is forbidden.
func (a AttributeValue) BytesVal() []byte {
return a.orig.GetBytesValue()
}

// SetStringVal replaces the string value associated with this AttributeValue,
// it also changes the type to be AttributeValueTypeString.
// Calling this function on zero-initialized AttributeValue will cause a panic.
Expand Down Expand Up @@ -221,6 +242,15 @@ func (a AttributeValue) SetBoolVal(v bool) {
a.orig.Value = &otlpcommon.AnyValue_BoolValue{BoolValue: v}
}

// SetBytesVal replaces the []byte value associated with this AttributeValue,
// it also changes the type to be AttributeValueTypeBytes.
// Calling this function on zero-initialized AttributeValue will cause a panic.
// The caller must ensure the []byte passed in is not modified after the call is made, sharing the data
// across multiple attributes is forbidden.
func (a AttributeValue) SetBytesVal(v []byte) {
a.orig.Value = &otlpcommon.AnyValue_BytesValue{BytesValue: v}
}

// copyTo copies the value to AnyValue. Will panic if dest is nil.
func (a AttributeValue) copyTo(dest *otlpcommon.AnyValue) {
switch v := a.orig.Value.(type) {
Expand Down Expand Up @@ -323,6 +353,8 @@ func (a AttributeValue) Equal(av AttributeValue) bool {
}
}
return true
case *otlpcommon.AnyValue_BytesValue:
return bytes.Equal(v.BytesValue, av.orig.GetBytesValue())
}

return false
Expand Down Expand Up @@ -367,6 +399,13 @@ func newAttributeKeyValue(k string, av AttributeValue) otlpcommon.KeyValue {
return orig
}

func newAttributeKeyValueBytes(k string, v []byte) otlpcommon.KeyValue {
orig := otlpcommon.KeyValue{Key: k}
akv := AttributeValue{&orig.Value}
akv.SetBytesVal(v)
return orig
}

// AttributeMap stores a map of attribute keys to values.
type AttributeMap struct {
orig *[]otlpcommon.KeyValue
Expand Down Expand Up @@ -503,6 +542,16 @@ func (am AttributeMap) InsertBool(k string, v bool) {
}
}

// InsertBytes adds the []byte Value to the map when the key does not exist.
// No action is applied to the map where the key already exists.
// The caller must ensure the []byte passed in is not modified after the call is made, sharing the data
// across multiple attributes is forbidden.
func (am AttributeMap) InsertBytes(k string, v []byte) {
if _, existing := am.Get(k); !existing {
*am.orig = append(*am.orig, newAttributeKeyValueBytes(k, v))
}
}

// Update updates an existing AttributeValue with a value.
// No action is applied to the map where the key does not exist.
//
Expand Down Expand Up @@ -548,6 +597,16 @@ func (am AttributeMap) UpdateBool(k string, v bool) {
}
}

// UpdateBytes updates an existing []byte Value with a value.
// No action is applied to the map where the key does not exist.
// The caller must ensure the []byte passed in is not modified after the call is made, sharing the data
// across multiple attributes is forbidden.
func (am AttributeMap) UpdateBytes(k string, v []byte) {
if av, existing := am.Get(k); existing {
av.SetBytesVal(v)
}
}

// Upsert performs the Insert or Update action. The AttributeValue is
// inserted to the map that did not originally have the key. The key/value is
// updated to the map where the key already existed.
Expand Down Expand Up @@ -608,6 +667,19 @@ func (am AttributeMap) UpsertBool(k string, v bool) {
}
}

// UpsertBytes performs the Insert or Update action. The []byte Value is
// inserted to the map that did not originally have the key. The key/value is
// updated to the map where the key already existed.
// The caller must ensure the []byte passed in is not modified after the call is made, sharing the data
// across multiple attributes is forbidden.
func (am AttributeMap) UpsertBytes(k string, v []byte) {
if av, existing := am.Get(k); existing {
av.SetBytesVal(v)
} else {
*am.orig = append(*am.orig, newAttributeKeyValueBytes(k, v))
}
}

// Sort sorts the entries in the AttributeMap so two instances can be compared.
// Returns the same instance to allow nicer code like:
// assert.EqualValues(t, expected.Sort(), actual.Sort())
Expand Down
71 changes: 70 additions & 1 deletion model/pdata/common_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,11 @@ func TestAttributeValue(t *testing.T) {
v.SetBoolVal(true)
assert.EqualValues(t, AttributeValueTypeBool, v.Type())
assert.True(t, v.BoolVal())

bytesValue := []byte{1, 2, 3, 4}
v = NewAttributeValueBytes(bytesValue)
assert.EqualValues(t, AttributeValueTypeBytes, v.Type())
assert.EqualValues(t, bytesValue, v.BytesVal())
}

func TestAttributeValueType(t *testing.T) {
Expand All @@ -69,6 +74,7 @@ func TestAttributeValueType(t *testing.T) {
assert.EqualValues(t, "DOUBLE", AttributeValueTypeDouble.String())
assert.EqualValues(t, "MAP", AttributeValueTypeMap.String())
assert.EqualValues(t, "ARRAY", AttributeValueTypeArray.String())
assert.EqualValues(t, "BYTES", AttributeValueTypeBytes.String())
}

func TestAttributeValueMap(t *testing.T) {
Expand Down Expand Up @@ -164,6 +170,10 @@ func TestNilOrigSetAttributeValue(t *testing.T) {
av = NewAttributeValueNull()
av.SetDoubleVal(1.23)
assert.EqualValues(t, 1.23, av.DoubleVal())

av = NewAttributeValueNull()
av.SetBytesVal([]byte{1, 2, 3})
assert.Equal(t, []byte{1, 2, 3}, av.BytesVal())
}

func TestAttributeValueEqual(t *testing.T) {
Expand Down Expand Up @@ -211,6 +221,16 @@ func TestAttributeValueEqual(t *testing.T) {
av1 = NewAttributeValueBool(false)
assert.True(t, av1.Equal(av2))

av2 = NewAttributeValueBytes([]byte{1, 2, 3})
assert.False(t, av1.Equal(av2))
assert.False(t, av2.Equal(av1))

av1 = NewAttributeValueBytes([]byte{1, 2, 4})
assert.False(t, av1.Equal(av2))

av1 = NewAttributeValueBytes([]byte{1, 2, 3})
assert.True(t, av1.Equal(av2))

av1 = NewAttributeValueArray()
av1.ArrayVal().AppendEmpty().SetIntVal(123)
assert.False(t, av1.Equal(av2))
Expand Down Expand Up @@ -279,6 +299,10 @@ func TestNilAttributeMap(t *testing.T) {
insertMapBool.InsertBool("k", true)
assert.EqualValues(t, generateTestBoolAttributeMap(), insertMapBool)

insertMapBytes := NewAttributeMap()
insertMapBytes.InsertBytes("k", []byte{1, 2, 3, 4, 5})
assert.EqualValues(t, generateTestBytesAttributeMap(), insertMapBytes)

updateMap := NewAttributeMap()
updateMap.Update("k", NewAttributeValueString("v"))
assert.EqualValues(t, NewAttributeMap(), updateMap)
Expand All @@ -299,6 +323,10 @@ func TestNilAttributeMap(t *testing.T) {
updateMapBool.UpdateBool("k", true)
assert.EqualValues(t, NewAttributeMap(), updateMapBool)

updateMapBytes := NewAttributeMap()
updateMapBytes.UpdateBytes("k", []byte{1, 2, 3})
assert.EqualValues(t, NewAttributeMap(), updateMapBytes)

upsertMap := NewAttributeMap()
upsertMap.Upsert("k", NewAttributeValueString("v"))
assert.EqualValues(t, generateTestAttributeMap(), upsertMap)
Expand All @@ -319,6 +347,10 @@ func TestNilAttributeMap(t *testing.T) {
upsertMapBool.UpsertBool("k", true)
assert.EqualValues(t, generateTestBoolAttributeMap(), upsertMapBool)

upsertMapBytes := NewAttributeMap()
upsertMapBytes.UpsertBytes("k", []byte{1, 2, 3, 4, 5})
assert.EqualValues(t, generateTestBytesAttributeMap(), upsertMapBytes)

deleteMap := NewAttributeMap()
assert.False(t, deleteMap.Delete("k"))
assert.EqualValues(t, NewAttributeMap(), deleteMap)
Expand Down Expand Up @@ -382,6 +414,12 @@ func TestAttributeMapWithEmpty(t *testing.T) {
assert.EqualValues(t, AttributeValueTypeBool, val.Type())
assert.True(t, val.BoolVal())

sm.InsertBytes("other_key_bytes", []byte{1, 2, 3})
val, exist = sm.Get("other_key_bytes")
assert.True(t, exist)
assert.EqualValues(t, AttributeValueTypeBytes, val.Type())
assert.EqualValues(t, []byte{1, 2, 3}, val.BytesVal())

sm.Update("other_key", NewAttributeValueString("yet_another_value"))
val, exist = sm.Get("other_key")
assert.True(t, exist)
Expand Down Expand Up @@ -412,6 +450,12 @@ func TestAttributeMapWithEmpty(t *testing.T) {
assert.EqualValues(t, AttributeValueTypeBool, val.Type())
assert.False(t, val.BoolVal())

sm.UpdateBytes("other_key_bytes", []byte{4, 5, 6})
val, exist = sm.Get("other_key_bytes")
assert.True(t, exist)
assert.EqualValues(t, AttributeValueTypeBytes, val.Type())
assert.EqualValues(t, []byte{4, 5, 6}, val.BytesVal())

sm.Upsert("other_key", NewAttributeValueString("other_value"))
val, exist = sm.Get("other_key")
assert.True(t, exist)
Expand Down Expand Up @@ -442,6 +486,12 @@ func TestAttributeMapWithEmpty(t *testing.T) {
assert.EqualValues(t, AttributeValueTypeBool, val.Type())
assert.True(t, val.BoolVal())

sm.UpsertBytes("other_key_bytes", []byte{7, 8, 9})
val, exist = sm.Get("other_key_bytes")
assert.True(t, exist)
assert.EqualValues(t, AttributeValueTypeBytes, val.Type())
assert.EqualValues(t, []byte{7, 8, 9}, val.BytesVal())

sm.Upsert("yet_another_key", NewAttributeValueString("yet_another_value"))
val, exist = sm.Get("yet_another_key")
assert.True(t, exist)
Expand Down Expand Up @@ -472,16 +522,24 @@ func TestAttributeMapWithEmpty(t *testing.T) {
assert.EqualValues(t, AttributeValueTypeBool, val.Type())
assert.False(t, val.BoolVal())

sm.UpsertBytes("yet_another_key_bytes", []byte{1})
val, exist = sm.Get("yet_another_key_bytes")
assert.True(t, exist)
assert.EqualValues(t, AttributeValueTypeBytes, val.Type())
assert.EqualValues(t, []byte{1}, val.BytesVal())

assert.True(t, sm.Delete("other_key"))
assert.True(t, sm.Delete("other_key_string"))
assert.True(t, sm.Delete("other_key_int"))
assert.True(t, sm.Delete("other_key_double"))
assert.True(t, sm.Delete("other_key_bool"))
assert.True(t, sm.Delete("other_key_bytes"))
assert.True(t, sm.Delete("yet_another_key"))
assert.True(t, sm.Delete("yet_another_key_string"))
assert.True(t, sm.Delete("yet_another_key_int"))
assert.True(t, sm.Delete("yet_another_key_double"))
assert.True(t, sm.Delete("yet_another_key_bool"))
assert.True(t, sm.Delete("yet_another_key_bytes"))
assert.False(t, sm.Delete("other_key"))
assert.False(t, sm.Delete("yet_another_key"))

Expand Down Expand Up @@ -518,9 +576,10 @@ func TestAttributeMap_Range(t *testing.T) {
"k_double": NewAttributeValueDouble(1.23),
"k_bool": NewAttributeValueBool(true),
"k_null": NewAttributeValueNull(),
"k_bytes": NewAttributeValueBytes([]byte{}),
}
am := NewAttributeMap().InitFromMap(rawMap)
assert.Equal(t, 5, am.Len())
assert.Equal(t, 6, am.Len())

calls := 0
am.Range(func(k string, v AttributeValue) bool {
Expand All @@ -547,13 +606,15 @@ func TestAttributeMap_InitFromMap(t *testing.T) {
"k_double": NewAttributeValueDouble(1.23),
"k_bool": NewAttributeValueBool(true),
"k_null": NewAttributeValueNull(),
"k_bytes": NewAttributeValueBytes([]byte{1, 2, 3}),
}
rawOrig := []otlpcommon.KeyValue{
newAttributeKeyValueString("k_string", "123"),
newAttributeKeyValueInt("k_int", 123),
newAttributeKeyValueDouble("k_double", 1.23),
newAttributeKeyValueBool("k_bool", true),
newAttributeKeyValueNull("k_null"),
newAttributeKeyValueBytes("k_bytes", []byte{1, 2, 3}),
}
am = NewAttributeMap().InitFromMap(rawMap)
assert.EqualValues(t, AttributeMap{orig: &rawOrig}.Sort(), am.Sort())
Expand Down Expand Up @@ -1091,6 +1152,14 @@ func generateTestBoolAttributeMap() AttributeMap {
return am
}

func generateTestBytesAttributeMap() AttributeMap {
am := NewAttributeMap()
am.InitFromMap(map[string]AttributeValue{
"k": NewAttributeValueBytes([]byte{1, 2, 3, 4, 5}),
})
return am
}

func TestAttributeValueArray(t *testing.T) {
a1 := NewAttributeValueArray()
assert.EqualValues(t, AttributeValueTypeArray, a1.Type())
Expand Down

0 comments on commit 3cfe4f8

Please sign in to comment.