set.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436
  1. // Copyright The OpenTelemetry Authors
  2. // SPDX-License-Identifier: Apache-2.0
  3. package attribute // import "go.opentelemetry.io/otel/attribute"
  4. import (
  5. "cmp"
  6. "encoding/json"
  7. "reflect"
  8. "slices"
  9. "sort"
  10. "go.opentelemetry.io/otel/attribute/internal/xxhash"
  11. )
  12. type (
  13. // Set is the representation for a distinct attribute set. It manages an
  14. // immutable set of attributes, with an internal cache for storing
  15. // attribute encodings.
  16. //
  17. // This type will remain comparable for backwards compatibility. The
  18. // equivalence of Sets across versions is not guaranteed to be stable.
  19. // Prior versions may find two Sets to be equal or not when compared
  20. // directly (i.e. ==), but subsequent versions may not. Users should use
  21. // the Equals method to ensure stable equivalence checking.
  22. //
  23. // Users should also use the Distinct returned from Equivalent as a map key
  24. // instead of a Set directly. Set has relatively poor performance when used
  25. // as a map key compared to Distinct.
  26. Set struct {
  27. hash uint64
  28. data any
  29. }
  30. // Distinct is an identifier of a Set which is very likely to be unique.
  31. //
  32. // Distinct should be used as a map key instead of a Set for to provide better
  33. // performance for map operations.
  34. Distinct struct {
  35. hash uint64
  36. }
  37. // Sortable implements sort.Interface, used for sorting KeyValue.
  38. //
  39. // Deprecated: This type is no longer used. It was added as a performance
  40. // optimization for Go < 1.21 that is no longer needed (Go < 1.21 is no
  41. // longer supported by the module).
  42. Sortable []KeyValue
  43. )
  44. // Compile time check these types remain comparable.
  45. var (
  46. _ = isComparable(Set{})
  47. _ = isComparable(Distinct{})
  48. )
  49. func isComparable[T comparable](t T) T { return t }
  50. var (
  51. // keyValueType is used in computeDistinctReflect.
  52. keyValueType = reflect.TypeFor[KeyValue]()
  53. // emptyHash is the hash of an empty set.
  54. emptyHash = xxhash.New().Sum64()
  55. // userDefinedEmptySet is an empty set. It was mistakenly exposed to users
  56. // as something they can assign to, so it must remain addressable and
  57. // mutable.
  58. //
  59. // This is kept for backwards compatibility, but should not be used in new code.
  60. userDefinedEmptySet = &Set{
  61. hash: emptyHash,
  62. data: [0]KeyValue{},
  63. }
  64. emptySet = Set{
  65. hash: emptyHash,
  66. data: [0]KeyValue{},
  67. }
  68. )
  69. // EmptySet returns a reference to a Set with no elements.
  70. //
  71. // This is a convenience provided for optimized calling utility.
  72. func EmptySet() *Set {
  73. // Continue to return the pointer to the user-defined empty set for
  74. // backwards-compatibility.
  75. //
  76. // New code should not use this, instead use emptySet.
  77. return userDefinedEmptySet
  78. }
  79. // Valid reports whether this value refers to a valid Set.
  80. func (d Distinct) Valid() bool { return d.hash != 0 }
  81. // reflectValue abbreviates reflect.ValueOf(d).
  82. func (l Set) reflectValue() reflect.Value {
  83. return reflect.ValueOf(l.data)
  84. }
  85. // Len returns the number of attributes in this set.
  86. func (l *Set) Len() int {
  87. if l == nil || l.hash == 0 {
  88. return 0
  89. }
  90. return l.reflectValue().Len()
  91. }
  92. // Get returns the KeyValue at ordered position idx in this set.
  93. func (l *Set) Get(idx int) (KeyValue, bool) {
  94. if l == nil || l.hash == 0 {
  95. return KeyValue{}, false
  96. }
  97. value := l.reflectValue()
  98. if idx >= 0 && idx < value.Len() {
  99. // Note: The Go compiler successfully avoids an allocation for
  100. // the interface{} conversion here:
  101. return value.Index(idx).Interface().(KeyValue), true
  102. }
  103. return KeyValue{}, false
  104. }
  105. // Value returns the value of a specified key in this set.
  106. func (l *Set) Value(k Key) (Value, bool) {
  107. if l == nil || l.hash == 0 {
  108. return Value{}, false
  109. }
  110. rValue := l.reflectValue()
  111. vlen := rValue.Len()
  112. idx := sort.Search(vlen, func(idx int) bool {
  113. return rValue.Index(idx).Interface().(KeyValue).Key >= k
  114. })
  115. if idx >= vlen {
  116. return Value{}, false
  117. }
  118. keyValue := rValue.Index(idx).Interface().(KeyValue)
  119. if k == keyValue.Key {
  120. return keyValue.Value, true
  121. }
  122. return Value{}, false
  123. }
  124. // HasValue reports whether a key is defined in this set.
  125. func (l *Set) HasValue(k Key) bool {
  126. if l == nil {
  127. return false
  128. }
  129. _, ok := l.Value(k)
  130. return ok
  131. }
  132. // Iter returns an iterator for visiting the attributes in this set.
  133. func (l *Set) Iter() Iterator {
  134. return Iterator{
  135. storage: l,
  136. idx: -1,
  137. }
  138. }
  139. // ToSlice returns the set of attributes belonging to this set, sorted, where
  140. // keys appear no more than once.
  141. func (l *Set) ToSlice() []KeyValue {
  142. iter := l.Iter()
  143. return iter.ToSlice()
  144. }
  145. // Equivalent returns a value that may be used as a map key. Equal Distinct
  146. // values are very likely to be equivalent attribute Sets. Distinct value of any
  147. // attribute set with the same elements as this, where sets are made unique by
  148. // choosing the last value in the input for any given key.
  149. func (l *Set) Equivalent() Distinct {
  150. if l == nil || l.hash == 0 {
  151. return Distinct{hash: emptySet.hash}
  152. }
  153. return Distinct{hash: l.hash}
  154. }
  155. // Equals reports whether the argument set is equivalent to this set.
  156. func (l *Set) Equals(o *Set) bool {
  157. if l.Equivalent() != o.Equivalent() {
  158. return false
  159. }
  160. if l == nil || l.hash == 0 {
  161. l = &emptySet
  162. }
  163. if o == nil || o.hash == 0 {
  164. o = &emptySet
  165. }
  166. return l.data == o.data
  167. }
  168. // Encoded returns the encoded form of this set, according to encoder.
  169. func (l *Set) Encoded(encoder Encoder) string {
  170. if l == nil || encoder == nil {
  171. return ""
  172. }
  173. return encoder.Encode(l.Iter())
  174. }
  175. // NewSet returns a new Set. See the documentation for
  176. // NewSetWithSortableFiltered for more details.
  177. //
  178. // Except for empty sets, this method adds an additional allocation compared
  179. // with calls that include a Sortable.
  180. func NewSet(kvs ...KeyValue) Set {
  181. s, _ := NewSetWithFiltered(kvs, nil)
  182. return s
  183. }
  184. // NewSetWithSortable returns a new Set. See the documentation for
  185. // NewSetWithSortableFiltered for more details.
  186. //
  187. // This call includes a Sortable option as a memory optimization.
  188. //
  189. // Deprecated: Use [NewSet] instead.
  190. func NewSetWithSortable(kvs []KeyValue, _ *Sortable) Set {
  191. s, _ := NewSetWithFiltered(kvs, nil)
  192. return s
  193. }
  194. // NewSetWithFiltered returns a new Set. See the documentation for
  195. // NewSetWithSortableFiltered for more details.
  196. //
  197. // This call includes a Filter to include/exclude attribute keys from the
  198. // return value. Excluded keys are returned as a slice of attribute values.
  199. func NewSetWithFiltered(kvs []KeyValue, filter Filter) (Set, []KeyValue) {
  200. // Check for empty set.
  201. if len(kvs) == 0 {
  202. return emptySet, nil
  203. }
  204. // Stable sort so the following de-duplication can implement
  205. // last-value-wins semantics.
  206. slices.SortStableFunc(kvs, func(a, b KeyValue) int {
  207. return cmp.Compare(a.Key, b.Key)
  208. })
  209. position := len(kvs) - 1
  210. offset := position - 1
  211. // The requirements stated above require that the stable
  212. // result be placed in the end of the input slice, while
  213. // overwritten values are swapped to the beginning.
  214. //
  215. // De-duplicate with last-value-wins semantics. Preserve
  216. // duplicate values at the beginning of the input slice.
  217. for ; offset >= 0; offset-- {
  218. if kvs[offset].Key == kvs[position].Key {
  219. continue
  220. }
  221. position--
  222. kvs[offset], kvs[position] = kvs[position], kvs[offset]
  223. }
  224. kvs = kvs[position:]
  225. if filter != nil {
  226. if div := filteredToFront(kvs, filter); div != 0 {
  227. return newSet(kvs[div:]), kvs[:div]
  228. }
  229. }
  230. return newSet(kvs), nil
  231. }
  232. // NewSetWithSortableFiltered returns a new Set.
  233. //
  234. // Duplicate keys are eliminated by taking the last value. This
  235. // re-orders the input slice so that unique last-values are contiguous
  236. // at the end of the slice.
  237. //
  238. // This ensures the following:
  239. //
  240. // - Last-value-wins semantics
  241. // - Caller sees the reordering, but doesn't lose values
  242. // - Repeated call preserve last-value wins.
  243. //
  244. // Note that methods are defined on Set, although this returns Set. Callers
  245. // can avoid memory allocations by:
  246. //
  247. // - allocating a Sortable for use as a temporary in this method
  248. // - allocating a Set for storing the return value of this constructor.
  249. //
  250. // The result maintains a cache of encoded attributes, by attribute.EncoderID.
  251. // This value should not be copied after its first use.
  252. //
  253. // The second []KeyValue return value is a list of attributes that were
  254. // excluded by the Filter (if non-nil).
  255. //
  256. // Deprecated: Use [NewSetWithFiltered] instead.
  257. func NewSetWithSortableFiltered(kvs []KeyValue, _ *Sortable, filter Filter) (Set, []KeyValue) {
  258. return NewSetWithFiltered(kvs, filter)
  259. }
  260. // filteredToFront filters slice in-place using keep function. All KeyValues that need to
  261. // be removed are moved to the front. All KeyValues that need to be kept are
  262. // moved (in-order) to the back. The index for the first KeyValue to be kept is
  263. // returned.
  264. func filteredToFront(slice []KeyValue, keep Filter) int {
  265. n := len(slice)
  266. j := n
  267. for i := n - 1; i >= 0; i-- {
  268. if keep(slice[i]) {
  269. j--
  270. slice[i], slice[j] = slice[j], slice[i]
  271. }
  272. }
  273. return j
  274. }
  275. // Filter returns a filtered copy of this Set. See the documentation for
  276. // NewSetWithSortableFiltered for more details.
  277. func (l *Set) Filter(re Filter) (Set, []KeyValue) {
  278. if re == nil {
  279. return *l, nil
  280. }
  281. // Iterate in reverse to the first attribute that will be filtered out.
  282. n := l.Len()
  283. first := n - 1
  284. for ; first >= 0; first-- {
  285. kv, _ := l.Get(first)
  286. if !re(kv) {
  287. break
  288. }
  289. }
  290. // No attributes will be dropped, return the immutable Set l and nil.
  291. if first < 0 {
  292. return *l, nil
  293. }
  294. // Copy now that we know we need to return a modified set.
  295. //
  296. // Do not do this in-place on the underlying storage of *Set l. Sets are
  297. // immutable and filtering should not change this.
  298. slice := l.ToSlice()
  299. // Don't re-iterate the slice if only slice[0] is filtered.
  300. if first == 0 {
  301. // It is safe to assume len(slice) >= 1 given we found at least one
  302. // attribute above that needs to be filtered out.
  303. return newSet(slice[1:]), slice[:1]
  304. }
  305. // Move the filtered slice[first] to the front (preserving order).
  306. kv := slice[first]
  307. copy(slice[1:first+1], slice[:first])
  308. slice[0] = kv
  309. // Do not re-evaluate re(slice[first+1:]).
  310. div := filteredToFront(slice[1:first+1], re) + 1
  311. return newSet(slice[div:]), slice[:div]
  312. }
  313. // newSet returns a new set based on the sorted and uniqued kvs.
  314. func newSet(kvs []KeyValue) Set {
  315. s := Set{
  316. hash: hashKVs(kvs),
  317. data: computeDataFixed(kvs),
  318. }
  319. if s.data == nil {
  320. s.data = computeDataReflect(kvs)
  321. }
  322. return s
  323. }
  324. // computeDataFixed computes a Set data for small slices. It returns nil if the
  325. // input is too large for this code path.
  326. func computeDataFixed(kvs []KeyValue) any {
  327. switch len(kvs) {
  328. case 1:
  329. return [1]KeyValue(kvs)
  330. case 2:
  331. return [2]KeyValue(kvs)
  332. case 3:
  333. return [3]KeyValue(kvs)
  334. case 4:
  335. return [4]KeyValue(kvs)
  336. case 5:
  337. return [5]KeyValue(kvs)
  338. case 6:
  339. return [6]KeyValue(kvs)
  340. case 7:
  341. return [7]KeyValue(kvs)
  342. case 8:
  343. return [8]KeyValue(kvs)
  344. case 9:
  345. return [9]KeyValue(kvs)
  346. case 10:
  347. return [10]KeyValue(kvs)
  348. default:
  349. return nil
  350. }
  351. }
  352. // computeDataReflect computes a Set data using reflection, works for any size
  353. // input.
  354. func computeDataReflect(kvs []KeyValue) any {
  355. at := reflect.New(reflect.ArrayOf(len(kvs), keyValueType)).Elem()
  356. for i, keyValue := range kvs {
  357. *(at.Index(i).Addr().Interface().(*KeyValue)) = keyValue
  358. }
  359. return at.Interface()
  360. }
  361. // MarshalJSON returns the JSON encoding of the Set.
  362. func (l *Set) MarshalJSON() ([]byte, error) {
  363. return json.Marshal(l.data)
  364. }
  365. // MarshalLog is the marshaling function used by the logging system to represent this Set.
  366. func (l Set) MarshalLog() any {
  367. kvs := make(map[string]string)
  368. for _, kv := range l.ToSlice() {
  369. kvs[string(kv.Key)] = kv.Value.Emit()
  370. }
  371. return kvs
  372. }
  373. // Len implements sort.Interface.
  374. func (l *Sortable) Len() int {
  375. return len(*l)
  376. }
  377. // Swap implements sort.Interface.
  378. func (l *Sortable) Swap(i, j int) {
  379. (*l)[i], (*l)[j] = (*l)[j], (*l)[i]
  380. }
  381. // Less implements sort.Interface.
  382. func (l *Sortable) Less(i, j int) bool {
  383. return (*l)[i].Key < (*l)[j].Key
  384. }