diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f25fd9008b4..7dead7084d3 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -228,11 +228,11 @@ all options to create a configured `config`. ```go // newConfig returns an appropriately configured config. -func newConfig([]Option) config { +func newConfig(options ...Option) config { // Set default values for config. config := config{/* […] */} for _, option := range options { - option.apply(&config) + config = option.apply(config) } // Preform any validation here. return config @@ -253,7 +253,7 @@ To set the value of the options a `config` contains, a corresponding ```go type Option interface { - apply(*config) + apply(config) config } ``` @@ -261,6 +261,9 @@ Having `apply` unexported makes sure that it will not be used externally. Moreover, the interface becomes sealed so the user cannot easily implement the interface on its own. +The `apply` method should return a modified version of the passed config. +This approach, instead of passing a pointer, is used to prevent the config from being allocated to the heap. + The name of the interface should be prefixed in the same way the corresponding `config` is (if at all). @@ -283,8 +286,9 @@ func With*(…) Option { … } ```go type defaultFalseOption bool -func (o defaultFalseOption) apply(c *config) { +func (o defaultFalseOption) apply(c config) config { c.Bool = bool(o) + return c } // WithOption sets a T to have an option included. @@ -296,8 +300,9 @@ func WithOption() Option { ```go type defaultTrueOption bool -func (o defaultTrueOption) apply(c *config) { +func (o defaultTrueOption) apply(c config) config { c.Bool = bool(o) + return c } // WithoutOption sets a T to have Bool option excluded. @@ -313,8 +318,9 @@ type myTypeOption struct { MyType MyType } -func (o myTypeOption) apply(c *config) { +func (o myTypeOption) apply(c config) config { c.MyType = o.MyType + return c } // WithMyType sets T to have include MyType. @@ -326,16 +332,17 @@ func WithMyType(t MyType) Option { ##### Functional Options ```go -type optionFunc func(*config) +type optionFunc func(config) config -func (fn optionFunc) apply(c *config) { - fn(c) +func (fn optionFunc) apply(c config) config { + return fn(c) } // WithMyType sets t as MyType. func WithMyType(t MyType) Option { - return optionFunc(func(c *config) { + return optionFunc(func(c config) config { c.MyType = t + return c }) } ``` @@ -370,12 +377,12 @@ type config struct { // DogOption apply Dog specific options. type DogOption interface { - applyDog(*config) + applyDog(config) config } // BirdOption apply Bird specific options. type BirdOption interface { - applyBird(*config) + applyBird(config) config } // Option apply options for all animals. @@ -385,17 +392,36 @@ type Option interface { } type weightOption float64 -func (o weightOption) applyDog(c *config) { c.Weight = float64(o) } -func (o weightOption) applyBird(c *config) { c.Weight = float64(o) } -func WithWeight(w float64) Option { return weightOption(w) } + +func (o weightOption) applyDog(c config) config { + c.Weight = float64(o) + return c +} + +func (o weightOption) applyBird(c config) config { + c.Weight = float64(o) + return c +} + +func WithWeight(w float64) Option { return weightOption(w) } type furColorOption string -func (o furColorOption) applyDog(c *config) { c.Color = string(o) } -func WithFurColor(c string) DogOption { return furColorOption(c) } + +func (o furColorOption) applyDog(c config) config { + c.Color = string(o) + return c +} + +func WithFurColor(c string) DogOption { return furColorOption(c) } type maxAltitudeOption float64 -func (o maxAltitudeOption) applyBird(c *config) { c.MaxAltitude = float64(o) } -func WithMaxAltitude(a float64) BirdOption { return maxAltitudeOption(a) } + +func (o maxAltitudeOption) applyBird(c config) config { + c.MaxAltitude = float64(o) + return c +} + +func WithMaxAltitude(a float64) BirdOption { return maxAltitudeOption(a) } func NewDog(name string, o ...DogOption) Dog {…} func NewBird(name string, o ...BirdOption) Bird {…} diff --git a/exporters/jaeger/uploader.go b/exporters/jaeger/uploader.go index 84a517985a7..d907f74b9f3 100644 --- a/exporters/jaeger/uploader.go +++ b/exporters/jaeger/uploader.go @@ -55,7 +55,7 @@ func (fn endpointOptionFunc) newBatchUploader() (batchUploader, error) { // will be used if neither are provided. func WithAgentEndpoint(options ...AgentEndpointOption) EndpointOption { return endpointOptionFunc(func() (batchUploader, error) { - cfg := &agentEndpointConfig{ + cfg := agentEndpointConfig{ agentClientUDPParams{ AttemptReconnecting: true, Host: envOr(envAgentHost, "localhost"), @@ -63,7 +63,7 @@ func WithAgentEndpoint(options ...AgentEndpointOption) EndpointOption { }, } for _, opt := range options { - opt.apply(cfg) + cfg = opt.apply(cfg) } client, err := newAgentClientUDP(cfg.agentClientUDPParams) @@ -76,17 +76,17 @@ func WithAgentEndpoint(options ...AgentEndpointOption) EndpointOption { } type AgentEndpointOption interface { - apply(*agentEndpointConfig) + apply(agentEndpointConfig) agentEndpointConfig } type agentEndpointConfig struct { agentClientUDPParams } -type agentEndpointOptionFunc func(*agentEndpointConfig) +type agentEndpointOptionFunc func(agentEndpointConfig) agentEndpointConfig -func (fn agentEndpointOptionFunc) apply(cfg *agentEndpointConfig) { - fn(cfg) +func (fn agentEndpointOptionFunc) apply(cfg agentEndpointConfig) agentEndpointConfig { + return fn(cfg) } // WithAgentHost sets a host to be used in the agent client endpoint. @@ -94,8 +94,9 @@ func (fn agentEndpointOptionFunc) apply(cfg *agentEndpointConfig) { // OTEL_EXPORTER_JAEGER_AGENT_HOST environment variable. // If this option is not passed and the env var is not set, "localhost" will be used by default. func WithAgentHost(host string) AgentEndpointOption { - return agentEndpointOptionFunc(func(o *agentEndpointConfig) { + return agentEndpointOptionFunc(func(o agentEndpointConfig) agentEndpointConfig { o.Host = host + return o }) } @@ -104,36 +105,41 @@ func WithAgentHost(host string) AgentEndpointOption { // OTEL_EXPORTER_JAEGER_AGENT_PORT environment variable. // If this option is not passed and the env var is not set, "6831" will be used by default. func WithAgentPort(port string) AgentEndpointOption { - return agentEndpointOptionFunc(func(o *agentEndpointConfig) { + return agentEndpointOptionFunc(func(o agentEndpointConfig) agentEndpointConfig { o.Port = port + return o }) } // WithLogger sets a logger to be used by agent client. func WithLogger(logger *log.Logger) AgentEndpointOption { - return agentEndpointOptionFunc(func(o *agentEndpointConfig) { + return agentEndpointOptionFunc(func(o agentEndpointConfig) agentEndpointConfig { o.Logger = logger + return o }) } // WithDisableAttemptReconnecting sets option to disable reconnecting udp client. func WithDisableAttemptReconnecting() AgentEndpointOption { - return agentEndpointOptionFunc(func(o *agentEndpointConfig) { + return agentEndpointOptionFunc(func(o agentEndpointConfig) agentEndpointConfig { o.AttemptReconnecting = false + return o }) } // WithAttemptReconnectingInterval sets the interval between attempts to re resolve agent endpoint. func WithAttemptReconnectingInterval(interval time.Duration) AgentEndpointOption { - return agentEndpointOptionFunc(func(o *agentEndpointConfig) { + return agentEndpointOptionFunc(func(o agentEndpointConfig) agentEndpointConfig { o.AttemptReconnectInterval = interval + return o }) } // WithMaxPacketSize sets the maximum UDP packet size for transport to the Jaeger agent. func WithMaxPacketSize(size int) AgentEndpointOption { - return agentEndpointOptionFunc(func(o *agentEndpointConfig) { + return agentEndpointOptionFunc(func(o agentEndpointConfig) agentEndpointConfig { o.MaxPacketSize = size + return o }) } @@ -149,7 +155,7 @@ func WithMaxPacketSize(size int) AgentEndpointOption { // If neither values are provided for the username or the password, they will not be set since there is no default. func WithCollectorEndpoint(options ...CollectorEndpointOption) EndpointOption { return endpointOptionFunc(func() (batchUploader, error) { - cfg := &collectorEndpointConfig{ + cfg := collectorEndpointConfig{ endpoint: envOr(envEndpoint, "http://localhost:14268/api/traces"), username: envOr(envUser, ""), password: envOr(envPassword, ""), @@ -157,7 +163,7 @@ func WithCollectorEndpoint(options ...CollectorEndpointOption) EndpointOption { } for _, opt := range options { - opt.apply(cfg) + cfg = opt.apply(cfg) } return &collectorUploader{ @@ -170,7 +176,7 @@ func WithCollectorEndpoint(options ...CollectorEndpointOption) EndpointOption { } type CollectorEndpointOption interface { - apply(*collectorEndpointConfig) + apply(collectorEndpointConfig) collectorEndpointConfig } type collectorEndpointConfig struct { @@ -187,10 +193,10 @@ type collectorEndpointConfig struct { httpClient *http.Client } -type collectorEndpointOptionFunc func(*collectorEndpointConfig) +type collectorEndpointOptionFunc func(collectorEndpointConfig) collectorEndpointConfig -func (fn collectorEndpointOptionFunc) apply(cfg *collectorEndpointConfig) { - fn(cfg) +func (fn collectorEndpointOptionFunc) apply(cfg collectorEndpointConfig) collectorEndpointConfig { + return fn(cfg) } // WithEndpoint is the URL for the Jaeger collector that spans are sent to. @@ -199,8 +205,9 @@ func (fn collectorEndpointOptionFunc) apply(cfg *collectorEndpointConfig) { // If this option is not passed and the environment variable is not set, // "http://localhost:14268/api/traces" will be used by default. func WithEndpoint(endpoint string) CollectorEndpointOption { - return collectorEndpointOptionFunc(func(o *collectorEndpointConfig) { + return collectorEndpointOptionFunc(func(o collectorEndpointConfig) collectorEndpointConfig { o.endpoint = endpoint + return o }) } @@ -209,8 +216,9 @@ func WithEndpoint(endpoint string) CollectorEndpointOption { // OTEL_EXPORTER_JAEGER_USER environment variable. // If this option is not passed and the environment variable is not set, no username will be set. func WithUsername(username string) CollectorEndpointOption { - return collectorEndpointOptionFunc(func(o *collectorEndpointConfig) { + return collectorEndpointOptionFunc(func(o collectorEndpointConfig) collectorEndpointConfig { o.username = username + return o }) } @@ -219,15 +227,17 @@ func WithUsername(username string) CollectorEndpointOption { // OTEL_EXPORTER_JAEGER_PASSWORD environment variable. // If this option is not passed and the environment variable is not set, no password will be set. func WithPassword(password string) CollectorEndpointOption { - return collectorEndpointOptionFunc(func(o *collectorEndpointConfig) { + return collectorEndpointOptionFunc(func(o collectorEndpointConfig) collectorEndpointConfig { o.password = password + return o }) } // WithHTTPClient sets the http client to be used to make request to the collector endpoint. func WithHTTPClient(client *http.Client) CollectorEndpointOption { - return collectorEndpointOptionFunc(func(o *collectorEndpointConfig) { + return collectorEndpointOptionFunc(func(o collectorEndpointConfig) collectorEndpointConfig { o.httpClient = client + return o }) } diff --git a/exporters/otlp/otlpmetric/exporter.go b/exporters/otlp/otlpmetric/exporter.go index 2cd90ac435a..36c41cce762 100644 --- a/exporters/otlp/otlpmetric/exporter.go +++ b/exporters/otlp/otlpmetric/exporter.go @@ -120,7 +120,7 @@ func NewUnstarted(client Client, opts ...Option) *Exporter { } for _, opt := range opts { - opt.apply(&cfg) + cfg = opt.apply(cfg) } e := &Exporter{ diff --git a/exporters/otlp/otlpmetric/internal/otlpconfig/envconfig.go b/exporters/otlp/otlpmetric/internal/otlpconfig/envconfig.go index a62b548496f..ecf2ecaf9c2 100644 --- a/exporters/otlp/otlpmetric/internal/otlpconfig/envconfig.go +++ b/exporters/otlp/otlpmetric/internal/otlpconfig/envconfig.go @@ -33,12 +33,12 @@ var DefaultEnvOptionsReader = EnvOptionsReader{ ReadFile: ioutil.ReadFile, } -func ApplyGRPCEnvConfigs(cfg *Config) { - DefaultEnvOptionsReader.ApplyGRPCEnvConfigs(cfg) +func ApplyGRPCEnvConfigs(cfg Config) Config { + return DefaultEnvOptionsReader.ApplyGRPCEnvConfigs(cfg) } -func ApplyHTTPEnvConfigs(cfg *Config) { - DefaultEnvOptionsReader.ApplyHTTPEnvConfigs(cfg) +func ApplyHTTPEnvConfigs(cfg Config) Config { + return DefaultEnvOptionsReader.ApplyHTTPEnvConfigs(cfg) } type EnvOptionsReader struct { @@ -46,18 +46,20 @@ type EnvOptionsReader struct { ReadFile func(filename string) ([]byte, error) } -func (e *EnvOptionsReader) ApplyHTTPEnvConfigs(cfg *Config) { +func (e *EnvOptionsReader) ApplyHTTPEnvConfigs(cfg Config) Config { opts := e.GetOptionsFromEnv() for _, opt := range opts { - opt.ApplyHTTPOption(cfg) + cfg = opt.ApplyHTTPOption(cfg) } + return cfg } -func (e *EnvOptionsReader) ApplyGRPCEnvConfigs(cfg *Config) { +func (e *EnvOptionsReader) ApplyGRPCEnvConfigs(cfg Config) Config { opts := e.GetOptionsFromEnv() for _, opt := range opts { - opt.ApplyGRPCOption(cfg) + cfg = opt.ApplyGRPCOption(cfg) } + return cfg } func (e *EnvOptionsReader) GetOptionsFromEnv() []GenericOption { @@ -74,7 +76,7 @@ func (e *EnvOptionsReader) GetOptionsFromEnv() []GenericOption { } else { opts = append(opts, WithSecure()) } - opts = append(opts, newSplitOption(func(cfg *Config) { + opts = append(opts, newSplitOption(func(cfg Config) Config { cfg.Metrics.Endpoint = u.Host // For endpoint URLs for OTLP/HTTP per-signal variables, the // URL MUST be used as-is without any modification. The only @@ -85,10 +87,12 @@ func (e *EnvOptionsReader) GetOptionsFromEnv() []GenericOption { path = "/" } cfg.Metrics.URLPath = path - }, func(cfg *Config) { + return cfg + }, func(cfg Config) Config { // For OTLP/gRPC endpoints, this is the target to which the // exporter is going to send telemetry. cfg.Metrics.Endpoint = path.Join(u.Host, u.Path) + return cfg })) } } else if v, ok = e.getEnvValue("ENDPOINT"); ok { @@ -101,16 +105,18 @@ func (e *EnvOptionsReader) GetOptionsFromEnv() []GenericOption { } else { opts = append(opts, WithSecure()) } - opts = append(opts, newSplitOption(func(cfg *Config) { + opts = append(opts, newSplitOption(func(cfg Config) Config { cfg.Metrics.Endpoint = u.Host // For OTLP/HTTP endpoint URLs without a per-signal // configuration, the passed endpoint is used as a base URL // and the signals are sent to these paths relative to that. cfg.Metrics.URLPath = path.Join(u.Path, DefaultMetricsPath) - }, func(cfg *Config) { + return cfg + }, func(cfg Config) Config { // For OTLP/gRPC endpoints, this is the target to which the // exporter is going to send telemetry. cfg.Metrics.Endpoint = path.Join(u.Host, u.Path) + return cfg })) } } diff --git a/exporters/otlp/otlpmetric/internal/otlpconfig/options.go b/exporters/otlp/otlpmetric/internal/otlpconfig/options.go index 8cfbc7dfcf8..fed8a82f1c7 100644 --- a/exporters/otlp/otlpmetric/internal/otlpconfig/options.go +++ b/exporters/otlp/otlpmetric/internal/otlpconfig/options.go @@ -90,9 +90,9 @@ func NewDefaultConfig() Config { // any unset setting using the default gRPC config values. func NewGRPCConfig(opts ...GRPCOption) Config { cfg := NewDefaultConfig() - ApplyGRPCEnvConfigs(&cfg) + cfg = ApplyGRPCEnvConfigs(cfg) for _, opt := range opts { - opt.ApplyGRPCOption(&cfg) + cfg = opt.ApplyGRPCOption(cfg) } if cfg.ServiceConfig != "" { @@ -129,8 +129,8 @@ func NewGRPCConfig(opts ...GRPCOption) Config { type ( // GenericOption applies an option to the HTTP or gRPC driver. GenericOption interface { - ApplyHTTPOption(*Config) - ApplyGRPCOption(*Config) + ApplyHTTPOption(Config) Config + ApplyGRPCOption(Config) Config // A private method to prevent users implementing the // interface and so future additions to it will not @@ -140,7 +140,7 @@ type ( // HTTPOption applies an option to the HTTP driver. HTTPOption interface { - ApplyHTTPOption(*Config) + ApplyHTTPOption(Config) Config // A private method to prevent users implementing the // interface and so future additions to it will not @@ -150,7 +150,7 @@ type ( // GRPCOption applies an option to the gRPC driver. GRPCOption interface { - ApplyGRPCOption(*Config) + ApplyGRPCOption(Config) Config // A private method to prevent users implementing the // interface and so future additions to it will not @@ -162,128 +162,138 @@ type ( // genericOption is an option that applies the same logic // for both gRPC and HTTP. type genericOption struct { - fn func(*Config) + fn func(Config) Config } -func (g *genericOption) ApplyGRPCOption(cfg *Config) { - g.fn(cfg) +func (g *genericOption) ApplyGRPCOption(cfg Config) Config { + return g.fn(cfg) } -func (g *genericOption) ApplyHTTPOption(cfg *Config) { - g.fn(cfg) +func (g *genericOption) ApplyHTTPOption(cfg Config) Config { + return g.fn(cfg) } func (genericOption) private() {} -func newGenericOption(fn func(cfg *Config)) GenericOption { +func newGenericOption(fn func(cfg Config) Config) GenericOption { return &genericOption{fn: fn} } // splitOption is an option that applies different logics // for gRPC and HTTP. type splitOption struct { - httpFn func(*Config) - grpcFn func(*Config) + httpFn func(Config) Config + grpcFn func(Config) Config } -func (g *splitOption) ApplyGRPCOption(cfg *Config) { - g.grpcFn(cfg) +func (g *splitOption) ApplyGRPCOption(cfg Config) Config { + return g.grpcFn(cfg) } -func (g *splitOption) ApplyHTTPOption(cfg *Config) { - g.httpFn(cfg) +func (g *splitOption) ApplyHTTPOption(cfg Config) Config { + return g.httpFn(cfg) } func (splitOption) private() {} -func newSplitOption(httpFn func(cfg *Config), grpcFn func(cfg *Config)) GenericOption { +func newSplitOption(httpFn func(cfg Config) Config, grpcFn func(cfg Config) Config) GenericOption { return &splitOption{httpFn: httpFn, grpcFn: grpcFn} } // httpOption is an option that is only applied to the HTTP driver. type httpOption struct { - fn func(*Config) + fn func(Config) Config } -func (h *httpOption) ApplyHTTPOption(cfg *Config) { - h.fn(cfg) +func (h *httpOption) ApplyHTTPOption(cfg Config) Config { + return h.fn(cfg) } func (httpOption) private() {} -func NewHTTPOption(fn func(cfg *Config)) HTTPOption { +func NewHTTPOption(fn func(cfg Config) Config) HTTPOption { return &httpOption{fn: fn} } // grpcOption is an option that is only applied to the gRPC driver. type grpcOption struct { - fn func(*Config) + fn func(Config) Config } -func (h *grpcOption) ApplyGRPCOption(cfg *Config) { - h.fn(cfg) +func (h *grpcOption) ApplyGRPCOption(cfg Config) Config { + return h.fn(cfg) } func (grpcOption) private() {} -func NewGRPCOption(fn func(cfg *Config)) GRPCOption { +func NewGRPCOption(fn func(cfg Config) Config) GRPCOption { return &grpcOption{fn: fn} } // Generic Options func WithEndpoint(endpoint string) GenericOption { - return newGenericOption(func(cfg *Config) { + return newGenericOption(func(cfg Config) Config { cfg.Metrics.Endpoint = endpoint + return cfg }) } func WithCompression(compression Compression) GenericOption { - return newGenericOption(func(cfg *Config) { + return newGenericOption(func(cfg Config) Config { cfg.Metrics.Compression = compression + return cfg }) } func WithURLPath(urlPath string) GenericOption { - return newGenericOption(func(cfg *Config) { + return newGenericOption(func(cfg Config) Config { cfg.Metrics.URLPath = urlPath + return cfg }) } func WithRetry(rc retry.Config) GenericOption { - return newGenericOption(func(cfg *Config) { + return newGenericOption(func(cfg Config) Config { cfg.RetryConfig = rc + return cfg }) } func WithTLSClientConfig(tlsCfg *tls.Config) GenericOption { - return newSplitOption(func(cfg *Config) { + return newSplitOption(func(cfg Config) Config { cfg.Metrics.TLSCfg = tlsCfg.Clone() - }, func(cfg *Config) { + return cfg + }, func(cfg Config) Config { cfg.Metrics.GRPCCredentials = credentials.NewTLS(tlsCfg) + return cfg }) } func WithInsecure() GenericOption { - return newGenericOption(func(cfg *Config) { + return newGenericOption(func(cfg Config) Config { cfg.Metrics.Insecure = true + return cfg }) } func WithSecure() GenericOption { - return newGenericOption(func(cfg *Config) { + return newGenericOption(func(cfg Config) Config { cfg.Metrics.Insecure = false + return cfg }) } func WithHeaders(headers map[string]string) GenericOption { - return newGenericOption(func(cfg *Config) { + return newGenericOption(func(cfg Config) Config { cfg.Metrics.Headers = headers + return cfg }) } func WithTimeout(duration time.Duration) GenericOption { - return newGenericOption(func(cfg *Config) { + return newGenericOption(func(cfg Config) Config { cfg.Metrics.Timeout = duration + return cfg }) } diff --git a/exporters/otlp/otlpmetric/internal/otlpconfig/options_test.go b/exporters/otlp/otlpmetric/internal/otlpconfig/options_test.go index ee267e4fd00..d82802603e3 100644 --- a/exporters/otlp/otlpmetric/internal/otlpconfig/options_test.go +++ b/exporters/otlp/otlpmetric/internal/otlpconfig/options_test.go @@ -387,9 +387,9 @@ func TestConfigs(t *testing.T) { // Tests Generic options as HTTP Options cfg := otlpconfig.NewDefaultConfig() - otlpconfig.ApplyHTTPEnvConfigs(&cfg) + cfg = otlpconfig.ApplyHTTPEnvConfigs(cfg) for _, opt := range tt.opts { - opt.ApplyHTTPOption(&cfg) + cfg = opt.ApplyHTTPOption(cfg) } tt.asserts(t, &cfg, false) diff --git a/exporters/otlp/otlpmetric/options.go b/exporters/otlp/otlpmetric/options.go index ce8a5f58c5a..bd8706a74d3 100644 --- a/exporters/otlp/otlpmetric/options.go +++ b/exporters/otlp/otlpmetric/options.go @@ -18,13 +18,13 @@ import "go.opentelemetry.io/otel/sdk/metric/export/aggregation" // Option are setting options passed to an Exporter on creation. type Option interface { - apply(*config) + apply(config) config } -type exporterOptionFunc func(*config) +type exporterOptionFunc func(config) config -func (fn exporterOptionFunc) apply(cfg *config) { - fn(cfg) +func (fn exporterOptionFunc) apply(cfg config) config { + return fn(cfg) } type config struct { @@ -36,7 +36,8 @@ type config struct { // aggregation). If not specified otherwise, exporter will use a // cumulative temporality selector. func WithMetricAggregationTemporalitySelector(selector aggregation.TemporalitySelector) Option { - return exporterOptionFunc(func(cfg *config) { + return exporterOptionFunc(func(cfg config) config { cfg.temporalitySelector = selector + return cfg }) } diff --git a/exporters/otlp/otlpmetric/otlpmetricgrpc/options.go b/exporters/otlp/otlpmetric/otlpmetricgrpc/options.go index e6d3919eab1..27769ff6b7c 100644 --- a/exporters/otlp/otlpmetric/otlpmetricgrpc/options.go +++ b/exporters/otlp/otlpmetric/otlpmetricgrpc/options.go @@ -28,7 +28,7 @@ import ( // Option applies an option to the gRPC driver. type Option interface { - applyGRPCOption(*otlpconfig.Config) + applyGRPCOption(otlpconfig.Config) otlpconfig.Config } func asGRPCOptions(opts []Option) []otlpconfig.GRPCOption { @@ -50,8 +50,8 @@ type wrappedOption struct { otlpconfig.GRPCOption } -func (w wrappedOption) applyGRPCOption(cfg *otlpconfig.Config) { - w.ApplyGRPCOption(cfg) +func (w wrappedOption) applyGRPCOption(cfg otlpconfig.Config) otlpconfig.Config { + return w.ApplyGRPCOption(cfg) } // WithInsecure disables client transport security for the exporter's gRPC @@ -77,8 +77,9 @@ func WithEndpoint(endpoint string) Option { // // This option has no effect if WithGRPCConn is used. func WithReconnectionPeriod(rp time.Duration) Option { - return wrappedOption{otlpconfig.NewGRPCOption(func(cfg *otlpconfig.Config) { + return wrappedOption{otlpconfig.NewGRPCOption(func(cfg otlpconfig.Config) otlpconfig.Config { cfg.ReconnectionPeriod = rp + return cfg })} } @@ -117,8 +118,9 @@ func WithHeaders(headers map[string]string) Option { // // This option has no effect if WithGRPCConn is used. func WithTLSCredentials(creds credentials.TransportCredentials) Option { - return wrappedOption{otlpconfig.NewGRPCOption(func(cfg *otlpconfig.Config) { + return wrappedOption{otlpconfig.NewGRPCOption(func(cfg otlpconfig.Config) otlpconfig.Config { cfg.Metrics.GRPCCredentials = creds + return cfg })} } @@ -126,8 +128,9 @@ func WithTLSCredentials(creds credentials.TransportCredentials) Option { // // This option has no effect if WithGRPCConn is used. func WithServiceConfig(serviceConfig string) Option { - return wrappedOption{otlpconfig.NewGRPCOption(func(cfg *otlpconfig.Config) { + return wrappedOption{otlpconfig.NewGRPCOption(func(cfg otlpconfig.Config) otlpconfig.Config { cfg.ServiceConfig = serviceConfig + return cfg })} } @@ -138,8 +141,9 @@ func WithServiceConfig(serviceConfig string) Option { // // This option has no effect if WithGRPCConn is used. func WithDialOption(opts ...grpc.DialOption) Option { - return wrappedOption{otlpconfig.NewGRPCOption(func(cfg *otlpconfig.Config) { + return wrappedOption{otlpconfig.NewGRPCOption(func(cfg otlpconfig.Config) otlpconfig.Config { cfg.DialOptions = opts + return cfg })} } @@ -152,8 +156,9 @@ func WithDialOption(opts ...grpc.DialOption) Option { // It is the callers responsibility to close the passed conn. The client // Shutdown method will not close this connection. func WithGRPCConn(conn *grpc.ClientConn) Option { - return wrappedOption{otlpconfig.NewGRPCOption(func(cfg *otlpconfig.Config) { + return wrappedOption{otlpconfig.NewGRPCOption(func(cfg otlpconfig.Config) otlpconfig.Config { cfg.GRPCConn = conn + return cfg })} } diff --git a/exporters/otlp/otlpmetric/otlpmetrichttp/client.go b/exporters/otlp/otlpmetric/otlpmetrichttp/client.go index b472611fb40..aa381f8e038 100644 --- a/exporters/otlp/otlpmetric/otlpmetrichttp/client.go +++ b/exporters/otlp/otlpmetric/otlpmetrichttp/client.go @@ -78,9 +78,9 @@ type client struct { // NewClient creates a new HTTP metric client. func NewClient(opts ...Option) otlpmetric.Client { cfg := otlpconfig.NewDefaultConfig() - otlpconfig.ApplyHTTPEnvConfigs(&cfg) + cfg = otlpconfig.ApplyHTTPEnvConfigs(cfg) for _, opt := range opts { - opt.applyHTTPOption(&cfg) + cfg = opt.applyHTTPOption(cfg) } for pathPtr, defaultPath := range map[*string]string{ diff --git a/exporters/otlp/otlpmetric/otlpmetrichttp/options.go b/exporters/otlp/otlpmetric/otlpmetrichttp/options.go index 61dbccc3078..bec26204c74 100644 --- a/exporters/otlp/otlpmetric/otlpmetrichttp/options.go +++ b/exporters/otlp/otlpmetric/otlpmetrichttp/options.go @@ -37,7 +37,7 @@ const ( // Option applies an option to the HTTP client. type Option interface { - applyHTTPOption(*otlpconfig.Config) + applyHTTPOption(otlpconfig.Config) otlpconfig.Config } // RetryConfig defines configuration for retrying batches in case of export @@ -48,8 +48,8 @@ type wrappedOption struct { otlpconfig.HTTPOption } -func (w wrappedOption) applyHTTPOption(cfg *otlpconfig.Config) { - w.ApplyHTTPOption(cfg) +func (w wrappedOption) applyHTTPOption(cfg otlpconfig.Config) otlpconfig.Config { + return w.ApplyHTTPOption(cfg) } // WithEndpoint allows one to set the address of the collector @@ -83,7 +83,7 @@ func WithMaxAttempts(maxAttempts int) Option { maxAttempts = 5 } return wrappedOption{ - otlpconfig.NewHTTPOption(func(cfg *otlpconfig.Config) { + otlpconfig.NewHTTPOption(func(cfg otlpconfig.Config) otlpconfig.Config { cfg.RetryConfig.Enabled = true var ( @@ -104,7 +104,7 @@ func WithMaxAttempts(maxAttempts int) Option { attempts := int64(maxE+init) / int64(maxI) if int64(maxAttempts) == attempts { - return + return cfg } maxE = time.Duration(int64(maxAttempts)*int64(maxI)) - init @@ -112,6 +112,8 @@ func WithMaxAttempts(maxAttempts int) Option { cfg.RetryConfig.InitialInterval = init cfg.RetryConfig.MaxInterval = maxI cfg.RetryConfig.MaxElapsedTime = maxE + + return cfg }), } } @@ -126,7 +128,7 @@ func WithBackoff(duration time.Duration) Option { duration = 300 * time.Millisecond } return wrappedOption{ - otlpconfig.NewHTTPOption(func(cfg *otlpconfig.Config) { + otlpconfig.NewHTTPOption(func(cfg otlpconfig.Config) otlpconfig.Config { cfg.RetryConfig.Enabled = true cfg.RetryConfig.MaxInterval = duration if cfg.RetryConfig.InitialInterval == 0 { @@ -135,6 +137,7 @@ func WithBackoff(duration time.Duration) Option { if cfg.RetryConfig.MaxElapsedTime == 0 { cfg.RetryConfig.MaxElapsedTime = retry.DefaultConfig.MaxElapsedTime } + return cfg }), } } diff --git a/exporters/otlp/otlptrace/internal/otlpconfig/envconfig.go b/exporters/otlp/otlptrace/internal/otlpconfig/envconfig.go index 2d1937beda2..77f13a1937b 100644 --- a/exporters/otlp/otlptrace/internal/otlpconfig/envconfig.go +++ b/exporters/otlp/otlptrace/internal/otlpconfig/envconfig.go @@ -33,12 +33,12 @@ var DefaultEnvOptionsReader = EnvOptionsReader{ ReadFile: ioutil.ReadFile, } -func ApplyGRPCEnvConfigs(cfg *Config) { - DefaultEnvOptionsReader.ApplyGRPCEnvConfigs(cfg) +func ApplyGRPCEnvConfigs(cfg Config) Config { + return DefaultEnvOptionsReader.ApplyGRPCEnvConfigs(cfg) } -func ApplyHTTPEnvConfigs(cfg *Config) { - DefaultEnvOptionsReader.ApplyHTTPEnvConfigs(cfg) +func ApplyHTTPEnvConfigs(cfg Config) Config { + return DefaultEnvOptionsReader.ApplyHTTPEnvConfigs(cfg) } type EnvOptionsReader struct { @@ -46,18 +46,20 @@ type EnvOptionsReader struct { ReadFile func(filename string) ([]byte, error) } -func (e *EnvOptionsReader) ApplyHTTPEnvConfigs(cfg *Config) { +func (e *EnvOptionsReader) ApplyHTTPEnvConfigs(cfg Config) Config { opts := e.GetOptionsFromEnv() for _, opt := range opts { - opt.ApplyHTTPOption(cfg) + cfg = opt.ApplyHTTPOption(cfg) } + return cfg } -func (e *EnvOptionsReader) ApplyGRPCEnvConfigs(cfg *Config) { +func (e *EnvOptionsReader) ApplyGRPCEnvConfigs(cfg Config) Config { opts := e.GetOptionsFromEnv() for _, opt := range opts { - opt.ApplyGRPCOption(cfg) + cfg = opt.ApplyGRPCOption(cfg) } + return cfg } func (e *EnvOptionsReader) GetOptionsFromEnv() []GenericOption { @@ -74,7 +76,7 @@ func (e *EnvOptionsReader) GetOptionsFromEnv() []GenericOption { } else { opts = append(opts, WithSecure()) } - opts = append(opts, newSplitOption(func(cfg *Config) { + opts = append(opts, newSplitOption(func(cfg Config) Config { cfg.Traces.Endpoint = u.Host // For endpoint URLs for OTLP/HTTP per-signal variables, the // URL MUST be used as-is without any modification. The only @@ -85,10 +87,12 @@ func (e *EnvOptionsReader) GetOptionsFromEnv() []GenericOption { path = "/" } cfg.Traces.URLPath = path - }, func(cfg *Config) { + return cfg + }, func(cfg Config) Config { // For OTLP/gRPC endpoints, this is the target to which the // exporter is going to send telemetry. cfg.Traces.Endpoint = path.Join(u.Host, u.Path) + return cfg })) } } else if v, ok = e.getEnvValue("ENDPOINT"); ok { @@ -101,16 +105,18 @@ func (e *EnvOptionsReader) GetOptionsFromEnv() []GenericOption { } else { opts = append(opts, WithSecure()) } - opts = append(opts, newSplitOption(func(cfg *Config) { + opts = append(opts, newSplitOption(func(cfg Config) Config { cfg.Traces.Endpoint = u.Host // For OTLP/HTTP endpoint URLs without a per-signal // configuration, the passed endpoint is used as a base URL // and the signals are sent to these paths relative to that. cfg.Traces.URLPath = path.Join(u.Path, DefaultTracesPath) - }, func(cfg *Config) { + return cfg + }, func(cfg Config) Config { // For OTLP/gRPC endpoints, this is the target to which the // exporter is going to send telemetry. cfg.Traces.Endpoint = path.Join(u.Host, u.Path) + return cfg })) } } diff --git a/exporters/otlp/otlptrace/internal/otlpconfig/options.go b/exporters/otlp/otlptrace/internal/otlpconfig/options.go index 2af734a9de8..e6fb14e00e8 100644 --- a/exporters/otlp/otlptrace/internal/otlpconfig/options.go +++ b/exporters/otlp/otlptrace/internal/otlpconfig/options.go @@ -83,9 +83,9 @@ func NewDefaultConfig() Config { // any unset setting using the default gRPC config values. func NewGRPCConfig(opts ...GRPCOption) Config { cfg := NewDefaultConfig() - ApplyGRPCEnvConfigs(&cfg) + cfg = ApplyGRPCEnvConfigs(cfg) for _, opt := range opts { - opt.ApplyGRPCOption(&cfg) + cfg = opt.ApplyGRPCOption(cfg) } if cfg.ServiceConfig != "" { @@ -122,8 +122,8 @@ func NewGRPCConfig(opts ...GRPCOption) Config { type ( // GenericOption applies an option to the HTTP or gRPC driver. GenericOption interface { - ApplyHTTPOption(*Config) - ApplyGRPCOption(*Config) + ApplyHTTPOption(Config) Config + ApplyGRPCOption(Config) Config // A private method to prevent users implementing the // interface and so future additions to it will not @@ -133,7 +133,7 @@ type ( // HTTPOption applies an option to the HTTP driver. HTTPOption interface { - ApplyHTTPOption(*Config) + ApplyHTTPOption(Config) Config // A private method to prevent users implementing the // interface and so future additions to it will not @@ -143,7 +143,7 @@ type ( // GRPCOption applies an option to the gRPC driver. GRPCOption interface { - ApplyGRPCOption(*Config) + ApplyGRPCOption(Config) Config // A private method to prevent users implementing the // interface and so future additions to it will not @@ -155,128 +155,138 @@ type ( // genericOption is an option that applies the same logic // for both gRPC and HTTP. type genericOption struct { - fn func(*Config) + fn func(Config) Config } -func (g *genericOption) ApplyGRPCOption(cfg *Config) { - g.fn(cfg) +func (g *genericOption) ApplyGRPCOption(cfg Config) Config { + return g.fn(cfg) } -func (g *genericOption) ApplyHTTPOption(cfg *Config) { - g.fn(cfg) +func (g *genericOption) ApplyHTTPOption(cfg Config) Config { + return g.fn(cfg) } func (genericOption) private() {} -func newGenericOption(fn func(cfg *Config)) GenericOption { +func newGenericOption(fn func(cfg Config) Config) GenericOption { return &genericOption{fn: fn} } // splitOption is an option that applies different logics // for gRPC and HTTP. type splitOption struct { - httpFn func(*Config) - grpcFn func(*Config) + httpFn func(Config) Config + grpcFn func(Config) Config } -func (g *splitOption) ApplyGRPCOption(cfg *Config) { - g.grpcFn(cfg) +func (g *splitOption) ApplyGRPCOption(cfg Config) Config { + return g.grpcFn(cfg) } -func (g *splitOption) ApplyHTTPOption(cfg *Config) { - g.httpFn(cfg) +func (g *splitOption) ApplyHTTPOption(cfg Config) Config { + return g.httpFn(cfg) } func (splitOption) private() {} -func newSplitOption(httpFn func(cfg *Config), grpcFn func(cfg *Config)) GenericOption { +func newSplitOption(httpFn func(cfg Config) Config, grpcFn func(cfg Config) Config) GenericOption { return &splitOption{httpFn: httpFn, grpcFn: grpcFn} } // httpOption is an option that is only applied to the HTTP driver. type httpOption struct { - fn func(*Config) + fn func(Config) Config } -func (h *httpOption) ApplyHTTPOption(cfg *Config) { - h.fn(cfg) +func (h *httpOption) ApplyHTTPOption(cfg Config) Config { + return h.fn(cfg) } func (httpOption) private() {} -func NewHTTPOption(fn func(cfg *Config)) HTTPOption { +func NewHTTPOption(fn func(cfg Config) Config) HTTPOption { return &httpOption{fn: fn} } // grpcOption is an option that is only applied to the gRPC driver. type grpcOption struct { - fn func(*Config) + fn func(Config) Config } -func (h *grpcOption) ApplyGRPCOption(cfg *Config) { - h.fn(cfg) +func (h *grpcOption) ApplyGRPCOption(cfg Config) Config { + return h.fn(cfg) } func (grpcOption) private() {} -func NewGRPCOption(fn func(cfg *Config)) GRPCOption { +func NewGRPCOption(fn func(cfg Config) Config) GRPCOption { return &grpcOption{fn: fn} } // Generic Options func WithEndpoint(endpoint string) GenericOption { - return newGenericOption(func(cfg *Config) { + return newGenericOption(func(cfg Config) Config { cfg.Traces.Endpoint = endpoint + return cfg }) } func WithCompression(compression Compression) GenericOption { - return newGenericOption(func(cfg *Config) { + return newGenericOption(func(cfg Config) Config { cfg.Traces.Compression = compression + return cfg }) } func WithURLPath(urlPath string) GenericOption { - return newGenericOption(func(cfg *Config) { + return newGenericOption(func(cfg Config) Config { cfg.Traces.URLPath = urlPath + return cfg }) } func WithRetry(rc retry.Config) GenericOption { - return newGenericOption(func(cfg *Config) { + return newGenericOption(func(cfg Config) Config { cfg.RetryConfig = rc + return cfg }) } func WithTLSClientConfig(tlsCfg *tls.Config) GenericOption { - return newSplitOption(func(cfg *Config) { + return newSplitOption(func(cfg Config) Config { cfg.Traces.TLSCfg = tlsCfg.Clone() - }, func(cfg *Config) { + return cfg + }, func(cfg Config) Config { cfg.Traces.GRPCCredentials = credentials.NewTLS(tlsCfg) + return cfg }) } func WithInsecure() GenericOption { - return newGenericOption(func(cfg *Config) { + return newGenericOption(func(cfg Config) Config { cfg.Traces.Insecure = true + return cfg }) } func WithSecure() GenericOption { - return newGenericOption(func(cfg *Config) { + return newGenericOption(func(cfg Config) Config { cfg.Traces.Insecure = false + return cfg }) } func WithHeaders(headers map[string]string) GenericOption { - return newGenericOption(func(cfg *Config) { + return newGenericOption(func(cfg Config) Config { cfg.Traces.Headers = headers + return cfg }) } func WithTimeout(duration time.Duration) GenericOption { - return newGenericOption(func(cfg *Config) { + return newGenericOption(func(cfg Config) Config { cfg.Traces.Timeout = duration + return cfg }) } diff --git a/exporters/otlp/otlptrace/internal/otlpconfig/options_test.go b/exporters/otlp/otlptrace/internal/otlpconfig/options_test.go index 20decbc37bc..b12e0bd9a5c 100644 --- a/exporters/otlp/otlptrace/internal/otlpconfig/options_test.go +++ b/exporters/otlp/otlptrace/internal/otlpconfig/options_test.go @@ -385,9 +385,9 @@ func TestConfigs(t *testing.T) { // Tests Generic options as HTTP Options cfg := otlpconfig.NewDefaultConfig() - otlpconfig.ApplyHTTPEnvConfigs(&cfg) + cfg = otlpconfig.ApplyHTTPEnvConfigs(cfg) for _, opt := range tt.opts { - opt.ApplyHTTPOption(&cfg) + cfg = opt.ApplyHTTPOption(cfg) } tt.asserts(t, &cfg, false) diff --git a/exporters/otlp/otlptrace/otlptracegrpc/options.go b/exporters/otlp/otlptrace/otlptracegrpc/options.go index 0b27a35a8e1..e2e5bd696f6 100644 --- a/exporters/otlp/otlptrace/otlptracegrpc/options.go +++ b/exporters/otlp/otlptrace/otlptracegrpc/options.go @@ -28,7 +28,7 @@ import ( // Option applies an option to the gRPC driver. type Option interface { - applyGRPCOption(*otlpconfig.Config) + applyGRPCOption(otlpconfig.Config) otlpconfig.Config } func asGRPCOptions(opts []Option) []otlpconfig.GRPCOption { @@ -50,8 +50,8 @@ type wrappedOption struct { otlpconfig.GRPCOption } -func (w wrappedOption) applyGRPCOption(cfg *otlpconfig.Config) { - w.ApplyGRPCOption(cfg) +func (w wrappedOption) applyGRPCOption(cfg otlpconfig.Config) otlpconfig.Config { + return w.ApplyGRPCOption(cfg) } // WithInsecure disables client transport security for the exporter's gRPC @@ -77,8 +77,9 @@ func WithEndpoint(endpoint string) Option { // // This option has no effect if WithGRPCConn is used. func WithReconnectionPeriod(rp time.Duration) Option { - return wrappedOption{otlpconfig.NewGRPCOption(func(cfg *otlpconfig.Config) { + return wrappedOption{otlpconfig.NewGRPCOption(func(cfg otlpconfig.Config) otlpconfig.Config { cfg.ReconnectionPeriod = rp + return cfg })} } @@ -117,8 +118,9 @@ func WithHeaders(headers map[string]string) Option { // // This option has no effect if WithGRPCConn is used. func WithTLSCredentials(creds credentials.TransportCredentials) Option { - return wrappedOption{otlpconfig.NewGRPCOption(func(cfg *otlpconfig.Config) { + return wrappedOption{otlpconfig.NewGRPCOption(func(cfg otlpconfig.Config) otlpconfig.Config { cfg.Traces.GRPCCredentials = creds + return cfg })} } @@ -126,8 +128,9 @@ func WithTLSCredentials(creds credentials.TransportCredentials) Option { // // This option has no effect if WithGRPCConn is used. func WithServiceConfig(serviceConfig string) Option { - return wrappedOption{otlpconfig.NewGRPCOption(func(cfg *otlpconfig.Config) { + return wrappedOption{otlpconfig.NewGRPCOption(func(cfg otlpconfig.Config) otlpconfig.Config { cfg.ServiceConfig = serviceConfig + return cfg })} } @@ -138,8 +141,9 @@ func WithServiceConfig(serviceConfig string) Option { // // This option has no effect if WithGRPCConn is used. func WithDialOption(opts ...grpc.DialOption) Option { - return wrappedOption{otlpconfig.NewGRPCOption(func(cfg *otlpconfig.Config) { + return wrappedOption{otlpconfig.NewGRPCOption(func(cfg otlpconfig.Config) otlpconfig.Config { cfg.DialOptions = opts + return cfg })} } @@ -152,8 +156,9 @@ func WithDialOption(opts ...grpc.DialOption) Option { // It is the callers responsibility to close the passed conn. The client // Shutdown method will not close this connection. func WithGRPCConn(conn *grpc.ClientConn) Option { - return wrappedOption{otlpconfig.NewGRPCOption(func(cfg *otlpconfig.Config) { + return wrappedOption{otlpconfig.NewGRPCOption(func(cfg otlpconfig.Config) otlpconfig.Config { cfg.GRPCConn = conn + return cfg })} } diff --git a/exporters/otlp/otlptrace/otlptracehttp/client.go b/exporters/otlp/otlptrace/otlptracehttp/client.go index dbc6c5ba785..81487f9b6f9 100644 --- a/exporters/otlp/otlptrace/otlptracehttp/client.go +++ b/exporters/otlp/otlptrace/otlptracehttp/client.go @@ -80,9 +80,9 @@ var _ otlptrace.Client = (*client)(nil) // NewClient creates a new HTTP trace client. func NewClient(opts ...Option) otlptrace.Client { cfg := otlpconfig.NewDefaultConfig() - otlpconfig.ApplyHTTPEnvConfigs(&cfg) + cfg = otlpconfig.ApplyHTTPEnvConfigs(cfg) for _, opt := range opts { - opt.applyHTTPOption(&cfg) + cfg = opt.applyHTTPOption(cfg) } for pathPtr, defaultPath := range map[*string]string{ diff --git a/exporters/otlp/otlptrace/otlptracehttp/options.go b/exporters/otlp/otlptrace/otlptracehttp/options.go index 5b52f8fc65c..e550cfb5d51 100644 --- a/exporters/otlp/otlptrace/otlptracehttp/options.go +++ b/exporters/otlp/otlptrace/otlptracehttp/options.go @@ -37,7 +37,7 @@ const ( // Option applies an option to the HTTP client. type Option interface { - applyHTTPOption(*otlpconfig.Config) + applyHTTPOption(otlpconfig.Config) otlpconfig.Config } // RetryConfig defines configuration for retrying batches in case of export @@ -48,8 +48,8 @@ type wrappedOption struct { otlpconfig.HTTPOption } -func (w wrappedOption) applyHTTPOption(cfg *otlpconfig.Config) { - w.ApplyHTTPOption(cfg) +func (w wrappedOption) applyHTTPOption(cfg otlpconfig.Config) otlpconfig.Config { + return w.ApplyHTTPOption(cfg) } // WithEndpoint allows one to set the address of the collector diff --git a/exporters/stdout/stdoutmetric/config.go b/exporters/stdout/stdoutmetric/config.go index 097afda83ce..305800ddbde 100644 --- a/exporters/stdout/stdoutmetric/config.go +++ b/exporters/stdout/stdoutmetric/config.go @@ -54,7 +54,7 @@ func newConfig(options ...Option) (config, error) { LabelEncoder: defaultLabelEncoder, } for _, opt := range options { - opt.apply(&cfg) + cfg = opt.apply(cfg) } return cfg, nil @@ -62,7 +62,7 @@ func newConfig(options ...Option) (config, error) { // Option sets the value of an option for a Config. type Option interface { - apply(*config) + apply(config) config } // WithWriter sets the export stream destination. @@ -74,8 +74,9 @@ type writerOption struct { W io.Writer } -func (o writerOption) apply(cfg *config) { +func (o writerOption) apply(cfg config) config { cfg.Writer = o.W + return cfg } // WithPrettyPrint sets the export stream format to use JSON. @@ -85,8 +86,9 @@ func WithPrettyPrint() Option { type prettyPrintOption bool -func (o prettyPrintOption) apply(cfg *config) { +func (o prettyPrintOption) apply(cfg config) config { cfg.PrettyPrint = bool(o) + return cfg } // WithoutTimestamps sets the export stream to not include timestamps. @@ -96,8 +98,9 @@ func WithoutTimestamps() Option { type timestampsOption bool -func (o timestampsOption) apply(cfg *config) { +func (o timestampsOption) apply(cfg config) config { cfg.Timestamps = bool(o) + return cfg } // WithLabelEncoder sets the label encoder used in export. @@ -109,6 +112,7 @@ type labelEncoderOption struct { LabelEncoder attribute.Encoder } -func (o labelEncoderOption) apply(cfg *config) { +func (o labelEncoderOption) apply(cfg config) config { cfg.LabelEncoder = o.LabelEncoder + return cfg } diff --git a/exporters/stdout/stdouttrace/config.go b/exporters/stdout/stdouttrace/config.go index c645ec86455..6b5a97b04cf 100644 --- a/exporters/stdout/stdouttrace/config.go +++ b/exporters/stdout/stdouttrace/config.go @@ -47,7 +47,7 @@ func newConfig(options ...Option) (config, error) { Timestamps: defaultTimestamps, } for _, opt := range options { - opt.apply(&cfg) + cfg = opt.apply(cfg) } return cfg, nil @@ -55,7 +55,7 @@ func newConfig(options ...Option) (config, error) { // Option sets the value of an option for a Config. type Option interface { - apply(*config) + apply(config) config } // WithWriter sets the export stream destination. @@ -67,8 +67,9 @@ type writerOption struct { W io.Writer } -func (o writerOption) apply(cfg *config) { +func (o writerOption) apply(cfg config) config { cfg.Writer = o.W + return cfg } // WithPrettyPrint sets the export stream format to use JSON. @@ -78,8 +79,9 @@ func WithPrettyPrint() Option { type prettyPrintOption bool -func (o prettyPrintOption) apply(cfg *config) { +func (o prettyPrintOption) apply(cfg config) config { cfg.PrettyPrint = bool(o) + return cfg } // WithoutTimestamps sets the export stream to not include timestamps. @@ -89,6 +91,7 @@ func WithoutTimestamps() Option { type timestampsOption bool -func (o timestampsOption) apply(cfg *config) { +func (o timestampsOption) apply(cfg config) config { cfg.Timestamps = bool(o) + return cfg } diff --git a/exporters/zipkin/zipkin.go b/exporters/zipkin/zipkin.go index 23a44a1ba97..5c7c20049d9 100644 --- a/exporters/zipkin/zipkin.go +++ b/exporters/zipkin/zipkin.go @@ -55,26 +55,28 @@ type config struct { // Option defines a function that configures the exporter. type Option interface { - apply(*config) + apply(config) config } -type optionFunc func(*config) +type optionFunc func(config) config -func (fn optionFunc) apply(cfg *config) { - fn(cfg) +func (fn optionFunc) apply(cfg config) config { + return fn(cfg) } // WithLogger configures the exporter to use the passed logger. func WithLogger(logger *log.Logger) Option { - return optionFunc(func(cfg *config) { + return optionFunc(func(cfg config) config { cfg.logger = logger + return cfg }) } // WithClient configures the exporter to use the passed HTTP client. func WithClient(client *http.Client) Option { - return optionFunc(func(cfg *config) { + return optionFunc(func(cfg config) config { cfg.client = client + return cfg }) } @@ -94,7 +96,7 @@ func New(collectorURL string, opts ...Option) (*Exporter, error) { cfg := config{} for _, opt := range opts { - opt.apply(&cfg) + cfg = opt.apply(cfg) } if cfg.client == nil { diff --git a/metric/config.go b/metric/config.go index 686ca7c1acb..3f722344fa7 100644 --- a/metric/config.go +++ b/metric/config.go @@ -38,7 +38,7 @@ func (cfg *InstrumentConfig) Unit() unit.Unit { type InstrumentOption interface { // ApplyMeter is used to set a InstrumentOption value of a // InstrumentConfig. - applyInstrument(*InstrumentConfig) + applyInstrument(InstrumentConfig) InstrumentConfig } // NewInstrumentConfig creates a new InstrumentConfig @@ -46,28 +46,30 @@ type InstrumentOption interface { func NewInstrumentConfig(opts ...InstrumentOption) InstrumentConfig { var config InstrumentConfig for _, o := range opts { - o.applyInstrument(&config) + config = o.applyInstrument(config) } return config } -type instrumentOptionFunc func(*InstrumentConfig) +type instrumentOptionFunc func(InstrumentConfig) InstrumentConfig -func (fn instrumentOptionFunc) applyInstrument(cfg *InstrumentConfig) { - fn(cfg) +func (fn instrumentOptionFunc) applyInstrument(cfg InstrumentConfig) InstrumentConfig { + return fn(cfg) } // WithDescription applies provided description. func WithDescription(desc string) InstrumentOption { - return instrumentOptionFunc(func(cfg *InstrumentConfig) { + return instrumentOptionFunc(func(cfg InstrumentConfig) InstrumentConfig { cfg.description = desc + return cfg }) } // WithUnit applies provided unit. func WithUnit(unit unit.Unit) InstrumentOption { - return instrumentOptionFunc(func(cfg *InstrumentConfig) { + return instrumentOptionFunc(func(cfg InstrumentConfig) InstrumentConfig { cfg.unit = unit + return cfg }) } @@ -90,7 +92,7 @@ func (cfg *MeterConfig) SchemaURL() string { // MeterOption is an interface for applying Meter options. type MeterOption interface { // ApplyMeter is used to set a MeterOption value of a MeterConfig. - applyMeter(*MeterConfig) + applyMeter(MeterConfig) MeterConfig } // NewMeterConfig creates a new MeterConfig and applies @@ -98,27 +100,29 @@ type MeterOption interface { func NewMeterConfig(opts ...MeterOption) MeterConfig { var config MeterConfig for _, o := range opts { - o.applyMeter(&config) + config = o.applyMeter(config) } return config } -type meterOptionFunc func(*MeterConfig) +type meterOptionFunc func(MeterConfig) MeterConfig -func (fn meterOptionFunc) applyMeter(cfg *MeterConfig) { - fn(cfg) +func (fn meterOptionFunc) applyMeter(cfg MeterConfig) MeterConfig { + return fn(cfg) } // WithInstrumentationVersion sets the instrumentation version. func WithInstrumentationVersion(version string) MeterOption { - return meterOptionFunc(func(config *MeterConfig) { + return meterOptionFunc(func(config MeterConfig) MeterConfig { config.instrumentationVersion = version + return config }) } // WithSchemaURL sets the schema URL. func WithSchemaURL(schemaURL string) MeterOption { - return meterOptionFunc(func(config *MeterConfig) { + return meterOptionFunc(func(config MeterConfig) MeterConfig { config.schemaURL = schemaURL + return config }) } diff --git a/sdk/metric/controller/basic/config.go b/sdk/metric/controller/basic/config.go index 01691ecadd1..f3a9830c6af 100644 --- a/sdk/metric/controller/basic/config.go +++ b/sdk/metric/controller/basic/config.go @@ -62,7 +62,7 @@ type config struct { // Option is the interface that applies the value to a configuration option. type Option interface { // apply sets the Option value of a Config. - apply(*config) + apply(config) config } // WithResource sets the Resource configuration option of a Config by merging it @@ -73,12 +73,13 @@ func WithResource(r *resource.Resource) Option { type resourceOption struct{ *resource.Resource } -func (o resourceOption) apply(cfg *config) { +func (o resourceOption) apply(cfg config) config { res, err := resource.Merge(cfg.Resource, o.Resource) if err != nil { otel.Handle(err) } cfg.Resource = res + return cfg } // WithCollectPeriod sets the CollectPeriod configuration option of a Config. @@ -88,8 +89,9 @@ func WithCollectPeriod(period time.Duration) Option { type collectPeriodOption time.Duration -func (o collectPeriodOption) apply(cfg *config) { +func (o collectPeriodOption) apply(cfg config) config { cfg.CollectPeriod = time.Duration(o) + return cfg } // WithCollectTimeout sets the CollectTimeout configuration option of a Config. @@ -99,8 +101,9 @@ func WithCollectTimeout(timeout time.Duration) Option { type collectTimeoutOption time.Duration -func (o collectTimeoutOption) apply(cfg *config) { +func (o collectTimeoutOption) apply(cfg config) config { cfg.CollectTimeout = time.Duration(o) + return cfg } // WithExporter sets the exporter configuration option of a Config. @@ -110,8 +113,9 @@ func WithExporter(exporter export.Exporter) Option { type exporterOption struct{ exporter export.Exporter } -func (o exporterOption) apply(cfg *config) { +func (o exporterOption) apply(cfg config) config { cfg.Exporter = o.exporter + return cfg } // WithPushTimeout sets the PushTimeout configuration option of a Config. @@ -121,6 +125,7 @@ func WithPushTimeout(timeout time.Duration) Option { type pushTimeoutOption time.Duration -func (o pushTimeoutOption) apply(cfg *config) { +func (o pushTimeoutOption) apply(cfg config) config { cfg.PushTimeout = time.Duration(o) + return cfg } diff --git a/sdk/metric/controller/basic/config_test.go b/sdk/metric/controller/basic/config_test.go index d93cc53a677..32757b8a966 100644 --- a/sdk/metric/controller/basic/config_test.go +++ b/sdk/metric/controller/basic/config_test.go @@ -26,12 +26,12 @@ import ( func TestWithResource(t *testing.T) { r := resource.NewSchemaless(attribute.String("A", "a")) - c := &config{} - WithResource(r).apply(c) + c := config{} + c = WithResource(r).apply(c) assert.Equal(t, r.Equivalent(), c.Resource.Equivalent()) // Ensure overwriting works. - c = &config{Resource: &resource.Resource{}} - WithResource(r).apply(c) + c = config{Resource: &resource.Resource{}} + c = WithResource(r).apply(c) assert.Equal(t, r.Equivalent(), c.Resource.Equivalent()) } diff --git a/sdk/metric/controller/basic/controller.go b/sdk/metric/controller/basic/controller.go index a684f65678e..ee694056228 100644 --- a/sdk/metric/controller/basic/controller.go +++ b/sdk/metric/controller/basic/controller.go @@ -112,13 +112,13 @@ type accumulatorCheckpointer struct { // and options (including optional exporter) to configure a metric // export pipeline. func New(checkpointerFactory export.CheckpointerFactory, opts ...Option) *Controller { - c := &config{ + c := config{ CollectPeriod: DefaultPeriod, CollectTimeout: DefaultPeriod, PushTimeout: DefaultPeriod, } for _, opt := range opts { - opt.apply(c) + c = opt.apply(c) } if c.Resource == nil { c.Resource = resource.Default() diff --git a/sdk/metric/processor/basic/basic.go b/sdk/metric/processor/basic/basic.go index 08912da0308..71101bc4bce 100644 --- a/sdk/metric/processor/basic/basic.go +++ b/sdk/metric/processor/basic/basic.go @@ -132,7 +132,7 @@ type factory struct { func NewFactory(aselector export.AggregatorSelector, tselector aggregation.TemporalitySelector, opts ...Option) export.CheckpointerFactory { var config config for _, opt := range opts { - opt.applyProcessor(&config) + config = opt.applyProcessor(config) } return factory{ aselector: aselector, diff --git a/sdk/metric/processor/basic/config.go b/sdk/metric/processor/basic/config.go index f4cf440cf4c..5170864d7e9 100644 --- a/sdk/metric/processor/basic/config.go +++ b/sdk/metric/processor/basic/config.go @@ -24,7 +24,7 @@ type config struct { } type Option interface { - applyProcessor(*config) + applyProcessor(config) config } // WithMemory sets the memory behavior of a Processor. If this is @@ -37,6 +37,7 @@ func WithMemory(memory bool) Option { type memoryOption bool -func (m memoryOption) applyProcessor(cfg *config) { +func (m memoryOption) applyProcessor(cfg config) config { cfg.Memory = bool(m) + return cfg } diff --git a/sdk/resource/config.go b/sdk/resource/config.go index 5fa45859b53..d80b5ae6214 100644 --- a/sdk/resource/config.go +++ b/sdk/resource/config.go @@ -31,7 +31,7 @@ type config struct { // Option is the interface that applies a configuration option. type Option interface { // apply sets the Option value of a config. - apply(*config) + apply(config) config } // WithAttributes adds attributes to the configured Resource. @@ -56,8 +56,9 @@ type detectorsOption struct { detectors []Detector } -func (o detectorsOption) apply(cfg *config) { +func (o detectorsOption) apply(cfg config) config { cfg.detectors = append(cfg.detectors, o.detectors...) + return cfg } // WithFromEnv adds attributes from environment variables to the configured resource. @@ -82,8 +83,9 @@ func WithSchemaURL(schemaURL string) Option { type schemaURLOption string -func (o schemaURLOption) apply(cfg *config) { +func (o schemaURLOption) apply(cfg config) config { cfg.schemaURL = string(o) + return cfg } // WithOS adds all the OS attributes to the configured Resource. diff --git a/sdk/resource/resource.go b/sdk/resource/resource.go index 4ef49b314fc..e842744ae91 100644 --- a/sdk/resource/resource.go +++ b/sdk/resource/resource.go @@ -48,7 +48,7 @@ var errMergeConflictSchemaURL = errors.New("cannot merge resource due to conflic func New(ctx context.Context, opts ...Option) (*Resource, error) { cfg := config{} for _, opt := range opts { - opt.apply(&cfg) + cfg = opt.apply(cfg) } resource, err := Detect(ctx, cfg.detectors...) diff --git a/sdk/trace/provider.go b/sdk/trace/provider.go index 68bdefe0c94..b4fdcd317a4 100644 --- a/sdk/trace/provider.go +++ b/sdk/trace/provider.go @@ -93,13 +93,13 @@ var _ trace.TracerProvider = &TracerProvider{} // The passed opts are used to override these default values and configure the // returned TracerProvider appropriately. func NewTracerProvider(opts ...TracerProviderOption) *TracerProvider { - o := &tracerProviderConfig{} + o := tracerProviderConfig{} for _, opt := range opts { - opt.apply(o) + o = opt.apply(o) } - ensureValidTracerProviderConfig(o) + o = ensureValidTracerProviderConfig(o) tp := &TracerProvider{ namedTracer: make(map[instrumentation.Library]*tracer), @@ -256,13 +256,13 @@ func (p *TracerProvider) Shutdown(ctx context.Context) error { } type TracerProviderOption interface { - apply(*tracerProviderConfig) + apply(tracerProviderConfig) tracerProviderConfig } -type traceProviderOptionFunc func(*tracerProviderConfig) +type traceProviderOptionFunc func(tracerProviderConfig) tracerProviderConfig -func (fn traceProviderOptionFunc) apply(cfg *tracerProviderConfig) { - fn(cfg) +func (fn traceProviderOptionFunc) apply(cfg tracerProviderConfig) tracerProviderConfig { + return fn(cfg) } // WithSyncer registers the exporter with the TracerProvider using a @@ -285,8 +285,9 @@ func WithBatcher(e SpanExporter, opts ...BatchSpanProcessorOption) TracerProvide // WithSpanProcessor registers the SpanProcessor with a TracerProvider. func WithSpanProcessor(sp SpanProcessor) TracerProviderOption { - return traceProviderOptionFunc(func(cfg *tracerProviderConfig) { + return traceProviderOptionFunc(func(cfg tracerProviderConfig) tracerProviderConfig { cfg.processors = append(cfg.processors, sp) + return cfg }) } @@ -298,12 +299,13 @@ 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) { + 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 }) } @@ -315,10 +317,11 @@ 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) { + return traceProviderOptionFunc(func(cfg tracerProviderConfig) tracerProviderConfig { if g != nil { cfg.idGenerator = g } + return cfg }) } @@ -330,10 +333,11 @@ func WithIDGenerator(g IDGenerator) TracerProviderOption { // If this option is not used, the TracerProvider will use a // ParentBased(AlwaysSample) Sampler by default. func WithSampler(s Sampler) TracerProviderOption { - return traceProviderOptionFunc(func(cfg *tracerProviderConfig) { + return traceProviderOptionFunc(func(cfg tracerProviderConfig) tracerProviderConfig { if s != nil { cfg.sampler = s } + return cfg }) } @@ -345,13 +349,14 @@ func WithSampler(s Sampler) TracerProviderOption { // If this option is not used, the TracerProvider will use the default // SpanLimits. func WithSpanLimits(sl SpanLimits) TracerProviderOption { - return traceProviderOptionFunc(func(cfg *tracerProviderConfig) { + return traceProviderOptionFunc(func(cfg tracerProviderConfig) tracerProviderConfig { cfg.spanLimits = sl + return cfg }) } // ensureValidTracerProviderConfig ensures that given TracerProviderConfig is valid. -func ensureValidTracerProviderConfig(cfg *tracerProviderConfig) { +func ensureValidTracerProviderConfig(cfg tracerProviderConfig) tracerProviderConfig { if cfg.sampler == nil { cfg.sampler = ParentBased(AlwaysSample()) } @@ -362,4 +367,5 @@ func ensureValidTracerProviderConfig(cfg *tracerProviderConfig) { if cfg.resource == nil { cfg.resource = resource.Default() } + return cfg } diff --git a/sdk/trace/sampling.go b/sdk/trace/sampling.go index 849248638c4..a4ac588f666 100644 --- a/sdk/trace/sampling.go +++ b/sdk/trace/sampling.go @@ -187,7 +187,7 @@ func configureSamplersForParentBased(samplers []ParentBasedSamplerOption) sample } for _, so := range samplers { - so.apply(&c) + c = so.apply(c) } return c @@ -201,7 +201,7 @@ type samplerConfig struct { // ParentBasedSamplerOption configures the sampler for a particular sampling case. type ParentBasedSamplerOption interface { - apply(*samplerConfig) + apply(samplerConfig) samplerConfig } // WithRemoteParentSampled sets the sampler for the case of sampled remote parent. @@ -213,8 +213,9 @@ type remoteParentSampledOption struct { s Sampler } -func (o remoteParentSampledOption) apply(config *samplerConfig) { +func (o remoteParentSampledOption) apply(config samplerConfig) samplerConfig { config.remoteParentSampled = o.s + return config } // WithRemoteParentNotSampled sets the sampler for the case of remote parent @@ -227,8 +228,9 @@ type remoteParentNotSampledOption struct { s Sampler } -func (o remoteParentNotSampledOption) apply(config *samplerConfig) { +func (o remoteParentNotSampledOption) apply(config samplerConfig) samplerConfig { config.remoteParentNotSampled = o.s + return config } // WithLocalParentSampled sets the sampler for the case of sampled local parent. @@ -240,8 +242,9 @@ type localParentSampledOption struct { s Sampler } -func (o localParentSampledOption) apply(config *samplerConfig) { +func (o localParentSampledOption) apply(config samplerConfig) samplerConfig { config.localParentSampled = o.s + return config } // WithLocalParentNotSampled sets the sampler for the case of local parent @@ -254,8 +257,9 @@ type localParentNotSampledOption struct { s Sampler } -func (o localParentNotSampledOption) apply(config *samplerConfig) { +func (o localParentNotSampledOption) apply(config samplerConfig) samplerConfig { config.localParentNotSampled = o.s + return config } func (pb parentBased) ShouldSample(p SamplingParameters) SamplingResult { diff --git a/trace/config.go b/trace/config.go index 8461a15ccd4..bcc333e04e2 100644 --- a/trace/config.go +++ b/trace/config.go @@ -41,20 +41,20 @@ func (t *TracerConfig) SchemaURL() string { func NewTracerConfig(options ...TracerOption) TracerConfig { var config TracerConfig for _, option := range options { - option.apply(&config) + config = option.apply(config) } return config } // TracerOption applies an option to a TracerConfig. type TracerOption interface { - apply(*TracerConfig) + apply(TracerConfig) TracerConfig } -type tracerOptionFunc func(*TracerConfig) +type tracerOptionFunc func(TracerConfig) TracerConfig -func (fn tracerOptionFunc) apply(cfg *TracerConfig) { - fn(cfg) +func (fn tracerOptionFunc) apply(cfg TracerConfig) TracerConfig { + return fn(cfg) } // SpanConfig is a group of options for a Span. @@ -106,7 +106,7 @@ func (cfg *SpanConfig) SpanKind() SpanKind { func NewSpanStartConfig(options ...SpanStartOption) SpanConfig { var c SpanConfig for _, option := range options { - option.applySpanStart(&c) + c = option.applySpanStart(c) } return c } @@ -118,7 +118,7 @@ func NewSpanStartConfig(options ...SpanStartOption) SpanConfig { func NewSpanEndConfig(options ...SpanEndOption) SpanConfig { var c SpanConfig for _, option := range options { - option.applySpanEnd(&c) + c = option.applySpanEnd(c) } return c } @@ -126,19 +126,19 @@ func NewSpanEndConfig(options ...SpanEndOption) SpanConfig { // SpanStartOption applies an option to a SpanConfig. These options are applicable // only when the span is created type SpanStartOption interface { - applySpanStart(*SpanConfig) + applySpanStart(SpanConfig) SpanConfig } -type spanOptionFunc func(*SpanConfig) +type spanOptionFunc func(SpanConfig) SpanConfig -func (fn spanOptionFunc) applySpanStart(cfg *SpanConfig) { - fn(cfg) +func (fn spanOptionFunc) applySpanStart(cfg SpanConfig) SpanConfig { + return fn(cfg) } // SpanEndOption applies an option to a SpanConfig. These options are // applicable only when the span is ended. type SpanEndOption interface { - applySpanEnd(*SpanConfig) + applySpanEnd(SpanConfig) SpanConfig } // EventConfig is a group of options for an Event. @@ -170,7 +170,7 @@ func (cfg *EventConfig) StackTrace() bool { func NewEventConfig(options ...EventOption) EventConfig { var c EventConfig for _, option := range options { - option.applyEvent(&c) + c = option.applyEvent(c) } if c.timestamp.IsZero() { c.timestamp = time.Now() @@ -180,7 +180,7 @@ func NewEventConfig(options ...EventOption) EventConfig { // EventOption applies span event options to an EventConfig. type EventOption interface { - applyEvent(*EventConfig) + applyEvent(EventConfig) EventConfig } // SpanOption are options that can be used at both the beginning and end of a span. @@ -203,12 +203,14 @@ type SpanEndEventOption interface { type attributeOption []attribute.KeyValue -func (o attributeOption) applySpan(c *SpanConfig) { +func (o attributeOption) applySpan(c SpanConfig) SpanConfig { c.attributes = append(c.attributes, []attribute.KeyValue(o)...) + return c } -func (o attributeOption) applySpanStart(c *SpanConfig) { o.applySpan(c) } -func (o attributeOption) applyEvent(c *EventConfig) { +func (o attributeOption) applySpanStart(c SpanConfig) SpanConfig { return o.applySpan(c) } +func (o attributeOption) applyEvent(c EventConfig) EventConfig { c.attributes = append(c.attributes, []attribute.KeyValue(o)...) + return c } var _ SpanStartEventOption = attributeOption{} @@ -234,10 +236,16 @@ type SpanEventOption interface { type timestampOption time.Time -func (o timestampOption) applySpan(c *SpanConfig) { c.timestamp = time.Time(o) } -func (o timestampOption) applySpanStart(c *SpanConfig) { o.applySpan(c) } -func (o timestampOption) applySpanEnd(c *SpanConfig) { o.applySpan(c) } -func (o timestampOption) applyEvent(c *EventConfig) { c.timestamp = time.Time(o) } +func (o timestampOption) applySpan(c SpanConfig) SpanConfig { + c.timestamp = time.Time(o) + return c +} +func (o timestampOption) applySpanStart(c SpanConfig) SpanConfig { return o.applySpan(c) } +func (o timestampOption) applySpanEnd(c SpanConfig) SpanConfig { return o.applySpan(c) } +func (o timestampOption) applyEvent(c EventConfig) EventConfig { + c.timestamp = time.Time(o) + return c +} var _ SpanEventOption = timestampOption{} @@ -249,9 +257,15 @@ func WithTimestamp(t time.Time) SpanEventOption { type stackTraceOption bool -func (o stackTraceOption) applyEvent(c *EventConfig) { c.stackTrace = bool(o) } -func (o stackTraceOption) applySpan(c *SpanConfig) { c.stackTrace = bool(o) } -func (o stackTraceOption) applySpanEnd(c *SpanConfig) { o.applySpan(c) } +func (o stackTraceOption) applyEvent(c EventConfig) EventConfig { + c.stackTrace = bool(o) + return c +} +func (o stackTraceOption) applySpan(c SpanConfig) SpanConfig { + c.stackTrace = bool(o) + return c +} +func (o stackTraceOption) applySpanEnd(c SpanConfig) SpanConfig { return o.applySpan(c) } // WithStackTrace sets the flag to capture the error with stack trace (e.g. true, false). func WithStackTrace(b bool) SpanEndEventOption { @@ -261,8 +275,9 @@ func WithStackTrace(b bool) SpanEndEventOption { // WithLinks adds links to a Span. The links are added to the existing Span // links, i.e. this does not overwrite. Links with invalid span context are ignored. func WithLinks(links ...Link) SpanStartOption { - return spanOptionFunc(func(cfg *SpanConfig) { + return spanOptionFunc(func(cfg SpanConfig) SpanConfig { cfg.links = append(cfg.links, links...) + return cfg }) } @@ -270,28 +285,32 @@ func WithLinks(links ...Link) SpanStartOption { // existing parent span context will be ignored when defining the Span's trace // identifiers. func WithNewRoot() SpanStartOption { - return spanOptionFunc(func(cfg *SpanConfig) { + return spanOptionFunc(func(cfg SpanConfig) SpanConfig { cfg.newRoot = true + return cfg }) } // WithSpanKind sets the SpanKind of a Span. func WithSpanKind(kind SpanKind) SpanStartOption { - return spanOptionFunc(func(cfg *SpanConfig) { + return spanOptionFunc(func(cfg SpanConfig) SpanConfig { cfg.spanKind = kind + return cfg }) } // WithInstrumentationVersion sets the instrumentation version. func WithInstrumentationVersion(version string) TracerOption { - return tracerOptionFunc(func(cfg *TracerConfig) { + return tracerOptionFunc(func(cfg TracerConfig) TracerConfig { cfg.instrumentationVersion = version + return cfg }) } // WithSchemaURL sets the schema URL for the Tracer. func WithSchemaURL(schemaURL string) TracerOption { - return tracerOptionFunc(func(cfg *TracerConfig) { + return tracerOptionFunc(func(cfg TracerConfig) TracerConfig { cfg.schemaURL = schemaURL + return cfg }) } diff --git a/trace/config_test.go b/trace/config_test.go index 877bd024eeb..a4cafcbcd09 100644 --- a/trace/config_test.go +++ b/trace/config_test.go @@ -252,3 +252,71 @@ func TestTracerConfig(t *testing.T) { assert.Equal(t, test.expected, config) } } + +// Save benchmark results to a file level var to avoid the compiler optimizing +// away the actual work. +var ( + tracerConfig TracerConfig + spanConfig SpanConfig + eventConfig EventConfig +) + +func BenchmarkNewTracerConfig(b *testing.B) { + opts := []TracerOption{ + WithInstrumentationVersion("testing verion"), + WithSchemaURL("testing URL"), + } + + b.ReportAllocs() + b.ResetTimer() + + for i := 0; i < b.N; i++ { + tracerConfig = NewTracerConfig(opts...) + } +} + +func BenchmarkNewSpanStartConfig(b *testing.B) { + opts := []SpanStartOption{ + WithAttributes(attribute.Bool("key", true)), + WithTimestamp(time.Now()), + WithLinks(Link{}), + WithNewRoot(), + WithSpanKind(SpanKindClient), + } + + b.ReportAllocs() + b.ResetTimer() + + for i := 0; i < b.N; i++ { + spanConfig = NewSpanStartConfig(opts...) + } +} + +func BenchmarkNewSpanEndConfig(b *testing.B) { + opts := []SpanEndOption{ + WithTimestamp(time.Now()), + WithStackTrace(true), + } + + b.ReportAllocs() + b.ResetTimer() + + for i := 0; i < b.N; i++ { + spanConfig = NewSpanEndConfig(opts...) + } +} + +func BenchmarkNewEventConfig(b *testing.B) { + opts := []EventOption{ + WithAttributes(attribute.Bool("key", true)), + WithTimestamp(time.Now()), + WithStackTrace(true), + } + + b.ReportAllocs() + b.ResetTimer() + + for i := 0; i < b.N; i++ { + eventConfig = NewEventConfig(opts...) + } +}