diff --git a/src/OpenTelemetry/.publicApi/net452/PublicAPI.Unshipped.txt b/src/OpenTelemetry/.publicApi/net452/PublicAPI.Unshipped.txt index 8de35a2051f..91ef33bbb57 100644 --- a/src/OpenTelemetry/.publicApi/net452/PublicAPI.Unshipped.txt +++ b/src/OpenTelemetry/.publicApi/net452/PublicAPI.Unshipped.txt @@ -1,4 +1,30 @@ OpenTelemetry.Trace.ParentBasedSampler.ParentBasedSampler(OpenTelemetry.Trace.Sampler rootSampler, OpenTelemetry.Trace.Sampler remoteParentSampled = null, OpenTelemetry.Trace.Sampler remoteParentNotSampled = null, OpenTelemetry.Trace.Sampler localParentSampled = null, OpenTelemetry.Trace.Sampler localParentNotSampled = null) -> void +OpenTelemetry.Trace.TracerProviderBuilderSdk +OpenTelemetry.Trace.TracerProviderBuilderSdk.TracerProviderBuilderSdk() -> void +OpenTelemetry.Trace.TracerProviderSdkOptions +OpenTelemetry.Trace.TracerProviderSdkOptions.InstrumentationFactories.get -> System.Collections.Generic.ICollection +OpenTelemetry.Trace.TracerProviderSdkOptions.InstrumentationFactory +OpenTelemetry.Trace.TracerProviderSdkOptions.InstrumentationFactory.InstrumentationFactory() -> void +OpenTelemetry.Trace.TracerProviderSdkOptions.InstrumentationFactory.InstrumentationFactory(string name, string version, System.Func factory) -> void +OpenTelemetry.Trace.TracerProviderSdkOptions.LegacyActivityOperationNames.get -> System.Collections.Generic.IDictionary +OpenTelemetry.Trace.TracerProviderSdkOptions.ProcessorFactories.get -> System.Collections.Generic.ICollection>> +OpenTelemetry.Trace.TracerProviderSdkOptions.ResourceFactory.get -> System.Func +OpenTelemetry.Trace.TracerProviderSdkOptions.ResourceFactory.set -> void +OpenTelemetry.Trace.TracerProviderSdkOptions.SamplerFactory.get -> System.Func +OpenTelemetry.Trace.TracerProviderSdkOptions.SamplerFactory.set -> void +OpenTelemetry.Trace.TracerProviderSdkOptions.SetErrorStatusOnException.get -> bool +OpenTelemetry.Trace.TracerProviderSdkOptions.SetErrorStatusOnException.set -> void +OpenTelemetry.Trace.TracerProviderSdkOptions.Sources.get -> System.Collections.Generic.ICollection +OpenTelemetry.Trace.TracerProviderSdkOptions.TracerProviderSdkOptions() -> void +override OpenTelemetry.Trace.TracerProviderBuilderSdk.AddInstrumentation(System.Func instrumentationFactory) -> OpenTelemetry.Trace.TracerProviderBuilder +override OpenTelemetry.Trace.TracerProviderBuilderSdk.AddSource(params string[] names) -> OpenTelemetry.Trace.TracerProviderBuilder +readonly OpenTelemetry.Trace.TracerProviderBuilderSdk.options -> OpenTelemetry.Trace.TracerProviderSdkOptions +readonly OpenTelemetry.Trace.TracerProviderSdkOptions.InstrumentationFactory.Factory -> System.Func +readonly OpenTelemetry.Trace.TracerProviderSdkOptions.InstrumentationFactory.Name -> string +readonly OpenTelemetry.Trace.TracerProviderSdkOptions.InstrumentationFactory.Version -> string static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddLegacySource(this OpenTelemetry.Trace.TracerProviderBuilder tracerProviderBuilder, string operationName) -> OpenTelemetry.Trace.TracerProviderBuilder +static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddProcessor(this OpenTelemetry.Trace.TracerProviderBuilder tracerProviderBuilder, System.Func> processorFactory) -> OpenTelemetry.Trace.TracerProviderBuilder static OpenTelemetry.Trace.TracerProviderBuilderExtensions.SetErrorStatusOnException(this OpenTelemetry.Trace.TracerProviderBuilder tracerProviderBuilder, bool enabled = true) -> OpenTelemetry.Trace.TracerProviderBuilder +static OpenTelemetry.Trace.TracerProviderBuilderExtensions.SetResourceBuilder(this OpenTelemetry.Trace.TracerProviderBuilder tracerProviderBuilder, System.Func resourceFactory) -> OpenTelemetry.Trace.TracerProviderBuilder +static OpenTelemetry.Trace.TracerProviderBuilderExtensions.SetSampler(this OpenTelemetry.Trace.TracerProviderBuilder tracerProviderBuilder, System.Func samplerFactory) -> OpenTelemetry.Trace.TracerProviderBuilder static OpenTelemetry.Trace.TracerProviderExtensions.ForceFlush(this OpenTelemetry.Trace.TracerProvider provider, int timeoutMilliseconds = -1) -> bool diff --git a/src/OpenTelemetry/Trace/TracerProviderBuilderExtensions.cs b/src/OpenTelemetry/Trace/TracerProviderBuilderExtensions.cs index 17b6ac026ce..73663301a48 100644 --- a/src/OpenTelemetry/Trace/TracerProviderBuilderExtensions.cs +++ b/src/OpenTelemetry/Trace/TracerProviderBuilderExtensions.cs @@ -49,7 +49,23 @@ public static TracerProviderBuilder SetSampler(this TracerProviderBuilder tracer { if (tracerProviderBuilder is TracerProviderBuilderSdk tracerProviderBuilderSdk) { - tracerProviderBuilderSdk.SetSampler(sampler); + tracerProviderBuilderSdk.SetSampler(() => sampler); + } + + return tracerProviderBuilder; + } + + /// + /// Sets sampler. + /// + /// TracerProviderBuilder instance. + /// Sampler instance. + /// Returns for chaining. + public static TracerProviderBuilder SetSampler(this TracerProviderBuilder tracerProviderBuilder, Func samplerFactory) + { + if (tracerProviderBuilder is TracerProviderBuilderSdk tracerProviderBuilderSdk) + { + tracerProviderBuilderSdk.SetSampler(samplerFactory); } return tracerProviderBuilder; @@ -66,7 +82,24 @@ public static TracerProviderBuilder SetResourceBuilder(this TracerProviderBuilde { if (tracerProviderBuilder is TracerProviderBuilderSdk tracerProviderBuilderSdk) { - tracerProviderBuilderSdk.SetResourceBuilder(resourceBuilder); + tracerProviderBuilderSdk.SetResource(() => resourceBuilder.Build()); + } + + return tracerProviderBuilder; + } + + /// + /// Sets the from which the Resource associated with + /// this provider is built from. Overwrites currently set ResourceBuilder. + /// + /// TracerProviderBuilder instance. + /// from which Resource will be built. + /// Returns for chaining. + public static TracerProviderBuilder SetResourceBuilder(this TracerProviderBuilder tracerProviderBuilder, Func resourceFactory) + { + if (tracerProviderBuilder is TracerProviderBuilderSdk tracerProviderBuilderSdk) + { + tracerProviderBuilderSdk.SetResource(resourceFactory); } return tracerProviderBuilder; @@ -76,13 +109,29 @@ public static TracerProviderBuilder SetResourceBuilder(this TracerProviderBuilde /// Adds processor to the provider. /// /// TracerProviderBuilder instance. - /// Activity processor to add. + /// to add. /// Returns for chaining. public static TracerProviderBuilder AddProcessor(this TracerProviderBuilder tracerProviderBuilder, BaseProcessor processor) { if (tracerProviderBuilder is TracerProviderBuilderSdk tracerProviderBuilderSdk) { - tracerProviderBuilderSdk.AddProcessor(processor); + tracerProviderBuilderSdk.AddProcessor(() => processor); + } + + return tracerProviderBuilder; + } + + /// + /// Adds processor to the provider. + /// + /// TracerProviderBuilder instance. + /// Function that builds a instance to add. + /// Returns for chaining. + public static TracerProviderBuilder AddProcessor(this TracerProviderBuilder tracerProviderBuilder, Func> processorFactory) + { + if (tracerProviderBuilder is TracerProviderBuilderSdk tracerProviderBuilderSdk) + { + tracerProviderBuilderSdk.AddProcessor(processorFactory); } return tracerProviderBuilder; diff --git a/src/OpenTelemetry/Trace/TracerProviderBuilderSdk.cs b/src/OpenTelemetry/Trace/TracerProviderBuilderSdk.cs index 3a9c6de9827..54c55fad1c3 100644 --- a/src/OpenTelemetry/Trace/TracerProviderBuilderSdk.cs +++ b/src/OpenTelemetry/Trace/TracerProviderBuilderSdk.cs @@ -15,7 +15,6 @@ // using System; -using System.Collections.Generic; using System.Diagnostics; using OpenTelemetry.Resources; @@ -24,18 +23,9 @@ namespace OpenTelemetry.Trace /// /// Build TracerProvider with Resource, Sampler, Processors and Instrumentation. /// - internal class TracerProviderBuilderSdk : TracerProviderBuilder + public class TracerProviderBuilderSdk : TracerProviderBuilder { - private readonly List instrumentationFactories = new List(); - private readonly List> processors = new List>(); - private readonly List sources = new List(); - private readonly Dictionary legacyActivityOperationNames = new Dictionary(StringComparer.OrdinalIgnoreCase); - private ResourceBuilder resourceBuilder = ResourceBuilder.CreateDefault(); - private Sampler sampler = new ParentBasedSampler(new AlwaysOnSampler()); - - internal TracerProviderBuilderSdk() - { - } + protected readonly TracerProviderSdkOptions options = new TracerProviderSdkOptions(); /// /// Adds an instrumentation to the provider. @@ -52,8 +42,8 @@ public override TracerProviderBuilder AddInstrumentation( throw new ArgumentNullException(nameof(instrumentationFactory)); } - this.instrumentationFactories.Add( - new InstrumentationFactory( + this.options.InstrumentationFactories.Add( + new TracerProviderSdkOptions.InstrumentationFactory( typeof(TInstrumentation).Name, "semver:" + typeof(TInstrumentation).Assembly.GetName().Version, instrumentationFactory)); @@ -82,7 +72,7 @@ public override TracerProviderBuilder AddSource(params string[] names) // TODO: We need to fix the listening model. // Today it ignores version. - this.sources.Add(name); + this.options.Sources.Add(name); } return this; @@ -96,35 +86,7 @@ public override TracerProviderBuilder AddSource(params string[] names) /// Returns for chaining. internal TracerProviderBuilder SetErrorStatusOnException(bool enabled) { - ExceptionProcessor existingExceptionProcessor = null; - - if (this.processors.Count > 0) - { - existingExceptionProcessor = this.processors[0] as ExceptionProcessor; - } - - if (enabled) - { - if (existingExceptionProcessor == null) - { - try - { - this.processors.Insert(0, new ExceptionProcessor()); - } - catch (Exception ex) - { - throw new NotSupportedException("SetErrorStatusOnException is not supported on this platform.", ex); - } - } - } - else - { - if (existingExceptionProcessor != null) - { - this.processors.RemoveAt(0); - existingExceptionProcessor.Dispose(); - } - } + this.options.SetErrorStatusOnException = enabled; return this; } @@ -132,11 +94,16 @@ internal TracerProviderBuilder SetErrorStatusOnException(bool enabled) /// /// Sets sampler. /// - /// Sampler instance. + /// Function that builds a instance. /// Returns for chaining. - internal TracerProviderBuilder SetSampler(Sampler sampler) + internal TracerProviderBuilder SetSampler(Func samplerFactory) { - this.sampler = sampler ?? throw new ArgumentNullException(nameof(sampler)); + if (samplerFactory == null) + { + throw new ArgumentNullException(nameof(samplerFactory)); + } + + this.options.SamplerFactory = samplerFactory; return this; } @@ -144,27 +111,32 @@ internal TracerProviderBuilder SetSampler(Sampler sampler) /// Sets the from which the Resource associated with /// this provider is built from. Overwrites currently set ResourceBuilder. /// - /// from which Resource will be built. + /// Function that builds a instance. /// Returns for chaining. - internal TracerProviderBuilder SetResourceBuilder(ResourceBuilder resourceBuilder) + internal TracerProviderBuilder SetResource(Func resourceFactory) { - this.resourceBuilder = resourceBuilder ?? throw new ArgumentNullException(nameof(resourceBuilder)); + if (resourceFactory == null) + { + throw new ArgumentNullException(nameof(resourceFactory)); + } + + this.options.ResourceFactory = resourceFactory; return this; } /// /// Adds processor to the provider. /// - /// Activity processor to add. + /// Function that builds a instance to add. /// Returns for chaining. - internal TracerProviderBuilder AddProcessor(BaseProcessor processor) + internal TracerProviderBuilder AddProcessor(Func> processorFactory) { - if (processor == null) + if (processorFactory == null) { - throw new ArgumentNullException(nameof(processor)); + throw new ArgumentNullException(nameof(processorFactory)); } - this.processors.Add(processor); + this.options.ProcessorFactories.Add(processorFactory); return this; } @@ -184,34 +156,14 @@ internal TracerProviderBuilder AddLegacySource(string operationName) throw new ArgumentException($"{nameof(operationName)} contains null or whitespace string."); } - this.legacyActivityOperationNames[operationName] = true; + this.options.LegacyActivityOperationNames[operationName] = true; return this; } internal TracerProvider Build() { - return new TracerProviderSdk( - this.resourceBuilder.Build(), - this.sources, - this.instrumentationFactories, - this.sampler, - this.processors, - this.legacyActivityOperationNames); - } - - internal readonly struct InstrumentationFactory - { - public readonly string Name; - public readonly string Version; - public readonly Func Factory; - - internal InstrumentationFactory(string name, string version, Func factory) - { - this.Name = name; - this.Version = version; - this.Factory = factory; - } + return new TracerProviderSdk(this.options); } } } diff --git a/src/OpenTelemetry/Trace/TracerProviderSdk.cs b/src/OpenTelemetry/Trace/TracerProviderSdk.cs index 82c2ec18a83..f01bfcff82c 100644 --- a/src/OpenTelemetry/Trace/TracerProviderSdk.cs +++ b/src/OpenTelemetry/Trace/TracerProviderSdk.cs @@ -32,32 +32,41 @@ internal class TracerProviderSdk : TracerProvider private readonly List instrumentations = new List(); private readonly ActivityListener listener; private readonly Sampler sampler; - private readonly Dictionary legacyActivityOperationNames; + private readonly IDictionary legacyActivityOperationNames; private BaseProcessor processor; private Action getRequestedDataAction; private bool supportLegacyActivity; - internal TracerProviderSdk( - Resource resource, - IEnumerable sources, - IEnumerable instrumentationFactories, - Sampler sampler, - List> processors, - Dictionary legacyActivityOperationNames) + internal TracerProviderSdk(TracerProviderSdkOptions options) { - this.Resource = resource; - this.sampler = sampler; - this.legacyActivityOperationNames = legacyActivityOperationNames; - this.supportLegacyActivity = legacyActivityOperationNames.Count > 0; + this.Resource = options.ResourceFactory?.Invoke(); + this.sampler = options.SamplerFactory?.Invoke(); + this.legacyActivityOperationNames = options.LegacyActivityOperationNames; + this.supportLegacyActivity = this.legacyActivityOperationNames.Count > 0; - foreach (var processor in processors) + if (options.SetErrorStatusOnException) { - this.AddProcessor(processor); + try + { + this.AddProcessor(new ExceptionProcessor()); + } + catch (Exception ex) + { + throw new NotSupportedException("SetErrorStatusOnException is not supported on this platform.", ex); + } + } + + if (options.ProcessorFactories.Any()) + { + foreach (var processor in options.ProcessorFactories) + { + this.AddProcessor(processor?.Invoke()); + } } - if (instrumentationFactories.Any()) + if (options.InstrumentationFactories.Any()) { - foreach (var instrumentationFactory in instrumentationFactories) + foreach (var instrumentationFactory in options.InstrumentationFactories) { this.instrumentations.Add(instrumentationFactory.Factory()); } @@ -73,19 +82,10 @@ internal TracerProviderSdk( if (this.supportLegacyActivity && string.IsNullOrEmpty(activity.Source.Name)) { // We have a legacy activity in hand now - if (legacyActivityOperationNames.ContainsKey(activity.OperationName)) + if (this.legacyActivityOperationNames.ContainsKey(activity.OperationName)) { - // Legacy activity matches the user configured list. - // Call sampler for the legacy activity - // unless suppressed. - if (!Sdk.SuppressInstrumentation) - { - this.getRequestedDataAction(activity); - } - else - { - activity.IsAllDataRequested = false; - } + // Legacy activity matches the user configured list. Call sampler for the legacy activity + this.getRequestedDataAction(activity); } else { @@ -113,7 +113,7 @@ internal TracerProviderSdk( if (this.supportLegacyActivity && string.IsNullOrEmpty(activity.Source.Name)) { // We have a legacy activity in hand now - if (!legacyActivityOperationNames.ContainsKey(activity.OperationName)) + if (!this.legacyActivityOperationNames.ContainsKey(activity.OperationName)) { // Legacy activity doesn't match the user configured list. No need to proceed further. return; @@ -140,13 +140,13 @@ internal TracerProviderSdk( }, }; - if (sampler is AlwaysOnSampler) + if (this.sampler is AlwaysOnSampler) { listener.Sample = (ref ActivityCreationOptions options) => !Sdk.SuppressInstrumentation ? ActivitySamplingResult.AllDataAndRecorded : ActivitySamplingResult.None; this.getRequestedDataAction = this.RunGetRequestedDataAlwaysOnSampler; } - else if (sampler is AlwaysOffSampler) + else if (this.sampler is AlwaysOffSampler) { listener.Sample = (ref ActivityCreationOptions options) => !Sdk.SuppressInstrumentation ? PropagateOrIgnoreData(options.Parent.TraceId) : ActivitySamplingResult.None; @@ -160,7 +160,7 @@ internal TracerProviderSdk( this.getRequestedDataAction = this.RunGetRequestedDataOtherSampler; } - if (sources.Any()) + if (options.Sources.Any()) { // Sources can be null. This happens when user // is only interested in InstrumentationLibraries @@ -169,7 +169,7 @@ internal TracerProviderSdk( var wildcardMode = false; // Validation of source name is already done in builder. - foreach (var name in sources) + foreach (var name in options.Sources) { if (name.Contains('*')) { @@ -179,7 +179,7 @@ internal TracerProviderSdk( if (wildcardMode) { - var pattern = "^(" + string.Join("|", from name in sources select '(' + Regex.Escape(name).Replace("\\*", ".*") + ')') + ")$"; + var pattern = "^(" + string.Join("|", from name in options.Sources select '(' + Regex.Escape(name).Replace("\\*", ".*") + ')') + ")$"; var regex = new Regex(pattern, RegexOptions.Compiled | RegexOptions.IgnoreCase); // Function which takes ActivitySource and returns true/false to indicate if it should be subscribed to @@ -193,7 +193,7 @@ internal TracerProviderSdk( { var activitySources = new Dictionary(StringComparer.OrdinalIgnoreCase); - foreach (var name in sources) + foreach (var name in options.Sources) { activitySources[name] = true; } diff --git a/src/OpenTelemetry/Trace/TracerProviderSdkOptions.cs b/src/OpenTelemetry/Trace/TracerProviderSdkOptions.cs new file mode 100644 index 00000000000..cbaf2962c84 --- /dev/null +++ b/src/OpenTelemetry/Trace/TracerProviderSdkOptions.cs @@ -0,0 +1,54 @@ +// +// Copyright The OpenTelemetry Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using OpenTelemetry.Resources; + +namespace OpenTelemetry.Trace +{ + public class TracerProviderSdkOptions + { + public Func ResourceFactory { get; set; } + + public ICollection Sources { get; } = new List(); + + public ICollection InstrumentationFactories { get; } = new List(); + + public Func SamplerFactory { get; set; } + + public ICollection>> ProcessorFactories { get; } = new List>>(); + + public IDictionary LegacyActivityOperationNames { get; } = new Dictionary(); + + public bool SetErrorStatusOnException { get; set; } = false; + + public readonly struct InstrumentationFactory + { + public readonly string Name; + public readonly string Version; + public readonly Func Factory; + + public InstrumentationFactory(string name, string version, Func factory) + { + this.Name = name; + this.Version = version; + this.Factory = factory; + } + } + } +}