You've already forked opentelemetry-go
							
							
				mirror of
				https://github.com/open-telemetry/opentelemetry-go.git
				synced 2025-10-31 00:07:40 +02:00 
			
		
		
		
	* Rename otel/label -> otel/attr Leave the imported name alone, to avoid a large diff and conflicts * Better import comment * Update CHANGELOG.md Co-authored-by: Tyler Yahn <MrAlias@users.noreply.github.com> * otel/attr -> otel/attribute * Missed the changelog entry * Get rid of import renaming * Merge remaining conflicts Co-authored-by: Tyler Yahn <MrAlias@users.noreply.github.com> Co-authored-by: Anthony Mirabella <a9@aneurysm9.com>
		
			
				
	
	
		
			92 lines
		
	
	
		
			2.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			92 lines
		
	
	
		
			2.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| // Copyright The OpenTelemetry Authors
 | |
| //
 | |
| // Licensed under the Apache License, Version 2.0 (the "License");
 | |
| // you may not use this file except in compliance with the License.
 | |
| // You may obtain a copy of the License at
 | |
| //
 | |
| //     http://www.apache.org/licenses/LICENSE-2.0
 | |
| //
 | |
| // Unless required by applicable law or agreed to in writing, software
 | |
| // distributed under the License is distributed on an "AS IS" BASIS,
 | |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | |
| // See the License for the specific language governing permissions and
 | |
| // limitations under the License.
 | |
| 
 | |
| package trace // import "go.opentelemetry.io/otel/sdk/trace"
 | |
| 
 | |
| import (
 | |
| 	"container/list"
 | |
| 
 | |
| 	"go.opentelemetry.io/otel/attribute"
 | |
| )
 | |
| 
 | |
| // attributesMap is a capped map of attributes, holding the most recent attributes.
 | |
| // Eviction is done via a LRU method, the oldest entry is removed to create room for a new entry.
 | |
| // Updates are allowed and they refresh the usage of the key.
 | |
| //
 | |
| // This is based from https://github.com/hashicorp/golang-lru/blob/master/simplelru/lru.go
 | |
| // With a subset of the its operations and specific for holding attribute.KeyValue
 | |
| type attributesMap struct {
 | |
| 	attributes   map[attribute.Key]*list.Element
 | |
| 	evictList    *list.List
 | |
| 	droppedCount int
 | |
| 	capacity     int
 | |
| }
 | |
| 
 | |
| func newAttributesMap(capacity int) *attributesMap {
 | |
| 	lm := &attributesMap{
 | |
| 		attributes: make(map[attribute.Key]*list.Element),
 | |
| 		evictList:  list.New(),
 | |
| 		capacity:   capacity,
 | |
| 	}
 | |
| 	return lm
 | |
| }
 | |
| 
 | |
| func (am *attributesMap) add(kv attribute.KeyValue) {
 | |
| 	// Check for existing item
 | |
| 	if ent, ok := am.attributes[kv.Key]; ok {
 | |
| 		am.evictList.MoveToFront(ent)
 | |
| 		ent.Value = &kv
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	// Add new item
 | |
| 	entry := am.evictList.PushFront(&kv)
 | |
| 	am.attributes[kv.Key] = entry
 | |
| 
 | |
| 	// Verify size not exceeded
 | |
| 	if am.evictList.Len() > am.capacity {
 | |
| 		am.removeOldest()
 | |
| 		am.droppedCount++
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // toKeyValue copies the attributesMap into a slice of attribute.KeyValue and
 | |
| // returns it. If the map is empty, a nil is returned.
 | |
| // TODO: Is it more efficient to return a pointer to the slice?
 | |
| func (am *attributesMap) toKeyValue() []attribute.KeyValue {
 | |
| 	len := am.evictList.Len()
 | |
| 	if len == 0 {
 | |
| 		return nil
 | |
| 	}
 | |
| 
 | |
| 	attributes := make([]attribute.KeyValue, 0, len)
 | |
| 	for ent := am.evictList.Back(); ent != nil; ent = ent.Prev() {
 | |
| 		if value, ok := ent.Value.(*attribute.KeyValue); ok {
 | |
| 			attributes = append(attributes, *value)
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	return attributes
 | |
| }
 | |
| 
 | |
| // removeOldest removes the oldest item from the cache.
 | |
| func (am *attributesMap) removeOldest() {
 | |
| 	ent := am.evictList.Back()
 | |
| 	if ent != nil {
 | |
| 		am.evictList.Remove(ent)
 | |
| 		kv := ent.Value.(*attribute.KeyValue)
 | |
| 		delete(am.attributes, kv.Key)
 | |
| 	}
 | |
| }
 |