diff --git a/CHANGELOG.md b/CHANGELOG.md index 3e9f4d5..a9165db 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). ## [Unreleased] +- Split up the tracing configuration options so user can decide exactly what gets traced and when [#104](https://github.com/xmidt-org/candlelight/pull/104) ## [v0.0.14] - Updated traceProvider to only sample traces with remote parents (configurable) [#100](https://github.com/xmidt-org/candlelight/pull/100) diff --git a/config.go b/config.go index e7b8926..f80a2ac 100644 --- a/config.go +++ b/config.go @@ -40,10 +40,16 @@ type Config struct { // TracerProvider. Providers map[string]ProviderConstructor `json:"-"` - // SampleLocalTraces defines whether local traces will be created and exported. - // SampleLocalTraces = true if you want to create and export local traces. Otherwise, - // only remote traces/spans will be sampled. - SampleLocalTraces bool `json:"sampleLocalTraces"` + // ParentBased and NoParent dictate if and when new spans should be created. + // ParentBased = "ignore" (default), tracing is effectively turned off and the "NoParent" value is ignored + // ParentBased = "honor", the sampling decision is made by the parent of the span + ParentBased string `json:"parentBased"` + + // NoParent decides if a root span should be initiated in the case where there is no existing parent + // This value is ignored if ParentBased = "ignore" + // NoParent = "never" (default), root spans are not initiated + // NoParent = "always", roots spans are initiated + NoParent string `json:"noParent"` } // TraceConfig will be used in TraceMiddleware to use config and TraceProvider diff --git a/tracerProvider.go b/tracerProvider.go index a658cf0..5c9d469 100644 --- a/tracerProvider.go +++ b/tracerProvider.go @@ -38,6 +38,8 @@ import ( var ( ErrTracerProviderNotFound = errors.New("TracerProvider builder could not be found") ErrTracerProviderBuildFailed = errors.New("Failed building TracerProvider") + ErrInvalidParentBasedValue = errors.New("Invalid ParentBased value provided in configuration") + ErrInvalidNoParentValue = errors.New("Invalid No Parent value provided in configuration") ) // DefaultTracerProvider is used when no provider is given. @@ -57,7 +59,8 @@ func ConfigureTracerProvider(config Config) (trace.TracerProvider, error) { // Handling camelcase of provider. config.Provider = strings.ToLower(config.Provider) providerConfig := config.Providers[config.Provider] - sampleLocalTraces := config.SampleLocalTraces + parentBasedTracing := config.ParentBased + noParentTracing := config.NoParent if providerConfig == nil { providerConfig = providersConfig[config.Provider] } @@ -65,12 +68,33 @@ func ConfigureTracerProvider(config Config) (trace.TracerProvider, error) { return nil, fmt.Errorf("%w for provider %s", ErrTracerProviderNotFound, config.Provider) } - // Setting up trace sampler based on SampleLocalTraces value in config file - // Default behavior: never sample local traces - sampler := sdktrace.ParentBased(sdktrace.NeverSample()) + // If parentBased value is empty, use default value + if parentBasedTracing == "" { + parentBasedTracing = "ignore" + } + + // If noParent value is empty, use default value + if noParentTracing == "" { + noParentTracing = "never" + } + + // Setting up trace sampler based on ParentBased and NoParent values in the config + var sampler sdktrace.Sampler - if sampleLocalTraces { - sampler = sdktrace.ParentBased(sdktrace.AlwaysSample()) + if parentBasedTracing == "ignore" { + sampler = sdktrace.NeverSample() + } else if parentBasedTracing == "honor" { + if noParentTracing == "never" { + sampler = sdktrace.ParentBased(sdktrace.NeverSample()) + + } else if noParentTracing == "always" { + sampler = sdktrace.ParentBased(sdktrace.AlwaysSample()) + + } else { + return nil, ErrInvalidNoParentValue + } + } else { + return nil, ErrInvalidParentBasedValue } provider, err := providerConfig(config, sampler) diff --git a/tracerProvider_test.go b/tracerProvider_test.go index b425eed..04b7aeb 100644 --- a/tracerProvider_test.go +++ b/tracerProvider_test.go @@ -34,17 +34,82 @@ func TestConfigureTracerProvider(t *testing.T) { { Description: "Otlp/gRPC: Valid", Config: Config{ - Provider: "otlp/grpc", - Endpoint: "http://localhost", + Provider: "otlp/grpc", + Endpoint: "http://localhost", + ParentBased: "ignore", + NoParent: "never", + }, + }, + { + Description: "Otlp/gRPC: Valid", + Config: Config{ + Provider: "otlp/grpc", + Endpoint: "http://localhost", + ParentBased: "honor", + NoParent: "never", + }, + }, + { + Description: "Otlp/gRPC: Valid", + Config: Config{ + Provider: "otlp/grpc", + Endpoint: "http://localhost", + ParentBased: "honor", + NoParent: "always", + }, + }, + { + Description: "Otlp/gRPC: Valid", + Config: Config{ + Provider: "otlp/grpc", + Endpoint: "http://localhost", + ParentBased: "ignore", + NoParent: "always", }, }, { Description: "Otlp/gRPC: Missing Endpoint", Config: Config{ - Provider: "otlp/grpc", + Provider: "otlp/grpc", + ParentBased: "ignore", + NoParent: "never", }, Err: ErrTracerProviderBuildFailed, }, + { + Description: "Valid Missing ParentBased Value", + Config: Config{ + Provider: "otlp/grpc", + Endpoint: "http://localhost", + }, + }, + { + Description: "Valid Missing NoParent Value", + Config: Config{ + Provider: "otlp/grpc", + Endpoint: "http://localhost", + ParentBased: "honor", + }, + }, + { + Description: "Invalid ParentBased Value", + Config: Config{ + Provider: "otlp/grpc", + Endpoint: "http://localhost", + ParentBased: "dishonor", + }, + Err: ErrInvalidParentBasedValue, + }, + { + Description: "Invalid No Parent Value", + Config: Config{ + Provider: "otlp/grpc", + Endpoint: "http://localhost", + ParentBased: "honor", + NoParent: "sometimes", + }, + Err: ErrInvalidNoParentValue, + }, { Description: "Otlp/HTTP: Valid", Config: Config{