You've already forked opentelemetry-go
mirror of
https://github.com/open-telemetry/opentelemetry-go.git
synced 2025-08-10 22:31:50 +02:00
Use Distinct instead of Set for map keys (#5027)
This commit is contained in:
@@ -15,15 +15,24 @@ type (
|
||||
// immutable set of attributes, with an internal cache for storing
|
||||
// attribute encodings.
|
||||
//
|
||||
// This type supports the Equivalent method of comparison using values of
|
||||
// type Distinct.
|
||||
// This type will remain comparable for backwards compatibility. The
|
||||
// equivalence of Sets across versions is not guaranteed to be stable.
|
||||
// Prior versions may find two Sets to be equal or not when compared
|
||||
// directly (i.e. ==), but subsequent versions may not. Users should use
|
||||
// the Equals method to ensure stable equivalence checking.
|
||||
//
|
||||
// Users should also use the Distinct returned from Equivalent as a map key
|
||||
// instead of a Set directly. In addition to that type providing guarantees
|
||||
// on stable equivalence, it may also provide performance improvements.
|
||||
Set struct {
|
||||
equivalent Distinct
|
||||
}
|
||||
|
||||
// Distinct wraps a variable-size array of KeyValue, constructed with keys
|
||||
// in sorted order. This can be used as a map key or for equality checking
|
||||
// between Sets.
|
||||
// Distinct is a unique identifier of a Set.
|
||||
//
|
||||
// Distinct is designed to be ensures equivalence stability: comparisons
|
||||
// will return the save value across versions. For this reason, Distinct
|
||||
// should always be used as a map key instead of a Set.
|
||||
Distinct struct {
|
||||
iface interface{}
|
||||
}
|
||||
|
@@ -95,7 +95,7 @@ func TestValue(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetComparability(t *testing.T) {
|
||||
func TestEquivalence(t *testing.T) {
|
||||
pairs := [][2]attribute.KeyValue{
|
||||
{
|
||||
attribute.Bool("Bool", true),
|
||||
@@ -139,12 +139,39 @@ func TestSetComparability(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
for _, p := range pairs {
|
||||
s0, s1 := attribute.NewSet(p[0]), attribute.NewSet(p[1])
|
||||
m := map[attribute.Set]struct{}{s0: {}}
|
||||
_, ok := m[s1]
|
||||
assert.Truef(t, ok, "%s not comparable", p[0].Value.Type())
|
||||
}
|
||||
t.Run("Distinct", func(t *testing.T) {
|
||||
for _, p := range pairs {
|
||||
s0, s1 := attribute.NewSet(p[0]), attribute.NewSet(p[1])
|
||||
m := map[attribute.Distinct]struct{}{s0.Equivalent(): {}}
|
||||
_, ok := m[s1.Equivalent()]
|
||||
assert.Truef(t, ok, "Distinct comparison of %s type: not equivalent", p[0].Value.Type())
|
||||
assert.Truef(
|
||||
t,
|
||||
ok,
|
||||
"Distinct comparison of %s type: not equivalent: %s != %s",
|
||||
p[0].Value.Type(),
|
||||
s0.Encoded(attribute.DefaultEncoder()),
|
||||
s1.Encoded(attribute.DefaultEncoder()),
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Set", func(t *testing.T) {
|
||||
// Maintain backwards compatibility.
|
||||
for _, p := range pairs {
|
||||
s0, s1 := attribute.NewSet(p[0]), attribute.NewSet(p[1])
|
||||
m := map[attribute.Set]struct{}{s0: {}}
|
||||
_, ok := m[s1]
|
||||
assert.Truef(
|
||||
t,
|
||||
ok,
|
||||
"Set comparison of %s type: not equivalent: %s != %s",
|
||||
p[0].Value.Type(),
|
||||
s0.Encoded(attribute.DefaultEncoder()),
|
||||
s1.Encoded(attribute.DefaultEncoder()),
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestAsSlice(t *testing.T) {
|
||||
|
Reference in New Issue
Block a user