Skip to content

Commit

Permalink
Unify the Config type across instrumentation (#226)
Browse files Browse the repository at this point in the history
* Initial idea to abstract Config internally

* Add Propagator to Config

* Test the Config.Copy method

* Add test for WithSpan

* Fix nil Config bug for mergedSpanStartOptions

* Move WithTracerProvider test to option_test

* Fix lint issues
  • Loading branch information
MrAlias authored Dec 8, 2021
1 parent c8d7b10 commit f051a59
Show file tree
Hide file tree
Showing 14 changed files with 633 additions and 334 deletions.
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@ require (
go.opentelemetry.io/otel v1.2.0
go.opentelemetry.io/otel/exporters/jaeger v1.2.0
go.opentelemetry.io/otel/sdk v1.2.0
go.opentelemetry.io/otel/trace v1.2.0
)
Original file line number Diff line number Diff line change
Expand Up @@ -17,35 +17,38 @@ package splunkleveldb
import (
"context"

"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/codes"
semconv "go.opentelemetry.io/otel/semconv/v1.7.0"
"go.opentelemetry.io/otel/trace"

splunkotel "github.com/signalfx/splunk-otel-go"
"github.com/signalfx/splunk-otel-go/instrumentation/internal"
)

// instrumentationName is the instrumentation library identifier for a Tracer.
const instrumentationName = "github.com/signalfx/splunk-otel-go/instrumentation/github.com/syndtr/goleveldb/leveldb/splunkleveldb"

// config contains tracing configuration options.
type config struct {
ctx context.Context
tracer trace.Tracer
defaultStartOpts []trace.SpanStartOption
*internal.Config

ctx context.Context
}

func newConfig(options ...Option) *config {
c := config{
defaultStartOpts: []trace.SpanStartOption{
trace.WithAttributes(
semconv.DBSystemKey.String("leveldb"),
semconv.NetTransportInProc,
),
// From the specification: span kind MUST always be CLIENT.
trace.WithSpanKind(trace.SpanKindClient),
},
Config: internal.NewConfig(instrumentationName, internal.OptionFunc(
func(c *internal.Config) {
c.DefaultStartOpts = []trace.SpanStartOption{
trace.WithAttributes(
semconv.DBSystemKey.String("leveldb"),
semconv.NetTransportInProc,
),
// From the specification: span kind MUST always be CLIENT.
trace.WithSpanKind(trace.SpanKindClient),
}
}),
),
ctx: context.Background(),
}

for _, o := range options {
Expand All @@ -54,95 +57,32 @@ func newConfig(options ...Option) *config {
}
}

if c.tracer == nil {
c.tracer = otel.Tracer(
instrumentationName,
trace.WithInstrumentationVersion(splunkotel.Version()),
trace.WithSchemaURL(semconv.SchemaURL),
)
}

if c.ctx == nil {
c.ctx = context.Background()
}

return &c
}

// resolveTracer returns an OTel tracer from the appropriate TracerProvider.
//
// If the passed context contains a span, the TracerProvider that created the
// tracer that created that span will be used. Otherwise, the TracerProvider
// from c is used.
func (c *config) resolveTracer() trace.Tracer {
// There is a possibility that the config was not created with newConfig,
// try to handle this situation gracefully.
if c == nil {
return otel.Tracer(
instrumentationName,
trace.WithInstrumentationVersion(splunkotel.Version()),
trace.WithSchemaURL(semconv.SchemaURL),
)
}

if span := trace.SpanFromContext(c.ctx); span.SpanContext().IsValid() {
return span.TracerProvider().Tracer(
instrumentationName,
trace.WithInstrumentationVersion(splunkotel.Version()),
trace.WithSchemaURL(semconv.SchemaURL),
)
}

if c.tracer == nil {
return otel.Tracer(
instrumentationName,
trace.WithInstrumentationVersion(splunkotel.Version()),
trace.WithSchemaURL(semconv.SchemaURL),
)
}
return c.tracer
// Option applies options to a configuration.
type Option interface {
apply(*config)
}

func (c *config) mergedSpanStartOptions(opts ...trace.SpanStartOption) []trace.SpanStartOption {
if c == nil {
if len(opts) == 0 {
return nil
}
} else {
if len(opts)+len(c.defaultStartOpts) == 0 {
return nil
}
}

var merged []trace.SpanStartOption
if c == nil || len(c.defaultStartOpts) == 0 {
merged = make([]trace.SpanStartOption, len(opts))
copy(merged, opts)
} else {
merged = make([]trace.SpanStartOption, len(c.defaultStartOpts)+len(opts))
copy(merged, c.defaultStartOpts)
copy(merged[len(c.defaultStartOpts):], opts)
}
return merged
type optConv struct {
iOpt internal.Option
}

// withSpan wraps the function f with a span.
func (c *config) withSpan(name string, f func() error, opts ...trace.SpanStartOption) error {
sso := c.mergedSpanStartOptions(opts...)
_, span := c.resolveTracer().Start(c.ctx, name, sso...)
err := f()
if err != nil {
span.RecordError(err)
span.SetStatus(codes.Error, err.Error())
}
span.End()
func (o optConv) apply(c *config) {
o.iOpt.Apply(c.Config)
}

return err
// WithTracerProvider returns an Option that sets the TracerProvider used with
// this instrumentation library.
func WithTracerProvider(tp trace.TracerProvider) Option {
return optConv{iOpt: internal.WithTracerProvider(tp)}
}

// Option applies options to a configuration.
type Option interface {
apply(*config)
// WithAttributes returns an Option that appends attr to the attributes set
// for every span created with this instrumentation library.
func WithAttributes(attr []attribute.KeyValue) Option {
return optConv{iOpt: internal.WithAttributes(attr)}
}

type optionFunc func(*config)
Expand All @@ -151,17 +91,6 @@ func (o optionFunc) apply(c *config) {
o(c)
}

// WithTracerProvider returns an Option that sets the TracerProvider used with
// this instrumentation library.
func WithTracerProvider(tp trace.TracerProvider) Option {
return optionFunc(func(c *config) {
c.tracer = tp.Tracer(
instrumentationName,
trace.WithInstrumentationVersion(splunkotel.Version()),
)
})
}

// WithContext returns an Option that sets the Context used with this
// instrumentation library by default. This is used to pass context of any
// existing trace to the instrumentation.
Expand All @@ -170,14 +99,3 @@ func WithContext(ctx context.Context) Option {
c.ctx = ctx
})
}

// WithAttributes returns an Option that appends attr to the attributes set
// for every span created with this instrumentation library.
func WithAttributes(attr []attribute.KeyValue) Option {
return optionFunc(func(c *config) {
c.defaultStartOpts = append(
c.defaultStartOpts,
trace.WithAttributes(attr...),
)
})
}

This file was deleted.

Loading

0 comments on commit f051a59

Please sign in to comment.