1
0
mirror of https://github.com/open-telemetry/opentelemetry-go.git synced 2026-06-03 18:35:08 +02:00

attribute: change INVALID Type to EMPTY and mark INVALID as deprecated (#8038)

Fixes https://github.com/open-telemetry/opentelemetry-go/issues/7932

Noticeable comment from previous PR:
https://github.com/open-telemetry/opentelemetry-go/pull/7942#discussion_r2913179215

Print the empty value as empty string per
https://opentelemetry.io/docs/specs/otel/common/#empty-values
This commit is contained in:
Robert Pająk
2026-03-12 09:43:04 +01:00
committed by GitHub
parent 205e24407e
commit f4da59e651
28 changed files with 136 additions and 119 deletions
+10
View File
@@ -11,6 +11,16 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
### Added
- Add service detection with `WithService` in `go.opentelemetry.io/otel/sdk/resource`. (#7642)
- Support attributes with empty value (`attribute.EMPTY`) in OTLP exporters (`go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc`, `go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc`, `go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc`, `go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp`, `go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp`, `go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp`). (#8038)
- Support attributes with empty value (`attribute.EMPTY`) in `go.opentelemetry.io/otel/sdk/metric/metricdata/metricdatatest`. (#8038)
### Changed
- Introduce the `EMPTY` Type in `go.opentelemetry.io/otel/attribute` to reflect that an empty value is now a valid value, with `INVALID` remaining as a deprecated alias of `EMPTY`. (#8038)
### Deprecated
- Deprecate `INVALID` in `go.opentelemetry.io/otel/attribute`. Use `EMPTY` instead. (#8038)
<!-- Released section -->
<!-- Don't change this section unless doing release -->
+3 -1
View File
@@ -27,6 +27,7 @@ const (
int64SliceID uint64 = 3762322556277578591 // "_[]int64" (little endian)
float64SliceID uint64 = 7308324551835016539 // "[]double" (little endian)
stringSliceID uint64 = 7453010373645655387 // "[]string" (little endian)
emptyID uint64 = 7305809155345288421 // "__empty_" (little endian)
)
// hashKVs returns a new xxHash64 hash of kvs.
@@ -80,7 +81,8 @@ func hashKV(h xxhash.Hash, kv KeyValue) xxhash.Hash {
for i := 0; i < rv.Len(); i++ {
h = h.String(rv.Index(i).String())
}
case INVALID:
case EMPTY:
h = h.Uint64(emptyID)
default:
// Logging is an alternative, but using the internal logger here
// causes an import cycle so it is not done.
+10 -2
View File
@@ -36,6 +36,7 @@ var keyVals = []func(string) KeyValue{
func(k string) KeyValue { return String(k, "bar") },
func(k string) KeyValue { return StringSlice(k, []string{"foo", "bar", "baz"}) },
func(k string) KeyValue { return StringSlice(k, []string{"[]i1"}) },
func(k string) KeyValue { return KeyValue{Key: Key(k)} }, // Empty value.
}
func TestHashKVsEquality(t *testing.T) {
@@ -155,8 +156,8 @@ func FuzzHashKVs(f *testing.F) {
0, int64(0), math.Inf(1), false, uint8(2))
f.Fuzz(func(t *testing.T, k1, k2, k3, k4, k5, s string, i int, i64 int64, fVal float64, b bool, sliceType uint8) {
// Test variable number of attributes (0-10).
numAttrs := len(k1) % 11 // Use key length to determine number of attributes.
// Test variable number of attributes (0-11).
numAttrs := len(k1) % 12 // Use key length to determine number of attributes.
if numAttrs == 0 && k1 == "" {
// Test empty set.
h := hashKVs(nil)
@@ -250,6 +251,11 @@ func FuzzHashKVs(f *testing.F) {
kvs = append(kvs, String("empty", ""))
}
// Add empty value.
if numAttrs > 10 {
kvs = append(kvs, KeyValue{Key: Key("empty_value")})
}
// Sort to ensure consistent ordering (as Set would do).
slices.SortFunc(kvs, func(a, b KeyValue) int {
return cmp.Compare(string(a.Key), string(b.Key))
@@ -301,6 +307,8 @@ func FuzzHashKVs(f *testing.F) {
if !math.IsNaN(val) && !math.IsInf(val, 0) {
modifiedKvs[0] = Float64(string(modifiedKvs[0].Key), val+1.0)
}
case EMPTY:
modifiedKvs[0] = String(string(modifiedKvs[0].Key), "not_empty")
}
h3 := hashKVs(modifiedKvs)
+5
View File
@@ -108,6 +108,11 @@ func TestEmit(t *testing.T) {
v: attribute.StringSliceValue([]string{"foo", "bar"}),
want: `["foo","bar"]`,
},
{
name: `test Key.Emit() can emit a string representing self.EMPTY`,
v: attribute.Value{},
want: "",
},
} {
t.Run(testcase.name, func(t *testing.T) {
// proto: func (v attribute.Value) Emit() string {
+1 -1
View File
@@ -15,7 +15,7 @@ type KeyValue struct {
// Valid reports whether kv is a valid OpenTelemetry attribute.
func (kv KeyValue) Valid() bool {
return kv.Key.Defined() && kv.Value.Type() != INVALID
return kv.Key.Defined()
}
// Bool creates a KeyValue with a BOOL Value type.
+7 -3
View File
@@ -86,11 +86,11 @@ func TestKeyValueValid(t *testing.T) {
kv: attribute.Key("").Bool(true),
},
{
desc: "INVALID value type should be invalid",
valid: false,
desc: "EMPTY value type should be valid",
valid: true,
kv: attribute.KeyValue{
Key: attribute.Key("valid key"),
// Default type is INVALID.
// Default type is EMPTY.
Value: attribute.Value{},
},
},
@@ -152,6 +152,10 @@ func TestIncorrectCast(t *testing.T) {
name: "StringSlice",
val: attribute.BoolSliceValue([]bool{true}),
},
{
name: "Empty",
val: attribute.Value{},
},
}
for _, tt := range testCases {
t.Run(tt.name, func(t *testing.T) {
+3 -3
View File
@@ -8,7 +8,7 @@ func _() {
// An "invalid array index" compiler error signifies that the constant values have changed.
// Re-run the stringer command to generate them again.
var x [1]struct{}
_ = x[INVALID-0]
_ = x[EMPTY-0]
_ = x[BOOL-1]
_ = x[INT64-2]
_ = x[FLOAT64-3]
@@ -19,9 +19,9 @@ func _() {
_ = x[STRINGSLICE-8]
}
const _Type_name = "INVALIDBOOLINT64FLOAT64STRINGBOOLSLICEINT64SLICEFLOAT64SLICESTRINGSLICE"
const _Type_name = "EMPTYBOOLINT64FLOAT64STRINGBOOLSLICEINT64SLICEFLOAT64SLICESTRINGSLICE"
var _Type_index = [...]uint8{0, 7, 11, 16, 23, 29, 38, 48, 60, 71}
var _Type_index = [...]uint8{0, 5, 9, 14, 21, 27, 36, 46, 58, 69}
func (i Type) String() string {
idx := int(i) - 0
+12 -2
View File
@@ -18,6 +18,8 @@ import (
type Type int // nolint: revive // redefines builtin Type.
// Value represents the value part in key-value pairs.
//
// Note that the zero value is a valid empty value.
type Value struct {
vtype Type
numeric uint64
@@ -26,8 +28,8 @@ type Value struct {
}
const (
// INVALID is used for a Value with no value set.
INVALID Type = iota
// EMPTY is used for a Value with no value set.
EMPTY Type = iota
// BOOL is a boolean Type Value.
BOOL
// INT64 is a 64-bit signed integral Type Value.
@@ -44,6 +46,10 @@ const (
FLOAT64SLICE
// STRINGSLICE is a slice of strings Type Value.
STRINGSLICE
// INVALID is used for a Value with no value set.
//
// Deprecated: Use EMPTY instead as an empty value is a valid value.
INVALID = EMPTY
)
// BoolValue creates a BOOL Value.
@@ -217,6 +223,8 @@ func (v Value) AsInterface() any {
return v.stringly
case STRINGSLICE:
return v.asStringSlice()
case EMPTY:
return nil
}
return unknownValueType{}
}
@@ -252,6 +260,8 @@ func (v Value) Emit() string {
return string(j)
case STRING:
return v.stringly
case EMPTY:
return ""
default:
return "unknown"
}
+14 -3
View File
@@ -86,14 +86,17 @@ func TestValue(t *testing.T) {
wantType: attribute.STRINGSLICE,
wantValue: []string{"forty-two", "negative three", "twelve"},
},
{
name: "empty value",
value: attribute.Value{},
wantType: attribute.EMPTY,
wantValue: nil,
},
} {
t.Logf("Running test case %s", testcase.name)
if testcase.value.Type() != testcase.wantType {
t.Errorf("wrong value type, got %#v, expected %#v", testcase.value.Type(), testcase.wantType)
}
if testcase.wantType == attribute.INVALID {
continue
}
got := testcase.value.AsInterface()
if diff := cmp.Diff(testcase.wantValue, got); diff != "" {
t.Errorf("+got, -want: %s", diff)
@@ -143,6 +146,10 @@ func TestEquivalence(t *testing.T) {
attribute.StringSlice("StringSlice", []string{"one", "two", "three"}),
attribute.StringSlice("StringSlice", []string{"one", "two", "three"}),
},
{
attribute.KeyValue{Key: "Empty"},
attribute.KeyValue{Key: "Empty"},
},
}
t.Run("Distinct", func(t *testing.T) {
@@ -234,6 +241,10 @@ func TestNotEquivalence(t *testing.T) {
attribute.StringSlice("StringSlice", []string{"one", "two", "three"}),
attribute.StringSlice("StringSlice", []string{"one", "two"}),
},
{
attribute.KeyValue{Key: "Empty"},
attribute.String("Empty", ""),
},
}
t.Run("Distinct", func(t *testing.T) {
@@ -26,8 +26,8 @@ var (
attrFloat64Slice = attribute.Float64Slice("float64 slice", []float64{-1, 1})
attrString = attribute.String("string", "o")
attrStringSlice = attribute.StringSlice("string slice", []string{"o", "n"})
attrInvalid = attribute.KeyValue{
Key: attribute.Key("invalid"),
attrEmpty = attribute.KeyValue{
Key: attribute.Key("empty"),
Value: attribute.Value{},
}
@@ -70,12 +70,7 @@ var (
kvFloat64Slice = &cpb.KeyValue{Key: "float64 slice", Value: valDblSlice}
kvString = &cpb.KeyValue{Key: "string", Value: valStrO}
kvStringSlice = &cpb.KeyValue{Key: "string slice", Value: valStrSlice}
kvInvalid = &cpb.KeyValue{
Key: "invalid",
Value: &cpb.AnyValue{
Value: &cpb.AnyValue_StringValue{StringValue: "INVALID"},
},
}
kvEmpty = &cpb.KeyValue{Key: "empty", Value: &cpb.AnyValue{}}
)
func TestAttrTransforms(t *testing.T) {
@@ -89,9 +84,9 @@ func TestAttrTransforms(t *testing.T) {
{"nil", nil, nil},
{"empty", []attribute.KeyValue{}, nil},
{
"invalid",
[]attribute.KeyValue{attrInvalid},
[]*cpb.KeyValue{kvInvalid},
"empty value",
[]attribute.KeyValue{attrEmpty},
[]*cpb.KeyValue{kvEmpty},
},
{
"bool",
@@ -156,7 +151,7 @@ func TestAttrTransforms(t *testing.T) {
attrFloat64Slice,
attrString,
attrStringSlice,
attrInvalid,
attrEmpty,
},
[]*cpb.KeyValue{
kvBool,
@@ -169,7 +164,7 @@ func TestAttrTransforms(t *testing.T) {
kvFloat64Slice,
kvString,
kvStringSlice,
kvInvalid,
kvEmpty,
},
},
} {
@@ -201,6 +201,7 @@ func AttrValue(v attribute.Value) *cpb.AnyValue {
Values: stringSliceValues(v.AsStringSlice()),
},
}
case attribute.EMPTY:
default:
av.Value = &cpb.AnyValue_StringValue{
StringValue: "INVALID",
@@ -327,6 +328,7 @@ func LogAttrValue(v api.Value) *cpb.AnyValue {
Values: LogAttrs(v.AsMap()),
},
}
case api.KindEmpty:
default:
av.Value = &cpb.AnyValue_StringValue{
StringValue: "INVALID",
@@ -24,7 +24,7 @@ var (
logAttrBytes = log.Bytes("bytes", []byte("test"))
logAttrSlice = log.Slice("slice", log.BoolValue(true))
logAttrMap = log.Map("map", logAttrString)
logAttrEmpty = log.Empty("")
logAttrEmpty = log.Empty("empty")
kvBytes = &cpb.KeyValue{
Key: "bytes",
@@ -54,11 +54,6 @@ var (
},
},
}
kvEmpty = &cpb.KeyValue{
Value: &cpb.AnyValue{
Value: &cpb.AnyValue_StringValue{StringValue: "INVALID"},
},
}
)
func TestLogAttrs(t *testing.T) {
@@ -26,8 +26,8 @@ var (
attrFloat64Slice = attribute.Float64Slice("float64 slice", []float64{-1, 1})
attrString = attribute.String("string", "o")
attrStringSlice = attribute.StringSlice("string slice", []string{"o", "n"})
attrInvalid = attribute.KeyValue{
Key: attribute.Key("invalid"),
attrEmpty = attribute.KeyValue{
Key: attribute.Key("empty"),
Value: attribute.Value{},
}
@@ -70,12 +70,7 @@ var (
kvFloat64Slice = &cpb.KeyValue{Key: "float64 slice", Value: valDblSlice}
kvString = &cpb.KeyValue{Key: "string", Value: valStrO}
kvStringSlice = &cpb.KeyValue{Key: "string slice", Value: valStrSlice}
kvInvalid = &cpb.KeyValue{
Key: "invalid",
Value: &cpb.AnyValue{
Value: &cpb.AnyValue_StringValue{StringValue: "INVALID"},
},
}
kvEmpty = &cpb.KeyValue{Key: "empty", Value: &cpb.AnyValue{}}
)
func TestAttrTransforms(t *testing.T) {
@@ -89,9 +84,9 @@ func TestAttrTransforms(t *testing.T) {
{"nil", nil, nil},
{"empty", []attribute.KeyValue{}, nil},
{
"invalid",
[]attribute.KeyValue{attrInvalid},
[]*cpb.KeyValue{kvInvalid},
"empty value",
[]attribute.KeyValue{attrEmpty},
[]*cpb.KeyValue{kvEmpty},
},
{
"bool",
@@ -156,7 +151,7 @@ func TestAttrTransforms(t *testing.T) {
attrFloat64Slice,
attrString,
attrStringSlice,
attrInvalid,
attrEmpty,
},
[]*cpb.KeyValue{
kvBool,
@@ -169,7 +164,7 @@ func TestAttrTransforms(t *testing.T) {
kvFloat64Slice,
kvString,
kvStringSlice,
kvInvalid,
kvEmpty,
},
},
} {
@@ -201,6 +201,7 @@ func AttrValue(v attribute.Value) *cpb.AnyValue {
Values: stringSliceValues(v.AsStringSlice()),
},
}
case attribute.EMPTY:
default:
av.Value = &cpb.AnyValue_StringValue{
StringValue: "INVALID",
@@ -327,6 +328,7 @@ func LogAttrValue(v api.Value) *cpb.AnyValue {
Values: LogAttrs(v.AsMap()),
},
}
case api.KindEmpty:
default:
av.Value = &cpb.AnyValue_StringValue{
StringValue: "INVALID",
@@ -24,7 +24,7 @@ var (
logAttrBytes = log.Bytes("bytes", []byte("test"))
logAttrSlice = log.Slice("slice", log.BoolValue(true))
logAttrMap = log.Map("map", logAttrString)
logAttrEmpty = log.Empty("")
logAttrEmpty = log.Empty("empty")
kvBytes = &cpb.KeyValue{
Key: "bytes",
@@ -54,11 +54,6 @@ var (
},
},
}
kvEmpty = &cpb.KeyValue{
Value: &cpb.AnyValue{
Value: &cpb.AnyValue_StringValue{StringValue: "INVALID"},
},
}
)
func TestLogAttrs(t *testing.T) {
@@ -87,6 +87,7 @@ func Value(v attribute.Value) *cpb.AnyValue {
Values: stringSliceValues(v.AsStringSlice()),
},
}
case attribute.EMPTY:
default:
av.Value = &cpb.AnyValue_StringValue{
StringValue: "INVALID",
@@ -26,8 +26,8 @@ var (
attrFloat64Slice = attribute.Float64Slice("float64 slice", []float64{-1, 1})
attrString = attribute.String("string", "o")
attrStringSlice = attribute.StringSlice("string slice", []string{"o", "n"})
attrInvalid = attribute.KeyValue{
Key: attribute.Key("invalid"),
attrEmpty = attribute.KeyValue{
Key: attribute.Key("empty"),
Value: attribute.Value{},
}
@@ -70,12 +70,7 @@ var (
kvFloat64Slice = &cpb.KeyValue{Key: "float64 slice", Value: valDblSlice}
kvString = &cpb.KeyValue{Key: "string", Value: valStrO}
kvStringSlice = &cpb.KeyValue{Key: "string slice", Value: valStrSlice}
kvInvalid = &cpb.KeyValue{
Key: "invalid",
Value: &cpb.AnyValue{
Value: &cpb.AnyValue_StringValue{StringValue: "INVALID"},
},
}
kvEmpty = &cpb.KeyValue{Key: "empty", Value: &cpb.AnyValue{}}
)
type attributeTest struct {
@@ -89,9 +84,9 @@ func TestAttributeTransforms(t *testing.T) {
{"nil", nil, nil},
{"empty", []attribute.KeyValue{}, nil},
{
"invalid",
[]attribute.KeyValue{attrInvalid},
[]*cpb.KeyValue{kvInvalid},
"empty",
[]attribute.KeyValue{attrEmpty},
[]*cpb.KeyValue{kvEmpty},
},
{
"bool",
@@ -156,7 +151,7 @@ func TestAttributeTransforms(t *testing.T) {
attrFloat64Slice,
attrString,
attrStringSlice,
attrInvalid,
attrEmpty,
},
[]*cpb.KeyValue{
kvBool,
@@ -169,7 +164,7 @@ func TestAttributeTransforms(t *testing.T) {
kvFloat64Slice,
kvString,
kvStringSlice,
kvInvalid,
kvEmpty,
},
},
} {
@@ -87,6 +87,7 @@ func Value(v attribute.Value) *cpb.AnyValue {
Values: stringSliceValues(v.AsStringSlice()),
},
}
case attribute.EMPTY:
default:
av.Value = &cpb.AnyValue_StringValue{
StringValue: "INVALID",
@@ -26,8 +26,8 @@ var (
attrFloat64Slice = attribute.Float64Slice("float64 slice", []float64{-1, 1})
attrString = attribute.String("string", "o")
attrStringSlice = attribute.StringSlice("string slice", []string{"o", "n"})
attrInvalid = attribute.KeyValue{
Key: attribute.Key("invalid"),
attrEmpty = attribute.KeyValue{
Key: attribute.Key("empty"),
Value: attribute.Value{},
}
@@ -70,12 +70,7 @@ var (
kvFloat64Slice = &cpb.KeyValue{Key: "float64 slice", Value: valDblSlice}
kvString = &cpb.KeyValue{Key: "string", Value: valStrO}
kvStringSlice = &cpb.KeyValue{Key: "string slice", Value: valStrSlice}
kvInvalid = &cpb.KeyValue{
Key: "invalid",
Value: &cpb.AnyValue{
Value: &cpb.AnyValue_StringValue{StringValue: "INVALID"},
},
}
kvEmpty = &cpb.KeyValue{Key: "empty", Value: &cpb.AnyValue{}}
)
type attributeTest struct {
@@ -89,9 +84,9 @@ func TestAttributeTransforms(t *testing.T) {
{"nil", nil, nil},
{"empty", []attribute.KeyValue{}, nil},
{
"invalid",
[]attribute.KeyValue{attrInvalid},
[]*cpb.KeyValue{kvInvalid},
"empty",
[]attribute.KeyValue{attrEmpty},
[]*cpb.KeyValue{kvEmpty},
},
{
"bool",
@@ -156,7 +151,7 @@ func TestAttributeTransforms(t *testing.T) {
attrFloat64Slice,
attrString,
attrStringSlice,
attrInvalid,
attrEmpty,
},
[]*cpb.KeyValue{
kvBool,
@@ -169,7 +164,7 @@ func TestAttributeTransforms(t *testing.T) {
kvFloat64Slice,
kvString,
kvStringSlice,
kvInvalid,
kvEmpty,
},
},
} {
@@ -93,6 +93,7 @@ func Value(v attribute.Value) *commonpb.AnyValue {
Values: stringSliceValues(v.AsStringSlice()),
},
}
case attribute.EMPTY:
default:
av.Value = &commonpb.AnyValue_StringValue{
StringValue: "INVALID",
@@ -27,6 +27,7 @@ func TestAttributes(t *testing.T) {
attribute.Float64("float64 to double", 1.61),
attribute.String("string to string", "string"),
attribute.Bool("bool to bool", true),
{Key: "empty to empty"},
},
[]*commonpb.KeyValue{
{
@@ -69,6 +70,10 @@ func TestAttributes(t *testing.T) {
},
},
},
{
Key: "empty to empty",
Value: &commonpb.AnyValue{},
},
},
},
} {
@@ -102,18 +107,14 @@ func TestArrayAttributes(t *testing.T) {
{
[]attribute.KeyValue{
{
Key: attribute.Key("invalid"),
Key: attribute.Key("empty"),
Value: attribute.Value{},
},
},
[]*commonpb.KeyValue{
{
Key: "invalid",
Value: &commonpb.AnyValue{
Value: &commonpb.AnyValue_StringValue{
StringValue: "INVALID",
},
},
Key: "empty",
Value: &commonpb.AnyValue{},
},
},
},
@@ -26,8 +26,8 @@ var (
attrFloat64Slice = attribute.Float64Slice("float64 slice", []float64{-1, 1})
attrString = attribute.String("string", "o")
attrStringSlice = attribute.StringSlice("string slice", []string{"o", "n"})
attrInvalid = attribute.KeyValue{
Key: attribute.Key("invalid"),
attrEmpty = attribute.KeyValue{
Key: attribute.Key("empty"),
Value: attribute.Value{},
}
@@ -70,12 +70,7 @@ var (
kvFloat64Slice = &cpb.KeyValue{Key: "float64 slice", Value: valDblSlice}
kvString = &cpb.KeyValue{Key: "string", Value: valStrO}
kvStringSlice = &cpb.KeyValue{Key: "string slice", Value: valStrSlice}
kvInvalid = &cpb.KeyValue{
Key: "invalid",
Value: &cpb.AnyValue{
Value: &cpb.AnyValue_StringValue{StringValue: "INVALID"},
},
}
kvEmpty = &cpb.KeyValue{Key: "empty", Value: &cpb.AnyValue{}}
)
func TestAttrTransforms(t *testing.T) {
@@ -89,9 +84,9 @@ func TestAttrTransforms(t *testing.T) {
{"nil", nil, nil},
{"empty", []attribute.KeyValue{}, nil},
{
"invalid",
[]attribute.KeyValue{attrInvalid},
[]*cpb.KeyValue{kvInvalid},
"empty value",
[]attribute.KeyValue{attrEmpty},
[]*cpb.KeyValue{kvEmpty},
},
{
"bool",
@@ -156,7 +151,7 @@ func TestAttrTransforms(t *testing.T) {
attrFloat64Slice,
attrString,
attrStringSlice,
attrInvalid,
attrEmpty,
},
[]*cpb.KeyValue{
kvBool,
@@ -169,7 +164,7 @@ func TestAttrTransforms(t *testing.T) {
kvFloat64Slice,
kvString,
kvStringSlice,
kvInvalid,
kvEmpty,
},
},
} {
@@ -201,6 +201,7 @@ func AttrValue(v attribute.Value) *cpb.AnyValue {
Values: stringSliceValues(v.AsStringSlice()),
},
}
case attribute.EMPTY:
default:
av.Value = &cpb.AnyValue_StringValue{
StringValue: "INVALID",
@@ -327,6 +328,7 @@ func LogAttrValue(v api.Value) *cpb.AnyValue {
Values: LogAttrs(v.AsMap()),
},
}
case api.KindEmpty:
default:
av.Value = &cpb.AnyValue_StringValue{
StringValue: "INVALID",
@@ -24,7 +24,7 @@ var (
logAttrBytes = log.Bytes("bytes", []byte("test"))
logAttrSlice = log.Slice("slice", log.BoolValue(true))
logAttrMap = log.Map("map", logAttrString)
logAttrEmpty = log.Empty("")
logAttrEmpty = log.Empty("empty")
kvBytes = &cpb.KeyValue{
Key: "bytes",
@@ -54,11 +54,6 @@ var (
},
},
}
kvEmpty = &cpb.KeyValue{
Value: &cpb.AnyValue{
Value: &cpb.AnyValue_StringValue{StringValue: "INVALID"},
},
}
)
func TestLogAttrs(t *testing.T) {
@@ -87,6 +87,7 @@ func Value(v attribute.Value) *cpb.AnyValue {
Values: stringSliceValues(v.AsStringSlice()),
},
}
case attribute.EMPTY:
default:
av.Value = &cpb.AnyValue_StringValue{
StringValue: "INVALID",
@@ -26,8 +26,8 @@ var (
attrFloat64Slice = attribute.Float64Slice("float64 slice", []float64{-1, 1})
attrString = attribute.String("string", "o")
attrStringSlice = attribute.StringSlice("string slice", []string{"o", "n"})
attrInvalid = attribute.KeyValue{
Key: attribute.Key("invalid"),
attrEmpty = attribute.KeyValue{
Key: attribute.Key("empty"),
Value: attribute.Value{},
}
@@ -70,12 +70,7 @@ var (
kvFloat64Slice = &cpb.KeyValue{Key: "float64 slice", Value: valDblSlice}
kvString = &cpb.KeyValue{Key: "string", Value: valStrO}
kvStringSlice = &cpb.KeyValue{Key: "string slice", Value: valStrSlice}
kvInvalid = &cpb.KeyValue{
Key: "invalid",
Value: &cpb.AnyValue{
Value: &cpb.AnyValue_StringValue{StringValue: "INVALID"},
},
}
kvEmpty = &cpb.KeyValue{Key: "empty", Value: &cpb.AnyValue{}}
)
type attributeTest struct {
@@ -89,9 +84,9 @@ func TestAttributeTransforms(t *testing.T) {
{"nil", nil, nil},
{"empty", []attribute.KeyValue{}, nil},
{
"invalid",
[]attribute.KeyValue{attrInvalid},
[]*cpb.KeyValue{kvInvalid},
"empty",
[]attribute.KeyValue{attrEmpty},
[]*cpb.KeyValue{kvEmpty},
},
{
"bool",
@@ -156,7 +151,7 @@ func TestAttributeTransforms(t *testing.T) {
attrFloat64Slice,
attrString,
attrStringSlice,
attrInvalid,
attrEmpty,
},
[]*cpb.KeyValue{
kvBool,
@@ -169,7 +164,7 @@ func TestAttributeTransforms(t *testing.T) {
kvFloat64Slice,
kvString,
kvStringSlice,
kvInvalid,
kvEmpty,
},
},
} {
+1 -1
View File
@@ -390,7 +390,7 @@ func (a KeyValue) String() string {
// ValueFromAttribute converts [attribute.Value] to [Value].
func ValueFromAttribute(value attribute.Value) Value {
switch value.Type() {
case attribute.INVALID:
case attribute.EMPTY:
return Value{}
case attribute.BOOL:
return BoolValue(value.AsBool())
@@ -558,6 +558,7 @@ func equalKeyValue(a, b attribute.KeyValue) bool {
if ok := slices.Equal(a.Value.AsStringSlice(), b.Value.AsStringSlice()); !ok {
return false
}
case attribute.EMPTY:
default:
// We control all types passed to this, panic to signal developers
// early they changed things in an incompatible way.