diff --git a/src/OpenTelemetry/CHANGELOG.md b/src/OpenTelemetry/CHANGELOG.md index f5cc05ea1d0..c7f737de356 100644 --- a/src/OpenTelemetry/CHANGELOG.md +++ b/src/OpenTelemetry/CHANGELOG.md @@ -2,8 +2,12 @@ ## Unreleased -* Renaming `BroadcastActivityProcessor` to `FanOutActivityProcessor` (#1015) -* Introduce `SuppressInstrumentationScope` API (#988). +* Support wildcard pattern matching for ActivitySource + ([#1023](https://github.com/open-telemetry/opentelemetry-dotnet/pull/1023)). +* Renaming `BroadcastActivityProcessor` to `FanOutActivityProcessor` + ([#1015](https://github.com/open-telemetry/opentelemetry-dotnet/pull/1015)). +* Introduce `SuppressInstrumentationScope` API + ([#988](https://github.com/open-telemetry/opentelemetry-dotnet/pull/988)). * `ActivityProcessor` implements `IDisposable`. * When `Dispose` occurs, it calls `ShutdownAsync`. * If you want a custom behavior for dispose, you will have to override the diff --git a/src/OpenTelemetry/Sdk.cs b/src/OpenTelemetry/Sdk.cs index d8412ca82dd..e8fae911f9a 100644 --- a/src/OpenTelemetry/Sdk.cs +++ b/src/OpenTelemetry/Sdk.cs @@ -18,6 +18,8 @@ using System.Collections.Generic; using System.Diagnostics; using System.Linq; +using System.Text; +using System.Text.RegularExpressions; using System.Threading; using OpenTelemetry.Metrics; using OpenTelemetry.Metrics.Export; @@ -163,11 +165,29 @@ public static TracerProvider CreateTracerProvider(Action public static TracerProvider CreateTracerProvider(IEnumerable sources, Sampler sampler = null, Resource resource = null) { - var activitySources = new Dictionary(StringComparer.OrdinalIgnoreCase); + if (sources == null) + { + throw new ArgumentNullException(nameof(sources)); + } + + if (!sources.Any()) + { + throw new ArgumentException($"{nameof(sources)} collection is empty."); + } + + var wildcardMode = false; foreach (var name in sources) { - activitySources[name] = true; + if (string.IsNullOrWhiteSpace(name)) + { + throw new ArgumentException($"{nameof(sources)} collection contains null or whitespace strings."); + } + + if (name.Contains('*')) + { + wildcardMode = true; + } } var provider = new TracerProviderSdk @@ -176,7 +196,7 @@ public static TracerProvider CreateTracerProvider(IEnumerable sources, S Sampler = sampler, }; - provider.ActivityListener = new ActivityListener + var listener = new ActivityListener { // Callback when Activity is started. ActivityStarted = (activity) => @@ -195,10 +215,6 @@ public static TracerProvider CreateTracerProvider(IEnumerable sources, S provider.ActivityProcessor?.OnEnd(activity); }, - // Function which takes ActivitySource and returns true/false to indicate if it should be subscribed to - // or not. - ShouldListenTo = (activitySource) => activitySources.ContainsKey(activitySource.Name), - // Setting this to true means TraceId will be always // available in sampling callbacks and will be the actual // traceid used, if activity ends up getting created. @@ -208,7 +224,32 @@ public static TracerProvider CreateTracerProvider(IEnumerable sources, S GetRequestedDataUsingContext = (ref ActivityCreationOptions options) => ComputeActivityDataRequest(options, sampler), }; - ActivitySource.AddActivityListener(provider.ActivityListener); + if (wildcardMode) + { + var pattern = "^(" + string.Join("|", from name in 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 + // or not. + listener.ShouldListenTo = (activitySource) => regex.IsMatch(activitySource.Name); + } + else + { + var activitySources = new Dictionary(StringComparer.OrdinalIgnoreCase); + + foreach (var name in sources) + { + activitySources[name] = true; + } + + // Function which takes ActivitySource and returns true/false to indicate if it should be subscribed to + // or not. + listener.ShouldListenTo = (activitySource) => activitySources.ContainsKey(activitySource.Name); + } + + ActivitySource.AddActivityListener(listener); + + provider.ActivityListener = listener; return provider; }