diff --git a/CHANGELOG.md b/CHANGELOG.md index 67a5b9a857b..e1181ef49a0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -45,6 +45,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm - Spans created by the global `Tracer` obtained from `go.opentelemetry.io/otel`, prior to a functioning `TracerProvider` being set, now propagate the span context from their parent if one exists. (#1901) - The `"go.opentelemetry.io/otel".Tracer` function now accepts tracer options. (#1902) - Move the `go.opentelemetry.io/otel/unit` package to `go.opentelemetry.io/otel/metric/unit`. (#1903) +- Refactor option types according to the contribution style guide. (#1882) ### Deprecated diff --git a/exporters/otlp/options.go b/exporters/otlp/options.go index f2d176f6e3a..bcd0ddc3d4d 100644 --- a/exporters/otlp/options.go +++ b/exporters/otlp/options.go @@ -28,7 +28,15 @@ const ( ) // ExporterOption are setting options passed to an Exporter on creation. -type ExporterOption func(*config) +type ExporterOption interface { + apply(*config) +} + +type exporterOptionFunc func(*config) + +func (fn exporterOptionFunc) apply(cfg *config) { + fn(cfg) +} type config struct { exportKindSelector metricsdk.ExportKindSelector @@ -39,14 +47,14 @@ type config struct { // aggregation). If not specified otherwise, exporter will use a // cumulative export kind selector. func WithMetricExportKindSelector(selector metricsdk.ExportKindSelector) ExporterOption { - return func(cfg *config) { + return exporterOptionFunc(func(cfg *config) { cfg.exportKindSelector = selector - } + }) } // SplitDriverOption provides options for setting up a split driver. type SplitDriverOption interface { - Apply(*splitDriver) + apply(*splitDriver) } // WithMetricDriver allows one to set the driver used for metrics @@ -59,7 +67,7 @@ type metricDriverOption struct { driver ProtocolDriver } -func (o metricDriverOption) Apply(s *splitDriver) { +func (o metricDriverOption) apply(s *splitDriver) { s.metric = o.driver } @@ -73,6 +81,6 @@ type traceDriverOption struct { driver ProtocolDriver } -func (o traceDriverOption) Apply(s *splitDriver) { +func (o traceDriverOption) apply(s *splitDriver) { s.trace = o.driver } diff --git a/exporters/otlp/otlp.go b/exporters/otlp/otlp.go index 8595ea42bd8..d2ba236456a 100644 --- a/exporters/otlp/otlp.go +++ b/exporters/otlp/otlp.go @@ -66,7 +66,7 @@ func NewUnstartedExporter(driver ProtocolDriver, opts ...ExporterOption) *Export exportKindSelector: metricsdk.CumulativeExportKindSelector(), } for _, opt := range opts { - opt(&cfg) + opt.apply(&cfg) } return &Exporter{ cfg: cfg, diff --git a/exporters/otlp/otlpgrpc/driver.go b/exporters/otlp/otlpgrpc/driver.go index 4b700ff11f2..dedfd3f214a 100644 --- a/exporters/otlp/otlpgrpc/driver.go +++ b/exporters/otlp/otlpgrpc/driver.go @@ -62,7 +62,7 @@ func NewDriver(opts ...Option) otlp.ProtocolDriver { cfg := otlpconfig.NewDefaultConfig() otlpconfig.ApplyGRPCEnvConfigs(&cfg) for _, opt := range opts { - opt.ApplyGRPCOption(&cfg) + opt.applyGRPCOption(&cfg) } d := &driver{} diff --git a/exporters/otlp/otlpgrpc/options.go b/exporters/otlp/otlpgrpc/options.go index 390bb276094..1b685e7a4d5 100644 --- a/exporters/otlp/otlpgrpc/options.go +++ b/exporters/otlp/otlpgrpc/options.go @@ -28,57 +28,65 @@ import ( // Option applies an option to the gRPC driver. type Option interface { + applyGRPCOption(*otlpconfig.Config) +} + +type wrappedOption struct { otlpconfig.GRPCOption } +func (w wrappedOption) applyGRPCOption(cfg *otlpconfig.Config) { + w.ApplyGRPCOption(cfg) +} + // WithInsecure disables client transport security for the exporter's gRPC connection // just like grpc.WithInsecure() https://pkg.go.dev/google.golang.org/grpc#WithInsecure // does. Note, by default, client security is required unless WithInsecure is used. func WithInsecure() Option { - return otlpconfig.WithInsecure() + return wrappedOption{otlpconfig.WithInsecure()} } // WithTracesInsecure disables client transport security for the traces exporter's gRPC connection // just like grpc.WithInsecure() https://pkg.go.dev/google.golang.org/grpc#WithInsecure // does. Note, by default, client security is required unless WithInsecure is used. func WithTracesInsecure() Option { - return otlpconfig.WithInsecureTraces() + return wrappedOption{otlpconfig.WithInsecureTraces()} } // WithInsecureMetrics disables client transport security for the metrics exporter's gRPC connection // just like grpc.WithInsecure() https://pkg.go.dev/google.golang.org/grpc#WithInsecure // does. Note, by default, client security is required unless WithInsecure is used. func WithInsecureMetrics() Option { - return otlpconfig.WithInsecureMetrics() + return wrappedOption{otlpconfig.WithInsecureMetrics()} } // WithEndpoint allows one to set the endpoint that the exporter will // connect to the collector on. If unset, it will instead try to use // connect to DefaultCollectorHost:DefaultCollectorPort. func WithEndpoint(endpoint string) Option { - return otlpconfig.WithEndpoint(endpoint) + return wrappedOption{otlpconfig.WithEndpoint(endpoint)} } // WithTracesEndpoint allows one to set the traces endpoint that the exporter will // connect to the collector on. If unset, it will instead try to use // connect to DefaultCollectorHost:DefaultCollectorPort. func WithTracesEndpoint(endpoint string) Option { - return otlpconfig.WithTracesEndpoint(endpoint) + return wrappedOption{otlpconfig.WithTracesEndpoint(endpoint)} } // WithMetricsEndpoint allows one to set the metrics endpoint that the exporter will // connect to the collector on. If unset, it will instead try to use // connect to DefaultCollectorHost:DefaultCollectorPort. func WithMetricsEndpoint(endpoint string) Option { - return otlpconfig.WithMetricsEndpoint(endpoint) + return wrappedOption{otlpconfig.WithMetricsEndpoint(endpoint)} } // WithReconnectionPeriod allows one to set the delay between next connection attempt // after failing to connect with the collector. -func WithReconnectionPeriod(rp time.Duration) otlpconfig.GRPCOption { - return otlpconfig.NewGRPCOption(func(cfg *otlpconfig.Config) { +func WithReconnectionPeriod(rp time.Duration) Option { + return wrappedOption{otlpconfig.NewGRPCOption(func(cfg *otlpconfig.Config) { cfg.ReconnectionPeriod = rp - }) + })} } func compressorToCompression(compressor string) otlp.Compression { @@ -97,7 +105,7 @@ func compressorToCompression(compressor string) otlp.Compression { // compressors auto-register on import, such as gzip, which can be registered by calling // `import _ "google.golang.org/grpc/encoding/gzip"`. func WithCompressor(compressor string) Option { - return otlpconfig.WithCompression(compressorToCompression(compressor)) + return wrappedOption{otlpconfig.WithCompression(compressorToCompression(compressor))} } // WithTracesCompression will set the compressor for the gRPC client to use when sending traces requests. @@ -106,7 +114,7 @@ func WithCompressor(compressor string) Option { // compressors auto-register on import, such as gzip, which can be registered by calling // `import _ "google.golang.org/grpc/encoding/gzip"`. func WithTracesCompression(compressor string) Option { - return otlpconfig.WithTracesCompression(compressorToCompression(compressor)) + return wrappedOption{otlpconfig.WithTracesCompression(compressorToCompression(compressor))} } // WithMetricsCompression will set the compressor for the gRPC client to use when sending metrics requests. @@ -115,22 +123,22 @@ func WithTracesCompression(compressor string) Option { // compressors auto-register on import, such as gzip, which can be registered by calling // `import _ "google.golang.org/grpc/encoding/gzip"`. func WithMetricsCompression(compressor string) Option { - return otlpconfig.WithMetricsCompression(compressorToCompression(compressor)) + return wrappedOption{otlpconfig.WithMetricsCompression(compressorToCompression(compressor))} } // WithHeaders will send the provided headers with gRPC requests. func WithHeaders(headers map[string]string) Option { - return otlpconfig.WithHeaders(headers) + return wrappedOption{otlpconfig.WithHeaders(headers)} } // WithTracesHeaders will send the provided headers with gRPC traces requests. func WithTracesHeaders(headers map[string]string) Option { - return otlpconfig.WithTracesHeaders(headers) + return wrappedOption{otlpconfig.WithTracesHeaders(headers)} } // WithMetricsHeaders will send the provided headers with gRPC metrics requests. func WithMetricsHeaders(headers map[string]string) Option { - return otlpconfig.WithMetricsHeaders(headers) + return wrappedOption{otlpconfig.WithMetricsHeaders(headers)} } // WithTLSCredentials allows the connection to use TLS credentials @@ -139,10 +147,10 @@ func WithMetricsHeaders(headers map[string]string) Option { // these credentials can be done in many ways e.g. plain file, in code tls.Config // or by certificate rotation, so it is up to the caller to decide what to use. func WithTLSCredentials(creds credentials.TransportCredentials) Option { - return otlpconfig.NewGRPCOption(func(cfg *otlpconfig.Config) { + return wrappedOption{otlpconfig.NewGRPCOption(func(cfg *otlpconfig.Config) { cfg.Traces.GRPCCredentials = creds cfg.Metrics.GRPCCredentials = creds - }) + })} } // WithTracesTLSCredentials allows the connection to use TLS credentials @@ -151,9 +159,9 @@ func WithTLSCredentials(creds credentials.TransportCredentials) Option { // these credentials can be done in many ways e.g. plain file, in code tls.Config // or by certificate rotation, so it is up to the caller to decide what to use. func WithTracesTLSCredentials(creds credentials.TransportCredentials) Option { - return otlpconfig.NewGRPCOption(func(cfg *otlpconfig.Config) { + return wrappedOption{otlpconfig.NewGRPCOption(func(cfg *otlpconfig.Config) { cfg.Traces.GRPCCredentials = creds - }) + })} } // WithMetricsTLSCredentials allows the connection to use TLS credentials @@ -162,43 +170,43 @@ func WithTracesTLSCredentials(creds credentials.TransportCredentials) Option { // these credentials can be done in many ways e.g. plain file, in code tls.Config // or by certificate rotation, so it is up to the caller to decide what to use. func WithMetricsTLSCredentials(creds credentials.TransportCredentials) Option { - return otlpconfig.NewGRPCOption(func(cfg *otlpconfig.Config) { + return wrappedOption{otlpconfig.NewGRPCOption(func(cfg *otlpconfig.Config) { cfg.Metrics.GRPCCredentials = creds - }) + })} } // WithServiceConfig defines the default gRPC service config used. func WithServiceConfig(serviceConfig string) Option { - return otlpconfig.NewGRPCOption(func(cfg *otlpconfig.Config) { + return wrappedOption{otlpconfig.NewGRPCOption(func(cfg *otlpconfig.Config) { cfg.ServiceConfig = serviceConfig - }) + })} } // WithDialOption opens support to any grpc.DialOption to be used. If it conflicts // with some other configuration the GRPC specified via the collector the ones here will // take preference since they are set last. func WithDialOption(opts ...grpc.DialOption) Option { - return otlpconfig.NewGRPCOption(func(cfg *otlpconfig.Config) { + return wrappedOption{otlpconfig.NewGRPCOption(func(cfg *otlpconfig.Config) { cfg.DialOptions = opts - }) + })} } // WithTimeout tells the driver the max waiting time for the backend to process // each spans or metrics batch. If unset, the default will be 10 seconds. func WithTimeout(duration time.Duration) Option { - return otlpconfig.WithTimeout(duration) + return wrappedOption{otlpconfig.WithTimeout(duration)} } // WithTracesTimeout tells the driver the max waiting time for the backend to process // each spans batch. If unset, the default will be 10 seconds. func WithTracesTimeout(duration time.Duration) Option { - return otlpconfig.WithTracesTimeout(duration) + return wrappedOption{otlpconfig.WithTracesTimeout(duration)} } // WithMetricsTimeout tells the driver the max waiting time for the backend to process // each metrics batch. If unset, the default will be 10 seconds. func WithMetricsTimeout(duration time.Duration) Option { - return otlpconfig.WithMetricsTimeout(duration) + return wrappedOption{otlpconfig.WithMetricsTimeout(duration)} } // WithRetry configures the retry policy for transient errors that may occurs when @@ -207,5 +215,5 @@ func WithMetricsTimeout(duration time.Duration) Option { // retry policy will retry after 5 seconds and increase exponentially after each // error for a total of 1 minute. func WithRetry(settings otlp.RetrySettings) Option { - return otlpconfig.WithRetry(settings) + return wrappedOption{otlpconfig.WithRetry(settings)} } diff --git a/exporters/otlp/otlphttp/driver.go b/exporters/otlp/otlphttp/driver.go index 6ad5d678c25..d30e5461082 100644 --- a/exporters/otlp/otlphttp/driver.go +++ b/exporters/otlp/otlphttp/driver.go @@ -86,7 +86,7 @@ func NewDriver(opts ...Option) otlp.ProtocolDriver { cfg := otlpconfig.NewDefaultConfig() otlpconfig.ApplyHTTPEnvConfigs(&cfg) for _, opt := range opts { - opt.ApplyHTTPOption(&cfg) + opt.applyHTTPOption(&cfg) } for pathPtr, defaultPath := range map[*string]string{ diff --git a/exporters/otlp/otlphttp/options.go b/exporters/otlp/otlphttp/options.go index f44c34df234..7ed35b284b9 100644 --- a/exporters/otlp/otlphttp/options.go +++ b/exporters/otlp/otlphttp/options.go @@ -43,16 +43,24 @@ const ( // Option applies an option to the HTTP driver. type Option interface { + applyHTTPOption(*otlpconfig.Config) +} + +type wrappedOption struct { otlpconfig.HTTPOption } +func (w wrappedOption) applyHTTPOption(cfg *otlpconfig.Config) { + w.ApplyHTTPOption(cfg) +} + // WithEndpoint allows one to set the address of the collector // endpoint that the driver will use to send metrics and spans. If // unset, it will instead try to use // DefaultCollectorHost:DefaultCollectorPort. Note that the endpoint // must not contain any URL path. func WithEndpoint(endpoint string) Option { - return otlpconfig.WithEndpoint(endpoint) + return wrappedOption{otlpconfig.WithEndpoint(endpoint)} } // WithTracesEndpoint allows one to set the address of the collector @@ -60,7 +68,7 @@ func WithEndpoint(endpoint string) Option { // unset, it will instead try to use the Endpoint configuration. // Note that the endpoint must not contain any URL path. func WithTracesEndpoint(endpoint string) Option { - return otlpconfig.WithTracesEndpoint(endpoint) + return wrappedOption{otlpconfig.WithTracesEndpoint(endpoint)} } // WithMetricsEndpoint allows one to set the address of the collector @@ -68,132 +76,132 @@ func WithTracesEndpoint(endpoint string) Option { // unset, it will instead try to use the Endpoint configuration. // Note that the endpoint must not contain any URL path. func WithMetricsEndpoint(endpoint string) Option { - return otlpconfig.WithMetricsEndpoint(endpoint) + return wrappedOption{otlpconfig.WithMetricsEndpoint(endpoint)} } // WithCompression tells the driver to compress the sent data. func WithCompression(compression otlp.Compression) Option { - return otlpconfig.WithCompression(compression) + return wrappedOption{otlpconfig.WithCompression(compression)} } // WithTracesCompression tells the driver to compress the sent traces data. func WithTracesCompression(compression otlp.Compression) Option { - return otlpconfig.WithTracesCompression(compression) + return wrappedOption{otlpconfig.WithTracesCompression(compression)} } // WithMetricsCompression tells the driver to compress the sent metrics data. func WithMetricsCompression(compression otlp.Compression) Option { - return otlpconfig.WithMetricsCompression(compression) + return wrappedOption{otlpconfig.WithMetricsCompression(compression)} } // WithTracesURLPath allows one to override the default URL path used // for sending traces. If unset, DefaultTracesPath will be used. func WithTracesURLPath(urlPath string) Option { - return otlpconfig.WithTracesURLPath(urlPath) + return wrappedOption{otlpconfig.WithTracesURLPath(urlPath)} } // WithMetricsURLPath allows one to override the default URL path used // for sending metrics. If unset, DefaultMetricsPath will be used. func WithMetricsURLPath(urlPath string) Option { - return otlpconfig.WithMetricsURLPath(urlPath) + return wrappedOption{otlpconfig.WithMetricsURLPath(urlPath)} } // WithMaxAttempts allows one to override how many times the driver // will try to send the payload in case of retryable errors. If unset, // DefaultMaxAttempts will be used. func WithMaxAttempts(maxAttempts int) Option { - return otlpconfig.WithMaxAttempts(maxAttempts) + return wrappedOption{otlpconfig.WithMaxAttempts(maxAttempts)} } // WithBackoff tells the driver to use the duration as a base of the // exponential backoff strategy. If unset, DefaultBackoff will be // used. func WithBackoff(duration time.Duration) Option { - return otlpconfig.WithBackoff(duration) + return wrappedOption{otlpconfig.WithBackoff(duration)} } // WithTLSClientConfig can be used to set up a custom TLS // configuration for the client used to send payloads to the // collector. Use it if you want to use a custom certificate. func WithTLSClientConfig(tlsCfg *tls.Config) Option { - return otlpconfig.WithTLSClientConfig(tlsCfg) + return wrappedOption{otlpconfig.WithTLSClientConfig(tlsCfg)} } // WithTracesTLSClientConfig can be used to set up a custom TLS // configuration for the client used to send traces. // Use it if you want to use a custom certificate. func WithTracesTLSClientConfig(tlsCfg *tls.Config) Option { - return otlpconfig.WithTracesTLSClientConfig(tlsCfg) + return wrappedOption{otlpconfig.WithTracesTLSClientConfig(tlsCfg)} } // WithMetricsTLSClientConfig can be used to set up a custom TLS // configuration for the client used to send metrics. // Use it if you want to use a custom certificate. func WithMetricsTLSClientConfig(tlsCfg *tls.Config) Option { - return otlpconfig.WithMetricsTLSClientConfig(tlsCfg) + return wrappedOption{otlpconfig.WithMetricsTLSClientConfig(tlsCfg)} } // WithInsecure tells the driver to connect to the collector using the // HTTP scheme, instead of HTTPS. func WithInsecure() Option { - return otlpconfig.WithInsecure() + return wrappedOption{otlpconfig.WithInsecure()} } // WithInsecureTraces tells the driver to connect to the traces collector using the // HTTP scheme, instead of HTTPS. func WithInsecureTraces() Option { - return otlpconfig.WithInsecureTraces() + return wrappedOption{otlpconfig.WithInsecureTraces()} } // WithInsecureMetrics tells the driver to connect to the metrics collector using the // HTTP scheme, instead of HTTPS. func WithInsecureMetrics() Option { - return otlpconfig.WithInsecureMetrics() + return wrappedOption{otlpconfig.WithInsecureMetrics()} } // WithHeaders allows one to tell the driver to send additional HTTP // headers with the payloads. Specifying headers like Content-Length, // Content-Encoding and Content-Type may result in a broken driver. func WithHeaders(headers map[string]string) Option { - return otlpconfig.WithHeaders(headers) + return wrappedOption{otlpconfig.WithHeaders(headers)} } // WithTracesHeaders allows one to tell the driver to send additional HTTP // headers with the trace payloads. Specifying headers like Content-Length, // Content-Encoding and Content-Type may result in a broken driver. func WithTracesHeaders(headers map[string]string) Option { - return otlpconfig.WithTracesHeaders(headers) + return wrappedOption{otlpconfig.WithTracesHeaders(headers)} } // WithMetricsHeaders allows one to tell the driver to send additional HTTP // headers with the metrics payloads. Specifying headers like Content-Length, // Content-Encoding and Content-Type may result in a broken driver. func WithMetricsHeaders(headers map[string]string) Option { - return otlpconfig.WithMetricsHeaders(headers) + return wrappedOption{otlpconfig.WithMetricsHeaders(headers)} } // WithMarshal tells the driver which wire format to use when sending to the // collector. If unset, MarshalProto will be used func WithMarshal(m otlp.Marshaler) Option { - return otlpconfig.NewHTTPOption(func(cfg *otlpconfig.Config) { + return wrappedOption{otlpconfig.NewHTTPOption(func(cfg *otlpconfig.Config) { cfg.Marshaler = m - }) + })} } // WithTimeout tells the driver the max waiting time for the backend to process // each spans or metrics batch. If unset, the default will be 10 seconds. func WithTimeout(duration time.Duration) Option { - return otlpconfig.WithTimeout(duration) + return wrappedOption{otlpconfig.WithTimeout(duration)} } // WithTracesTimeout tells the driver the max waiting time for the backend to process // each spans batch. If unset, the default will be 10 seconds. func WithTracesTimeout(duration time.Duration) Option { - return otlpconfig.WithTracesTimeout(duration) + return wrappedOption{otlpconfig.WithTracesTimeout(duration)} } // WithMetricsTimeout tells the driver the max waiting time for the backend to process // each metrics batch. If unset, the default will be 10 seconds. func WithMetricsTimeout(duration time.Duration) Option { - return otlpconfig.WithMetricsTimeout(duration) + return wrappedOption{otlpconfig.WithMetricsTimeout(duration)} } diff --git a/exporters/otlp/protocoldriver.go b/exporters/otlp/protocoldriver.go index 5d15b378ce5..21c38bbf24d 100644 --- a/exporters/otlp/protocoldriver.go +++ b/exporters/otlp/protocoldriver.go @@ -84,7 +84,7 @@ func NewSplitDriver(opts ...SplitDriverOption) ProtocolDriver { trace: &noopDriver{}, } for _, opt := range opts { - opt.Apply(&driver) + opt.apply(&driver) } return &driver } diff --git a/exporters/stdout/config.go b/exporters/stdout/config.go index 994c245b098..f434f47cf51 100644 --- a/exporters/stdout/config.go +++ b/exporters/stdout/config.go @@ -30,8 +30,8 @@ var ( defaultDisableMetricExport = false ) -// Config contains options for the STDOUT exporter. -type Config struct { +// config contains options for the STDOUT exporter. +type config struct { // Writer is the destination. If not set, os.Stdout is used. Writer io.Writer @@ -53,9 +53,9 @@ type Config struct { DisableMetricExport bool } -// NewConfig creates a validated Config configured with options. -func NewConfig(options ...Option) (Config, error) { - config := Config{ +// newConfig creates a validated Config configured with options. +func newConfig(options ...Option) (config, error) { + cfg := config{ Writer: defaultWriter, PrettyPrint: defaultPrettyPrint, Timestamps: defaultTimestamps, @@ -64,21 +64,15 @@ func NewConfig(options ...Option) (Config, error) { DisableMetricExport: defaultDisableMetricExport, } for _, opt := range options { - opt.Apply(&config) + opt.apply(&cfg) } - return config, nil + return cfg, nil } // Option sets the value of an option for a Config. type Option interface { - // Apply option value to Config. - Apply(*Config) - - // A private method to prevent users implementing the - // interface and so future additions to it will not - // violate compatibility. - private() + apply(*config) } // WithWriter sets the export stream destination. @@ -90,12 +84,10 @@ type writerOption struct { W io.Writer } -func (o writerOption) Apply(config *Config) { - config.Writer = o.W +func (o writerOption) apply(cfg *config) { + cfg.Writer = o.W } -func (writerOption) private() {} - // WithPrettyPrint sets the export stream format to use JSON. func WithPrettyPrint() Option { return prettyPrintOption(true) @@ -103,12 +95,10 @@ func WithPrettyPrint() Option { type prettyPrintOption bool -func (o prettyPrintOption) Apply(config *Config) { - config.PrettyPrint = bool(o) +func (o prettyPrintOption) apply(cfg *config) { + cfg.PrettyPrint = bool(o) } -func (prettyPrintOption) private() {} - // WithoutTimestamps sets the export stream to not include timestamps. func WithoutTimestamps() Option { return timestampsOption(false) @@ -116,12 +106,10 @@ func WithoutTimestamps() Option { type timestampsOption bool -func (o timestampsOption) Apply(config *Config) { - config.Timestamps = bool(o) +func (o timestampsOption) apply(cfg *config) { + cfg.Timestamps = bool(o) } -func (timestampsOption) private() {} - // WithLabelEncoder sets the label encoder used in export. func WithLabelEncoder(enc attribute.Encoder) Option { return labelEncoderOption{enc} @@ -131,12 +119,10 @@ type labelEncoderOption struct { LabelEncoder attribute.Encoder } -func (o labelEncoderOption) Apply(config *Config) { - config.LabelEncoder = o.LabelEncoder +func (o labelEncoderOption) apply(cfg *config) { + cfg.LabelEncoder = o.LabelEncoder } -func (labelEncoderOption) private() {} - // WithoutTraceExport disables all trace exporting. func WithoutTraceExport() Option { return disableTraceExportOption(true) @@ -144,12 +130,10 @@ func WithoutTraceExport() Option { type disableTraceExportOption bool -func (o disableTraceExportOption) Apply(config *Config) { - config.DisableTraceExport = bool(o) +func (o disableTraceExportOption) apply(cfg *config) { + cfg.DisableTraceExport = bool(o) } -func (disableTraceExportOption) private() {} - // WithoutMetricExport disables all metric exporting. func WithoutMetricExport() Option { return disableMetricExportOption(true) @@ -157,8 +141,6 @@ func WithoutMetricExport() Option { type disableMetricExportOption bool -func (o disableMetricExportOption) Apply(config *Config) { - config.DisableMetricExport = bool(o) +func (o disableMetricExportOption) apply(cfg *config) { + cfg.DisableMetricExport = bool(o) } - -func (disableMetricExportOption) private() {} diff --git a/exporters/stdout/exporter.go b/exporters/stdout/exporter.go index 88b0b9ad9e5..443fc1806b9 100644 --- a/exporters/stdout/exporter.go +++ b/exporters/stdout/exporter.go @@ -38,13 +38,13 @@ var ( // NewExporter creates an Exporter with the passed options. func NewExporter(options ...Option) (*Exporter, error) { - config, err := NewConfig(options...) + cfg, err := newConfig(options...) if err != nil { return nil, err } return &Exporter{ - traceExporter: traceExporter{config: config}, - metricExporter: metricExporter{config}, + traceExporter: traceExporter{config: cfg}, + metricExporter: metricExporter{cfg}, }, nil } diff --git a/exporters/stdout/metric.go b/exporters/stdout/metric.go index 9ea020da59b..ae20f1d61db 100644 --- a/exporters/stdout/metric.go +++ b/exporters/stdout/metric.go @@ -28,7 +28,7 @@ import ( ) type metricExporter struct { - config Config + config config } var _ exportmetric.Exporter = &metricExporter{} diff --git a/exporters/stdout/trace.go b/exporters/stdout/trace.go index 3aaefc54873..1022b13b548 100644 --- a/exporters/stdout/trace.go +++ b/exporters/stdout/trace.go @@ -26,7 +26,7 @@ import ( // Exporter is an implementation of trace.SpanSyncer that writes spans to stdout. type traceExporter struct { - config Config + config config stoppedMu sync.RWMutex stopped bool diff --git a/exporters/trace/jaeger/env_test.go b/exporters/trace/jaeger/env_test.go index 11fa80c2ee7..182d30ec928 100644 --- a/exporters/trace/jaeger/env_test.go +++ b/exporters/trace/jaeger/env_test.go @@ -180,20 +180,20 @@ func TestEnvOrWithCollectorEndpointOptionsFromEnv(t *testing.T) { envEndpoint string envUsername string envPassword string - defaultCollectorEndpointOptions CollectorEndpointOptions - expectedCollectorEndpointOptions CollectorEndpointOptions + defaultCollectorEndpointOptions collectorEndpointConfig + expectedCollectorEndpointOptions collectorEndpointConfig }{ { name: "overrides value via environment variables", envEndpoint: "http://localhost:14252", envUsername: "username", envPassword: "password", - defaultCollectorEndpointOptions: CollectorEndpointOptions{ + defaultCollectorEndpointOptions: collectorEndpointConfig{ endpoint: "endpoint not to be used", username: "foo", password: "bar", }, - expectedCollectorEndpointOptions: CollectorEndpointOptions{ + expectedCollectorEndpointOptions: collectorEndpointConfig{ endpoint: "http://localhost:14252", username: "username", password: "password", @@ -204,12 +204,12 @@ func TestEnvOrWithCollectorEndpointOptionsFromEnv(t *testing.T) { envEndpoint: "", envUsername: "", envPassword: "", - defaultCollectorEndpointOptions: CollectorEndpointOptions{ + defaultCollectorEndpointOptions: collectorEndpointConfig{ endpoint: "endpoint to be used", username: "foo", password: "bar", }, - expectedCollectorEndpointOptions: CollectorEndpointOptions{ + expectedCollectorEndpointOptions: collectorEndpointConfig{ endpoint: "endpoint to be used", username: "foo", password: "bar", diff --git a/exporters/trace/jaeger/jaeger.go b/exporters/trace/jaeger/jaeger.go index 8eb09450237..cb24243002f 100644 --- a/exporters/trace/jaeger/jaeger.go +++ b/exporters/trace/jaeger/jaeger.go @@ -45,7 +45,7 @@ const ( // NewRawExporter returns an OTel Exporter implementation that exports the // collected spans to Jaeger. func NewRawExporter(endpointOption EndpointOption) (*Exporter, error) { - uploader, err := endpointOption() + uploader, err := endpointOption.newBatchUploader() if err != nil { return nil, err } diff --git a/exporters/trace/jaeger/jaeger_test.go b/exporters/trace/jaeger/jaeger_test.go index 8156c1fc8a2..6d0d035c908 100644 --- a/exporters/trace/jaeger/jaeger_test.go +++ b/exporters/trace/jaeger/jaeger_test.go @@ -63,9 +63,9 @@ func TestNewExportPipelinePassthroughError(t *testing.T) { { name: "failing underlying NewRawExporter", failing: true, - epo: func() (batchUploader, error) { + epo: endpointOptionFunc(func() (batchUploader, error) { return nil, errors.New("error") - }, + }), }, { name: "with default agent endpoint", @@ -142,16 +142,16 @@ func (c *testCollectorEndpoint) upload(_ context.Context, batch *gen.Batch) erro var _ batchUploader = (*testCollectorEndpoint)(nil) -func withTestCollectorEndpoint() func() (batchUploader, error) { - return func() (batchUploader, error) { +func withTestCollectorEndpoint() EndpointOption { + return endpointOptionFunc(func() (batchUploader, error) { return &testCollectorEndpoint{}, nil - } + }) } -func withTestCollectorEndpointInjected(ce *testCollectorEndpoint) func() (batchUploader, error) { - return func() (batchUploader, error) { +func withTestCollectorEndpointInjected(ce *testCollectorEndpoint) EndpointOption { + return endpointOptionFunc(func() (batchUploader, error) { return ce, nil - } + }) } func TestExporterExportSpan(t *testing.T) { diff --git a/exporters/trace/jaeger/uploader.go b/exporters/trace/jaeger/uploader.go index 3d45f76e4e8..5f7bd4e32dd 100644 --- a/exporters/trace/jaeger/uploader.go +++ b/exporters/trace/jaeger/uploader.go @@ -35,7 +35,15 @@ type batchUploader interface { shutdown(context.Context) error } -type EndpointOption func() (batchUploader, error) +type EndpointOption interface { + newBatchUploader() (batchUploader, error) +} + +type endpointOptionFunc func() (batchUploader, error) + +func (fn endpointOptionFunc) newBatchUploader() (batchUploader, error) { + return fn() +} // WithAgentEndpoint configures the Jaeger exporter to send spans to a jaeger-agent. This will // use the following environment variables for configuration if no explicit option is provided: @@ -46,8 +54,8 @@ type EndpointOption func() (batchUploader, error) // The passed options will take precedence over any environment variables and default values // will be used if neither are provided. func WithAgentEndpoint(options ...AgentEndpointOption) EndpointOption { - return func() (batchUploader, error) { - o := &AgentEndpointOptions{ + return endpointOptionFunc(func() (batchUploader, error) { + cfg := &agentEndpointConfig{ agentClientUDPParams{ AttemptReconnecting: true, Host: envOr(envAgentHost, "localhost"), @@ -55,32 +63,40 @@ func WithAgentEndpoint(options ...AgentEndpointOption) EndpointOption { }, } for _, opt := range options { - opt(o) + opt.apply(cfg) } - client, err := newAgentClientUDP(o.agentClientUDPParams) + client, err := newAgentClientUDP(cfg.agentClientUDPParams) if err != nil { return nil, err } return &agentUploader{client: client}, nil - } + }) } -type AgentEndpointOption func(o *AgentEndpointOptions) +type AgentEndpointOption interface { + apply(*agentEndpointConfig) +} -type AgentEndpointOptions struct { +type agentEndpointConfig struct { agentClientUDPParams } +type agentEndpointOptionFunc func(*agentEndpointConfig) + +func (fn agentEndpointOptionFunc) apply(cfg *agentEndpointConfig) { + fn(cfg) +} + // WithAgentHost sets a host to be used in the agent client endpoint. // This option overrides any value set for the // 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 func(o *AgentEndpointOptions) { + return agentEndpointOptionFunc(func(o *agentEndpointConfig) { o.Host = host - } + }) } // WithAgentPort sets a port to be used in the agent client endpoint. @@ -88,37 +104,37 @@ 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, "6832" will be used by default. func WithAgentPort(port string) AgentEndpointOption { - return func(o *AgentEndpointOptions) { + return agentEndpointOptionFunc(func(o *agentEndpointConfig) { o.Port = port - } + }) } // WithLogger sets a logger to be used by agent client. func WithLogger(logger *log.Logger) AgentEndpointOption { - return func(o *AgentEndpointOptions) { + return agentEndpointOptionFunc(func(o *agentEndpointConfig) { o.Logger = logger - } + }) } // WithDisableAttemptReconnecting sets option to disable reconnecting udp client. func WithDisableAttemptReconnecting() AgentEndpointOption { - return func(o *AgentEndpointOptions) { + return agentEndpointOptionFunc(func(o *agentEndpointConfig) { o.AttemptReconnecting = false - } + }) } // WithAttemptReconnectingInterval sets the interval between attempts to re resolve agent endpoint. func WithAttemptReconnectingInterval(interval time.Duration) AgentEndpointOption { - return func(o *AgentEndpointOptions) { + return agentEndpointOptionFunc(func(o *agentEndpointConfig) { o.AttemptReconnectInterval = interval - } + }) } // WithMaxPacketSize sets the maximum UDP packet size for transport to the Jaeger agent. func WithMaxPacketSize(size int) AgentEndpointOption { - return func(o *AgentEndpointOptions) { + return agentEndpointOptionFunc(func(o *agentEndpointConfig) { o.MaxPacketSize = size - } + }) } // WithCollectorEndpoint defines the full url to the Jaeger HTTP Thrift collector. This will @@ -132,8 +148,8 @@ func WithMaxPacketSize(size int) AgentEndpointOption { // If neither values are provided for the endpoint, the default value of "http://localhost:14268/api/traces" will be used. // 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 func() (batchUploader, error) { - o := &CollectorEndpointOptions{ + return endpointOptionFunc(func() (batchUploader, error) { + cfg := &collectorEndpointConfig{ endpoint: envOr(envEndpoint, "http://localhost:14268/api/traces"), username: envOr(envUser, ""), password: envOr(envPassword, ""), @@ -141,21 +157,23 @@ func WithCollectorEndpoint(options ...CollectorEndpointOption) EndpointOption { } for _, opt := range options { - opt(o) + opt.apply(cfg) } return &collectorUploader{ - endpoint: o.endpoint, - username: o.username, - password: o.password, - httpClient: o.httpClient, + endpoint: cfg.endpoint, + username: cfg.username, + password: cfg.password, + httpClient: cfg.httpClient, }, nil - } + }) } -type CollectorEndpointOption func(o *CollectorEndpointOptions) +type CollectorEndpointOption interface { + apply(*collectorEndpointConfig) +} -type CollectorEndpointOptions struct { +type collectorEndpointConfig struct { // endpoint for sending spans directly to a collector. endpoint string @@ -169,15 +187,21 @@ type CollectorEndpointOptions struct { httpClient *http.Client } +type collectorEndpointOptionFunc func(*collectorEndpointConfig) + +func (fn collectorEndpointOptionFunc) apply(cfg *collectorEndpointConfig) { + fn(cfg) +} + // WithEndpoint is the URL for the Jaeger collector that spans are sent to. // This option overrides any value set for the // OTEL_EXPORTER_JAEGER_ENDPOINT environment variable. // 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 func(o *CollectorEndpointOptions) { + return collectorEndpointOptionFunc(func(o *collectorEndpointConfig) { o.endpoint = endpoint - } + }) } // WithUsername sets the username to be used in the authorization header sent for all requests to the collector. @@ -185,9 +209,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 func(o *CollectorEndpointOptions) { + return collectorEndpointOptionFunc(func(o *collectorEndpointConfig) { o.username = username - } + }) } // WithPassword sets the password to be used in the authorization header sent for all requests to the collector. @@ -195,16 +219,16 @@ 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 func(o *CollectorEndpointOptions) { + return collectorEndpointOptionFunc(func(o *collectorEndpointConfig) { o.password = password - } + }) } // WithHTTPClient sets the http client to be used to make request to the collector endpoint. func WithHTTPClient(client *http.Client) CollectorEndpointOption { - return func(o *CollectorEndpointOptions) { + return collectorEndpointOptionFunc(func(o *collectorEndpointConfig) { o.httpClient = client - } + }) } // agentUploader implements batchUploader interface sending batches to diff --git a/exporters/trace/zipkin/zipkin.go b/exporters/trace/zipkin/zipkin.go index afb0c24d95b..ee926912307 100644 --- a/exporters/trace/zipkin/zipkin.go +++ b/exporters/trace/zipkin/zipkin.go @@ -36,7 +36,7 @@ type Exporter struct { url string client *http.Client logger *log.Logger - o options + config config stoppedMu sync.RWMutex stopped bool @@ -47,34 +47,42 @@ var ( ) // Options contains configuration for the exporter. -type options struct { +type config struct { client *http.Client logger *log.Logger tpOpts []sdktrace.TracerProviderOption } // Option defines a function that configures the exporter. -type Option func(*options) +type Option interface { + apply(*config) +} + +type optionFunc func(*config) + +func (fn optionFunc) apply(cfg *config) { + fn(cfg) +} // WithLogger configures the exporter to use the passed logger. func WithLogger(logger *log.Logger) Option { - return func(opts *options) { - opts.logger = logger - } + return optionFunc(func(cfg *config) { + cfg.logger = logger + }) } // WithClient configures the exporter to use the passed HTTP client. func WithClient(client *http.Client) Option { - return func(opts *options) { - opts.client = client - } + return optionFunc(func(cfg *config) { + cfg.client = client + }) } // WithSDKOptions configures options passed to the created TracerProvider. func WithSDKOptions(tpOpts ...sdktrace.TracerProviderOption) Option { - return func(opts *options) { - opts.tpOpts = tpOpts - } + return optionFunc(func(cfg *config) { + cfg.tpOpts = tpOpts + }) } // NewRawExporter creates a new Zipkin exporter. @@ -90,18 +98,18 @@ func NewRawExporter(collectorURL string, opts ...Option) (*Exporter, error) { return nil, errors.New("invalid collector URL") } - o := options{} + cfg := config{} for _, opt := range opts { - opt(&o) + opt.apply(&cfg) } - if o.client == nil { - o.client = http.DefaultClient + if cfg.client == nil { + cfg.client = http.DefaultClient } return &Exporter{ url: collectorURL, - client: o.client, - logger: o.logger, - o: o, + client: cfg.client, + logger: cfg.logger, + config: cfg, }, nil } @@ -113,7 +121,7 @@ func NewExportPipeline(collectorURL string, opts ...Option) (*sdktrace.TracerPro return nil, err } - tpOpts := append(exporter.o.tpOpts, sdktrace.WithBatcher(exporter)) + tpOpts := append(exporter.config.tpOpts, sdktrace.WithBatcher(exporter)) tp := sdktrace.NewTracerProvider(tpOpts...) return tp, err diff --git a/oteltest/config.go b/oteltest/config.go index da695da4aa3..bf12c28d9e7 100644 --- a/oteltest/config.go +++ b/oteltest/config.go @@ -53,7 +53,7 @@ type config struct { func newConfig(opts ...Option) config { conf := config{} for _, opt := range opts { - opt.Apply(&conf) + opt.apply(&conf) } if conf.SpanContextFunc == nil { conf.SpanContextFunc = defaultSpanContextFunc() @@ -63,24 +63,14 @@ func newConfig(opts ...Option) config { // Option applies an option to a config. type Option interface { - Apply(*config) - - // A private method to prevent users implementing the - // interface and so future additions to it will not - // violate compatibility. - private() + apply(*config) } -type option struct{} - -func (option) private() {} - type spanContextFuncOption struct { - option SpanContextFunc func(context.Context) trace.SpanContext } -func (o spanContextFuncOption) Apply(c *config) { +func (o spanContextFuncOption) apply(c *config) { c.SpanContextFunc = o.SpanContextFunc } @@ -91,11 +81,10 @@ func WithSpanContextFunc(f func(context.Context) trace.SpanContext) Option { } type spanRecorderOption struct { - option SpanRecorder *SpanRecorder } -func (o spanRecorderOption) Apply(c *config) { +func (o spanRecorderOption) apply(c *config) { c.SpanRecorder = o.SpanRecorder } diff --git a/sdk/metric/controller/basic/config.go b/sdk/metric/controller/basic/config.go index 87be85b9000..4e16afa90cc 100644 --- a/sdk/metric/controller/basic/config.go +++ b/sdk/metric/controller/basic/config.go @@ -21,8 +21,8 @@ import ( "go.opentelemetry.io/otel/sdk/resource" ) -// Config contains configuration for a basic Controller. -type Config struct { +// config contains configuration for a basic Controller. +type config struct { // Resource is the OpenTelemetry resource associated with all Meters // created by the Controller. Resource *resource.Resource @@ -60,8 +60,8 @@ 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 sets the Option value of a Config. + apply(*config) } // WithResource sets the Resource configuration option of a Config by merging it @@ -73,8 +73,8 @@ func WithResource(r *resource.Resource) Option { type resourceOption struct{ *resource.Resource } -func (o resourceOption) Apply(config *Config) { - config.Resource = o.Resource +func (o resourceOption) apply(cfg *config) { + cfg.Resource = o.Resource } // WithCollectPeriod sets the CollectPeriod configuration option of a Config. @@ -84,8 +84,8 @@ func WithCollectPeriod(period time.Duration) Option { type collectPeriodOption time.Duration -func (o collectPeriodOption) Apply(config *Config) { - config.CollectPeriod = time.Duration(o) +func (o collectPeriodOption) apply(cfg *config) { + cfg.CollectPeriod = time.Duration(o) } // WithCollectTimeout sets the CollectTimeout configuration option of a Config. @@ -95,8 +95,8 @@ func WithCollectTimeout(timeout time.Duration) Option { type collectTimeoutOption time.Duration -func (o collectTimeoutOption) Apply(config *Config) { - config.CollectTimeout = time.Duration(o) +func (o collectTimeoutOption) apply(cfg *config) { + cfg.CollectTimeout = time.Duration(o) } // WithExporter sets the exporter configuration option of a Config. @@ -106,8 +106,8 @@ func WithExporter(exporter export.Exporter) Option { type exporterOption struct{ exporter export.Exporter } -func (o exporterOption) Apply(config *Config) { - config.Exporter = o.exporter +func (o exporterOption) apply(cfg *config) { + cfg.Exporter = o.exporter } // WithPushTimeout sets the PushTimeout configuration option of a Config. @@ -117,6 +117,6 @@ func WithPushTimeout(timeout time.Duration) Option { type pushTimeoutOption time.Duration -func (o pushTimeoutOption) Apply(config *Config) { - config.PushTimeout = time.Duration(o) +func (o pushTimeoutOption) apply(cfg *config) { + cfg.PushTimeout = time.Duration(o) } diff --git a/sdk/metric/controller/basic/config_test.go b/sdk/metric/controller/basic/config_test.go index 51a42494b5e..8bbf07de81e 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.NewWithAttributes(attribute.String("A", "a")) - c := &Config{} - WithResource(r).Apply(c) + c := &config{} + 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{}} + 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 9a2e12777b4..59fa444a1ab 100644 --- a/sdk/metric/controller/basic/controller.go +++ b/sdk/metric/controller/basic/controller.go @@ -78,13 +78,13 @@ type Controller struct { // options (including optional exporter) to configure a metric // export pipeline. func New(checkpointer export.Checkpointer, opts ...Option) *Controller { - c := &Config{ + c := &config{ CollectPeriod: DefaultPeriod, CollectTimeout: DefaultPeriod, PushTimeout: DefaultPeriod, } for _, opt := range opts { - opt.Apply(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 39d1972dc9b..e4b3847ad2b 100644 --- a/sdk/metric/processor/basic/basic.go +++ b/sdk/metric/processor/basic/basic.go @@ -93,7 +93,7 @@ type ( } state struct { - config Config + config config // RWMutex implements locking for the `CheckpointSet` interface. sync.RWMutex @@ -139,7 +139,7 @@ func New(aselector export.AggregatorSelector, eselector export.ExportKindSelecto }, } for _, opt := range opts { - opt.ApplyProcessor(&p.config) + opt.applyProcessor(&p.config) } return p } diff --git a/sdk/metric/processor/basic/config.go b/sdk/metric/processor/basic/config.go index bf9d976c809..736f646aaf8 100644 --- a/sdk/metric/processor/basic/config.go +++ b/sdk/metric/processor/basic/config.go @@ -14,8 +14,8 @@ package basic // import "go.opentelemetry.io/otel/sdk/metric/processor/basic" -// Config contains the options for configuring a basic metric processor. -type Config struct { +// config contains the options for configuring a basic metric processor. +type config struct { // Memory controls whether the processor remembers metric // instruments and label sets that were previously reported. // When Memory is true, CheckpointSet.ForEach() will visit @@ -24,7 +24,7 @@ type Config struct { } type Option interface { - ApplyProcessor(*Config) + applyProcessor(*config) } // WithMemory sets the memory behavior of a Processor. If this is @@ -37,6 +37,6 @@ func WithMemory(memory bool) Option { type memoryOption bool -func (m memoryOption) ApplyProcessor(config *Config) { - config.Memory = bool(m) +func (m memoryOption) applyProcessor(cfg *config) { + cfg.Memory = bool(m) } diff --git a/sdk/resource/config.go b/sdk/resource/config.go index d83a3ece263..7324b745d19 100644 --- a/sdk/resource/config.go +++ b/sdk/resource/config.go @@ -28,19 +28,10 @@ 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) - - // A private method to prevent users implementing the - // interface and so future additions to it will not - // violate compatibility. - private() + // apply sets the Option value of a config. + apply(*config) } -type option struct{} - -func (option) private() {} - // WithAttributes adds attributes to the configured Resource. func WithAttributes(attributes ...attribute.KeyValue) Option { return WithDetectors(detectAttributes{attributes}) @@ -60,12 +51,10 @@ func WithDetectors(detectors ...Detector) Option { } type detectorsOption struct { - option detectors []Detector } -// Apply implements Option. -func (o detectorsOption) Apply(cfg *config) { +func (o detectorsOption) apply(cfg *config) { cfg.detectors = append(cfg.detectors, o.detectors...) } diff --git a/sdk/resource/resource.go b/sdk/resource/resource.go index baf9f2c977e..a2d36ae13e7 100644 --- a/sdk/resource/resource.go +++ b/sdk/resource/resource.go @@ -47,7 +47,7 @@ var ( func New(ctx context.Context, opts ...Option) (*Resource, error) { cfg := config{} for _, opt := range opts { - opt.Apply(&cfg) + opt.apply(&cfg) } return Detect(ctx, cfg.detectors...) diff --git a/sdk/trace/provider.go b/sdk/trace/provider.go index 83e1fe5e8d3..083c0b9946a 100644 --- a/sdk/trace/provider.go +++ b/sdk/trace/provider.go @@ -31,11 +31,13 @@ const ( defaultTracerName = "go.opentelemetry.io/otel/sdk/tracer" ) -// TODO (MrAlias): unify this API option design: -// https://github.com/open-telemetry/opentelemetry-go/issues/536 - -// TracerProviderConfig -type TracerProviderConfig struct { +// tracerProviderConfig +type tracerProviderConfig struct { + // processors contains collection of SpanProcessors that are processing pipeline + // for spans in the trace signal. + // SpanProcessors registered with a TracerProvider and are called at the start + // and end of a Span's lifecycle, and are called in the order they are + // registered. processors []SpanProcessor // sampler is the default sampler used when creating new spans. @@ -51,8 +53,6 @@ type TracerProviderConfig struct { resource *resource.Resource } -type TracerProviderOption func(*TracerProviderConfig) - type TracerProvider struct { mu sync.Mutex namedTracer map[instrumentation.Library]*tracer @@ -76,10 +76,10 @@ 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(o) + opt.apply(o) } ensureValidTracerProviderConfig(o) @@ -234,6 +234,16 @@ func (p *TracerProvider) Shutdown(ctx context.Context) error { return nil } +type TracerProviderOption interface { + apply(*tracerProviderConfig) +} + +type traceProviderOptionFunc func(*tracerProviderConfig) + +func (fn traceProviderOptionFunc) apply(cfg *tracerProviderConfig) { + fn(cfg) +} + // WithSyncer registers the exporter with the TracerProvider using a // SimpleSpanProcessor. // @@ -254,9 +264,9 @@ func WithBatcher(e SpanExporter, opts ...BatchSpanProcessorOption) TracerProvide // WithSpanProcessor registers the SpanProcessor with a TracerProvider. func WithSpanProcessor(sp SpanProcessor) TracerProviderOption { - return func(opts *TracerProviderConfig) { - opts.processors = append(opts.processors, sp) - } + return traceProviderOptionFunc(func(cfg *tracerProviderConfig) { + cfg.processors = append(cfg.processors, sp) + }) } // WithResource returns a TracerProviderOption that will configure the @@ -267,9 +277,9 @@ 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 func(opts *TracerProviderConfig) { - opts.resource = resource.Merge(resource.Environment(), r) - } + return traceProviderOptionFunc(func(cfg *tracerProviderConfig) { + cfg.resource = resource.Merge(resource.Environment(), r) + }) } // WithIDGenerator returns a TracerProviderOption that will configure the @@ -280,11 +290,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 func(opts *TracerProviderConfig) { + return traceProviderOptionFunc(func(cfg *tracerProviderConfig) { if g != nil { - opts.idGenerator = g + cfg.idGenerator = g } - } + }) } // WithSampler returns a TracerProviderOption that will configure the Sampler @@ -295,11 +305,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 func(opts *TracerProviderConfig) { + return traceProviderOptionFunc(func(cfg *tracerProviderConfig) { if s != nil { - opts.sampler = s + cfg.sampler = s } - } + }) } // WithSpanLimits returns a TracerProviderOption that will configure the @@ -310,13 +320,13 @@ func WithSampler(s Sampler) TracerProviderOption { // If this option is not used, the TracerProvider will use the default // SpanLimits. func WithSpanLimits(sl SpanLimits) TracerProviderOption { - return func(opts *TracerProviderConfig) { - opts.spanLimits = sl - } + return traceProviderOptionFunc(func(cfg *tracerProviderConfig) { + cfg.spanLimits = sl + }) } // ensureValidTracerProviderConfig ensures that given TracerProviderConfig is valid. -func ensureValidTracerProviderConfig(cfg *TracerProviderConfig) { +func ensureValidTracerProviderConfig(cfg *tracerProviderConfig) { if cfg.sampler == nil { cfg.sampler = ParentBased(AlwaysSample()) } diff --git a/sdk/trace/sampling.go b/sdk/trace/sampling.go index 86fc3108dc3..5345f82882e 100644 --- a/sdk/trace/sampling.go +++ b/sdk/trace/sampling.go @@ -164,11 +164,11 @@ func ParentBased(root Sampler, samplers ...ParentBasedSamplerOption) Sampler { type parentBased struct { root Sampler - config config + config samplerConfig } -func configureSamplersForParentBased(samplers []ParentBasedSamplerOption) config { - c := config{ +func configureSamplersForParentBased(samplers []ParentBasedSamplerOption) samplerConfig { + c := samplerConfig{ remoteParentSampled: AlwaysSample(), remoteParentNotSampled: NeverSample(), localParentSampled: AlwaysSample(), @@ -176,26 +176,21 @@ func configureSamplersForParentBased(samplers []ParentBasedSamplerOption) config } for _, so := range samplers { - so.Apply(&c) + so.apply(&c) } return c } -// config is a group of options for parentBased sampler. -type config struct { +// samplerConfig is a group of options for parentBased sampler. +type samplerConfig struct { remoteParentSampled, remoteParentNotSampled Sampler localParentSampled, localParentNotSampled Sampler } // ParentBasedSamplerOption configures the sampler for a particular sampling case. type ParentBasedSamplerOption interface { - Apply(*config) - - // A private method to prevent users implementing the - // interface and so future additions to it will not - // violate compatibility. - private() + apply(*samplerConfig) } // WithRemoteParentSampled sets the sampler for the case of sampled remote parent. @@ -207,12 +202,10 @@ type remoteParentSampledOption struct { s Sampler } -func (o remoteParentSampledOption) Apply(config *config) { +func (o remoteParentSampledOption) apply(config *samplerConfig) { config.remoteParentSampled = o.s } -func (remoteParentSampledOption) private() {} - // WithRemoteParentNotSampled sets the sampler for the case of remote parent // which is not sampled. func WithRemoteParentNotSampled(s Sampler) ParentBasedSamplerOption { @@ -223,12 +216,10 @@ type remoteParentNotSampledOption struct { s Sampler } -func (o remoteParentNotSampledOption) Apply(config *config) { +func (o remoteParentNotSampledOption) apply(config *samplerConfig) { config.remoteParentNotSampled = o.s } -func (remoteParentNotSampledOption) private() {} - // WithLocalParentSampled sets the sampler for the case of sampled local parent. func WithLocalParentSampled(s Sampler) ParentBasedSamplerOption { return localParentSampledOption{s} @@ -238,12 +229,10 @@ type localParentSampledOption struct { s Sampler } -func (o localParentSampledOption) Apply(config *config) { +func (o localParentSampledOption) apply(config *samplerConfig) { config.localParentSampled = o.s } -func (localParentSampledOption) private() {} - // WithLocalParentNotSampled sets the sampler for the case of local parent // which is not sampled. func WithLocalParentNotSampled(s Sampler) ParentBasedSamplerOption { @@ -254,12 +243,10 @@ type localParentNotSampledOption struct { s Sampler } -func (o localParentNotSampledOption) Apply(config *config) { +func (o localParentNotSampledOption) apply(config *samplerConfig) { config.localParentNotSampled = o.s } -func (localParentNotSampledOption) private() {} - func (pb parentBased) ShouldSample(p SamplingParameters) SamplingResult { psc := trace.SpanContextFromContext(p.ParentContext) if psc.IsValid() {