1
0
mirror of https://github.com/open-telemetry/opentelemetry-go.git synced 2024-12-12 10:04:29 +02:00
opentelemetry-go/sdk/resource/resource.go

156 lines
4.2 KiB
Go
Raw Normal View History

// 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 resource // import "go.opentelemetry.io/otel/sdk/resource"
import (
"go.opentelemetry.io/otel/label"
)
// Resource describes an entity about which identifying information
// and metadata is exposed. Resource is an immutable object,
// equivalent to a map from key to unique value.
//
// Resources should be passed and stored as pointers
// (`*resource.Resource`). The `nil` value is equivalent to an empty
// Resource.
type Resource struct {
labels label.Set
}
var emptyResource Resource
// NewWithAttributes creates a resource from a set of attributes. If there are
// duplicate keys present in the list of attributes, then the last
// value found for the key is preserved.
func NewWithAttributes(kvs ...label.KeyValue) *Resource {
return &Resource{
labels: label.NewSet(kvs...),
}
}
// String implements the Stringer interface and provides a
// human-readable form of the resource.
//
// Avoid using this representation as the key in a map of resources,
// use Equivalent() as the key instead.
func (r *Resource) String() string {
if r == nil {
return ""
Update Resource (#613) * Update Resource When looking at grouping telemetry in an exporter based on the Resource it is ideal if a map can be make with the key being represented by a Resource. However, given the Resource is not hashable, this is not possible. This add a `String` method that can be used as a map key during grouping. Additionally, this means the Resource now implements the `Stringer` interface providing human-readable info when prited. The internal structure of the Resource is changed. A static slice containing all key-values in a sorted order replaces the existing map. Additionally a set of keys is added to accommodate lookup during `Merge`. Also, the string representation is kept in an internal field so as to save processing for the `String` method (all fields are assumed to be static after creation). The `Attributes` method now returns a sorted slice of the associated key-values. The `Merge` method has been updated to support the changed structure of the Resource. New tests are added to validate the `String` method. * Update comment * Change loop into returned append * Update key-value less func Keys are unique in this package, treat them that way. * Remove unnecessary allocation on empty attributes * Update `Merge` method Remove incomplete sorting of merged slices. Instead use the `sort` package. Add tests to catch sorting failure identified. * Apply suggestions from code review Co-Authored-By: ET <evantorrie@users.noreply.github.com> * Escape Resource string representation To ensure uniqueness of the string representation, the key-value content needs to be escaped. * Switch to an eager evaluation for the `String` method * Refactor `Merge` method Leave optimization to the future and simplify the merge. * Add AttributeIterator Include a method for a user of the Resource to iterate over the related attributes without needed to copy the attributes. * Fix ineffectual * Fix lint * Add licenses * keys -> keySet for Resource Co-authored-by: ET <evantorrie@users.noreply.github.com> Co-authored-by: Rahul Patel <rahulpa@google.com>
2020-04-07 21:15:36 +02:00
}
return r.labels.Encoded(label.DefaultEncoder())
Update Resource (#613) * Update Resource When looking at grouping telemetry in an exporter based on the Resource it is ideal if a map can be make with the key being represented by a Resource. However, given the Resource is not hashable, this is not possible. This add a `String` method that can be used as a map key during grouping. Additionally, this means the Resource now implements the `Stringer` interface providing human-readable info when prited. The internal structure of the Resource is changed. A static slice containing all key-values in a sorted order replaces the existing map. Additionally a set of keys is added to accommodate lookup during `Merge`. Also, the string representation is kept in an internal field so as to save processing for the `String` method (all fields are assumed to be static after creation). The `Attributes` method now returns a sorted slice of the associated key-values. The `Merge` method has been updated to support the changed structure of the Resource. New tests are added to validate the `String` method. * Update comment * Change loop into returned append * Update key-value less func Keys are unique in this package, treat them that way. * Remove unnecessary allocation on empty attributes * Update `Merge` method Remove incomplete sorting of merged slices. Instead use the `sort` package. Add tests to catch sorting failure identified. * Apply suggestions from code review Co-Authored-By: ET <evantorrie@users.noreply.github.com> * Escape Resource string representation To ensure uniqueness of the string representation, the key-value content needs to be escaped. * Switch to an eager evaluation for the `String` method * Refactor `Merge` method Leave optimization to the future and simplify the merge. * Add AttributeIterator Include a method for a user of the Resource to iterate over the related attributes without needed to copy the attributes. * Fix ineffectual * Fix lint * Add licenses * keys -> keySet for Resource Co-authored-by: ET <evantorrie@users.noreply.github.com> Co-authored-by: Rahul Patel <rahulpa@google.com>
2020-04-07 21:15:36 +02:00
}
// Attributes returns a copy of attributes from the resource in a sorted order.
// To avoid allocating a new slice, use an iterator.
func (r *Resource) Attributes() []label.KeyValue {
if r == nil {
r = Empty()
}
return r.labels.ToSlice()
Update Resource (#613) * Update Resource When looking at grouping telemetry in an exporter based on the Resource it is ideal if a map can be make with the key being represented by a Resource. However, given the Resource is not hashable, this is not possible. This add a `String` method that can be used as a map key during grouping. Additionally, this means the Resource now implements the `Stringer` interface providing human-readable info when prited. The internal structure of the Resource is changed. A static slice containing all key-values in a sorted order replaces the existing map. Additionally a set of keys is added to accommodate lookup during `Merge`. Also, the string representation is kept in an internal field so as to save processing for the `String` method (all fields are assumed to be static after creation). The `Attributes` method now returns a sorted slice of the associated key-values. The `Merge` method has been updated to support the changed structure of the Resource. New tests are added to validate the `String` method. * Update comment * Change loop into returned append * Update key-value less func Keys are unique in this package, treat them that way. * Remove unnecessary allocation on empty attributes * Update `Merge` method Remove incomplete sorting of merged slices. Instead use the `sort` package. Add tests to catch sorting failure identified. * Apply suggestions from code review Co-Authored-By: ET <evantorrie@users.noreply.github.com> * Escape Resource string representation To ensure uniqueness of the string representation, the key-value content needs to be escaped. * Switch to an eager evaluation for the `String` method * Refactor `Merge` method Leave optimization to the future and simplify the merge. * Add AttributeIterator Include a method for a user of the Resource to iterate over the related attributes without needed to copy the attributes. * Fix ineffectual * Fix lint * Add licenses * keys -> keySet for Resource Co-authored-by: ET <evantorrie@users.noreply.github.com> Co-authored-by: Rahul Patel <rahulpa@google.com>
2020-04-07 21:15:36 +02:00
}
// Iter returns an interator of the Resource attributes.
// This is ideal to use if you do not want a copy of the attributes.
func (r *Resource) Iter() label.Iterator {
if r == nil {
r = Empty()
}
return r.labels.Iter()
Update Resource (#613) * Update Resource When looking at grouping telemetry in an exporter based on the Resource it is ideal if a map can be make with the key being represented by a Resource. However, given the Resource is not hashable, this is not possible. This add a `String` method that can be used as a map key during grouping. Additionally, this means the Resource now implements the `Stringer` interface providing human-readable info when prited. The internal structure of the Resource is changed. A static slice containing all key-values in a sorted order replaces the existing map. Additionally a set of keys is added to accommodate lookup during `Merge`. Also, the string representation is kept in an internal field so as to save processing for the `String` method (all fields are assumed to be static after creation). The `Attributes` method now returns a sorted slice of the associated key-values. The `Merge` method has been updated to support the changed structure of the Resource. New tests are added to validate the `String` method. * Update comment * Change loop into returned append * Update key-value less func Keys are unique in this package, treat them that way. * Remove unnecessary allocation on empty attributes * Update `Merge` method Remove incomplete sorting of merged slices. Instead use the `sort` package. Add tests to catch sorting failure identified. * Apply suggestions from code review Co-Authored-By: ET <evantorrie@users.noreply.github.com> * Escape Resource string representation To ensure uniqueness of the string representation, the key-value content needs to be escaped. * Switch to an eager evaluation for the `String` method * Refactor `Merge` method Leave optimization to the future and simplify the merge. * Add AttributeIterator Include a method for a user of the Resource to iterate over the related attributes without needed to copy the attributes. * Fix ineffectual * Fix lint * Add licenses * keys -> keySet for Resource Co-authored-by: ET <evantorrie@users.noreply.github.com> Co-authored-by: Rahul Patel <rahulpa@google.com>
2020-04-07 21:15:36 +02:00
}
// Equal returns true when a Resource is equivalent to this Resource.
func (r *Resource) Equal(eq *Resource) bool {
if r == nil {
r = Empty()
}
if eq == nil {
eq = Empty()
}
return r.Equivalent() == eq.Equivalent()
Update Resource (#613) * Update Resource When looking at grouping telemetry in an exporter based on the Resource it is ideal if a map can be make with the key being represented by a Resource. However, given the Resource is not hashable, this is not possible. This add a `String` method that can be used as a map key during grouping. Additionally, this means the Resource now implements the `Stringer` interface providing human-readable info when prited. The internal structure of the Resource is changed. A static slice containing all key-values in a sorted order replaces the existing map. Additionally a set of keys is added to accommodate lookup during `Merge`. Also, the string representation is kept in an internal field so as to save processing for the `String` method (all fields are assumed to be static after creation). The `Attributes` method now returns a sorted slice of the associated key-values. The `Merge` method has been updated to support the changed structure of the Resource. New tests are added to validate the `String` method. * Update comment * Change loop into returned append * Update key-value less func Keys are unique in this package, treat them that way. * Remove unnecessary allocation on empty attributes * Update `Merge` method Remove incomplete sorting of merged slices. Instead use the `sort` package. Add tests to catch sorting failure identified. * Apply suggestions from code review Co-Authored-By: ET <evantorrie@users.noreply.github.com> * Escape Resource string representation To ensure uniqueness of the string representation, the key-value content needs to be escaped. * Switch to an eager evaluation for the `String` method * Refactor `Merge` method Leave optimization to the future and simplify the merge. * Add AttributeIterator Include a method for a user of the Resource to iterate over the related attributes without needed to copy the attributes. * Fix ineffectual * Fix lint * Add licenses * keys -> keySet for Resource Co-authored-by: ET <evantorrie@users.noreply.github.com> Co-authored-by: Rahul Patel <rahulpa@google.com>
2020-04-07 21:15:36 +02:00
}
// Merge creates a new resource by combining resource a and b.
//
// If there are common keys between resource a and b, then the value
// from resource a is preserved.
func Merge(a, b *Resource) *Resource {
if a == nil && b == nil {
return Empty()
}
if a == nil {
return b
}
if b == nil {
return a
}
2020-05-21 18:53:34 +02:00
// Note: 'a' labels will overwrite 'b' with last-value-wins in label.Key()
// Meaning this is equivalent to: append(b.Attributes(), a.Attributes()...)
mi := label.NewMergeIterator(a.LabelSet(), b.LabelSet())
combine := make([]label.KeyValue, 0, a.Len()+b.Len())
for mi.Next() {
combine = append(combine, mi.Label())
}
return NewWithAttributes(combine...)
}
// Empty returns an instance of Resource with no attributes. It is
// equivalent to a `nil` Resource.
func Empty() *Resource {
return &emptyResource
}
// Equivalent returns an object that can be compared for equality
// between two resources. This value is suitable for use as a key in
// a map.
func (r *Resource) Equivalent() label.Distinct {
return r.LabelSet().Equivalent()
}
// LabelSet returns the equivalent *label.Set.
func (r *Resource) LabelSet() *label.Set {
if r == nil {
r = Empty()
}
return &r.labels
}
Add support for Resources in the SDK (#552) * Add support for Resources in the SDK Add `Config` types for the push `Controller` and the `SDK`. Included with this are helper functions to configure the `ErrorHandler` and `Resource`. Add a `Resource` to the Meter `Descriptor`. The choice to add the `Resource` here (instead of say a `Record` or the `Instrument` itself) was motivated by the definition of the `Descriptor` as the way to uniquely describe a metric instrument. Update the push `Controller` and default `SDK` to pass down their configured `Resource` from instantiation to the metric instruments. * Update New SDK constructor documentation * Change NewDescriptor constructor to take opts Add DescriptorConfig and DescriptorOption to configure the metric Descriptor with the description, unit, keys, and resource. Update all function calls to NewDescriptor to use new function signature. * Apply suggestions from code review Co-Authored-By: Rahul Patel <rghetia@yahoo.com> * Update and add copyright notices * Update push controller creator func Pass the configured ErrorHandler for the controller to the SDK. * Update Resource integration with the SDK Add back the Resource field to the Descriptor that was moved in the last merge with master. Add a resource.Provider interface. Have the default SDK implement the new resource.Provider interface and integrate the new interface into the newSync/newAsync workflows. Now, if the SDK has a Resource defined it will be passed to all Descriptors created for the instruments it creates. * Remove nil check for metric SDK config * Fix and add test for API Options Add an `Equal` method to the Resource so it can be compared with github.com/google/go-cmp/cmp. Add additional test of the API Option unit tests to ensure WithResource correctly sets a new resource. * Move the resource.Provider interface to the API package Move the interface to where it is used. Fix spelling. * Remove errant line * Remove nil checks for the push controller config * Fix check SDK implements Resourcer * Apply suggestions from code review Co-Authored-By: Rahul Patel <rghetia@yahoo.com> Co-authored-by: Rahul Patel <rghetia@yahoo.com>
2020-03-20 17:58:32 +02:00
// MarshalJSON encodes labels as a JSON list of { "Key": "...", "Value": ... }
// pairs in order sorted by key.
func (r *Resource) MarshalJSON() ([]byte, error) {
if r == nil {
r = Empty()
}
return r.labels.MarshalJSON()
Add support for Resources in the SDK (#552) * Add support for Resources in the SDK Add `Config` types for the push `Controller` and the `SDK`. Included with this are helper functions to configure the `ErrorHandler` and `Resource`. Add a `Resource` to the Meter `Descriptor`. The choice to add the `Resource` here (instead of say a `Record` or the `Instrument` itself) was motivated by the definition of the `Descriptor` as the way to uniquely describe a metric instrument. Update the push `Controller` and default `SDK` to pass down their configured `Resource` from instantiation to the metric instruments. * Update New SDK constructor documentation * Change NewDescriptor constructor to take opts Add DescriptorConfig and DescriptorOption to configure the metric Descriptor with the description, unit, keys, and resource. Update all function calls to NewDescriptor to use new function signature. * Apply suggestions from code review Co-Authored-By: Rahul Patel <rghetia@yahoo.com> * Update and add copyright notices * Update push controller creator func Pass the configured ErrorHandler for the controller to the SDK. * Update Resource integration with the SDK Add back the Resource field to the Descriptor that was moved in the last merge with master. Add a resource.Provider interface. Have the default SDK implement the new resource.Provider interface and integrate the new interface into the newSync/newAsync workflows. Now, if the SDK has a Resource defined it will be passed to all Descriptors created for the instruments it creates. * Remove nil check for metric SDK config * Fix and add test for API Options Add an `Equal` method to the Resource so it can be compared with github.com/google/go-cmp/cmp. Add additional test of the API Option unit tests to ensure WithResource correctly sets a new resource. * Move the resource.Provider interface to the API package Move the interface to where it is used. Fix spelling. * Remove errant line * Remove nil checks for the push controller config * Fix check SDK implements Resourcer * Apply suggestions from code review Co-Authored-By: Rahul Patel <rghetia@yahoo.com> Co-authored-by: Rahul Patel <rghetia@yahoo.com>
2020-03-20 17:58:32 +02:00
}
// Len returns the number of unique key-values in this Resource.
func (r *Resource) Len() int {
if r == nil {
return 0
}
return r.labels.Len()
}
// Encoded returns an encoded representation of the resource by
// applying a label encoder. The result is cached by the underlying
// label set.
func (r *Resource) Encoded(enc label.Encoder) string {
if r == nil {
return ""
}
return r.labels.Encoded(enc)
}