Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions attribute/set.go
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,47 @@ func NewSetWithFiltered(kvs []KeyValue, filter Filter) (Set, []KeyValue) {
return newSet(kvs), nil
}

// NewDistinctWithFilter returns a Distinct identifier for the filtered attribute set,
// and the sorted and de-duplicated slice of attributes. It modifies the input slice
// in-place to sort and de-duplicate the attributes.
//
// The returned Distinct represents the equivalence class of the attribute set after
// the filter is applied. The returned slice contains all unique attributes, including
// those that did not pass the filter.
func NewDistinctWithFilter(kvs []KeyValue, filter Filter) (Distinct, []KeyValue) {
if len(kvs) == 0 {
return Distinct{hash: emptyHash}, kvs
}

// Stable sort so the following de-duplication can implement
// last-value-wins semantics.
slices.SortStableFunc(kvs, func(a, b KeyValue) int {
return cmp.Compare(a.Key, b.Key)
})

position := len(kvs) - 1
offset := position - 1

// De-duplicate with last-value-wins semantics.
for ; offset >= 0; offset-- {
if kvs[offset].Key == kvs[position].Key {
continue
}
position--
kvs[offset], kvs[position] = kvs[position], kvs[offset]
}
kvs = kvs[position:]

h := xxhash.New()
for _, kv := range kvs {
if filter == nil || filter(kv) {
h = hashKV(h, kv)
}
}

return Distinct{hash: h.Sum64()}, kvs
}

// NewSetWithSortableFiltered returns a new Set.
//
// Duplicate keys are eliminated by taking the last value. This
Expand Down
27 changes: 27 additions & 0 deletions metric/x/bound.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0

package x // import "go.opentelemetry.io/otel/metric/x"

import (
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/metric"
)

// Float64Binder is an interface that can be implemented by instruments that support
// binding attributes ahead of time.
type Float64Binder interface {
// Bind returns a metric.Float64Counter for the given attributes.
// The returned counter is bound to the attributes and should be optimized
// for performance by avoiding map lookups on every Add call.
Bind(attrs ...attribute.KeyValue) metric.Float64Counter
}

// Int64Binder is an interface that can be implemented by instruments that support
// binding attributes ahead of time.
type Int64Binder interface {
// Bind returns a metric.Int64Counter for the given attributes.
// The returned counter is bound to the attributes and should be optimized
// for performance by avoiding map lookups on every Add call.
Bind(attrs ...attribute.KeyValue) metric.Int64Counter
}
Loading