Skip to content

Commit

Permalink
Document and check resource comparability (#6272)
Browse files Browse the repository at this point in the history
Ensure backwards compatibility by adding a compile-time check that the
Resource remains comparable.

Document the shortcomings of direct comparison of a Resource.

---------

Co-authored-by: Robert Pająk <[email protected]>
  • Loading branch information
MrAlias and pellared authored Feb 12, 2025
1 parent afbe545 commit 3c1286a
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 5 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
- The `go.opentelemetry.io/otel/semconv/v1.30.0` package.
The package contains semantic conventions from the `v1.30.0` version of the OpenTelemetry Semantic Conventions.
See the [migration documentation](./semconv/v1.30.0/MIGRATION.md) for information on how to upgrade from `go.opentelemetry.io/otel/semconv/v1.28.0`(#6240)
- Document the pitfalls of using `Resource` as a comparable type.
`Resource.Equal` and `Resource.Equivalent` should be used instead. (#6272)

### Changed

Expand Down
25 changes: 20 additions & 5 deletions sdk/resource/resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,22 @@ import (
// Resources should be passed and stored as pointers
// (`*resource.Resource`). The `nil` value is equivalent to an empty
// Resource.
//
// Note that the Go == operator compares not just the resource attributes but
// also all other internals of the Resource type. Therefore, Resource values
// should not be used as map or database keys. In general, the [Resource.Equal]
// method should be used instead of direct comparison with ==, since that
// method ensures the correct comparison of resource attributes, and the
// [attribute.Distinct] returned from [Resource.Equivalent] should be used for
// map and database keys instead.
type Resource struct {
attrs attribute.Set
schemaURL string
}

// Compile-time check that the Resource remains comparable.
var _ map[Resource]struct{} = nil

var (
defaultResource *Resource
defaultResourceOnce sync.Once
Expand Down Expand Up @@ -137,15 +148,19 @@ func (r *Resource) Iter() attribute.Iterator {
return r.attrs.Iter()
}

// Equal returns true when a Resource is equivalent to this Resource.
func (r *Resource) Equal(eq *Resource) bool {
// Equal returns whether r and o represent the same resource. Two resources can
// be equal even if they have different schema URLs.
//
// See the documentation on the [Resource] type for the pitfalls of using ==
// with Resource values; most code should use Equal instead.
func (r *Resource) Equal(o *Resource) bool {
if r == nil {
r = Empty()
}
if eq == nil {
eq = Empty()
if o == nil {
o = Empty()
}
return r.Equivalent() == eq.Equivalent()
return r.Equivalent() == o.Equivalent()
}

// Merge creates a new [Resource] by merging a and b.
Expand Down

0 comments on commit 3c1286a

Please sign in to comment.