github.com/mdaxf/iac@v0.0.0-20240519030858-58a061660378/vendor_skip/go.opentelemetry.io/otel/attribute/set.go (about)

     1  // Copyright The OpenTelemetry Authors
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package attribute // import "go.opentelemetry.io/otel/attribute"
    16  
    17  import (
    18  	"encoding/json"
    19  	"reflect"
    20  	"sort"
    21  	"sync"
    22  )
    23  
    24  type (
    25  	// Set is the representation for a distinct attribute set. It manages an
    26  	// immutable set of attributes, with an internal cache for storing
    27  	// attribute encodings.
    28  	//
    29  	// This type supports the Equivalent method of comparison using values of
    30  	// type Distinct.
    31  	Set struct {
    32  		equivalent Distinct
    33  	}
    34  
    35  	// Distinct wraps a variable-size array of KeyValue, constructed with keys
    36  	// in sorted order. This can be used as a map key or for equality checking
    37  	// between Sets.
    38  	Distinct struct {
    39  		iface interface{}
    40  	}
    41  
    42  	// Sortable implements sort.Interface, used for sorting KeyValue. This is
    43  	// an exported type to support a memory optimization. A pointer to one of
    44  	// these is needed for the call to sort.Stable(), which the caller may
    45  	// provide in order to avoid an allocation. See NewSetWithSortable().
    46  	Sortable []KeyValue
    47  )
    48  
    49  var (
    50  	// keyValueType is used in computeDistinctReflect.
    51  	keyValueType = reflect.TypeOf(KeyValue{})
    52  
    53  	// emptySet is returned for empty attribute sets.
    54  	emptySet = &Set{
    55  		equivalent: Distinct{
    56  			iface: [0]KeyValue{},
    57  		},
    58  	}
    59  
    60  	// sortables is a pool of Sortables used to create Sets with a user does
    61  	// not provide one.
    62  	sortables = sync.Pool{
    63  		New: func() interface{} { return new(Sortable) },
    64  	}
    65  )
    66  
    67  // EmptySet returns a reference to a Set with no elements.
    68  //
    69  // This is a convenience provided for optimized calling utility.
    70  func EmptySet() *Set {
    71  	return emptySet
    72  }
    73  
    74  // reflectValue abbreviates reflect.ValueOf(d).
    75  func (d Distinct) reflectValue() reflect.Value {
    76  	return reflect.ValueOf(d.iface)
    77  }
    78  
    79  // Valid returns true if this value refers to a valid Set.
    80  func (d Distinct) Valid() bool {
    81  	return d.iface != nil
    82  }
    83  
    84  // Len returns the number of attributes in this set.
    85  func (l *Set) Len() int {
    86  	if l == nil || !l.equivalent.Valid() {
    87  		return 0
    88  	}
    89  	return l.equivalent.reflectValue().Len()
    90  }
    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.equivalent.Valid() {
    95  		return KeyValue{}, false
    96  	}
    97  	value := l.equivalent.reflectValue()
    98  
    99  	if idx >= 0 && idx < value.Len() {
   100  		// Note: The Go compiler successfully avoids an allocation for
   101  		// the interface{} conversion here:
   102  		return value.Index(idx).Interface().(KeyValue), true
   103  	}
   104  
   105  	return KeyValue{}, false
   106  }
   107  
   108  // Value returns the value of a specified key in this set.
   109  func (l *Set) Value(k Key) (Value, bool) {
   110  	if l == nil || !l.equivalent.Valid() {
   111  		return Value{}, false
   112  	}
   113  	rValue := l.equivalent.reflectValue()
   114  	vlen := rValue.Len()
   115  
   116  	idx := sort.Search(vlen, func(idx int) bool {
   117  		return rValue.Index(idx).Interface().(KeyValue).Key >= k
   118  	})
   119  	if idx >= vlen {
   120  		return Value{}, false
   121  	}
   122  	keyValue := rValue.Index(idx).Interface().(KeyValue)
   123  	if k == keyValue.Key {
   124  		return keyValue.Value, true
   125  	}
   126  	return Value{}, false
   127  }
   128  
   129  // HasValue tests whether a key is defined in this set.
   130  func (l *Set) HasValue(k Key) bool {
   131  	if l == nil {
   132  		return false
   133  	}
   134  	_, ok := l.Value(k)
   135  	return ok
   136  }
   137  
   138  // Iter returns an iterator for visiting the attributes in this set.
   139  func (l *Set) Iter() Iterator {
   140  	return Iterator{
   141  		storage: l,
   142  		idx:     -1,
   143  	}
   144  }
   145  
   146  // ToSlice returns the set of attributes belonging to this set, sorted, where
   147  // keys appear no more than once.
   148  func (l *Set) ToSlice() []KeyValue {
   149  	iter := l.Iter()
   150  	return iter.ToSlice()
   151  }
   152  
   153  // Equivalent returns a value that may be used as a map key. The Distinct type
   154  // guarantees that the result will equal the equivalent. Distinct value of any
   155  // attribute set with the same elements as this, where sets are made unique by
   156  // choosing the last value in the input for any given key.
   157  func (l *Set) Equivalent() Distinct {
   158  	if l == nil || !l.equivalent.Valid() {
   159  		return emptySet.equivalent
   160  	}
   161  	return l.equivalent
   162  }
   163  
   164  // Equals returns true if the argument set is equivalent to this set.
   165  func (l *Set) Equals(o *Set) bool {
   166  	return l.Equivalent() == o.Equivalent()
   167  }
   168  
   169  // Encoded returns the encoded form of this set, according to encoder.
   170  func (l *Set) Encoded(encoder Encoder) string {
   171  	if l == nil || encoder == nil {
   172  		return ""
   173  	}
   174  
   175  	return encoder.Encode(l.Iter())
   176  }
   177  
   178  func empty() Set {
   179  	return Set{
   180  		equivalent: emptySet.equivalent,
   181  	}
   182  }
   183  
   184  // NewSet returns a new Set. See the documentation for
   185  // NewSetWithSortableFiltered for more details.
   186  //
   187  // Except for empty sets, this method adds an additional allocation compared
   188  // with calls that include a Sortable.
   189  func NewSet(kvs ...KeyValue) Set {
   190  	// Check for empty set.
   191  	if len(kvs) == 0 {
   192  		return empty()
   193  	}
   194  	srt := sortables.Get().(*Sortable)
   195  	s, _ := NewSetWithSortableFiltered(kvs, srt, nil)
   196  	sortables.Put(srt)
   197  	return s
   198  }
   199  
   200  // NewSetWithSortable returns a new Set. See the documentation for
   201  // NewSetWithSortableFiltered for more details.
   202  //
   203  // This call includes a Sortable option as a memory optimization.
   204  func NewSetWithSortable(kvs []KeyValue, tmp *Sortable) Set {
   205  	// Check for empty set.
   206  	if len(kvs) == 0 {
   207  		return empty()
   208  	}
   209  	s, _ := NewSetWithSortableFiltered(kvs, tmp, nil)
   210  	return s
   211  }
   212  
   213  // NewSetWithFiltered returns a new Set. See the documentation for
   214  // NewSetWithSortableFiltered for more details.
   215  //
   216  // This call includes a Filter to include/exclude attribute keys from the
   217  // return value. Excluded keys are returned as a slice of attribute values.
   218  func NewSetWithFiltered(kvs []KeyValue, filter Filter) (Set, []KeyValue) {
   219  	// Check for empty set.
   220  	if len(kvs) == 0 {
   221  		return empty(), nil
   222  	}
   223  	srt := sortables.Get().(*Sortable)
   224  	s, filtered := NewSetWithSortableFiltered(kvs, srt, filter)
   225  	sortables.Put(srt)
   226  	return s, filtered
   227  }
   228  
   229  // NewSetWithSortableFiltered returns a new Set.
   230  //
   231  // Duplicate keys are eliminated by taking the last value.  This
   232  // re-orders the input slice so that unique last-values are contiguous
   233  // at the end of the slice.
   234  //
   235  // This ensures the following:
   236  //
   237  // - Last-value-wins semantics
   238  // - Caller sees the reordering, but doesn't lose values
   239  // - Repeated call preserve last-value wins.
   240  //
   241  // Note that methods are defined on Set, although this returns Set. Callers
   242  // can avoid memory allocations by:
   243  //
   244  // - allocating a Sortable for use as a temporary in this method
   245  // - allocating a Set for storing the return value of this constructor.
   246  //
   247  // The result maintains a cache of encoded attributes, by attribute.EncoderID.
   248  // This value should not be copied after its first use.
   249  //
   250  // The second []KeyValue return value is a list of attributes that were
   251  // excluded by the Filter (if non-nil).
   252  func NewSetWithSortableFiltered(kvs []KeyValue, tmp *Sortable, filter Filter) (Set, []KeyValue) {
   253  	// Check for empty set.
   254  	if len(kvs) == 0 {
   255  		return empty(), nil
   256  	}
   257  
   258  	*tmp = kvs
   259  
   260  	// Stable sort so the following de-duplication can implement
   261  	// last-value-wins semantics.
   262  	sort.Stable(tmp)
   263  
   264  	*tmp = nil
   265  
   266  	position := len(kvs) - 1
   267  	offset := position - 1
   268  
   269  	// The requirements stated above require that the stable
   270  	// result be placed in the end of the input slice, while
   271  	// overwritten values are swapped to the beginning.
   272  	//
   273  	// De-duplicate with last-value-wins semantics.  Preserve
   274  	// duplicate values at the beginning of the input slice.
   275  	for ; offset >= 0; offset-- {
   276  		if kvs[offset].Key == kvs[position].Key {
   277  			continue
   278  		}
   279  		position--
   280  		kvs[offset], kvs[position] = kvs[position], kvs[offset]
   281  	}
   282  	if filter != nil {
   283  		return filterSet(kvs[position:], filter)
   284  	}
   285  	return Set{
   286  		equivalent: computeDistinct(kvs[position:]),
   287  	}, nil
   288  }
   289  
   290  // filterSet reorders kvs so that included keys are contiguous at the end of
   291  // the slice, while excluded keys precede the included keys.
   292  func filterSet(kvs []KeyValue, filter Filter) (Set, []KeyValue) {
   293  	var excluded []KeyValue
   294  
   295  	// Move attributes that do not match the filter so they're adjacent before
   296  	// calling computeDistinct().
   297  	distinctPosition := len(kvs)
   298  
   299  	// Swap indistinct keys forward and distinct keys toward the
   300  	// end of the slice.
   301  	offset := len(kvs) - 1
   302  	for ; offset >= 0; offset-- {
   303  		if filter(kvs[offset]) {
   304  			distinctPosition--
   305  			kvs[offset], kvs[distinctPosition] = kvs[distinctPosition], kvs[offset]
   306  			continue
   307  		}
   308  	}
   309  	excluded = kvs[:distinctPosition]
   310  
   311  	return Set{
   312  		equivalent: computeDistinct(kvs[distinctPosition:]),
   313  	}, excluded
   314  }
   315  
   316  // Filter returns a filtered copy of this Set. See the documentation for
   317  // NewSetWithSortableFiltered for more details.
   318  func (l *Set) Filter(re Filter) (Set, []KeyValue) {
   319  	if re == nil {
   320  		return Set{
   321  			equivalent: l.equivalent,
   322  		}, nil
   323  	}
   324  
   325  	// Note: This could be refactored to avoid the temporary slice
   326  	// allocation, if it proves to be expensive.
   327  	return filterSet(l.ToSlice(), re)
   328  }
   329  
   330  // computeDistinct returns a Distinct using either the fixed- or
   331  // reflect-oriented code path, depending on the size of the input. The input
   332  // slice is assumed to already be sorted and de-duplicated.
   333  func computeDistinct(kvs []KeyValue) Distinct {
   334  	iface := computeDistinctFixed(kvs)
   335  	if iface == nil {
   336  		iface = computeDistinctReflect(kvs)
   337  	}
   338  	return Distinct{
   339  		iface: iface,
   340  	}
   341  }
   342  
   343  // computeDistinctFixed computes a Distinct for small slices. It returns nil
   344  // if the input is too large for this code path.
   345  func computeDistinctFixed(kvs []KeyValue) interface{} {
   346  	switch len(kvs) {
   347  	case 1:
   348  		ptr := new([1]KeyValue)
   349  		copy((*ptr)[:], kvs)
   350  		return *ptr
   351  	case 2:
   352  		ptr := new([2]KeyValue)
   353  		copy((*ptr)[:], kvs)
   354  		return *ptr
   355  	case 3:
   356  		ptr := new([3]KeyValue)
   357  		copy((*ptr)[:], kvs)
   358  		return *ptr
   359  	case 4:
   360  		ptr := new([4]KeyValue)
   361  		copy((*ptr)[:], kvs)
   362  		return *ptr
   363  	case 5:
   364  		ptr := new([5]KeyValue)
   365  		copy((*ptr)[:], kvs)
   366  		return *ptr
   367  	case 6:
   368  		ptr := new([6]KeyValue)
   369  		copy((*ptr)[:], kvs)
   370  		return *ptr
   371  	case 7:
   372  		ptr := new([7]KeyValue)
   373  		copy((*ptr)[:], kvs)
   374  		return *ptr
   375  	case 8:
   376  		ptr := new([8]KeyValue)
   377  		copy((*ptr)[:], kvs)
   378  		return *ptr
   379  	case 9:
   380  		ptr := new([9]KeyValue)
   381  		copy((*ptr)[:], kvs)
   382  		return *ptr
   383  	case 10:
   384  		ptr := new([10]KeyValue)
   385  		copy((*ptr)[:], kvs)
   386  		return *ptr
   387  	default:
   388  		return nil
   389  	}
   390  }
   391  
   392  // computeDistinctReflect computes a Distinct using reflection, works for any
   393  // size input.
   394  func computeDistinctReflect(kvs []KeyValue) interface{} {
   395  	at := reflect.New(reflect.ArrayOf(len(kvs), keyValueType)).Elem()
   396  	for i, keyValue := range kvs {
   397  		*(at.Index(i).Addr().Interface().(*KeyValue)) = keyValue
   398  	}
   399  	return at.Interface()
   400  }
   401  
   402  // MarshalJSON returns the JSON encoding of the Set.
   403  func (l *Set) MarshalJSON() ([]byte, error) {
   404  	return json.Marshal(l.equivalent.iface)
   405  }
   406  
   407  // MarshalLog is the marshaling function used by the logging system to represent this exporter.
   408  func (l Set) MarshalLog() interface{} {
   409  	kvs := make(map[string]string)
   410  	for _, kv := range l.ToSlice() {
   411  		kvs[string(kv.Key)] = kv.Value.Emit()
   412  	}
   413  	return kvs
   414  }
   415  
   416  // Len implements sort.Interface.
   417  func (l *Sortable) Len() int {
   418  	return len(*l)
   419  }
   420  
   421  // Swap implements sort.Interface.
   422  func (l *Sortable) Swap(i, j int) {
   423  	(*l)[i], (*l)[j] = (*l)[j], (*l)[i]
   424  }
   425  
   426  // Less implements sort.Interface.
   427  func (l *Sortable) Less(i, j int) bool {
   428  	return (*l)[i].Key < (*l)[j].Key
   429  }