@@ -22,6 +22,7 @@ import (
2222 sdktrace "go.opentelemetry.io/otel/sdk/trace"
2323 semconv "go.opentelemetry.io/otel/semconv/v1.12.0"
2424 "go.opentelemetry.io/otel/trace"
25+ "go.opentelemetry.io/otel/trace/noop"
2526
2627 "github.com/circleci/ex/config/secret"
2728 "github.com/circleci/ex/o11y"
@@ -82,11 +83,11 @@ func New(conf Config) (o11y.Provider, error) {
8283 exporters = append (exporters , http )
8384 }
8485
85- var sampler * deterministicSampler
86+ var sampler * DeterministicSampler
8687 if conf .SampleTraces {
87- sampler = & deterministicSampler {
88- sampleKeyFunc : conf .SampleKeyFunc ,
89- sampleRates : conf .SampleRates ,
88+ sampler = & DeterministicSampler {
89+ SampleKeyFunc : conf .SampleKeyFunc ,
90+ SampleRates : conf .SampleRates ,
9091 }
9192 }
9293
@@ -104,9 +105,9 @@ func New(conf Config) (o11y.Provider, error) {
104105 exporters = append (exporters , text )
105106 }
106107
107- tp := traceProvider (multipleExporter {
108- exporters : exporters ,
109- sampler : sampler ,
108+ tp := traceProvider (MultipleExporter {
109+ Exporters : exporters ,
110+ Sampler : sampler ,
110111 }, conf )
111112
112113 // set the global options
@@ -121,6 +122,15 @@ func New(conf Config) (o11y.Provider, error) {
121122 }, nil
122123}
123124
125+ // NewMetricsOnly returns a metrics only provider, to capture the span metrics behavior.
126+ // This can be used to compose with a custom provider to access span based metrics.
127+ func NewMetricsOnly (metrics o11y.ClosableMetricsProvider ) o11y.Provider {
128+ return & Provider {
129+ metricsProvider : metrics ,
130+ tracer : noop .NewTracerProvider ().Tracer ("" ),
131+ }
132+ }
133+
124134func NewHttpExporter (conf Config ) (* otlptrace.Exporter , error ) {
125135 var serviceName , serviceVersion string
126136 for _ , a := range conf .ResourceAttributes {
@@ -326,7 +336,9 @@ func (o Provider) Log(ctx context.Context, name string, fields ...o11y.Pair) {
326336
327337func (o Provider ) Close (ctx context.Context ) {
328338 // TODO Handle these errors in a sensible manner where possible
329- _ = o .tp .Shutdown (ctx )
339+ if o .tp != nil {
340+ _ = o .tp .Shutdown (ctx )
341+ }
330342 if o .metricsProvider != nil {
331343 _ = o .metricsProvider .Close ()
332344 }
@@ -543,37 +555,37 @@ func (s *span) snapshotFields() map[string]any {
543555 return res
544556}
545557
546- type multipleExporter struct {
547- exporters []sdktrace.SpanExporter
548- sampler * deterministicSampler
558+ type MultipleExporter struct {
559+ Exporters []sdktrace.SpanExporter
560+ Sampler * DeterministicSampler
549561}
550562
551- func (m multipleExporter ) ExportSpans (ctx context.Context , spans []sdktrace.ReadOnlySpan ) error {
563+ func (m MultipleExporter ) ExportSpans (ctx context.Context , spans []sdktrace.ReadOnlySpan ) error {
552564 spans = m .sampleSpans (spans )
553- for _ , e := range m .exporters {
565+ for _ , e := range m .Exporters {
554566 if err := e .ExportSpans (ctx , spans ); err != nil {
555567 return err
556568 }
557569 }
558570 return nil
559571}
560572
561- func (m multipleExporter ) Shutdown (ctx context.Context ) error {
562- for _ , e := range m .exporters {
573+ func (m MultipleExporter ) Shutdown (ctx context.Context ) error {
574+ for _ , e := range m .Exporters {
563575 if err := e .Shutdown (ctx ); err != nil {
564576 return err
565577 }
566578 }
567579 return nil
568580}
569581
570- func (m multipleExporter ) sampleSpans (spans []sdktrace.ReadOnlySpan ) []sdktrace.ReadOnlySpan {
571- if m .sampler == nil {
582+ func (m MultipleExporter ) sampleSpans (spans []sdktrace.ReadOnlySpan ) []sdktrace.ReadOnlySpan {
583+ if m .Sampler == nil {
572584 return spans
573585 }
574586 ss := make ([]sdktrace.ReadOnlySpan , 0 , len (spans ))
575587 for _ , s := range spans {
576- if ok , rate := m .sampler .shouldSample (s ); ok {
588+ if ok , rate := m .Sampler .shouldSample (s ); ok {
577589 ss = append (ss , sampleRateSpan {ReadOnlySpan : s , rate : rate })
578590 }
579591 }
0 commit comments