diff --git a/vendor/go.opentelemetry.io/otel/label/set.go b/vendor/go.opentelemetry.io/otel/label/set.go
new file mode 100644
index 0000000..3bd5263
--- /dev/null
+++ b/vendor/go.opentelemetry.io/otel/label/set.go
@@ -0,0 +1,468 @@
+// 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 label
+
+import (
+	"encoding/json"
+	"reflect"
+	"sort"
+	"sync"
+)
+
+type (
+	// Set is the representation for a distinct label set.  It
+	// manages an immutable set of labels, with an internal cache
+	// for storing label encodings.
+	//
+	// This type supports the `Equivalent` method of comparison
+	// using values of type `Distinct`.
+	//
+	// This type is used to implement:
+	// 1. Metric labels
+	// 2. Resource sets
+	// 3. Correlation map (TODO)
+	Set struct {
+		equivalent Distinct
+
+		lock     sync.Mutex
+		encoders [maxConcurrentEncoders]EncoderID
+		encoded  [maxConcurrentEncoders]string
+	}
+
+	// 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 struct {
+		iface interface{}
+	}
+
+	// Filter supports removing certain labels from label sets.
+	// When the filter returns true, the label will be kept in
+	// the filtered label set.  When the filter returns false, the
+	// label is excluded from the filtered label set, and the
+	// label instead appears in the `removed` list of excluded labels.
+	Filter func(KeyValue) bool
+
+	// Sortable implements `sort.Interface`, used for sorting
+	// `KeyValue`.  This is an exported type to support a
+	// memory optimization.  A pointer to one of these is needed
+	// for the call to `sort.Stable()`, which the caller may
+	// provide in order to avoid an allocation.  See
+	// `NewSetWithSortable()`.
+	Sortable []KeyValue
+)
+
+var (
+	// keyValueType is used in `computeDistinctReflect`.
+	keyValueType = reflect.TypeOf(KeyValue{})
+
+	// emptySet is returned for empty label sets.
+	emptySet = &Set{
+		equivalent: Distinct{
+			iface: [0]KeyValue{},
+		},
+	}
+)
+
+const maxConcurrentEncoders = 3
+
+func EmptySet() *Set {
+	return emptySet
+}
+
+// reflect abbreviates `reflect.ValueOf`.
+func (d Distinct) reflect() reflect.Value {
+	return reflect.ValueOf(d.iface)
+}
+
+// Valid returns true if this value refers to a valid `*Set`.
+func (d Distinct) Valid() bool {
+	return d.iface != nil
+}
+
+// Len returns the number of labels in this set.
+func (l *Set) Len() int {
+	if l == nil || !l.equivalent.Valid() {
+		return 0
+	}
+	return l.equivalent.reflect().Len()
+}
+
+// Get returns the KeyValue at ordered position `idx` in this set.
+func (l *Set) Get(idx int) (KeyValue, bool) {
+	if l == nil {
+		return KeyValue{}, false
+	}
+	value := l.equivalent.reflect()
+
+	if idx >= 0 && idx < value.Len() {
+		// Note: The Go compiler successfully avoids an allocation for
+		// the interface{} conversion here:
+		return value.Index(idx).Interface().(KeyValue), true
+	}
+
+	return KeyValue{}, false
+}
+
+// Value returns the value of a specified key in this set.
+func (l *Set) Value(k Key) (Value, bool) {
+	if l == nil {
+		return Value{}, false
+	}
+	rValue := l.equivalent.reflect()
+	vlen := rValue.Len()
+
+	idx := sort.Search(vlen, func(idx int) bool {
+		return rValue.Index(idx).Interface().(KeyValue).Key >= k
+	})
+	if idx >= vlen {
+		return Value{}, false
+	}
+	keyValue := rValue.Index(idx).Interface().(KeyValue)
+	if k == keyValue.Key {
+		return keyValue.Value, true
+	}
+	return Value{}, false
+}
+
+// HasValue tests whether a key is defined in this set.
+func (l *Set) HasValue(k Key) bool {
+	if l == nil {
+		return false
+	}
+	_, ok := l.Value(k)
+	return ok
+}
+
+// Iter returns an iterator for visiting the labels in this set.
+func (l *Set) Iter() Iterator {
+	return Iterator{
+		storage: l,
+		idx:     -1,
+	}
+}
+
+// ToSlice returns the set of labels belonging to this set, sorted,
+// where keys appear no more than once.
+func (l *Set) ToSlice() []KeyValue {
+	iter := l.Iter()
+	return iter.ToSlice()
+}
+
+// Equivalent returns a value that may be used as a map key.  The
+// Distinct type guarantees that the result will equal the equivalent
+// Distinct value of any label set with the same elements as this,
+// where sets are made unique by choosing the last value in the input
+// for any given key.
+func (l *Set) Equivalent() Distinct {
+	if l == nil || !l.equivalent.Valid() {
+		return emptySet.equivalent
+	}
+	return l.equivalent
+}
+
+// Equals returns true if the argument set is equivalent to this set.
+func (l *Set) Equals(o *Set) bool {
+	return l.Equivalent() == o.Equivalent()
+}
+
+// Encoded returns the encoded form of this set, according to
+// `encoder`.  The result will be cached in this `*Set`.
+func (l *Set) Encoded(encoder Encoder) string {
+	if l == nil || encoder == nil {
+		return ""
+	}
+
+	id := encoder.ID()
+	if !id.Valid() {
+		// Invalid IDs are not cached.
+		return encoder.Encode(l.Iter())
+	}
+
+	var lookup *string
+	l.lock.Lock()
+	for idx := 0; idx < maxConcurrentEncoders; idx++ {
+		if l.encoders[idx] == id {
+			lookup = &l.encoded[idx]
+			break
+		}
+	}
+	l.lock.Unlock()
+
+	if lookup != nil {
+		return *lookup
+	}
+
+	r := encoder.Encode(l.Iter())
+
+	l.lock.Lock()
+	defer l.lock.Unlock()
+
+	for idx := 0; idx < maxConcurrentEncoders; idx++ {
+		if l.encoders[idx] == id {
+			return l.encoded[idx]
+		}
+		if !l.encoders[idx].Valid() {
+			l.encoders[idx] = id
+			l.encoded[idx] = r
+			return r
+		}
+	}
+
+	// TODO: This is a performance cliff.  Find a way for this to
+	// generate a warning.
+	return r
+}
+
+func empty() Set {
+	return Set{
+		equivalent: emptySet.equivalent,
+	}
+}
+
+// NewSet returns a new `Set`.  See the documentation for
+// `NewSetWithSortableFiltered` for more details.
+//
+// Except for empty sets, this method adds an additional allocation
+// compared with calls that include a `*Sortable`.
+func NewSet(kvs ...KeyValue) Set {
+	// Check for empty set.
+	if len(kvs) == 0 {
+		return empty()
+	}
+	s, _ := NewSetWithSortableFiltered(kvs, new(Sortable), nil)
+	return s //nolint
+}
+
+// NewSetWithSortable returns a new `Set`.  See the documentation for
+// `NewSetWithSortableFiltered` for more details.
+//
+// This call includes a `*Sortable` option as a memory optimization.
+func NewSetWithSortable(kvs []KeyValue, tmp *Sortable) Set {
+	// Check for empty set.
+	if len(kvs) == 0 {
+		return empty()
+	}
+	s, _ := NewSetWithSortableFiltered(kvs, tmp, nil)
+	return s //nolint
+}
+
+// NewSetWithFiltered returns a new `Set`.  See the documentation for
+// `NewSetWithSortableFiltered` for more details.
+//
+// This call includes a `Filter` to include/exclude label keys from
+// the return value.  Excluded keys are returned as a slice of label
+// values.
+func NewSetWithFiltered(kvs []KeyValue, filter Filter) (Set, []KeyValue) {
+	// Check for empty set.
+	if len(kvs) == 0 {
+		return empty(), nil
+	}
+	return NewSetWithSortableFiltered(kvs, new(Sortable), filter)
+}
+
+// NewSetWithSortableFiltered returns a new `Set`.
+//
+// Duplicate keys are eliminated by taking the last value.  This
+// re-orders the input slice so that unique last-values are contiguous
+// at the end of the slice.
+//
+// This ensures the following:
+//
+// - Last-value-wins semantics
+// - Caller sees the reordering, but doesn't lose values
+// - Repeated call preserve last-value wins.
+//
+// Note that methods are defined on `*Set`, although this returns `Set`.
+// Callers can avoid memory allocations by:
+//
+// - allocating a `Sortable` for use as a temporary in this method
+// - allocating a `Set` for storing the return value of this
+//   constructor.
+//
+// The result maintains a cache of encoded labels, by label.EncoderID.
+// This value should not be copied after its first use.
+//
+// The second `[]KeyValue` return value is a list of labels that were
+// excluded by the Filter (if non-nil).
+func NewSetWithSortableFiltered(kvs []KeyValue, tmp *Sortable, filter Filter) (Set, []KeyValue) {
+	// Check for empty set.
+	if len(kvs) == 0 {
+		return empty(), nil
+	}
+
+	*tmp = kvs
+
+	// Stable sort so the following de-duplication can implement
+	// last-value-wins semantics.
+	sort.Stable(tmp)
+
+	*tmp = nil
+
+	position := len(kvs) - 1
+	offset := position - 1
+
+	// The requirements stated above require that the stable
+	// result be placed in the end of the input slice, while
+	// overwritten values are swapped to the beginning.
+	//
+	// De-duplicate with last-value-wins semantics.  Preserve
+	// duplicate values at the beginning of the input slice.
+	for ; offset >= 0; offset-- {
+		if kvs[offset].Key == kvs[position].Key {
+			continue
+		}
+		position--
+		kvs[offset], kvs[position] = kvs[position], kvs[offset]
+	}
+	if filter != nil {
+		return filterSet(kvs[position:], filter)
+	}
+	return Set{
+		equivalent: computeDistinct(kvs[position:]),
+	}, nil
+}
+
+// filterSet reorders `kvs` so that included keys are contiguous at
+// the end of the slice, while excluded keys precede the included keys.
+func filterSet(kvs []KeyValue, filter Filter) (Set, []KeyValue) {
+	var excluded []KeyValue
+
+	// Move labels that do not match the filter so
+	// they're adjacent before calling computeDistinct().
+	distinctPosition := len(kvs)
+
+	// Swap indistinct keys forward and distinct keys toward the
+	// end of the slice.
+	offset := len(kvs) - 1
+	for ; offset >= 0; offset-- {
+		if filter(kvs[offset]) {
+			distinctPosition--
+			kvs[offset], kvs[distinctPosition] = kvs[distinctPosition], kvs[offset]
+			continue
+		}
+	}
+	excluded = kvs[:distinctPosition]
+
+	return Set{
+		equivalent: computeDistinct(kvs[distinctPosition:]),
+	}, excluded
+}
+
+// Filter returns a filtered copy of this `Set`.  See the
+// documentation for `NewSetWithSortableFiltered` for more details.
+func (l *Set) Filter(re Filter) (Set, []KeyValue) {
+	if re == nil {
+		return Set{
+			equivalent: l.equivalent,
+		}, nil
+	}
+
+	// Note: This could be refactored to avoid the temporary slice
+	// allocation, if it proves to be expensive.
+	return filterSet(l.ToSlice(), re)
+}
+
+// computeDistinct returns a `Distinct` using either the fixed- or
+// reflect-oriented code path, depending on the size of the input.
+// The input slice is assumed to already be sorted and de-duplicated.
+func computeDistinct(kvs []KeyValue) Distinct {
+	iface := computeDistinctFixed(kvs)
+	if iface == nil {
+		iface = computeDistinctReflect(kvs)
+	}
+	return Distinct{
+		iface: iface,
+	}
+}
+
+// computeDistinctFixed computes a `Distinct` for small slices.  It
+// returns nil if the input is too large for this code path.
+func computeDistinctFixed(kvs []KeyValue) interface{} {
+	switch len(kvs) {
+	case 1:
+		ptr := new([1]KeyValue)
+		copy((*ptr)[:], kvs)
+		return *ptr
+	case 2:
+		ptr := new([2]KeyValue)
+		copy((*ptr)[:], kvs)
+		return *ptr
+	case 3:
+		ptr := new([3]KeyValue)
+		copy((*ptr)[:], kvs)
+		return *ptr
+	case 4:
+		ptr := new([4]KeyValue)
+		copy((*ptr)[:], kvs)
+		return *ptr
+	case 5:
+		ptr := new([5]KeyValue)
+		copy((*ptr)[:], kvs)
+		return *ptr
+	case 6:
+		ptr := new([6]KeyValue)
+		copy((*ptr)[:], kvs)
+		return *ptr
+	case 7:
+		ptr := new([7]KeyValue)
+		copy((*ptr)[:], kvs)
+		return *ptr
+	case 8:
+		ptr := new([8]KeyValue)
+		copy((*ptr)[:], kvs)
+		return *ptr
+	case 9:
+		ptr := new([9]KeyValue)
+		copy((*ptr)[:], kvs)
+		return *ptr
+	case 10:
+		ptr := new([10]KeyValue)
+		copy((*ptr)[:], kvs)
+		return *ptr
+	default:
+		return nil
+	}
+}
+
+// computeDistinctReflect computes a `Distinct` using reflection,
+// works for any size input.
+func computeDistinctReflect(kvs []KeyValue) interface{} {
+	at := reflect.New(reflect.ArrayOf(len(kvs), keyValueType)).Elem()
+	for i, keyValue := range kvs {
+		*(at.Index(i).Addr().Interface().(*KeyValue)) = keyValue
+	}
+	return at.Interface()
+}
+
+// MarshalJSON returns the JSON encoding of the `*Set`.
+func (l *Set) MarshalJSON() ([]byte, error) {
+	return json.Marshal(l.equivalent.iface)
+}
+
+// Len implements `sort.Interface`.
+func (l *Sortable) Len() int {
+	return len(*l)
+}
+
+// Swap implements `sort.Interface`.
+func (l *Sortable) Swap(i, j int) {
+	(*l)[i], (*l)[j] = (*l)[j], (*l)[i]
+}
+
+// Less implements `sort.Interface`.
+func (l *Sortable) Less(i, j int) bool {
+	return (*l)[i].Key < (*l)[j].Key
+}
