diff --git a/attribute/set.go b/attribute/set.go index fb6da51450c..7cb3e720dde 100644 --- a/attribute/set.go +++ b/attribute/set.go @@ -113,9 +113,11 @@ func (l *Set) Value(k Key) (Value, bool) { rValue := l.equivalent.reflectValue() vlen := rValue.Len() - idx := sort.Search(vlen, func(idx int) bool { - return rValue.Index(idx).Interface().(KeyValue).Key >= k - }) + idx := sort.Search( + vlen, func(idx int) bool { + return rValue.Index(idx).Interface().(KeyValue).Key >= k + }, + ) if idx >= vlen { return Value{}, false } @@ -427,6 +429,13 @@ func (l *Set) MarshalJSON() ([]byte, error) { return json.Marshal(l.equivalent.iface) } +// MarshalableToJSON returns a value that is marshalable to JSON form. +// The returned value can be passed as an argument to json.Marshal() or +// be placed in any other structure that itself is passed to json.Marshal(). +func (l *Set) MarshalableToJSON() any { + return l.equivalent.iface +} + // MarshalLog is the marshaling function used by the logging system to represent this Set. func (l Set) MarshalLog() interface{} { kvs := make(map[string]string) diff --git a/example/dice/otel.go b/example/dice/otel.go index 0b30735007a..8185c1412f8 100644 --- a/example/dice/otel.go +++ b/example/dice/otel.go @@ -31,7 +31,9 @@ import ( // setupOTelSDK bootstraps the OpenTelemetry pipeline. // If it does not return an error, make sure to call shutdown for proper cleanup. -func setupOTelSDK(ctx context.Context, serviceName, serviceVersion string) (shutdown func(context.Context) error, err error) { +func setupOTelSDK(ctx context.Context, serviceName, serviceVersion string) ( + shutdown func(context.Context) error, err error, +) { var shutdownFuncs []func(context.Context) error // shutdown calls cleanup functions registered via shutdownFuncs. @@ -84,11 +86,14 @@ func setupOTelSDK(ctx context.Context, serviceName, serviceVersion string) (shut } func newResource(serviceName, serviceVersion string) (*resource.Resource, error) { - return resource.Merge(resource.Default(), - resource.NewWithAttributes(semconv.SchemaURL, + return resource.Merge( + resource.Default(), + resource.NewWithAttributes( + semconv.SchemaURL, semconv.ServiceName(serviceName), semconv.ServiceVersion(serviceVersion), - )) + ), + ) } func newPropagator() propagation.TextMapPropagator { @@ -100,31 +105,38 @@ func newPropagator() propagation.TextMapPropagator { func newTraceProvider(res *resource.Resource) (*trace.TracerProvider, error) { traceExporter, err := stdouttrace.New( - stdouttrace.WithPrettyPrint()) + stdouttrace.WithPrettyPrint(), + ) if err != nil { return nil, err } traceProvider := trace.NewTracerProvider( - trace.WithBatcher(traceExporter, + trace.WithBatcher( + traceExporter, // Default is 5s. Set to 1s for demonstrative purposes. - trace.WithBatchTimeout(time.Second)), + trace.WithBatchTimeout(time.Second), + ), trace.WithResource(res), ) return traceProvider, nil } func newMeterProvider(res *resource.Resource) (*metric.MeterProvider, error) { - metricExporter, err := stdoutmetric.New() + metricExporter, err := stdoutmetric.New(stdoutmetric.WithPrettyPrint()) if err != nil { return nil, err } meterProvider := metric.NewMeterProvider( metric.WithResource(res), - metric.WithReader(metric.NewPeriodicReader(metricExporter, - // Default is 1m. Set to 3s for demonstrative purposes. - metric.WithInterval(3*time.Second))), + metric.WithReader( + metric.NewPeriodicReader( + metricExporter, + // Default is 1m. Set to 3s for demonstrative purposes. + metric.WithInterval(3*time.Second), + ), + ), ) return meterProvider, nil } diff --git a/example/otel-collector/go.mod b/example/otel-collector/go.mod index e3bb6ec5f33..f1a5f497142 100644 --- a/example/otel-collector/go.mod +++ b/example/otel-collector/go.mod @@ -12,7 +12,7 @@ require ( go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.23.0-rc.1 go.opentelemetry.io/otel/sdk v1.23.0-rc.1 go.opentelemetry.io/otel/trace v1.23.0-rc.1 - google.golang.org/grpc v1.60.1 + google.golang.org/grpc v1.61.0 ) require ( @@ -20,15 +20,15 @@ require ( github.com/go-logr/logr v1.4.1 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/golang/protobuf v1.5.3 // indirect - github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.23.0-rc.1 // indirect go.opentelemetry.io/otel/metric v1.23.0-rc.1 // indirect go.opentelemetry.io/proto/otlp v1.1.0 // indirect - golang.org/x/net v0.19.0 // indirect + golang.org/x/net v0.20.0 // indirect golang.org/x/sys v0.16.0 // indirect golang.org/x/text v0.14.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20240102182953-50ed04b92917 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240102182953-50ed04b92917 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240125205218-1f4bbc51befe // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240125205218-1f4bbc51befe // indirect google.golang.org/protobuf v1.32.0 // indirect ) @@ -39,3 +39,47 @@ replace go.opentelemetry.io/otel/exporters/otlp/otlptrace => ../../exporters/otl replace go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc => ../../exporters/otlp/otlptrace/otlptracegrpc replace go.opentelemetry.io/otel/metric => ../../metric + +replace go.opentelemetry.io/proto/otlp => ../../../opentelemetry-proto-go/otlp/ + +replace go.opentelemetry.io/otel/bridge/opencensus => ../../bridge/opencensus + +replace go.opentelemetry.io/otel/bridge/opencensus/test => ../../bridge/opencensus/test + +replace go.opentelemetry.io/otel/bridge/opentracing => ../../bridge/opentracing + +replace go.opentelemetry.io/otel/bridge/opentracing/test => ../../bridge/opentracing/test + +replace go.opentelemetry.io/otel/example/dice => ../dice + +replace go.opentelemetry.io/otel/example/namedtracer => ../namedtracer + +replace go.opentelemetry.io/otel/example/opencensus => ../opencensus + +replace go.opentelemetry.io/otel/example/otel-collector => ./ + +replace go.opentelemetry.io/otel/example/passthrough => ../passthrough + +replace go.opentelemetry.io/otel/example/prometheus => ../prometheus + +replace go.opentelemetry.io/otel/example/zipkin => ../zipkin + +replace go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc => ../../exporters/otlp/otlpmetric/otlpmetricgrpc + +replace go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp => ../../exporters/otlp/otlpmetric/otlpmetrichttp + +replace go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp => ../../exporters/otlp/otlptrace/otlptracehttp + +replace go.opentelemetry.io/otel/exporters/prometheus => ../../exporters/prometheus + +replace go.opentelemetry.io/otel/exporters/stdout/stdoutmetric => ../../exporters/stdout/stdoutmetric + +replace go.opentelemetry.io/otel/exporters/stdout/stdouttrace => ../../exporters/stdout/stdouttrace + +replace go.opentelemetry.io/otel/exporters/zipkin => ../../exporters/zipkin + +replace go.opentelemetry.io/otel/internal/tools => ../../internal/tools + +replace go.opentelemetry.io/otel/schema => ../../schema + +replace go.opentelemetry.io/otel/sdk/metric => ../../sdk/metric diff --git a/example/otel-collector/go.sum b/example/otel-collector/go.sum index 07ef3c0add3..5d4356be474 100644 --- a/example/otel-collector/go.sum +++ b/example/otel-collector/go.sum @@ -11,27 +11,25 @@ github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0 h1:Wqo399gCIufwto+VfwCSvsnfGpF/w5E9CNxSwbpD6No= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0/go.mod h1:qmOFXW2epJhM0qSnUUYpldc7gVz2KMQwJ/QYCDIa7XU= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1 h1:/c3QmbOGMGTOumP2iT/rCwB7b0QDGLKzqOmktBjT+Is= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1/go.mod h1:5SN9VR2LTsRFsrEC6FHgRbTWrTHu6tqPeKxEQv15giM= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= -go.opentelemetry.io/proto/otlp v1.1.0 h1:2Di21piLrCqJ3U3eXGCTPHE9R8Nh+0uglSnOyxikMeI= -go.opentelemetry.io/proto/otlp v1.1.0/go.mod h1:GpBHCBWiqvVLDqmHZsoMM3C5ySeKTC7ej/RNTae6MdY= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= -golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= -golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= +golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo= +golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/genproto v0.0.0-20231212172506-995d672761c0 h1:YJ5pD9rF8o9Qtta0Cmy9rdBwkSjrTCT6XTiUQVOtIos= -google.golang.org/genproto/googleapis/api v0.0.0-20240102182953-50ed04b92917 h1:rcS6EyEaoCO52hQDupoSfrxI3R6C2Tq741is7X8OvnM= -google.golang.org/genproto/googleapis/api v0.0.0-20240102182953-50ed04b92917/go.mod h1:CmlNWB9lSezaYELKS5Ym1r44VrrbPUa7JTvw+6MbpJ0= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240102182953-50ed04b92917 h1:6G8oQ016D88m1xAKljMlBOOGWDZkes4kMhgGFlf8WcQ= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240102182953-50ed04b92917/go.mod h1:xtjpI3tXFPP051KaWnhvxkiubL/6dJ18vLVf7q2pTOU= -google.golang.org/grpc v1.60.1 h1:26+wFr+cNqSGFcOXcabYC0lUVJVRa2Sb2ortSK7VrEU= -google.golang.org/grpc v1.60.1/go.mod h1:OlCHIeLYqSSsLi6i49B5QGdzaMZK9+M7LXN2FKz4eGM= +google.golang.org/genproto v0.0.0-20240116215550-a9fa1716bcac h1:ZL/Teoy/ZGnzyrqK/Optxxp2pmVh+fmJ97slxSRyzUg= +google.golang.org/genproto/googleapis/api v0.0.0-20240125205218-1f4bbc51befe h1:0poefMBYvYbs7g5UkjS6HcxBPaTRAmznle9jnxYoAI8= +google.golang.org/genproto/googleapis/api v0.0.0-20240125205218-1f4bbc51befe/go.mod h1:4jWUdICTdgc3Ibxmr8nAJiiLHwQBY0UI0XZcEMaFKaA= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240125205218-1f4bbc51befe h1:bQnxqljG/wqi4NTXu2+DJ3n7APcEA882QZ1JvhQAq9o= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240125205218-1f4bbc51befe/go.mod h1:PAREbraiVEVGVdTZsVWjSbbTtSyGbAgIIvni8a8CD5s= +google.golang.org/grpc v1.61.0 h1:TOvOcuXn30kRao+gfcvsebNEa5iZIiLkisYEkf7R7o0= +google.golang.org/grpc v1.61.0/go.mod h1:VUbo7IFqmF1QtCAstipjG0GIoq49KvMe9+h1jFLBNJs= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= diff --git a/exporters/otlp/otlptrace/go.mod b/exporters/otlp/otlptrace/go.mod index 11da29b0356..4059de9b70d 100644 --- a/exporters/otlp/otlptrace/go.mod +++ b/exporters/otlp/otlptrace/go.mod @@ -32,3 +32,5 @@ replace go.opentelemetry.io/otel/sdk => ../../../sdk replace go.opentelemetry.io/otel/trace => ../../../trace replace go.opentelemetry.io/otel/metric => ../../../metric + +replace go.opentelemetry.io/proto/otlp => ../../../../opentelemetry-proto-go/otlp/ diff --git a/exporters/otlp/otlptrace/go.sum b/exporters/otlp/otlptrace/go.sum index 6d12cac9adc..d4b11e72106 100644 --- a/exporters/otlp/otlptrace/go.sum +++ b/exporters/otlp/otlptrace/go.sum @@ -23,8 +23,6 @@ github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjR github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -go.opentelemetry.io/proto/otlp v1.1.0 h1:2Di21piLrCqJ3U3eXGCTPHE9R8Nh+0uglSnOyxikMeI= -go.opentelemetry.io/proto/otlp v1.1.0/go.mod h1:GpBHCBWiqvVLDqmHZsoMM3C5ySeKTC7ej/RNTae6MdY= golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= diff --git a/exporters/otlp/otlptrace/internal/tracetransform/resource.go b/exporters/otlp/otlptrace/internal/tracetransform/resource.go index 05a1f78adbc..21c15de7174 100644 --- a/exporters/otlp/otlptrace/internal/tracetransform/resource.go +++ b/exporters/otlp/otlptrace/internal/tracetransform/resource.go @@ -15,8 +15,9 @@ package tracetransform // import "go.opentelemetry.io/otel/exporters/otlp/otlptrace/internal/tracetransform" import ( - "go.opentelemetry.io/otel/sdk/resource" resourcepb "go.opentelemetry.io/proto/otlp/resource/v1" + + "go.opentelemetry.io/otel/sdk/resource" ) // Resource transforms a Resource into an OTLP Resource. @@ -24,5 +25,13 @@ func Resource(r *resource.Resource) *resourcepb.Resource { if r == nil { return nil } - return &resourcepb.Resource{Attributes: ResourceAttributes(r)} + + attrs := Iterator(r.Iter()) + entityId := Iterator(r.EntityId().Iter()) + + return &resourcepb.Resource{ + Attributes: attrs, + EntityType: r.EntityType(), + EntityId: entityId, + } } diff --git a/exporters/otlp/otlptrace/otlptracegrpc/go.mod b/exporters/otlp/otlptrace/otlptracegrpc/go.mod index b0dcf22e888..2267e267e1d 100644 --- a/exporters/otlp/otlptrace/otlptracegrpc/go.mod +++ b/exporters/otlp/otlptrace/otlptracegrpc/go.mod @@ -11,8 +11,8 @@ require ( go.opentelemetry.io/otel/trace v1.23.0-rc.1 go.opentelemetry.io/proto/otlp v1.1.0 go.uber.org/goleak v1.3.0 - google.golang.org/genproto/googleapis/rpc v0.0.0-20240102182953-50ed04b92917 - google.golang.org/grpc v1.60.1 + google.golang.org/genproto/googleapis/rpc v0.0.0-20240125205218-1f4bbc51befe + google.golang.org/grpc v1.61.0 google.golang.org/protobuf v1.32.0 ) @@ -21,14 +21,14 @@ require ( github.com/go-logr/logr v1.4.1 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/golang/protobuf v1.5.3 // indirect - github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1 // indirect github.com/kr/text v0.2.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect go.opentelemetry.io/otel/metric v1.23.0-rc.1 // indirect - golang.org/x/net v0.19.0 // indirect + golang.org/x/net v0.20.0 // indirect golang.org/x/sys v0.16.0 // indirect golang.org/x/text v0.14.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20240102182953-50ed04b92917 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240125205218-1f4bbc51befe // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) @@ -41,3 +41,49 @@ replace go.opentelemetry.io/otel/exporters/otlp/otlptrace => ../ replace go.opentelemetry.io/otel/trace => ../../../../trace replace go.opentelemetry.io/otel/metric => ../../../../metric + +replace go.opentelemetry.io/proto/otlp => ../../../../../opentelemetry-proto-go/otlp/ + +replace go.opentelemetry.io/otel/bridge/opencensus => ../../../../bridge/opencensus + +replace go.opentelemetry.io/otel/bridge/opencensus/test => ../../../../bridge/opencensus/test + +replace go.opentelemetry.io/otel/bridge/opentracing => ../../../../bridge/opentracing + +replace go.opentelemetry.io/otel/bridge/opentracing/test => ../../../../bridge/opentracing/test + +replace go.opentelemetry.io/otel/example/dice => ../../../../example/dice + +replace go.opentelemetry.io/otel/example/namedtracer => ../../../../example/namedtracer + +replace go.opentelemetry.io/otel/example/opencensus => ../../../../example/opencensus + +replace go.opentelemetry.io/otel/example/otel-collector => ../../../../example/otel-collector + +replace go.opentelemetry.io/otel/example/passthrough => ../../../../example/passthrough + +replace go.opentelemetry.io/otel/example/prometheus => ../../../../example/prometheus + +replace go.opentelemetry.io/otel/example/zipkin => ../../../../example/zipkin + +replace go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc => ../../otlpmetric/otlpmetricgrpc + +replace go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp => ../../otlpmetric/otlpmetrichttp + +replace go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc => ./ + +replace go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp => ../otlptracehttp + +replace go.opentelemetry.io/otel/exporters/prometheus => ../../../prometheus + +replace go.opentelemetry.io/otel/exporters/stdout/stdoutmetric => ../../../stdout/stdoutmetric + +replace go.opentelemetry.io/otel/exporters/stdout/stdouttrace => ../../../stdout/stdouttrace + +replace go.opentelemetry.io/otel/exporters/zipkin => ../../../zipkin + +replace go.opentelemetry.io/otel/internal/tools => ../../../../internal/tools + +replace go.opentelemetry.io/otel/schema => ../../../../schema + +replace go.opentelemetry.io/otel/sdk/metric => ../../../../sdk/metric diff --git a/exporters/otlp/otlptrace/otlptracegrpc/go.sum b/exporters/otlp/otlptrace/otlptracegrpc/go.sum index 471ffacf102..bd42f420560 100644 --- a/exporters/otlp/otlptrace/otlptracegrpc/go.sum +++ b/exporters/otlp/otlptrace/otlptracegrpc/go.sum @@ -13,8 +13,8 @@ github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0 h1:Wqo399gCIufwto+VfwCSvsnfGpF/w5E9CNxSwbpD6No= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0/go.mod h1:qmOFXW2epJhM0qSnUUYpldc7gVz2KMQwJ/QYCDIa7XU= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1 h1:/c3QmbOGMGTOumP2iT/rCwB7b0QDGLKzqOmktBjT+Is= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1/go.mod h1:5SN9VR2LTsRFsrEC6FHgRbTWrTHu6tqPeKxEQv15giM= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= @@ -23,24 +23,22 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -go.opentelemetry.io/proto/otlp v1.1.0 h1:2Di21piLrCqJ3U3eXGCTPHE9R8Nh+0uglSnOyxikMeI= -go.opentelemetry.io/proto/otlp v1.1.0/go.mod h1:GpBHCBWiqvVLDqmHZsoMM3C5ySeKTC7ej/RNTae6MdY= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= -golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= -golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= +golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo= +golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/genproto v0.0.0-20231212172506-995d672761c0 h1:YJ5pD9rF8o9Qtta0Cmy9rdBwkSjrTCT6XTiUQVOtIos= -google.golang.org/genproto/googleapis/api v0.0.0-20240102182953-50ed04b92917 h1:rcS6EyEaoCO52hQDupoSfrxI3R6C2Tq741is7X8OvnM= -google.golang.org/genproto/googleapis/api v0.0.0-20240102182953-50ed04b92917/go.mod h1:CmlNWB9lSezaYELKS5Ym1r44VrrbPUa7JTvw+6MbpJ0= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240102182953-50ed04b92917 h1:6G8oQ016D88m1xAKljMlBOOGWDZkes4kMhgGFlf8WcQ= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240102182953-50ed04b92917/go.mod h1:xtjpI3tXFPP051KaWnhvxkiubL/6dJ18vLVf7q2pTOU= -google.golang.org/grpc v1.60.1 h1:26+wFr+cNqSGFcOXcabYC0lUVJVRa2Sb2ortSK7VrEU= -google.golang.org/grpc v1.60.1/go.mod h1:OlCHIeLYqSSsLi6i49B5QGdzaMZK9+M7LXN2FKz4eGM= +google.golang.org/genproto v0.0.0-20240116215550-a9fa1716bcac h1:ZL/Teoy/ZGnzyrqK/Optxxp2pmVh+fmJ97slxSRyzUg= +google.golang.org/genproto/googleapis/api v0.0.0-20240125205218-1f4bbc51befe h1:0poefMBYvYbs7g5UkjS6HcxBPaTRAmznle9jnxYoAI8= +google.golang.org/genproto/googleapis/api v0.0.0-20240125205218-1f4bbc51befe/go.mod h1:4jWUdICTdgc3Ibxmr8nAJiiLHwQBY0UI0XZcEMaFKaA= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240125205218-1f4bbc51befe h1:bQnxqljG/wqi4NTXu2+DJ3n7APcEA882QZ1JvhQAq9o= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240125205218-1f4bbc51befe/go.mod h1:PAREbraiVEVGVdTZsVWjSbbTtSyGbAgIIvni8a8CD5s= +google.golang.org/grpc v1.61.0 h1:TOvOcuXn30kRao+gfcvsebNEa5iZIiLkisYEkf7R7o0= +google.golang.org/grpc v1.61.0/go.mod h1:VUbo7IFqmF1QtCAstipjG0GIoq49KvMe9+h1jFLBNJs= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= diff --git a/exporters/otlp/otlptrace/otlptracehttp/go.mod b/exporters/otlp/otlptrace/otlptracehttp/go.mod index ae9a1ed2bc2..f927bf773de 100644 --- a/exporters/otlp/otlptrace/otlptracehttp/go.mod +++ b/exporters/otlp/otlptrace/otlptracehttp/go.mod @@ -10,7 +10,7 @@ require ( go.opentelemetry.io/otel/sdk v1.23.0-rc.1 go.opentelemetry.io/otel/trace v1.23.0-rc.1 go.opentelemetry.io/proto/otlp v1.1.0 - google.golang.org/grpc v1.60.1 + google.golang.org/grpc v1.61.0 google.golang.org/protobuf v1.32.0 ) @@ -19,15 +19,15 @@ require ( github.com/go-logr/logr v1.4.1 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/golang/protobuf v1.5.3 // indirect - github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1 // indirect github.com/kr/text v0.2.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect go.opentelemetry.io/otel/metric v1.23.0-rc.1 // indirect - golang.org/x/net v0.19.0 // indirect + golang.org/x/net v0.20.0 // indirect golang.org/x/sys v0.16.0 // indirect golang.org/x/text v0.14.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20240102182953-50ed04b92917 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240102182953-50ed04b92917 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240125205218-1f4bbc51befe // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240125205218-1f4bbc51befe // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) @@ -40,3 +40,49 @@ replace go.opentelemetry.io/otel/sdk => ../../../../sdk replace go.opentelemetry.io/otel/trace => ../../../../trace replace go.opentelemetry.io/otel/metric => ../../../../metric + +replace go.opentelemetry.io/proto/otlp => ../../../../../opentelemetry-proto-go/otlp/ + +replace go.opentelemetry.io/otel/bridge/opencensus => ../../../../bridge/opencensus + +replace go.opentelemetry.io/otel/bridge/opencensus/test => ../../../../bridge/opencensus/test + +replace go.opentelemetry.io/otel/bridge/opentracing => ../../../../bridge/opentracing + +replace go.opentelemetry.io/otel/bridge/opentracing/test => ../../../../bridge/opentracing/test + +replace go.opentelemetry.io/otel/example/dice => ../../../../example/dice + +replace go.opentelemetry.io/otel/example/namedtracer => ../../../../example/namedtracer + +replace go.opentelemetry.io/otel/example/opencensus => ../../../../example/opencensus + +replace go.opentelemetry.io/otel/example/otel-collector => ../../../../example/otel-collector + +replace go.opentelemetry.io/otel/example/passthrough => ../../../../example/passthrough + +replace go.opentelemetry.io/otel/example/prometheus => ../../../../example/prometheus + +replace go.opentelemetry.io/otel/example/zipkin => ../../../../example/zipkin + +replace go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc => ../../otlpmetric/otlpmetricgrpc + +replace go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp => ../../otlpmetric/otlpmetrichttp + +replace go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc => ../otlptracegrpc + +replace go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp => ./ + +replace go.opentelemetry.io/otel/exporters/prometheus => ../../../prometheus + +replace go.opentelemetry.io/otel/exporters/stdout/stdoutmetric => ../../../stdout/stdoutmetric + +replace go.opentelemetry.io/otel/exporters/stdout/stdouttrace => ../../../stdout/stdouttrace + +replace go.opentelemetry.io/otel/exporters/zipkin => ../../../zipkin + +replace go.opentelemetry.io/otel/internal/tools => ../../../../internal/tools + +replace go.opentelemetry.io/otel/schema => ../../../../schema + +replace go.opentelemetry.io/otel/sdk/metric => ../../../../sdk/metric diff --git a/exporters/otlp/otlptrace/otlptracehttp/go.sum b/exporters/otlp/otlptrace/otlptracehttp/go.sum index f1773891403..f6f8cd8e47e 100644 --- a/exporters/otlp/otlptrace/otlptracehttp/go.sum +++ b/exporters/otlp/otlptrace/otlptracehttp/go.sum @@ -13,8 +13,8 @@ github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0 h1:Wqo399gCIufwto+VfwCSvsnfGpF/w5E9CNxSwbpD6No= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0/go.mod h1:qmOFXW2epJhM0qSnUUYpldc7gVz2KMQwJ/QYCDIa7XU= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1 h1:/c3QmbOGMGTOumP2iT/rCwB7b0QDGLKzqOmktBjT+Is= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1/go.mod h1:5SN9VR2LTsRFsrEC6FHgRbTWrTHu6tqPeKxEQv15giM= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= @@ -23,22 +23,20 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -go.opentelemetry.io/proto/otlp v1.1.0 h1:2Di21piLrCqJ3U3eXGCTPHE9R8Nh+0uglSnOyxikMeI= -go.opentelemetry.io/proto/otlp v1.1.0/go.mod h1:GpBHCBWiqvVLDqmHZsoMM3C5ySeKTC7ej/RNTae6MdY= -golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= -golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= +golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo= +golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/genproto v0.0.0-20231212172506-995d672761c0 h1:YJ5pD9rF8o9Qtta0Cmy9rdBwkSjrTCT6XTiUQVOtIos= -google.golang.org/genproto/googleapis/api v0.0.0-20240102182953-50ed04b92917 h1:rcS6EyEaoCO52hQDupoSfrxI3R6C2Tq741is7X8OvnM= -google.golang.org/genproto/googleapis/api v0.0.0-20240102182953-50ed04b92917/go.mod h1:CmlNWB9lSezaYELKS5Ym1r44VrrbPUa7JTvw+6MbpJ0= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240102182953-50ed04b92917 h1:6G8oQ016D88m1xAKljMlBOOGWDZkes4kMhgGFlf8WcQ= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240102182953-50ed04b92917/go.mod h1:xtjpI3tXFPP051KaWnhvxkiubL/6dJ18vLVf7q2pTOU= -google.golang.org/grpc v1.60.1 h1:26+wFr+cNqSGFcOXcabYC0lUVJVRa2Sb2ortSK7VrEU= -google.golang.org/grpc v1.60.1/go.mod h1:OlCHIeLYqSSsLi6i49B5QGdzaMZK9+M7LXN2FKz4eGM= +google.golang.org/genproto v0.0.0-20240116215550-a9fa1716bcac h1:ZL/Teoy/ZGnzyrqK/Optxxp2pmVh+fmJ97slxSRyzUg= +google.golang.org/genproto/googleapis/api v0.0.0-20240125205218-1f4bbc51befe h1:0poefMBYvYbs7g5UkjS6HcxBPaTRAmznle9jnxYoAI8= +google.golang.org/genproto/googleapis/api v0.0.0-20240125205218-1f4bbc51befe/go.mod h1:4jWUdICTdgc3Ibxmr8nAJiiLHwQBY0UI0XZcEMaFKaA= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240125205218-1f4bbc51befe h1:bQnxqljG/wqi4NTXu2+DJ3n7APcEA882QZ1JvhQAq9o= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240125205218-1f4bbc51befe/go.mod h1:PAREbraiVEVGVdTZsVWjSbbTtSyGbAgIIvni8a8CD5s= +google.golang.org/grpc v1.61.0 h1:TOvOcuXn30kRao+gfcvsebNEa5iZIiLkisYEkf7R7o0= +google.golang.org/grpc v1.61.0/go.mod h1:VUbo7IFqmF1QtCAstipjG0GIoq49KvMe9+h1jFLBNJs= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= diff --git a/sdk/resource/builtin.go b/sdk/resource/builtin.go index 6a2c08293a8..94f93abcb43 100644 --- a/sdk/resource/builtin.go +++ b/sdk/resource/builtin.go @@ -22,6 +22,7 @@ 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" ) @@ -41,9 +42,10 @@ type ( host struct{} stringDetector struct { - schemaURL string - K attribute.Key - F func() (string, error) + schemaURL string + K attribute.Key + F func() (string, error) + entityType string } defaultServiceNameDetector struct{} @@ -78,6 +80,14 @@ 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) { @@ -89,13 +99,20 @@ 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()) } - return NewWithAttributes(sd.schemaURL, sd.K.String(value)), nil + id := attribute.NewSet(sd.K.String(value)) + entity := internal.EntityData{ + Type: sd.entityType, + Id: id, + Attrs: id, + } + return NewWithEntity(sd.schemaURL, &entity), nil } // Detect implements Detector. func (defaultServiceNameDetector) Detect(ctx context.Context) (*Resource, error) { - return StringDetector( + return StringDetectorWithEntity( semconv.SchemaURL, + "service", semconv.ServiceNameKey, func() (string, error) { executable, err := os.Executable() diff --git a/sdk/resource/config.go b/sdk/resource/config.go index f263919f6ec..613809f42d2 100644 --- a/sdk/resource/config.go +++ b/sdk/resource/config.go @@ -26,6 +26,9 @@ type config struct { detectors []Detector // SchemaURL to associate with the Resource. schemaURL string + + entityType string + entityId []attribute.KeyValue } // Option is the interface that applies a configuration option. @@ -93,6 +96,22 @@ 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 entityOption struct { + entityType string + entityId []attribute.KeyValue +} + +func (o entityOption) apply(cfg config) config { + cfg.entityType = o.entityType + cfg.entityId = o.entityId + return cfg +} + // WithOS adds all the OS attributes to the configured Resource. // See individual WithOS* functions to configure specific attributes. func WithOS() Option { diff --git a/sdk/resource/internal/entity.go b/sdk/resource/internal/entity.go new file mode 100644 index 00000000000..ec8d29041b5 --- /dev/null +++ b/sdk/resource/internal/entity.go @@ -0,0 +1,62 @@ +package internal + +import "go.opentelemetry.io/otel/attribute" + +type EntityData struct { + // Defines the producing entity type of this resource, e.g "service", "k8s.pod", etc. + // Empty for legacy Resources that are not entity-aware. + Type string + // Set of attributes that identify the entity. + // Note that a copy of identifying attributes will be also recorded in the Attrs field. + Id attribute.Set + + Attrs attribute.Set +} + +func MergeEntities(a, b *EntityData) *EntityData { + // Note: 'b' attributes will overwrite 'a' with last-value-wins in attribute.Key() + // Meaning this is equivalent to: append(a.Attributes(), b.Attributes()...) + mergedAttrs := mergeAttrs(&b.Attrs, &a.Attrs) + + var mergedType string + var mergedId attribute.Set + + if a.Type == b.Type { + mergedType = a.Type + mergedId = mergeAttrs(&b.Id, &a.Id) + } else { + if a.Type == "" { + mergedType = b.Type + mergedId = b.Id + } else if b.Type == "" { + mergedType = a.Type + mergedId = a.Id + } else { + // Different non-empty entities. + mergedId = a.Id + // TODO: merge the id of the updating Entity into the non-identifying + // attributes of the old Resource, attributes from the updating Entity + // take precedence. + panic("not implemented") + } + } + + return &EntityData{ + Type: mergedType, + Id: mergedId, + Attrs: mergedAttrs, + } +} + +func mergeAttrs(a, b *attribute.Set) attribute.Set { + if a.Len()+b.Len() == 0 { + return *attribute.EmptySet() + } + + mi := attribute.NewMergeIterator(a, b) + combine := make([]attribute.KeyValue, 0, a.Len()+b.Len()) + for mi.Next() { + combine = append(combine, mi.Attribute()) + } + return attribute.NewSet(combine...) +} diff --git a/sdk/resource/resource.go b/sdk/resource/resource.go index 8c69ba25a4f..c3e3e8ac209 100644 --- a/sdk/resource/resource.go +++ b/sdk/resource/resource.go @@ -16,11 +16,13 @@ package resource // import "go.opentelemetry.io/otel/sdk/resource" import ( "context" + "encoding/json" "errors" "sync" "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/sdk/resource/internal" ) // Resource describes an entity about which identifying information @@ -31,8 +33,10 @@ import ( // (`*resource.Resource`). The `nil` value is equivalent to an empty // Resource. type Resource struct { - attrs attribute.Set schemaURL string + + // Producing entity. + entity internal.EntityData } var ( @@ -49,7 +53,16 @@ func New(ctx context.Context, opts ...Option) (*Resource, error) { cfg = opt.apply(cfg) } - r := &Resource{schemaURL: cfg.schemaURL} + entityId, _ := attribute.NewSetWithFiltered( + cfg.entityId, func(kv attribute.KeyValue) bool { + return kv.Valid() + }, + ) + + r := &Resource{ + schemaURL: cfg.schemaURL, + entity: internal.EntityData{Type: cfg.entityType, Id: entityId}, + } return r, detect(ctx, r, cfg.detectors) } @@ -63,6 +76,30 @@ func NewWithAttributes(schemaURL string, attrs ...attribute.KeyValue) *Resource return resource } +// NewWithEntity creates a resource from entity and attrs and associates the resource with a +// schema URL. If attrs or entityId contains duplicate keys, the last value will be used. If attrs or entityId +// contains any invalid items those items will be dropped. The attrs and entityId are assumed to be +// in a schema identified by schemaURL. +func NewWithEntity( + schemaURL string, entity *internal.EntityData, +) *Resource { + resource := NewSchemaless(entity.Attrs.ToSlice()...) + resource.schemaURL = schemaURL + resource.entity = *entity + //resource.entity.Type = entityType + + // Ensure attributes comply with the specification: + // https://github.com/open-telemetry/opentelemetry-specification/blob/v1.20.0/specification/common/README.md#attribute + //id, _ := attribute.NewSetWithFiltered( + // entityId, func(kv attribute.KeyValue) bool { + // return kv.Valid() + // }, + //) + // + //resource.entity.Id = id + return resource +} + // NewSchemaless creates a resource from attrs. If attrs contains duplicate keys, // the last value will be used. If attrs contains any invalid items those items will // be dropped. The resource will not be associated with a schema URL. If the schema @@ -74,16 +111,18 @@ func NewSchemaless(attrs ...attribute.KeyValue) *Resource { // Ensure attributes comply with the specification: // https://github.com/open-telemetry/opentelemetry-specification/blob/v1.20.0/specification/common/README.md#attribute - s, _ := attribute.NewSetWithFiltered(attrs, func(kv attribute.KeyValue) bool { - return kv.Valid() - }) + s, _ := attribute.NewSetWithFiltered( + attrs, func(kv attribute.KeyValue) bool { + return kv.Valid() + }, + ) // If attrs only contains invalid entries do not allocate a new resource. if s.Len() == 0 { return &Resource{} } - return &Resource{attrs: s} //nolint + return &Resource{entity: internal.EntityData{Id: attribute.NewSet(), Attrs: s}} //nolint } // String implements the Stringer interface and provides a @@ -95,7 +134,7 @@ func (r *Resource) String() string { if r == nil { return "" } - return r.attrs.Encoded(attribute.DefaultEncoder()) + return r.entity.Attrs.Encoded(attribute.DefaultEncoder()) } // MarshalLog is the marshaling function used by the logging system to represent this Resource. @@ -104,7 +143,7 @@ func (r *Resource) MarshalLog() interface{} { Attributes attribute.Set SchemaURL string }{ - Attributes: r.attrs, + Attributes: r.entity.Attrs, SchemaURL: r.schemaURL, } } @@ -115,7 +154,7 @@ func (r *Resource) Attributes() []attribute.KeyValue { if r == nil { r = Empty() } - return r.attrs.ToSlice() + return r.entity.Attrs.ToSlice() } // SchemaURL returns the schema URL associated with Resource r. @@ -126,13 +165,27 @@ func (r *Resource) SchemaURL() string { return r.schemaURL } +func (r *Resource) EntityId() *attribute.Set { + if r == nil { + return attribute.EmptySet() + } + return &r.entity.Id +} + +func (r *Resource) EntityType() string { + if r == nil { + return "" + } + return r.entity.Type +} + // Iter returns an iterator of the Resource attributes. // This is ideal to use if you do not want a copy of the attributes. func (r *Resource) Iter() attribute.Iterator { if r == nil { r = Empty() } - return r.attrs.Iter() + return r.entity.Attrs.Iter() } // Equal returns true when a Resource is equivalent to this Resource. @@ -180,14 +233,9 @@ func Merge(a, b *Resource) (*Resource, error) { return Empty(), errMergeConflictSchemaURL } - // Note: 'b' attributes will overwrite 'a' with last-value-wins in attribute.Key() - // Meaning this is equivalent to: append(a.Attributes(), b.Attributes()...) - mi := attribute.NewMergeIterator(b.Set(), a.Set()) - combine := make([]attribute.KeyValue, 0, a.Len()+b.Len()) - for mi.Next() { - combine = append(combine, mi.Attribute()) - } - merged := NewWithAttributes(schemaURL, combine...) + mergedEntity := internal.MergeEntities(&a.entity, &b.entity) + merged := NewWithEntity(schemaURL, mergedEntity) + return merged, nil } @@ -200,22 +248,24 @@ func Empty() *Resource { // Default returns an instance of Resource with a default // "service.name" and OpenTelemetrySDK attributes. func Default() *Resource { - defaultResourceOnce.Do(func() { - var err error - defaultResource, err = Detect( - context.Background(), - defaultServiceNameDetector{}, - fromEnv{}, - telemetrySDK{}, - ) - if err != nil { - otel.Handle(err) - } - // If Detect did not return a valid resource, fall back to emptyResource. - if defaultResource == nil { - defaultResource = &Resource{} - } - }) + defaultResourceOnce.Do( + func() { + var err error + defaultResource, err = Detect( + context.Background(), + defaultServiceNameDetector{}, + fromEnv{}, + telemetrySDK{}, + ) + if err != nil { + otel.Handle(err) + } + // If Detect did not return a valid resource, fall back to emptyResource. + if defaultResource == nil { + defaultResource = &Resource{} + } + }, + ) return defaultResource } @@ -242,7 +292,7 @@ func (r *Resource) Set() *attribute.Set { if r == nil { r = Empty() } - return &r.attrs + return &r.entity.Attrs } // MarshalJSON encodes the resource attributes as a JSON list of { "Key": @@ -251,7 +301,27 @@ func (r *Resource) MarshalJSON() ([]byte, error) { if r == nil { r = Empty() } - return r.attrs.MarshalJSON() + + rjson := struct { + Attributes any + SchemaURL string + Entity struct { + Type string + Id any + } + }{ + Attributes: r.entity.Attrs.MarshalableToJSON(), + SchemaURL: r.schemaURL, + Entity: struct { + Type string + Id any + }{ + Type: r.entity.Type, + Id: r.entity.Id.MarshalableToJSON(), + }, + } + + return json.Marshal(rjson) } // Len returns the number of unique key-values in this Resource. @@ -259,7 +329,7 @@ func (r *Resource) Len() int { if r == nil { return 0 } - return r.attrs.Len() + return r.entity.Attrs.Len() } // Encoded returns an encoded representation of the resource. @@ -267,5 +337,5 @@ func (r *Resource) Encoded(enc attribute.Encoder) string { if r == nil { return "" } - return r.attrs.Encoded(enc) + return r.entity.Attrs.Encoded(enc) } diff --git a/sdk/resource/resource_test.go b/sdk/resource/resource_test.go index baed4a31336..8ba400f0f25 100644 --- a/sdk/resource/resource_test.go +++ b/sdk/resource/resource_test.go @@ -67,15 +67,18 @@ func TestNewWithAttributes(t *testing.T) { }, } for _, c := range cases { - t.Run(fmt.Sprintf("case-%s", c.name), func(t *testing.T) { - res := resource.NewSchemaless(c.in...) - if diff := cmp.Diff( - res.Attributes(), - c.want, - cmp.AllowUnexported(attribute.Value{})); diff != "" { - t.Fatalf("unwanted result: diff %+v,", diff) - } - }) + t.Run( + fmt.Sprintf("case-%s", c.name), func(t *testing.T) { + res := resource.NewSchemaless(c.in...) + if diff := cmp.Diff( + res.Attributes(), + c.want, + cmp.AllowUnexported(attribute.Value{}), + ); diff != "" { + t.Fatalf("unwanted result: diff %+v,", diff) + } + }, + ) } } @@ -188,21 +191,24 @@ func TestMerge(t *testing.T) { }, } for _, c := range cases { - t.Run(fmt.Sprintf("case-%s", c.name), func(t *testing.T) { - res, err := resource.Merge(c.a, c.b) - if c.isErr { - assert.Error(t, err) - } else { - assert.NoError(t, err) - } - assert.EqualValues(t, c.schemaURL, res.SchemaURL()) - if diff := cmp.Diff( - res.Attributes(), - c.want, - cmp.AllowUnexported(attribute.Value{})); diff != "" { - t.Fatalf("unwanted result: diff %+v,", diff) - } - }) + t.Run( + fmt.Sprintf("case-%s", c.name), func(t *testing.T) { + res, err := resource.Merge(c.a, c.b) + if c.isErr { + assert.Error(t, err) + } else { + assert.NoError(t, err) + } + assert.EqualValues(t, c.schemaURL, res.SchemaURL()) + if diff := cmp.Diff( + res.Attributes(), + c.want, + cmp.AllowUnexported(attribute.Value{}), + ); diff != "" { + t.Fatalf("unwanted result: diff %+v,", diff) + } + }, + ) } } @@ -224,8 +230,10 @@ func TestDefault(t *testing.T) { serviceName, _ := res.Set().Value(semconv.ServiceNameKey) require.True(t, strings.HasPrefix(serviceName.AsString(), "unknown_service:")) - require.Greaterf(t, len(serviceName.AsString()), len("unknown_service:"), - "default service.name should include executable name") + require.Greaterf( + t, len(serviceName.AsString()), len("unknown_service:"), + "default service.name should include executable name", + ) require.Contains(t, res.Attributes(), semconv.TelemetrySDKLanguageGo) require.Contains(t, res.Attributes(), semconv.TelemetrySDKVersion(sdk.Version())) @@ -310,9 +318,11 @@ func TestMarshalJSON(t *testing.T) { r := resource.NewSchemaless(attribute.Int64("A", 1), attribute.String("C", "D")) data, err := json.Marshal(r) require.NoError(t, err) - require.Equal(t, - `[{"Key":"A","Value":{"Type":"INT64","Value":1}},{"Key":"C","Value":{"Type":"STRING","Value":"D"}}]`, - string(data)) + require.Equal( + t, + `{"Attributes":[{"Key":"A","Value":{"Type":"INT64","Value":1}},{"Key":"C","Value":{"Type":"STRING","Value":"D"}}],"SchemaURL":"","Entity":{"Type":"","Id":[]}}`, + string(data), + ) } func TestNew(t *testing.T) { @@ -416,7 +426,10 @@ func TestNew(t *testing.T) { options: []resource.Option{ resource.WithDetectors( resource.StringDetector("https://opentelemetry.io/schemas/1.0.0", semconv.HostNameKey, os.Hostname), - resource.StringDetector("https://opentelemetry.io/schemas/1.1.0", semconv.HostNameKey, func() (string, error) { return "", errors.New("fail") }), + resource.StringDetector( + "https://opentelemetry.io/schemas/1.1.0", semconv.HostNameKey, + func() (string, error) { return "", errors.New("fail") }, + ), ), resource.WithSchemaURL("https://opentelemetry.io/schemas/1.2.0"), }, @@ -426,30 +439,34 @@ func TestNew(t *testing.T) { }, } for _, tt := range tc { - t.Run(tt.name, func(t *testing.T) { - store, err := ottest.SetEnvVariables(map[string]string{ - envVar: tt.envars, - }) - require.NoError(t, err) - defer func() { require.NoError(t, store.Restore()) }() - - ctx := context.Background() - res, err := resource.New(ctx, tt.options...) - - if tt.isErr { - require.Error(t, err) - } else { + t.Run( + tt.name, func(t *testing.T) { + store, err := ottest.SetEnvVariables( + map[string]string{ + envVar: tt.envars, + }, + ) require.NoError(t, err) - } + defer func() { require.NoError(t, store.Restore()) }() - require.EqualValues(t, tt.resourceValues, toMap(res)) + ctx := context.Background() + res, err := resource.New(ctx, tt.options...) - // TODO: do we need to ensure that resource is never nil and eliminate the - // following if? - if res != nil { - assert.EqualValues(t, tt.schemaURL, res.SchemaURL()) - } - }) + if tt.isErr { + require.Error(t, err) + } else { + require.NoError(t, err) + } + + require.EqualValues(t, tt.resourceValues, toMap(res)) + + // TODO: do we need to ensure that resource is never nil and eliminate the + // following if? + if res != nil { + assert.EqualValues(t, tt.schemaURL, res.SchemaURL()) + } + }, + ) } } @@ -458,12 +475,16 @@ func TestNewWrapedError(t *testing.T) { _, err := resource.New( context.Background(), resource.WithDetectors( - resource.StringDetector("", "", func() (string, error) { - return "", localErr - }), - resource.StringDetector("", "", func() (string, error) { - return "", assert.AnError - }), + resource.StringDetector( + "", "", func() (string, error) { + return "", localErr + }, + ), + resource.StringDetector( + "", "", func() (string, error) { + return "", assert.AnError + }, + ), ), ) @@ -478,14 +499,17 @@ func TestWithHostID(t *testing.T) { ctx := context.Background() - res, err := resource.New(ctx, + res, err := resource.New( + ctx, resource.WithHostID(), ) require.NoError(t, err) - require.EqualValues(t, map[string]string{ - "host.id": "f2c668b579780554f70f72a063dc0864", - }, toMap(res)) + require.EqualValues( + t, map[string]string{ + "host.id": "f2c668b579780554f70f72a063dc0864", + }, toMap(res), + ) } func TestWithHostIDError(t *testing.T) { @@ -494,7 +518,8 @@ func TestWithHostIDError(t *testing.T) { ctx := context.Background() - res, err := resource.New(ctx, + res, err := resource.New( + ctx, resource.WithHostID(), ) @@ -508,14 +533,17 @@ func TestWithOSType(t *testing.T) { ctx := context.Background() - res, err := resource.New(ctx, + res, err := resource.New( + ctx, resource.WithOSType(), ) require.NoError(t, err) - require.EqualValues(t, map[string]string{ - "os.type": "linux", - }, toMap(res)) + require.EqualValues( + t, map[string]string{ + "os.type": "linux", + }, toMap(res), + ) } func TestWithOSDescription(t *testing.T) { @@ -524,14 +552,17 @@ func TestWithOSDescription(t *testing.T) { ctx := context.Background() - res, err := resource.New(ctx, + res, err := resource.New( + ctx, resource.WithOSDescription(), ) require.NoError(t, err) - require.EqualValues(t, map[string]string{ - "os.description": "Test", - }, toMap(res)) + require.EqualValues( + t, map[string]string{ + "os.description": "Test", + }, toMap(res), + ) } func TestWithOS(t *testing.T) { @@ -540,148 +571,178 @@ func TestWithOS(t *testing.T) { ctx := context.Background() - res, err := resource.New(ctx, + res, err := resource.New( + ctx, resource.WithOS(), ) require.NoError(t, err) - require.EqualValues(t, map[string]string{ - "os.type": "linux", - "os.description": "Test", - }, toMap(res)) + require.EqualValues( + t, map[string]string{ + "os.type": "linux", + "os.description": "Test", + }, toMap(res), + ) } func TestWithProcessPID(t *testing.T) { mockProcessAttributesProvidersWithErrors() ctx := context.Background() - res, err := resource.New(ctx, + res, err := resource.New( + ctx, resource.WithProcessPID(), ) require.NoError(t, err) - require.EqualValues(t, map[string]string{ - "process.pid": fmt.Sprint(fakePID), - }, toMap(res)) + require.EqualValues( + t, map[string]string{ + "process.pid": fmt.Sprint(fakePID), + }, toMap(res), + ) } func TestWithProcessExecutableName(t *testing.T) { mockProcessAttributesProvidersWithErrors() ctx := context.Background() - res, err := resource.New(ctx, + res, err := resource.New( + ctx, resource.WithProcessExecutableName(), ) require.NoError(t, err) - require.EqualValues(t, map[string]string{ - "process.executable.name": fakeExecutableName, - }, toMap(res)) + require.EqualValues( + t, map[string]string{ + "process.executable.name": fakeExecutableName, + }, toMap(res), + ) } func TestWithProcessExecutablePath(t *testing.T) { mockProcessAttributesProviders() ctx := context.Background() - res, err := resource.New(ctx, + res, err := resource.New( + ctx, resource.WithProcessExecutablePath(), ) require.NoError(t, err) - require.EqualValues(t, map[string]string{ - "process.executable.path": fakeExecutablePath, - }, toMap(res)) + require.EqualValues( + t, map[string]string{ + "process.executable.path": fakeExecutablePath, + }, toMap(res), + ) } func TestWithProcessCommandArgs(t *testing.T) { mockProcessAttributesProvidersWithErrors() ctx := context.Background() - res, err := resource.New(ctx, + res, err := resource.New( + ctx, resource.WithProcessCommandArgs(), ) require.NoError(t, err) - require.EqualValues(t, map[string]string{ - "process.command_args": fmt.Sprint(fakeCommandArgs), - }, toMap(res)) + require.EqualValues( + t, map[string]string{ + "process.command_args": fmt.Sprint(fakeCommandArgs), + }, toMap(res), + ) } func TestWithProcessOwner(t *testing.T) { mockProcessAttributesProviders() ctx := context.Background() - res, err := resource.New(ctx, + res, err := resource.New( + ctx, resource.WithProcessOwner(), ) require.NoError(t, err) - require.EqualValues(t, map[string]string{ - "process.owner": fakeOwner, - }, toMap(res)) + require.EqualValues( + t, map[string]string{ + "process.owner": fakeOwner, + }, toMap(res), + ) } func TestWithProcessRuntimeName(t *testing.T) { mockProcessAttributesProvidersWithErrors() ctx := context.Background() - res, err := resource.New(ctx, + res, err := resource.New( + ctx, resource.WithProcessRuntimeName(), ) require.NoError(t, err) - require.EqualValues(t, map[string]string{ - "process.runtime.name": fakeRuntimeName, - }, toMap(res)) + require.EqualValues( + t, map[string]string{ + "process.runtime.name": fakeRuntimeName, + }, toMap(res), + ) } func TestWithProcessRuntimeVersion(t *testing.T) { mockProcessAttributesProvidersWithErrors() ctx := context.Background() - res, err := resource.New(ctx, + res, err := resource.New( + ctx, resource.WithProcessRuntimeVersion(), ) require.NoError(t, err) - require.EqualValues(t, map[string]string{ - "process.runtime.version": fakeRuntimeVersion, - }, toMap(res)) + require.EqualValues( + t, map[string]string{ + "process.runtime.version": fakeRuntimeVersion, + }, toMap(res), + ) } func TestWithProcessRuntimeDescription(t *testing.T) { mockProcessAttributesProvidersWithErrors() ctx := context.Background() - res, err := resource.New(ctx, + res, err := resource.New( + ctx, resource.WithProcessRuntimeDescription(), ) require.NoError(t, err) - require.EqualValues(t, map[string]string{ - "process.runtime.description": fakeRuntimeDescription, - }, toMap(res)) + require.EqualValues( + t, map[string]string{ + "process.runtime.description": fakeRuntimeDescription, + }, toMap(res), + ) } func TestWithProcess(t *testing.T) { mockProcessAttributesProviders() ctx := context.Background() - res, err := resource.New(ctx, + res, err := resource.New( + ctx, resource.WithProcess(), ) require.NoError(t, err) - require.EqualValues(t, map[string]string{ - "process.pid": fmt.Sprint(fakePID), - "process.executable.name": fakeExecutableName, - "process.executable.path": fakeExecutablePath, - "process.command_args": fmt.Sprint(fakeCommandArgs), - "process.owner": fakeOwner, - "process.runtime.name": fakeRuntimeName, - "process.runtime.version": fakeRuntimeVersion, - "process.runtime.description": fakeRuntimeDescription, - }, toMap(res)) + require.EqualValues( + t, map[string]string{ + "process.pid": fmt.Sprint(fakePID), + "process.executable.name": fakeExecutableName, + "process.executable.path": fakeExecutablePath, + "process.command_args": fmt.Sprint(fakeCommandArgs), + "process.owner": fakeOwner, + "process.runtime.name": fakeRuntimeName, + "process.runtime.version": fakeRuntimeVersion, + "process.runtime.description": fakeRuntimeDescription, + }, toMap(res), + ) } func toMap(res *resource.Resource) map[string]string { @@ -738,18 +799,21 @@ func TestWithContainerID(t *testing.T) { } for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - resource.SetContainerProviders(tc.containerIDProvider) - - res, err := resource.New(context.Background(), - resource.WithContainerID(), - ) - - if tc.expectedErr { - assert.Error(t, err) - } - assert.Equal(t, tc.expectedResource, toMap(res)) - }) + t.Run( + tc.name, func(t *testing.T) { + resource.SetContainerProviders(tc.containerIDProvider) + + res, err := resource.New( + context.Background(), + resource.WithContainerID(), + ) + + if tc.expectedErr { + assert.Error(t, err) + } + assert.Equal(t, tc.expectedResource, toMap(res)) + }, + ) } } @@ -757,18 +821,23 @@ func TestWithContainer(t *testing.T) { t.Cleanup(restoreAttributesProviders) fakeContainerID := "fake-container-id" - resource.SetContainerProviders(func() (string, error) { - return fakeContainerID, nil - }) + resource.SetContainerProviders( + func() (string, error) { + return fakeContainerID, nil + }, + ) - res, err := resource.New(context.Background(), + res, err := resource.New( + context.Background(), resource.WithContainer(), ) assert.NoError(t, err) - assert.Equal(t, map[string]string{ - string(semconv.ContainerIDKey): fakeContainerID, - }, toMap(res)) + assert.Equal( + t, map[string]string{ + string(semconv.ContainerIDKey): fakeContainerID, + }, toMap(res), + ) } func TestResourceConcurrentSafe(t *testing.T) { diff --git a/sdk/trace/provider.go b/sdk/trace/provider.go index b1ac608464a..108d50e65c0 100644 --- a/sdk/trace/provider.go +++ b/sdk/trace/provider.go @@ -233,11 +233,13 @@ func (p *TracerProvider) UnregisterSpanProcessor(sp SpanProcessor) { } } if stopOnce != nil { - stopOnce.state.Do(func() { - if err := sp.Shutdown(context.Background()); err != nil { - otel.Handle(err) - } - }) + stopOnce.state.Do( + func() { + if err := sp.Shutdown(context.Background()); err != nil { + otel.Handle(err) + } + }, + ) } if len(spss) > 1 { copy(spss[idx:], spss[idx+1:]) @@ -294,9 +296,11 @@ func (p *TracerProvider) Shutdown(ctx context.Context) error { } var err error - sps.state.Do(func() { - err = sps.sp.Shutdown(ctx) - }) + sps.state.Do( + func() { + err = sps.sp.Shutdown(ctx) + }, + ) if err != nil { if retErr == nil { retErr = err @@ -345,10 +349,12 @@ func WithBatcher(e SpanExporter, opts ...BatchSpanProcessorOption) TracerProvide // WithSpanProcessor registers the SpanProcessor with a TracerProvider. func WithSpanProcessor(sp SpanProcessor) TracerProviderOption { - return traceProviderOptionFunc(func(cfg tracerProviderConfig) tracerProviderConfig { - cfg.processors = append(cfg.processors, sp) - return cfg - }) + return traceProviderOptionFunc( + func(cfg tracerProviderConfig) tracerProviderConfig { + cfg.processors = append(cfg.processors, sp) + return cfg + }, + ) } // WithResource returns a TracerProviderOption that will configure the @@ -359,14 +365,29 @@ func WithSpanProcessor(sp SpanProcessor) TracerProviderOption { // If this option is not used, the TracerProvider will use the // resource.Default() Resource by default. func WithResource(r *resource.Resource) TracerProviderOption { - return traceProviderOptionFunc(func(cfg tracerProviderConfig) tracerProviderConfig { - var err error - cfg.resource, err = resource.Merge(resource.Environment(), r) - if err != nil { - otel.Handle(err) - } - return cfg - }) + return traceProviderOptionFunc( + func(cfg tracerProviderConfig) tracerProviderConfig { + var err error + cfg.resource, err = resource.Merge(resource.Environment(), r) + if err != nil { + otel.Handle(err) + } + return cfg + }, + ) +} + +func WithEntity(r *resource.Resource) TracerProviderOption { + return traceProviderOptionFunc( + func(cfg tracerProviderConfig) tracerProviderConfig { + var err error + cfg.resource, err = resource.Merge(resource.Environment(), r) + if err != nil { + otel.Handle(err) + } + return cfg + }, + ) } // WithIDGenerator returns a TracerProviderOption that will configure the @@ -377,12 +398,14 @@ func WithResource(r *resource.Resource) TracerProviderOption { // If this option is not used, the TracerProvider will use a random number // IDGenerator by default. func WithIDGenerator(g IDGenerator) TracerProviderOption { - return traceProviderOptionFunc(func(cfg tracerProviderConfig) tracerProviderConfig { - if g != nil { - cfg.idGenerator = g - } - return cfg - }) + return traceProviderOptionFunc( + func(cfg tracerProviderConfig) tracerProviderConfig { + if g != nil { + cfg.idGenerator = g + } + return cfg + }, + ) } // WithSampler returns a TracerProviderOption that will configure the Sampler @@ -396,12 +419,14 @@ func WithIDGenerator(g IDGenerator) TracerProviderOption { // contains invalid/unsupported configuration, the TracerProvider will use a // ParentBased(AlwaysSample) Sampler by default. func WithSampler(s Sampler) TracerProviderOption { - return traceProviderOptionFunc(func(cfg tracerProviderConfig) tracerProviderConfig { - if s != nil { - cfg.sampler = s - } - return cfg - }) + return traceProviderOptionFunc( + func(cfg tracerProviderConfig) tracerProviderConfig { + if s != nil { + cfg.sampler = s + } + return cfg + }, + ) } // WithSpanLimits returns a TracerProviderOption that configures a @@ -438,10 +463,12 @@ func WithSpanLimits(sl SpanLimits) TracerProviderOption { if sl.AttributePerLinkCountLimit <= 0 { sl.AttributePerLinkCountLimit = DefaultAttributePerLinkCountLimit } - return traceProviderOptionFunc(func(cfg tracerProviderConfig) tracerProviderConfig { - cfg.spanLimits = sl - return cfg - }) + return traceProviderOptionFunc( + func(cfg tracerProviderConfig) tracerProviderConfig { + cfg.spanLimits = sl + return cfg + }, + ) } // WithRawSpanLimits returns a TracerProviderOption that configures a @@ -460,10 +487,12 @@ func WithSpanLimits(sl SpanLimits) TracerProviderOption { // limits defined by environment variables, or the defaults if unset. Refer to // the NewSpanLimits documentation for information about this relationship. func WithRawSpanLimits(limits SpanLimits) TracerProviderOption { - return traceProviderOptionFunc(func(cfg tracerProviderConfig) tracerProviderConfig { - cfg.spanLimits = limits - return cfg - }) + return traceProviderOptionFunc( + func(cfg tracerProviderConfig) tracerProviderConfig { + cfg.spanLimits = limits + return cfg + }, + ) } func applyTracerProviderEnvConfigs(cfg tracerProviderConfig) tracerProviderConfig {