Skip to content

Commit

Permalink
Support multiple entity refs in the Resource
Browse files Browse the repository at this point in the history
  • Loading branch information
tigrannajaryan committed Oct 18, 2024
1 parent 781faa5 commit 7f149b1
Show file tree
Hide file tree
Showing 12 changed files with 551 additions and 208 deletions.
9 changes: 9 additions & 0 deletions attribute/set.go
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,15 @@ func filteredToFront(slice []KeyValue, keep Filter) int {
return j
}

func (l *Set) Clone() Set {
s, _ := l.Filter(
func(KeyValue) bool {
return true
},
)
return s
}

// Filter returns a filtered copy of this Set. See the documentation for
// NewSetWithSortableFiltered for more details.
func (l *Set) Filter(re Filter) (Set, []KeyValue) {
Expand Down
25 changes: 20 additions & 5 deletions example/dice/otel.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"time"

"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/exporters/stdout/stdoutmetric"
"go.opentelemetry.io/otel/exporters/stdout/stdouttrace"
"go.opentelemetry.io/otel/propagation"
Expand Down Expand Up @@ -86,14 +87,28 @@ func setupOTelSDK(ctx context.Context, serviceName, serviceVersion string) (
}

func newResource(serviceName, serviceVersion string) (*resource.Resource, error) {
return resource.Merge(
resource.Default(),
resource.NewWithAttributes(
res, err := resource.New(
context.Background(),
resource.WithHost(),
resource.WithHostID(),
resource.WithProcess(),
resource.WithEntity(
semconv.SchemaURL,
semconv.ServiceName(serviceName),
semconv.ServiceVersion(serviceVersion),
"service",
[]attribute.KeyValue{
semconv.ServiceName(serviceName),
semconv.ServiceVersion(serviceVersion),
},
nil,
),
)
if err != nil {
return nil, err
}
return resource.Merge(
resource.Default(),
res,
)
}

func newPropagator() propagation.TextMapPropagator {
Expand Down
18 changes: 14 additions & 4 deletions exporters/otlp/otlptrace/internal/tracetransform/resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,21 @@ func Resource(r *resource.Resource) *resourcepb.Resource {
}

attrs := Iterator(r.Iter())
entityId := Iterator(r.EntityId().Iter())

return &resourcepb.Resource{
out := &resourcepb.Resource{
Attributes: attrs,
EntityType: r.EntityType(),
EntityId: entityId,
}

for _, entity := range r.EntityRefs() {
out.Entities = append(
out.Entities, &resourcepb.ResourceEntityRef{
SchemaUrl: entity.SchemaUrl(),
Type: entity.Type(),
IdAttrKeys: entity.Id(),
DescrAttrKeys: entity.Attrs(),
},
)
}

return out
}
1 change: 1 addition & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
Expand Down
65 changes: 33 additions & 32 deletions sdk/resource/builtin.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import (

"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/sdk"
"go.opentelemetry.io/otel/sdk/resource/internal"
semconv "go.opentelemetry.io/otel/semconv/v1.24.0"
)

Expand All @@ -42,10 +41,9 @@ type (
host struct{}

stringDetector struct {
schemaURL string
K attribute.Key
F func() (string, error)
entityType string
schemaURL string
K attribute.Key
F func() (string, error)
}

defaultServiceNameDetector struct{}
Expand All @@ -70,7 +68,19 @@ func (telemetrySDK) Detect(context.Context) (*Resource, error) {

// Detect returns a *Resource that describes the host being run on.
func (host) Detect(ctx context.Context) (*Resource, error) {
return StringDetector(semconv.SchemaURL, semconv.HostNameKey, os.Hostname).Detect(ctx)
name, err := os.Hostname()
if err != nil {
return nil, err
}
return NewWithEntities(
[]Entity{
{
Type: "host",
Attrs: attribute.NewSet(semconv.HostName(name)),
SchemaURL: semconv.SchemaURL,
},
},
)
}

// StringDetector returns a Detector that will produce a *Resource
Expand All @@ -80,14 +90,6 @@ func StringDetector(schemaURL string, k attribute.Key, f func() (string, error))
return stringDetector{schemaURL: schemaURL, K: k, F: f}
}

// StringDetectorWithEntity returns a Detector that will produce a *Resource
// containing the string as a value corresponding to k. The Id of entity of the
// resource will also be set to the same key/value pair.
// The resulting Resource will have the specified schemaURL.
func StringDetectorWithEntity(schemaURL string, entityType string, k attribute.Key, f func() (string, error)) Detector {
return stringDetector{schemaURL: schemaURL, K: k, F: f, entityType: entityType}
}

// Detect returns a *Resource that describes the string as a value
// corresponding to attribute.Key as well as the specific schemaURL.
func (sd stringDetector) Detect(ctx context.Context) (*Resource, error) {
Expand All @@ -99,27 +101,26 @@ func (sd stringDetector) Detect(ctx context.Context) (*Resource, error) {
if !a.Valid() {
return nil, fmt.Errorf("invalid attribute: %q -> %q", a.Key, a.Value.Emit())
}
id := attribute.NewSet(sd.K.String(value))
entity := internal.EntityData{
Type: sd.entityType,
Id: id,
Attrs: id,
}
return NewWithEntity(sd.schemaURL, &entity), nil
return NewWithAttributes(sd.schemaURL, sd.K.String(value)), nil
}

// Detect implements Detector.
func (defaultServiceNameDetector) Detect(ctx context.Context) (*Resource, error) {
return StringDetectorWithEntity(
semconv.SchemaURL,
"service",
semconv.ServiceNameKey,
func() (string, error) {
executable, err := os.Executable()
if err != nil {
return "unknown_service:go", nil
}
return "unknown_service:" + filepath.Base(executable), nil
serviceName := ""
executable, err := os.Executable()
if err != nil {
serviceName = "unknown_service:go"
} else {
serviceName = "unknown_service:" + filepath.Base(executable)
}

return NewWithEntities(
[]Entity{
{
Type: "service",
Id: attribute.NewSet(semconv.ServiceName(serviceName)),
SchemaURL: semconv.SchemaURL,
},
},
).Detect(ctx)
)
}
40 changes: 28 additions & 12 deletions sdk/resource/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ type config struct {
// SchemaURL to associate with the Resource.
schemaURL string

entityType string
entityId []attribute.KeyValue
//entityType string
//entityId []attribute.KeyValue
}

// Option is the interface that applies a configuration option.
Expand Down Expand Up @@ -96,20 +96,36 @@ func (o schemaURLOption) apply(cfg config) config {
return cfg
}

// WithEntity sets the schema URL for the configured resource.
func WithEntity(entityType string, entityId ...attribute.KeyValue) Option {
return entityOption{entityType, entityId}
type entityDetector struct {
SchemaURL string
Type string
Id []attribute.KeyValue
Attrs []attribute.KeyValue
}

type entityOption struct {
entityType string
entityId []attribute.KeyValue
func (e entityDetector) Detect(ctx context.Context) (*Resource, error) {
return NewWithEntities(
[]Entity{
{
Type: e.Type,
Id: attribute.NewSet(e.Id...),
Attrs: attribute.NewSet(e.Attrs...),
SchemaURL: e.SchemaURL,
},
},
)
}

func (o entityOption) apply(cfg config) config {
cfg.entityType = o.entityType
cfg.entityId = o.entityId
return cfg
// WithEntity sets the schema URL for the configured resource.
func WithEntity(schemaURL string, entityType string, id, attrs []attribute.KeyValue) Option {
return WithDetectors(
entityDetector{
SchemaURL: schemaURL,
Type: entityType,
Id: id,
Attrs: attrs,
},
)
}

// WithOS adds all the OS attributes to the configured Resource.
Expand Down
10 changes: 10 additions & 0 deletions sdk/resource/entity.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package resource

import "go.opentelemetry.io/otel/attribute"

type Entity struct {
Type string
Id attribute.Set
Attrs attribute.Set
SchemaURL string
}
49 changes: 49 additions & 0 deletions sdk/resource/entityref.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package resource

import "go.opentelemetry.io/otel/attribute"

type resourceEntityRef struct {
schemaUrl string

// Defines the entity type, e.g "service", "k8s.pod", etc.
typ string

// Set of Resource attribute keys that identify the entity.
id map[attribute.Key]bool

// Set of Resource attribute keys that describe the entity.
attrs map[attribute.Key]bool

// id and attrs are cached as slices for faster exporting.
idAsSlice []string
attrsAsSlice []string
}

// updateCache must be called after id or attrs are modified to make
// sure the cache is up to date.
func (r *resourceEntityRef) updateCache() {
r.idAsSlice = r.idAsSlice[:0]
for k := range r.id {
r.idAsSlice = append(r.idAsSlice, string(k))
}
r.attrsAsSlice = r.attrsAsSlice[:0]
for k := range r.attrs {
r.attrsAsSlice = append(r.attrsAsSlice, string(k))
}
}

func (r *resourceEntityRef) SchemaUrl() string {
return r.schemaUrl
}

func (r *resourceEntityRef) Type() string {
return r.typ
}

func (r *resourceEntityRef) Id() []string {
return r.idAsSlice
}

func (r *resourceEntityRef) Attrs() []string {
return r.attrsAsSlice
}
14 changes: 10 additions & 4 deletions sdk/resource/host_id.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"errors"
"strings"

"go.opentelemetry.io/otel/attribute"
semconv "go.opentelemetry.io/otel/semconv/v1.24.0"
)

Expand Down Expand Up @@ -113,8 +114,13 @@ func (hostIDDetector) Detect(ctx context.Context) (*Resource, error) {
return nil, err
}

return NewWithAttributes(
semconv.SchemaURL,
semconv.HostID(hostID),
), nil
return NewWithEntities(
[]Entity{
{
Type: "host",
Id: attribute.NewSet(semconv.HostID(hostID)),
SchemaURL: semconv.SchemaURL,
},
},
)
}
Loading

0 comments on commit 7f149b1

Please sign in to comment.