diff --git a/CHANGELOG.md b/CHANGELOG.md index dab99e27b5..58a135506b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ - The ITraceContext now includes an [Origin](https://develop.sentry.dev/sdk/telemetry/traces/trace-origin/), which is set automatically and is primarily used internally by the Sentry server ([#3564](https://github.com/getsentry/sentry-dotnet/pull/3564)) - `Device.BatteryLevel` and `Device.ProcessorFrequency` are now stored as floats rather than ints, to align with the Cocoa and Java SDKs ([#3567](https://github.com/getsentry/sentry-dotnet/pull/3567)) - `SentryOptions.EnableTracing` has been removed. Instead, tracing should be enabled or disabled by setting the `SentryOptions.TracesSampleRate` or by using `SentryOptions.TracesSampler` to configure a sampling function ([#3569](https://github.com/getsentry/sentry-dotnet/pull/3569)) +- The `FailedRequestTargets`, `TagFilters` and `TracePropagationTargets` options have all been changed from `SubstringOrRegexPattern` to `IList` ([#3566](https://github.com/getsentry/sentry-dotnet/pull/3566)) ## 4.10.2 diff --git a/src/Sentry/BindableSentryOptions.cs b/src/Sentry/BindableSentryOptions.cs index cf3816ef1b..53f0c076aa 100644 --- a/src/Sentry/BindableSentryOptions.cs +++ b/src/Sentry/BindableSentryOptions.cs @@ -55,7 +55,7 @@ public void ApplyTo(SentryOptions options) { options.IsGlobalModeEnabled = IsGlobalModeEnabled ?? options.IsGlobalModeEnabled; options.EnableScopeSync = EnableScopeSync ?? options.EnableScopeSync; - options.TagFilters = TagFilters?.Select(s => new SubstringOrRegexPattern(s)).ToList() ?? options.TagFilters; + options.TagFilters = TagFilters?.Select(s => new StringOrRegex(s)).ToList() ?? options.TagFilters; options.SendDefaultPii = SendDefaultPii ?? options.SendDefaultPii; options.IsEnvironmentUser = IsEnvironmentUser ?? options.IsEnvironmentUser; options.ServerName = ServerName ?? options.ServerName; @@ -80,12 +80,12 @@ public void ApplyTo(SentryOptions options) options.DeduplicateMode = DeduplicateMode ?? options.DeduplicateMode; options.CacheDirectoryPath = CacheDirectoryPath ?? options.CacheDirectoryPath; options.CaptureFailedRequests = CaptureFailedRequests ?? options.CaptureFailedRequests; - options.FailedRequestTargets = FailedRequestTargets?.Select(s => new SubstringOrRegexPattern(s)).ToList() ?? options.FailedRequestTargets; + options.FailedRequestTargets = FailedRequestTargets?.Select(s => new StringOrRegex(s)).ToList() ?? options.FailedRequestTargets; options.InitCacheFlushTimeout = InitCacheFlushTimeout ?? options.InitCacheFlushTimeout; options.DefaultTags = DefaultTags ?? options.DefaultTags; options.TracesSampleRate = TracesSampleRate ?? options.TracesSampleRate; options.ProfilesSampleRate = ProfilesSampleRate ?? options.ProfilesSampleRate; - options.TracePropagationTargets = TracePropagationTargets?.Select(s => new SubstringOrRegexPattern(s)).ToList() ?? options.TracePropagationTargets; + options.TracePropagationTargets = TracePropagationTargets?.Select(s => new StringOrRegex(s)).ToList() ?? options.TracePropagationTargets; options.StackTraceMode = StackTraceMode ?? options.StackTraceMode; options.MaxAttachmentSize = MaxAttachmentSize ?? options.MaxAttachmentSize; options.DetectStartupTime = DetectStartupTime ?? options.DetectStartupTime; diff --git a/src/Sentry/BuiltInSystemDiagnosticsMeters.cs b/src/Sentry/BuiltInSystemDiagnosticsMeters.cs index df5b2849fa..d631557531 100644 --- a/src/Sentry/BuiltInSystemDiagnosticsMeters.cs +++ b/src/Sentry/BuiltInSystemDiagnosticsMeters.cs @@ -1,7 +1,9 @@ +using Sentry.Internal; + namespace Sentry; /// -/// Well known values for built in metrics that can be configured for +/// Well known values for built-in metrics that can be configured for /// /// public static partial class BuiltInSystemDiagnosticsMeters @@ -20,150 +22,150 @@ public static partial class BuiltInSystemDiagnosticsMeters private const string SystemNetHttpPattern = @"^System\.Net\.Http$"; /// - /// Matches the built in Microsoft.AspNetCore.Hosting metrics + /// Matches the built-in Microsoft.AspNetCore.Hosting metrics /// #if NET8_0_OR_GREATER - public static readonly SubstringOrRegexPattern MicrosoftAspNetCoreHosting = MicrosoftAspNetCoreHostingRegex(); + public static readonly StringOrRegex MicrosoftAspNetCoreHosting = MicrosoftAspNetCoreHostingRegex(); [GeneratedRegex(MicrosoftAspNetCoreHostingPattern, RegexOptions.Compiled)] private static partial Regex MicrosoftAspNetCoreHostingRegex(); #else - public static readonly SubstringOrRegexPattern MicrosoftAspNetCoreHosting = new Regex(MicrosoftAspNetCoreHostingPattern, RegexOptions.Compiled); + public static readonly StringOrRegex MicrosoftAspNetCoreHosting = new Regex(MicrosoftAspNetCoreHostingPattern, RegexOptions.Compiled); #endif /// - /// Matches the built in Microsoft.AspNetCore.Routing metrics + /// Matches the built-in Microsoft.AspNetCore.Routing metrics /// #if NET8_0_OR_GREATER - public static readonly SubstringOrRegexPattern MicrosoftAspNetCoreRouting = MicrosoftAspNetCoreRoutingRegex(); + public static readonly StringOrRegex MicrosoftAspNetCoreRouting = MicrosoftAspNetCoreRoutingRegex(); [GeneratedRegex(MicrosoftAspNetCoreRoutingPattern, RegexOptions.Compiled)] private static partial Regex MicrosoftAspNetCoreRoutingRegex(); #else - public static readonly SubstringOrRegexPattern MicrosoftAspNetCoreRouting = new Regex(MicrosoftAspNetCoreRoutingPattern, RegexOptions.Compiled); + public static readonly StringOrRegex MicrosoftAspNetCoreRouting = new Regex(MicrosoftAspNetCoreRoutingPattern, RegexOptions.Compiled); #endif /// - /// Matches the built in Microsoft.AspNetCore.Diagnostics metrics + /// Matches the built-in Microsoft.AspNetCore.Diagnostics metrics /// #if NET8_0_OR_GREATER - public static readonly SubstringOrRegexPattern MicrosoftAspNetCoreDiagnostics = MicrosoftAspNetCoreDiagnosticsRegex(); + public static readonly StringOrRegex MicrosoftAspNetCoreDiagnostics = MicrosoftAspNetCoreDiagnosticsRegex(); [GeneratedRegex(MicrosoftAspNetCoreDiagnosticsPattern, RegexOptions.Compiled)] private static partial Regex MicrosoftAspNetCoreDiagnosticsRegex(); #else - public static readonly SubstringOrRegexPattern MicrosoftAspNetCoreDiagnostics = new Regex(MicrosoftAspNetCoreDiagnosticsPattern, RegexOptions.Compiled); + public static readonly StringOrRegex MicrosoftAspNetCoreDiagnostics = new Regex(MicrosoftAspNetCoreDiagnosticsPattern, RegexOptions.Compiled); #endif /// - /// Matches the built in Microsoft.AspNetCore.RateLimiting metrics + /// Matches the built-in Microsoft.AspNetCore.RateLimiting metrics /// #if NET8_0_OR_GREATER - public static readonly SubstringOrRegexPattern MicrosoftAspNetCoreRateLimiting = MicrosoftAspNetCoreRateLimitingRegex(); + public static readonly StringOrRegex MicrosoftAspNetCoreRateLimiting = MicrosoftAspNetCoreRateLimitingRegex(); [GeneratedRegex(MicrosoftAspNetCoreRateLimitingPattern, RegexOptions.Compiled)] private static partial Regex MicrosoftAspNetCoreRateLimitingRegex(); #else - public static readonly SubstringOrRegexPattern MicrosoftAspNetCoreRateLimiting = new Regex(MicrosoftAspNetCoreRateLimitingPattern, RegexOptions.Compiled); + public static readonly StringOrRegex MicrosoftAspNetCoreRateLimiting = new Regex(MicrosoftAspNetCoreRateLimitingPattern, RegexOptions.Compiled); #endif /// - /// Matches the built in Microsoft.AspNetCore.HeaderParsing metrics + /// Matches the built-in Microsoft.AspNetCore.HeaderParsing metrics /// #if NET8_0_OR_GREATER - public static readonly SubstringOrRegexPattern MicrosoftAspNetCoreHeaderParsing = MicrosoftAspNetCoreHeaderParsingRegex(); + public static readonly StringOrRegex MicrosoftAspNetCoreHeaderParsing = MicrosoftAspNetCoreHeaderParsingRegex(); [GeneratedRegex(MicrosoftAspNetCoreHeaderParsingPattern, RegexOptions.Compiled)] private static partial Regex MicrosoftAspNetCoreHeaderParsingRegex(); #else - public static readonly SubstringOrRegexPattern MicrosoftAspNetCoreHeaderParsing = new Regex(MicrosoftAspNetCoreHeaderParsingPattern, RegexOptions.Compiled); + public static readonly StringOrRegex MicrosoftAspNetCoreHeaderParsing = new Regex(MicrosoftAspNetCoreHeaderParsingPattern, RegexOptions.Compiled); #endif /// - /// Matches the built in Microsoft.AspNetCore.Server.Kestrel metrics + /// Matches the built-in Microsoft.AspNetCore.Server.Kestrel metrics /// #if NET8_0_OR_GREATER - public static readonly SubstringOrRegexPattern MicrosoftAspNetCoreServerKestrel = MicrosoftAspNetCoreServerKestrelRegex(); + public static readonly StringOrRegex MicrosoftAspNetCoreServerKestrel = MicrosoftAspNetCoreServerKestrelRegex(); [GeneratedRegex(MicrosoftAspNetCoreServerKestrelPattern, RegexOptions.Compiled)] private static partial Regex MicrosoftAspNetCoreServerKestrelRegex(); #else - public static readonly SubstringOrRegexPattern MicrosoftAspNetCoreServerKestrel = new Regex(MicrosoftAspNetCoreServerKestrelPattern, RegexOptions.Compiled); + public static readonly StringOrRegex MicrosoftAspNetCoreServerKestrel = new Regex(MicrosoftAspNetCoreServerKestrelPattern, RegexOptions.Compiled); #endif /// - /// Matches the built in Microsoft.AspNetCore.Http.Connections metrics + /// Matches the built-in Microsoft.AspNetCore.Http.Connections metrics /// #if NET8_0_OR_GREATER - public static readonly SubstringOrRegexPattern MicrosoftAspNetCoreHttpConnections = MicrosoftAspNetCoreHttpConnectionsRegex(); + public static readonly StringOrRegex MicrosoftAspNetCoreHttpConnections = MicrosoftAspNetCoreHttpConnectionsRegex(); [GeneratedRegex(MicrosoftAspNetCoreHttpConnectionsPattern, RegexOptions.Compiled)] private static partial Regex MicrosoftAspNetCoreHttpConnectionsRegex(); #else - public static readonly SubstringOrRegexPattern MicrosoftAspNetCoreHttpConnections = new Regex(MicrosoftAspNetCoreHttpConnectionsPattern, RegexOptions.Compiled); + public static readonly StringOrRegex MicrosoftAspNetCoreHttpConnections = new Regex(MicrosoftAspNetCoreHttpConnectionsPattern, RegexOptions.Compiled); #endif /// - /// Matches the built in Microsoft.Extensions.Diagnostics.HealthChecks metrics + /// Matches the built-in Microsoft.Extensions.Diagnostics.HealthChecks metrics /// #if NET8_0_OR_GREATER - public static readonly SubstringOrRegexPattern MicrosoftExtensionsDiagnosticsHealthChecks = MicrosoftExtensionsDiagnosticsHealthChecksRegex(); + public static readonly StringOrRegex MicrosoftExtensionsDiagnosticsHealthChecks = MicrosoftExtensionsDiagnosticsHealthChecksRegex(); [GeneratedRegex(MicrosoftExtensionsDiagnosticsHealthChecksPattern, RegexOptions.Compiled)] private static partial Regex MicrosoftExtensionsDiagnosticsHealthChecksRegex(); #else - public static readonly SubstringOrRegexPattern MicrosoftExtensionsDiagnosticsHealthChecks = new Regex(MicrosoftExtensionsDiagnosticsHealthChecksPattern, RegexOptions.Compiled); + public static readonly StringOrRegex MicrosoftExtensionsDiagnosticsHealthChecks = new Regex(MicrosoftExtensionsDiagnosticsHealthChecksPattern, RegexOptions.Compiled); #endif /// - /// Matches the built in Microsoft.Extensions.Diagnostics.ResourceMonitoring metrics + /// Matches the built-in Microsoft.Extensions.Diagnostics.ResourceMonitoring metrics /// #if NET8_0_OR_GREATER - public static readonly SubstringOrRegexPattern MicrosoftExtensionsDiagnosticsResourceMonitoring = MicrosoftExtensionsDiagnosticsResourceMonitoringRegex(); + public static readonly StringOrRegex MicrosoftExtensionsDiagnosticsResourceMonitoring = MicrosoftExtensionsDiagnosticsResourceMonitoringRegex(); [GeneratedRegex(MicrosoftExtensionsDiagnosticsResourceMonitoringPattern, RegexOptions.Compiled)] private static partial Regex MicrosoftExtensionsDiagnosticsResourceMonitoringRegex(); #else - public static readonly SubstringOrRegexPattern MicrosoftExtensionsDiagnosticsResourceMonitoring = new Regex(MicrosoftExtensionsDiagnosticsResourceMonitoringPattern, RegexOptions.Compiled); + public static readonly StringOrRegex MicrosoftExtensionsDiagnosticsResourceMonitoring = new Regex(MicrosoftExtensionsDiagnosticsResourceMonitoringPattern, RegexOptions.Compiled); #endif /// - /// Matches the built in System.Net.NameResolution metrics + /// Matches the built-in System.Net.NameResolution metrics /// #if NET8_0_OR_GREATER - public static readonly SubstringOrRegexPattern OpenTelemetryInstrumentationRuntime = OpenTelemetryInstrumentationRuntimeRegex(); + public static readonly StringOrRegex OpenTelemetryInstrumentationRuntime = OpenTelemetryInstrumentationRuntimeRegex(); [GeneratedRegex(OpenTelemetryInstrumentationRuntimePattern, RegexOptions.Compiled)] private static partial Regex OpenTelemetryInstrumentationRuntimeRegex(); #else - public static readonly SubstringOrRegexPattern OpenTelemetryInstrumentationRuntime = new Regex(OpenTelemetryInstrumentationRuntimePattern, RegexOptions.Compiled); + public static readonly StringOrRegex OpenTelemetryInstrumentationRuntime = new Regex(OpenTelemetryInstrumentationRuntimePattern, RegexOptions.Compiled); #endif /// - /// Matches the built in System.Net.NameResolution metrics + /// Matches the built-in System.Net.NameResolution metrics /// #if NET8_0_OR_GREATER - public static readonly SubstringOrRegexPattern SystemNetNameResolution = SystemNetNameResolutionRegex(); + public static readonly StringOrRegex SystemNetNameResolution = SystemNetNameResolutionRegex(); [GeneratedRegex(SystemNetNameResolutionPattern, RegexOptions.Compiled)] private static partial Regex SystemNetNameResolutionRegex(); #else - public static readonly SubstringOrRegexPattern SystemNetNameResolution = new Regex(SystemNetNameResolutionPattern, RegexOptions.Compiled); + public static readonly StringOrRegex SystemNetNameResolution = new Regex(SystemNetNameResolutionPattern, RegexOptions.Compiled); #endif /// - /// Matches the built in metrics + /// Matches the built-in metrics /// #if NET8_0_OR_GREATER - public static readonly SubstringOrRegexPattern SystemNetHttp = SystemNetHttpRegex(); + public static readonly StringOrRegex SystemNetHttp = SystemNetHttpRegex(); [GeneratedRegex(SystemNetHttpPattern, RegexOptions.Compiled)] private static partial Regex SystemNetHttpRegex(); #else - public static readonly SubstringOrRegexPattern SystemNetHttp = new Regex(SystemNetHttpPattern, RegexOptions.Compiled); + public static readonly StringOrRegex SystemNetHttp = new Regex(SystemNetHttpPattern, RegexOptions.Compiled); #endif - private static readonly Lazy> LazyAll = new(() => new List + private static readonly Lazy> LazyAll = new(() => new List { MicrosoftAspNetCoreHosting, MicrosoftAspNetCoreRouting, @@ -180,8 +182,8 @@ public static partial class BuiltInSystemDiagnosticsMeters }); /// - /// Matches all built in metrics + /// Matches all built-in metrics /// /// - public static IList All => LazyAll.Value; + public static IList All => LazyAll.Value; } diff --git a/src/Sentry/ExperimentalMetricsOptions.cs b/src/Sentry/ExperimentalMetricsOptions.cs index 5a71606c36..0b07ad0e0b 100644 --- a/src/Sentry/ExperimentalMetricsOptions.cs +++ b/src/Sentry/ExperimentalMetricsOptions.cs @@ -1,3 +1,5 @@ +using Sentry.Internal; + namespace Sentry; /// @@ -11,7 +13,7 @@ public class ExperimentalMetricsOptions /// public bool EnableCodeLocations { get; set; } = true; - private IList _captureSystemDiagnosticsInstruments = new List(); + private IList _captureSystemDiagnosticsInstruments = new List(); /// /// @@ -19,13 +21,13 @@ public class ExperimentalMetricsOptions /// matches one of the items in this list will be collected and reported to Sentry. /// /// - /// These can be either custom Instruments that you have created or any of the built in metrics that are available. + /// These can be either custom Instruments that you have created or any of the built-in metrics that are available. /// /// /// See https://learn.microsoft.com/en-us/dotnet/core/diagnostics/built-in-metrics for more information. /// /// - public IList CaptureSystemDiagnosticsInstruments + public IList CaptureSystemDiagnosticsInstruments { // NOTE: During configuration binding, .NET 6 and lower used to just call Add on the existing item. // .NET 7 changed this to call the setter with an array that already starts with the old value. @@ -34,7 +36,7 @@ public IList CaptureSystemDiagnosticsInstruments set => _captureSystemDiagnosticsInstruments = value.WithConfigBinding(); } - private IList _captureSystemDiagnosticsMeters = BuiltInSystemDiagnosticsMeters.All; + private IList _captureSystemDiagnosticsMeters = BuiltInSystemDiagnosticsMeters.All; /// /// @@ -42,13 +44,13 @@ public IList CaptureSystemDiagnosticsInstruments /// whose name matches one of the items in this list will be collected and reported to Sentry. /// /// - /// These can be either custom Instruments that you have created or any of the built in metrics that are available. + /// These can be either custom Instruments that you have created or any of the built-in metrics that are available. /// /// /// See https://learn.microsoft.com/en-us/dotnet/core/diagnostics/built-in-metrics for more information. /// /// - public IList CaptureSystemDiagnosticsMeters + public IList CaptureSystemDiagnosticsMeters { // NOTE: During configuration binding, .NET 6 and lower used to just call Add on the existing item. // .NET 7 changed this to call the setter with an array that already starts with the old value. diff --git a/src/Sentry/Internal/DelimitedPrefixOrPatternMatcher.cs b/src/Sentry/Internal/DelimitedPrefixOrPatternMatcher.cs index 29e53f111a..d842c74ef9 100644 --- a/src/Sentry/Internal/DelimitedPrefixOrPatternMatcher.cs +++ b/src/Sentry/Internal/DelimitedPrefixOrPatternMatcher.cs @@ -7,11 +7,11 @@ internal class DelimitedPrefixOrPatternMatcher(char delimiter = '.', StringCompa { public bool IsMatch(StringOrRegex stringOrRegex, string value) { - if (stringOrRegex._prefix is not null) + if (stringOrRegex._string is not null) { // Check for a prefix followed by the separator - return stringOrRegex._prefix != null && value.StartsWith(stringOrRegex._prefix, comparison) && - value.Length > stringOrRegex._prefix.Length && value[stringOrRegex._prefix.Length] == delimiter; + return stringOrRegex._string != null && value.StartsWith(stringOrRegex._string, comparison) && + value.Length > stringOrRegex._string.Length && value[stringOrRegex._string.Length] == delimiter; } // Check for any regex match followed by the separator diff --git a/src/Sentry/Internal/IStringOrRegexMatcher.cs b/src/Sentry/Internal/IStringOrRegexMatcher.cs index 07345d1aca..916eb5fc55 100644 --- a/src/Sentry/Internal/IStringOrRegexMatcher.cs +++ b/src/Sentry/Internal/IStringOrRegexMatcher.cs @@ -2,5 +2,8 @@ namespace Sentry.Internal; internal interface IStringOrRegexMatcher { + /// + /// Evaluates if the given value matches the string or regex. + /// bool IsMatch(StringOrRegex stringOrRegex, string value); } diff --git a/src/Sentry/Internal/PrefixOrPatternMatcher.cs b/src/Sentry/Internal/PrefixOrPatternMatcher.cs index c07e6f6cef..1bf6f17f94 100644 --- a/src/Sentry/Internal/PrefixOrPatternMatcher.cs +++ b/src/Sentry/Internal/PrefixOrPatternMatcher.cs @@ -7,7 +7,7 @@ internal class PrefixOrPatternMatcher(StringComparison comparison = StringCompar { public bool IsMatch(StringOrRegex stringOrRegex, string value) { - return (stringOrRegex._prefix != null && value.StartsWith(stringOrRegex._prefix, comparison)) || + return (stringOrRegex._string != null && value.StartsWith(stringOrRegex._string, comparison)) || stringOrRegex?._regex?.IsMatch(value) == true; } } diff --git a/src/Sentry/Internal/StringOrRegex.cs b/src/Sentry/Internal/StringOrRegex.cs deleted file mode 100644 index 164d41728a..0000000000 --- a/src/Sentry/Internal/StringOrRegex.cs +++ /dev/null @@ -1,82 +0,0 @@ -namespace Sentry.Internal; - -/// -/// Stores either a plain string or a Regular Expression, typically to match against filters in the SentryOptions -/// -internal class StringOrRegex -{ - internal readonly Regex? _regex; - internal readonly string? _prefix; - - /// - /// Constructs a instance. - /// - /// The prefix or regular expression pattern to match on. - public StringOrRegex(string stringOrRegex) - { - _prefix = stringOrRegex; - } - - /// - /// Constructs a instance. - /// - /// - /// - /// Use this constructor when you want the match to be performed using a regular expression. - /// - public StringOrRegex(Regex regex) => _regex = regex; - - /// - /// Implicitly converts a to a . - /// - /// - public static implicit operator StringOrRegex(string stringOrRegex) - { - return new StringOrRegex(stringOrRegex); - } - - /// - /// Implicitly converts a to a . - /// - /// - public static implicit operator StringOrRegex(Regex regex) - { - return new StringOrRegex(regex); - } - - /// - public override string ToString() => _prefix ?? _regex?.ToString() ?? ""; - - /// - public override bool Equals(object? obj) - { - return - (obj is StringOrRegex pattern) - && pattern.ToString() == ToString(); - } - - /// - public override int GetHashCode() - { - return ToString().GetHashCode(); - } -} - -internal static class StringOrRegexExtensions -{ - public static bool MatchesAny(this string parameter, List? patterns, IStringOrRegexMatcher matcher) - { - if (patterns is null) - { - return false; - } - foreach (var stringOrRegex in patterns) - { - if (matcher.IsMatch(stringOrRegex, parameter)) - { - return true; - } - } - return false; - } -} diff --git a/src/Sentry/Internal/SystemDiagnosticsMetricsListener.cs b/src/Sentry/Internal/SystemDiagnosticsMetricsListener.cs index af8fe4fbbd..10d613669f 100644 --- a/src/Sentry/Internal/SystemDiagnosticsMetricsListener.cs +++ b/src/Sentry/Internal/SystemDiagnosticsMetricsListener.cs @@ -24,8 +24,8 @@ internal SystemDiagnosticsMetricsListener(ExperimentalMetricsOptions metricsOpti _metricsAggregator = new Lazy(metricsAggregatorResolver); _sentryListener.InstrumentPublished = (instrument, listener) => { - if (metricsOptions.CaptureSystemDiagnosticsMeters.ContainsMatch(instrument.Meter.Name) - || metricsOptions.CaptureSystemDiagnosticsInstruments.ContainsMatch(instrument.Name)) + if (metricsOptions.CaptureSystemDiagnosticsMeters.MatchesSubstringOrRegex(instrument.Meter.Name) + || metricsOptions.CaptureSystemDiagnosticsInstruments.MatchesSubstringOrRegex(instrument.Name)) { listener.EnableMeasurementEvents(instrument); } diff --git a/src/Sentry/Scope.cs b/src/Sentry/Scope.cs index 6d4cefb92a..8c29c7edd8 100644 --- a/src/Sentry/Scope.cs +++ b/src/Sentry/Scope.cs @@ -307,7 +307,7 @@ public void SetExtra(string key, object? value) /// public void SetTag(string key, string value) { - if (Options.TagFilters.Any(x => x.IsMatch(key))) + if (Options.TagFilters.MatchesSubstringOrRegex(key)) { return; } diff --git a/src/Sentry/SentryFailedRequestHandler.cs b/src/Sentry/SentryFailedRequestHandler.cs index 9ff93bc231..8280dc0661 100644 --- a/src/Sentry/SentryFailedRequestHandler.cs +++ b/src/Sentry/SentryFailedRequestHandler.cs @@ -38,7 +38,7 @@ public void HandleResponse(HttpResponseMessage response) // Ignore requests that don't match the FailedRequestTargets var requestString = uri.ToString(); - if (!Options.FailedRequestTargets.ContainsMatch(requestString)) + if (!Options.FailedRequestTargets.MatchesSubstringOrRegex(requestString)) { return; } diff --git a/src/Sentry/SentryMessageHandler.cs b/src/Sentry/SentryMessageHandler.cs index 693b9ad25e..8784ef1822 100644 --- a/src/Sentry/SentryMessageHandler.cs +++ b/src/Sentry/SentryMessageHandler.cs @@ -133,7 +133,7 @@ private void PropagateTraceHeaders(HttpRequestMessage request, string url) } } - if (_options?.TracePropagationTargets.ContainsMatch(url) is true or null) + if (_options?.TracePropagationTargets.MatchesSubstringOrRegex(url) is true or null) { AddSentryTraceHeader(request); AddBaggageHeader(request); diff --git a/src/Sentry/SentryOptions.cs b/src/Sentry/SentryOptions.cs index 3480207ab5..7ce83f9057 100644 --- a/src/Sentry/SentryOptions.cs +++ b/src/Sentry/SentryOptions.cs @@ -218,7 +218,7 @@ internal IEnumerable Integrations /// /// List of substrings or regular expression patterns to filter out tags /// - public ICollection TagFilters { get; set; } = new List(); + public IList TagFilters { get; set; } = new List(); /// /// The worker used by the client to pass envelopes. @@ -707,16 +707,16 @@ public IDiagnosticLogger? DiagnosticLogger }; // The default failed request target list will match anything, but adding to the list should clear that. - private Lazy> _failedRequestTargets = new(() => - new AutoClearingList( - new[] { new SubstringOrRegexPattern(".*") }, clearOnNextAdd: true)); + private Lazy> _failedRequestTargets = new(() => + new AutoClearingList( + new[] { new StringOrRegex(".*") }, clearOnNextAdd: true)); /// /// The SDK will only capture HTTP Client errors if the HTTP Request URL is a match for any of the failedRequestsTargets. /// Targets may be URLs or Regular expressions. /// Matches "*." by default. /// - public IList FailedRequestTargets + public IList FailedRequestTargets { get => _failedRequestTargets.Value; set => _failedRequestTargets = new(value.WithConfigBinding); @@ -862,11 +862,11 @@ public double? ProfilesSampleRate public Func? TracesSampler { get; set; } // The default propagation list will match anything, but adding to the list should clear that. - private IList _tracePropagationTargets = new AutoClearingList - (new[] { new SubstringOrRegexPattern(".*") }, clearOnNextAdd: true); + private IList _tracePropagationTargets = new AutoClearingList + (new[] { new StringOrRegex(".*") }, clearOnNextAdd: true); /// - /// A customizable list of objects, each containing either a + /// A customizable list of objects, each containing either a /// substring or regular expression pattern that can be used to control which outgoing HTTP requests /// will have the sentry-trace and baggage headers propagated, for purposes of distributed tracing. /// The default value contains a single value of .*, which matches everything. @@ -876,7 +876,7 @@ public double? ProfilesSampleRate /// /// Adding an item to the default list will clear the .* value automatically. /// - public IList TracePropagationTargets + public IList TracePropagationTargets { // NOTE: During configuration binding, .NET 6 and lower used to just call Add on the existing item. // .NET 7 changed this to call the setter with an array that already starts with the old value. @@ -888,7 +888,7 @@ public IList TracePropagationTargets internal ITransactionProfilerFactory? TransactionProfilerFactory { get; set; } private StackTraceMode? _stackTraceMode; - private readonly List _integrations = new(); + private readonly List _integrations; /// /// ATTENTION: This option will change how issues are grouped in Sentry! diff --git a/src/Sentry/StringOrRegex.cs b/src/Sentry/StringOrRegex.cs new file mode 100644 index 0000000000..1a5e672e8a --- /dev/null +++ b/src/Sentry/StringOrRegex.cs @@ -0,0 +1,128 @@ +using Sentry.Internal; + +namespace Sentry; + +/// +/// Stores either a plain string or a Regular Expression, typically to match against filters in the SentryOptions +/// +[TypeConverter(typeof(StringOrRegexTypeConverter))] +public class StringOrRegex +{ + internal readonly Regex? _regex; + internal readonly string? _string; + + /// + /// Constructs a instance. + /// + /// The prefix or regular expression pattern to match on. + public StringOrRegex(string stringOrRegex) + { + _string = stringOrRegex; + } + + /// + /// Constructs a instance. + /// + /// + /// + /// Use this constructor when you want the match to be performed using a regular expression. + /// + public StringOrRegex(Regex regex) => _regex = regex; + + /// + /// Implicitly converts a to a . + /// + /// + public static implicit operator StringOrRegex(string stringOrRegex) + { + return new StringOrRegex(stringOrRegex); + } + + /// + /// Implicitly converts a to a . + /// + /// + public static implicit operator StringOrRegex(Regex regex) + { + return new StringOrRegex(regex); + } + + /// + public override string ToString() => _string ?? _regex?.ToString() ?? ""; + + /// + public override bool Equals(object? obj) + { + return + (obj is StringOrRegex pattern) + && pattern.ToString() == ToString(); + } + + /// + public override int GetHashCode() + { + return ToString().GetHashCode(); + } +} + +internal static class StringOrRegexExtensions +{ + public static bool MatchesAny(this string parameter, IEnumerable? patterns, IStringOrRegexMatcher matcher) + { + if (patterns is null) + { + return false; + } + foreach (var stringOrRegex in patterns) + { + if (matcher.IsMatch(stringOrRegex, parameter)) + { + return true; + } + } + return false; + } + + public static bool MatchesSubstringOrRegex(this IEnumerable? patterns, string parameter) + => parameter.MatchesAny(patterns, SubstringOrPatternMatcher.Default); + + /// + /// During configuration binding, .NET 6 and lower used to just call Add on the existing item. + /// .NET 7 changed this to call the setter with an array that already starts with the old value. + /// We have to handle both cases. + /// + /// The List Type + /// The set of values to be assigned + /// A IList of type T that will be consistent even if it has been set via Config + public static IList WithConfigBinding(this IList value) + where T : StringOrRegex + { + switch (value.Count) + { + case 1 when value[0].ToString() == ".*": + // There's only one item in the list, and it's the wildcard, so reset to the initial state. + return new AutoClearingList(value, clearOnNextAdd: true); + + case > 1: + // There's more than one item in the list. Remove the wildcard. + var targets = value.ToList(); + targets.RemoveAll(t => t.ToString() == ".*"); + return targets; + + default: + return value; + } + } +} + +/// +/// This class allows the TracePropagationTargets option to be set from config, such as appSettings.json +/// +internal class StringOrRegexTypeConverter : TypeConverter +{ + public override bool CanConvertFrom(ITypeDescriptorContext? context, Type sourceType) => + sourceType == typeof(string); + + public override object ConvertFrom(ITypeDescriptorContext? context, CultureInfo? culture, object value) => + new StringOrRegex((string)value); +} diff --git a/src/Sentry/SubstringOrPatternMatcher.cs b/src/Sentry/SubstringOrPatternMatcher.cs new file mode 100644 index 0000000000..15e716e19b --- /dev/null +++ b/src/Sentry/SubstringOrPatternMatcher.cs @@ -0,0 +1,19 @@ +using Sentry.Internal; + +namespace Sentry; + +/// +/// Provides a pattern that can be used to match against other strings as either a substring or regular expression. +/// +/// The string comparison type to use when matching for substrings. +internal class SubstringOrPatternMatcher(StringComparison comparison = StringComparison.OrdinalIgnoreCase) + : IStringOrRegexMatcher +{ + internal static SubstringOrPatternMatcher Default { get; } = new(); + + public bool IsMatch(StringOrRegex stringOrRegex, string value) + { + return (stringOrRegex._string != null && (stringOrRegex._string == ".*" || value.Contains(stringOrRegex._string, comparison))) || + stringOrRegex._regex?.IsMatch(value) == true; + } +} diff --git a/src/Sentry/SubstringOrRegexPattern.cs b/src/Sentry/SubstringOrRegexPattern.cs deleted file mode 100644 index 1d8913b838..0000000000 --- a/src/Sentry/SubstringOrRegexPattern.cs +++ /dev/null @@ -1,160 +0,0 @@ -using Sentry.Internal; - -namespace Sentry; - -// TODO: This class can be replaced with an implementation of IStringOrRegexMatcher in the next major version bump. -/// -/// Provides a pattern that can be used to match against other strings as either a substring or regular expression. -/// -[TypeConverter(typeof(SubstringOrRegexPatternTypeConverter))] -public class SubstringOrRegexPattern -{ - private readonly Regex? _regex; - private readonly string? _substring; - private readonly StringComparison _stringComparison; - - /// - /// Constructs a instance. - /// - /// The substring or regular expression pattern to match on. - /// The string comparison type to use when matching. - public SubstringOrRegexPattern( - string substringOrRegexPattern, - StringComparison comparison = StringComparison.OrdinalIgnoreCase) - { - _substring = substringOrRegexPattern; - _stringComparison = comparison; - _regex = TryParseRegex(substringOrRegexPattern, comparison); - } - - /// - /// Constructs a instance. - /// - /// - /// - /// Use this constructor when you need to control the regular expression matching options. - /// We recommend setting at least for performance, and - /// (unless you have culture-specific matching needs). - /// The constructor sets these by default. - /// - public SubstringOrRegexPattern(Regex regex) => _regex = regex; - - /// - /// Implicitly converts a to a . - /// - /// - public static implicit operator SubstringOrRegexPattern(string substringOrRegexPattern) - { - return new SubstringOrRegexPattern(substringOrRegexPattern); - } - - /// - /// Implicitly converts a to a . - /// - /// - public static implicit operator SubstringOrRegexPattern(Regex regex) - { - return new SubstringOrRegexPattern(regex); - } - - /// - public override string ToString() => _substring ?? _regex?.ToString() ?? ""; - - /// - public override bool Equals(object? obj) - { - return - (obj is SubstringOrRegexPattern pattern) - && pattern.ToString() == ToString(); - } - - /// - public override int GetHashCode() - { - return ToString().GetHashCode(); - } - - internal Regex? Regex => _regex; - - internal bool IsMatch(string str) => - _substring == ".*" || // perf shortcut - (_substring != null && str.Contains(_substring, _stringComparison)) || - _regex?.IsMatch(str) == true; - - private static Regex? TryParseRegex(string pattern, StringComparison comparison) - { - try - { - var regexOptions = RegexOptions.Compiled; - - if (comparison is - StringComparison.InvariantCulture or - StringComparison.InvariantCultureIgnoreCase or - StringComparison.Ordinal or - StringComparison.OrdinalIgnoreCase) - { - regexOptions |= RegexOptions.CultureInvariant; - } - - if (comparison is - StringComparison.CurrentCultureIgnoreCase or - StringComparison.InvariantCultureIgnoreCase or - StringComparison.OrdinalIgnoreCase) - { - regexOptions |= RegexOptions.IgnoreCase; - } - - return new Regex(pattern, regexOptions); - } - catch - { - // not a valid regex - return null; - } - } -} - -internal static class SubstringOrRegexPatternExtensions -{ - public static bool ContainsMatch(this IEnumerable targets, string str) => - targets.Any(t => t.IsMatch(str)); - - /// - /// During configuration binding, .NET 6 and lower used to just call Add on the existing item. - /// .NET 7 changed this to call the setter with an array that already starts with the old value. - /// We have to handle both cases. - /// - /// The List Type - /// The set of values to be assigned - /// A IList of type T that will be consistent even if it has been set via Config - public static IList WithConfigBinding(this IList value) - where T : SubstringOrRegexPattern - { - switch (value.Count) - { - case 1 when value[0].ToString() == ".*": - // There's only one item in the list, and it's the wildcard, so reset to the initial state. - return new AutoClearingList(value, clearOnNextAdd: true); - - case > 1: - // There's more than one item in the list. Remove the wildcard. - var targets = value.ToList(); - targets.RemoveAll(t => t.ToString() == ".*"); - return targets; - - default: - return value; - } - } -} - -internal class SubstringOrRegexPatternTypeConverter : TypeConverter -{ - // This class allows the TracePropagationTargets option to be set from config, such as appSettings.json - - public override bool CanConvertFrom(ITypeDescriptorContext? context, Type sourceType) => - sourceType == typeof(string); - - public override object ConvertFrom(ITypeDescriptorContext? context, CultureInfo? culture, object value) => - new SubstringOrRegexPattern((string)value); -} diff --git a/test/Sentry.Extensions.Logging.Tests/SentryLoggingOptionsSetupTests.cs b/test/Sentry.Extensions.Logging.Tests/SentryLoggingOptionsSetupTests.cs index d6ffa6ac1e..778215de16 100644 --- a/test/Sentry.Extensions.Logging.Tests/SentryLoggingOptionsSetupTests.cs +++ b/test/Sentry.Extensions.Logging.Tests/SentryLoggingOptionsSetupTests.cs @@ -14,7 +14,7 @@ public void Configure_BindsConfigurationToOptions() { IsGlobalModeEnabled = true, EnableScopeSync = true, - TagFilters = new List { "tag1", "tag2" }, + TagFilters = new List { "tag1", "tag2" }, SendDefaultPii = true, IsEnvironmentUser = true, ServerName = "FakeServerName", @@ -40,11 +40,11 @@ public void Configure_BindsConfigurationToOptions() CacheDirectoryPath = "~/test", CaptureFailedRequests = true, // FailedRequestStatusCodes = IList, - FailedRequestTargets = new List { "target1", "target2" }, + FailedRequestTargets = ["target1", "target2"], InitCacheFlushTimeout = TimeSpan.FromSeconds(27), // DefaultTags = Dictionary, TracesSampleRate = 0.8f, - TracePropagationTargets = new List { "target3", "target4" }, + TracePropagationTargets = new List { "target3", "target4" }, StackTraceMode = StackTraceMode.Enhanced, MaxAttachmentSize = 21478, DetectStartupTime = StartupTimeDetectionMode.Fast, @@ -62,8 +62,8 @@ public void Configure_BindsConfigurationToOptions() { ["IsGlobalModeEnabled"] = expected.IsGlobalModeEnabled.ToString(), ["EnableScopeSync"] = expected.EnableScopeSync.ToString(), - ["TagFilters:0"] = "tag1", - ["TagFilters:1"] = "tag2", + ["TagFilters:0"] = expected.TagFilters.First().ToString(), + ["TagFilters:1"] = expected.TagFilters.Last().ToString(), ["SendDefaultPii"] = expected.SendDefaultPii.ToString(), ["IsEnvironmentUser"] = expected.IsEnvironmentUser.ToString(), ["ServerName"] = expected.ServerName, diff --git a/test/Sentry.Tests/ApiApprovalTests.Run.DotNet6_0.verified.txt b/test/Sentry.Tests/ApiApprovalTests.Run.DotNet6_0.verified.txt index 2fb50223fa..ffeeaf451f 100644 --- a/test/Sentry.Tests/ApiApprovalTests.Run.DotNet6_0.verified.txt +++ b/test/Sentry.Tests/ApiApprovalTests.Run.DotNet6_0.verified.txt @@ -42,19 +42,19 @@ namespace Sentry } public static class BuiltInSystemDiagnosticsMeters { - public static readonly Sentry.SubstringOrRegexPattern MicrosoftAspNetCoreDiagnostics; - public static readonly Sentry.SubstringOrRegexPattern MicrosoftAspNetCoreHeaderParsing; - public static readonly Sentry.SubstringOrRegexPattern MicrosoftAspNetCoreHosting; - public static readonly Sentry.SubstringOrRegexPattern MicrosoftAspNetCoreHttpConnections; - public static readonly Sentry.SubstringOrRegexPattern MicrosoftAspNetCoreRateLimiting; - public static readonly Sentry.SubstringOrRegexPattern MicrosoftAspNetCoreRouting; - public static readonly Sentry.SubstringOrRegexPattern MicrosoftAspNetCoreServerKestrel; - public static readonly Sentry.SubstringOrRegexPattern MicrosoftExtensionsDiagnosticsHealthChecks; - public static readonly Sentry.SubstringOrRegexPattern MicrosoftExtensionsDiagnosticsResourceMonitoring; - public static readonly Sentry.SubstringOrRegexPattern OpenTelemetryInstrumentationRuntime; - public static readonly Sentry.SubstringOrRegexPattern SystemNetHttp; - public static readonly Sentry.SubstringOrRegexPattern SystemNetNameResolution; - public static System.Collections.Generic.IList All { get; } + public static readonly Sentry.StringOrRegex MicrosoftAspNetCoreDiagnostics; + public static readonly Sentry.StringOrRegex MicrosoftAspNetCoreHeaderParsing; + public static readonly Sentry.StringOrRegex MicrosoftAspNetCoreHosting; + public static readonly Sentry.StringOrRegex MicrosoftAspNetCoreHttpConnections; + public static readonly Sentry.StringOrRegex MicrosoftAspNetCoreRateLimiting; + public static readonly Sentry.StringOrRegex MicrosoftAspNetCoreRouting; + public static readonly Sentry.StringOrRegex MicrosoftAspNetCoreServerKestrel; + public static readonly Sentry.StringOrRegex MicrosoftExtensionsDiagnosticsHealthChecks; + public static readonly Sentry.StringOrRegex MicrosoftExtensionsDiagnosticsResourceMonitoring; + public static readonly Sentry.StringOrRegex OpenTelemetryInstrumentationRuntime; + public static readonly Sentry.StringOrRegex SystemNetHttp; + public static readonly Sentry.StringOrRegex SystemNetNameResolution; + public static System.Collections.Generic.IList All { get; } } public class ByteAttachmentContent : Sentry.IAttachmentContent { @@ -106,8 +106,8 @@ namespace Sentry public class ExperimentalMetricsOptions { public ExperimentalMetricsOptions() { } - public System.Collections.Generic.IList CaptureSystemDiagnosticsInstruments { get; set; } - public System.Collections.Generic.IList CaptureSystemDiagnosticsMeters { get; set; } + public System.Collections.Generic.IList CaptureSystemDiagnosticsInstruments { get; set; } + public System.Collections.Generic.IList CaptureSystemDiagnosticsMeters { get; set; } public bool EnableCodeLocations { get; set; } } public class FileAttachmentContent : Sentry.IAttachmentContent @@ -671,7 +671,7 @@ namespace Sentry public string? Environment { get; set; } public Sentry.ExperimentalMetricsOptions? ExperimentalMetrics { get; set; } public System.Collections.Generic.IList FailedRequestStatusCodes { get; set; } - public System.Collections.Generic.IList FailedRequestTargets { get; set; } + public System.Collections.Generic.IList FailedRequestTargets { get; set; } public System.TimeSpan FlushTimeout { get; set; } public System.Net.IWebProxy? HttpProxy { get; set; } public System.TimeSpan InitCacheFlushTimeout { get; set; } @@ -697,8 +697,8 @@ namespace Sentry public System.TimeSpan ShutdownTimeout { get; set; } public string SpotlightUrl { get; set; } public Sentry.StackTraceMode StackTraceMode { get; set; } - public System.Collections.Generic.ICollection TagFilters { get; set; } - public System.Collections.Generic.IList TracePropagationTargets { get; set; } + public System.Collections.Generic.IList TagFilters { get; set; } + public System.Collections.Generic.IList TracePropagationTargets { get; set; } public double? TracesSampleRate { get; set; } public System.Func? TracesSampler { get; set; } public Sentry.Extensibility.ITransport? Transport { get; set; } @@ -1118,16 +1118,16 @@ namespace Sentry public StreamAttachmentContent(System.IO.Stream stream) { } public System.IO.Stream GetStream() { } } - [System.ComponentModel.TypeConverter(typeof(Sentry.SubstringOrRegexPatternTypeConverter))] - public class SubstringOrRegexPattern + [System.ComponentModel.TypeConverter(typeof(Sentry.StringOrRegexTypeConverter))] + public class StringOrRegex { - public SubstringOrRegexPattern(System.Text.RegularExpressions.Regex regex) { } - public SubstringOrRegexPattern(string substringOrRegexPattern, System.StringComparison comparison = 5) { } + public StringOrRegex(string stringOrRegex) { } + public StringOrRegex(System.Text.RegularExpressions.Regex regex) { } public override bool Equals(object? obj) { } public override int GetHashCode() { } public override string ToString() { } - public static Sentry.SubstringOrRegexPattern op_Implicit(string substringOrRegexPattern) { } - public static Sentry.SubstringOrRegexPattern op_Implicit(System.Text.RegularExpressions.Regex regex) { } + public static Sentry.StringOrRegex op_Implicit(string stringOrRegex) { } + public static Sentry.StringOrRegex op_Implicit(System.Text.RegularExpressions.Regex regex) { } } public class TransactionContext : Sentry.SpanContext, Sentry.ITransactionContext, Sentry.Protocol.ITraceContext { diff --git a/test/Sentry.Tests/ApiApprovalTests.Run.DotNet7_0.verified.txt b/test/Sentry.Tests/ApiApprovalTests.Run.DotNet7_0.verified.txt index 2fb50223fa..ffeeaf451f 100644 --- a/test/Sentry.Tests/ApiApprovalTests.Run.DotNet7_0.verified.txt +++ b/test/Sentry.Tests/ApiApprovalTests.Run.DotNet7_0.verified.txt @@ -42,19 +42,19 @@ namespace Sentry } public static class BuiltInSystemDiagnosticsMeters { - public static readonly Sentry.SubstringOrRegexPattern MicrosoftAspNetCoreDiagnostics; - public static readonly Sentry.SubstringOrRegexPattern MicrosoftAspNetCoreHeaderParsing; - public static readonly Sentry.SubstringOrRegexPattern MicrosoftAspNetCoreHosting; - public static readonly Sentry.SubstringOrRegexPattern MicrosoftAspNetCoreHttpConnections; - public static readonly Sentry.SubstringOrRegexPattern MicrosoftAspNetCoreRateLimiting; - public static readonly Sentry.SubstringOrRegexPattern MicrosoftAspNetCoreRouting; - public static readonly Sentry.SubstringOrRegexPattern MicrosoftAspNetCoreServerKestrel; - public static readonly Sentry.SubstringOrRegexPattern MicrosoftExtensionsDiagnosticsHealthChecks; - public static readonly Sentry.SubstringOrRegexPattern MicrosoftExtensionsDiagnosticsResourceMonitoring; - public static readonly Sentry.SubstringOrRegexPattern OpenTelemetryInstrumentationRuntime; - public static readonly Sentry.SubstringOrRegexPattern SystemNetHttp; - public static readonly Sentry.SubstringOrRegexPattern SystemNetNameResolution; - public static System.Collections.Generic.IList All { get; } + public static readonly Sentry.StringOrRegex MicrosoftAspNetCoreDiagnostics; + public static readonly Sentry.StringOrRegex MicrosoftAspNetCoreHeaderParsing; + public static readonly Sentry.StringOrRegex MicrosoftAspNetCoreHosting; + public static readonly Sentry.StringOrRegex MicrosoftAspNetCoreHttpConnections; + public static readonly Sentry.StringOrRegex MicrosoftAspNetCoreRateLimiting; + public static readonly Sentry.StringOrRegex MicrosoftAspNetCoreRouting; + public static readonly Sentry.StringOrRegex MicrosoftAspNetCoreServerKestrel; + public static readonly Sentry.StringOrRegex MicrosoftExtensionsDiagnosticsHealthChecks; + public static readonly Sentry.StringOrRegex MicrosoftExtensionsDiagnosticsResourceMonitoring; + public static readonly Sentry.StringOrRegex OpenTelemetryInstrumentationRuntime; + public static readonly Sentry.StringOrRegex SystemNetHttp; + public static readonly Sentry.StringOrRegex SystemNetNameResolution; + public static System.Collections.Generic.IList All { get; } } public class ByteAttachmentContent : Sentry.IAttachmentContent { @@ -106,8 +106,8 @@ namespace Sentry public class ExperimentalMetricsOptions { public ExperimentalMetricsOptions() { } - public System.Collections.Generic.IList CaptureSystemDiagnosticsInstruments { get; set; } - public System.Collections.Generic.IList CaptureSystemDiagnosticsMeters { get; set; } + public System.Collections.Generic.IList CaptureSystemDiagnosticsInstruments { get; set; } + public System.Collections.Generic.IList CaptureSystemDiagnosticsMeters { get; set; } public bool EnableCodeLocations { get; set; } } public class FileAttachmentContent : Sentry.IAttachmentContent @@ -671,7 +671,7 @@ namespace Sentry public string? Environment { get; set; } public Sentry.ExperimentalMetricsOptions? ExperimentalMetrics { get; set; } public System.Collections.Generic.IList FailedRequestStatusCodes { get; set; } - public System.Collections.Generic.IList FailedRequestTargets { get; set; } + public System.Collections.Generic.IList FailedRequestTargets { get; set; } public System.TimeSpan FlushTimeout { get; set; } public System.Net.IWebProxy? HttpProxy { get; set; } public System.TimeSpan InitCacheFlushTimeout { get; set; } @@ -697,8 +697,8 @@ namespace Sentry public System.TimeSpan ShutdownTimeout { get; set; } public string SpotlightUrl { get; set; } public Sentry.StackTraceMode StackTraceMode { get; set; } - public System.Collections.Generic.ICollection TagFilters { get; set; } - public System.Collections.Generic.IList TracePropagationTargets { get; set; } + public System.Collections.Generic.IList TagFilters { get; set; } + public System.Collections.Generic.IList TracePropagationTargets { get; set; } public double? TracesSampleRate { get; set; } public System.Func? TracesSampler { get; set; } public Sentry.Extensibility.ITransport? Transport { get; set; } @@ -1118,16 +1118,16 @@ namespace Sentry public StreamAttachmentContent(System.IO.Stream stream) { } public System.IO.Stream GetStream() { } } - [System.ComponentModel.TypeConverter(typeof(Sentry.SubstringOrRegexPatternTypeConverter))] - public class SubstringOrRegexPattern + [System.ComponentModel.TypeConverter(typeof(Sentry.StringOrRegexTypeConverter))] + public class StringOrRegex { - public SubstringOrRegexPattern(System.Text.RegularExpressions.Regex regex) { } - public SubstringOrRegexPattern(string substringOrRegexPattern, System.StringComparison comparison = 5) { } + public StringOrRegex(string stringOrRegex) { } + public StringOrRegex(System.Text.RegularExpressions.Regex regex) { } public override bool Equals(object? obj) { } public override int GetHashCode() { } public override string ToString() { } - public static Sentry.SubstringOrRegexPattern op_Implicit(string substringOrRegexPattern) { } - public static Sentry.SubstringOrRegexPattern op_Implicit(System.Text.RegularExpressions.Regex regex) { } + public static Sentry.StringOrRegex op_Implicit(string stringOrRegex) { } + public static Sentry.StringOrRegex op_Implicit(System.Text.RegularExpressions.Regex regex) { } } public class TransactionContext : Sentry.SpanContext, Sentry.ITransactionContext, Sentry.Protocol.ITraceContext { diff --git a/test/Sentry.Tests/ApiApprovalTests.Run.DotNet8_0.verified.txt b/test/Sentry.Tests/ApiApprovalTests.Run.DotNet8_0.verified.txt index f593dedb0a..1306e6e938 100644 --- a/test/Sentry.Tests/ApiApprovalTests.Run.DotNet8_0.verified.txt +++ b/test/Sentry.Tests/ApiApprovalTests.Run.DotNet8_0.verified.txt @@ -42,19 +42,19 @@ namespace Sentry } public static class BuiltInSystemDiagnosticsMeters { - public static readonly Sentry.SubstringOrRegexPattern MicrosoftAspNetCoreDiagnostics; - public static readonly Sentry.SubstringOrRegexPattern MicrosoftAspNetCoreHeaderParsing; - public static readonly Sentry.SubstringOrRegexPattern MicrosoftAspNetCoreHosting; - public static readonly Sentry.SubstringOrRegexPattern MicrosoftAspNetCoreHttpConnections; - public static readonly Sentry.SubstringOrRegexPattern MicrosoftAspNetCoreRateLimiting; - public static readonly Sentry.SubstringOrRegexPattern MicrosoftAspNetCoreRouting; - public static readonly Sentry.SubstringOrRegexPattern MicrosoftAspNetCoreServerKestrel; - public static readonly Sentry.SubstringOrRegexPattern MicrosoftExtensionsDiagnosticsHealthChecks; - public static readonly Sentry.SubstringOrRegexPattern MicrosoftExtensionsDiagnosticsResourceMonitoring; - public static readonly Sentry.SubstringOrRegexPattern OpenTelemetryInstrumentationRuntime; - public static readonly Sentry.SubstringOrRegexPattern SystemNetHttp; - public static readonly Sentry.SubstringOrRegexPattern SystemNetNameResolution; - public static System.Collections.Generic.IList All { get; } + public static readonly Sentry.StringOrRegex MicrosoftAspNetCoreDiagnostics; + public static readonly Sentry.StringOrRegex MicrosoftAspNetCoreHeaderParsing; + public static readonly Sentry.StringOrRegex MicrosoftAspNetCoreHosting; + public static readonly Sentry.StringOrRegex MicrosoftAspNetCoreHttpConnections; + public static readonly Sentry.StringOrRegex MicrosoftAspNetCoreRateLimiting; + public static readonly Sentry.StringOrRegex MicrosoftAspNetCoreRouting; + public static readonly Sentry.StringOrRegex MicrosoftAspNetCoreServerKestrel; + public static readonly Sentry.StringOrRegex MicrosoftExtensionsDiagnosticsHealthChecks; + public static readonly Sentry.StringOrRegex MicrosoftExtensionsDiagnosticsResourceMonitoring; + public static readonly Sentry.StringOrRegex OpenTelemetryInstrumentationRuntime; + public static readonly Sentry.StringOrRegex SystemNetHttp; + public static readonly Sentry.StringOrRegex SystemNetNameResolution; + public static System.Collections.Generic.IList All { get; } } public class ByteAttachmentContent : Sentry.IAttachmentContent { @@ -107,8 +107,8 @@ namespace Sentry public class ExperimentalMetricsOptions { public ExperimentalMetricsOptions() { } - public System.Collections.Generic.IList CaptureSystemDiagnosticsInstruments { get; set; } - public System.Collections.Generic.IList CaptureSystemDiagnosticsMeters { get; set; } + public System.Collections.Generic.IList CaptureSystemDiagnosticsInstruments { get; set; } + public System.Collections.Generic.IList CaptureSystemDiagnosticsMeters { get; set; } public bool EnableCodeLocations { get; set; } } public class FileAttachmentContent : Sentry.IAttachmentContent @@ -672,7 +672,7 @@ namespace Sentry public string? Environment { get; set; } public Sentry.ExperimentalMetricsOptions? ExperimentalMetrics { get; set; } public System.Collections.Generic.IList FailedRequestStatusCodes { get; set; } - public System.Collections.Generic.IList FailedRequestTargets { get; set; } + public System.Collections.Generic.IList FailedRequestTargets { get; set; } public System.TimeSpan FlushTimeout { get; set; } public System.Net.IWebProxy? HttpProxy { get; set; } public System.TimeSpan InitCacheFlushTimeout { get; set; } @@ -698,8 +698,8 @@ namespace Sentry public System.TimeSpan ShutdownTimeout { get; set; } public string SpotlightUrl { get; set; } public Sentry.StackTraceMode StackTraceMode { get; set; } - public System.Collections.Generic.ICollection TagFilters { get; set; } - public System.Collections.Generic.IList TracePropagationTargets { get; set; } + public System.Collections.Generic.IList TagFilters { get; set; } + public System.Collections.Generic.IList TracePropagationTargets { get; set; } public double? TracesSampleRate { get; set; } public System.Func? TracesSampler { get; set; } public Sentry.Extensibility.ITransport? Transport { get; set; } @@ -1120,16 +1120,16 @@ namespace Sentry public StreamAttachmentContent(System.IO.Stream stream) { } public System.IO.Stream GetStream() { } } - [System.ComponentModel.TypeConverter(typeof(Sentry.SubstringOrRegexPatternTypeConverter))] - public class SubstringOrRegexPattern + [System.ComponentModel.TypeConverter(typeof(Sentry.StringOrRegexTypeConverter))] + public class StringOrRegex { - public SubstringOrRegexPattern(System.Text.RegularExpressions.Regex regex) { } - public SubstringOrRegexPattern(string substringOrRegexPattern, System.StringComparison comparison = 5) { } + public StringOrRegex(string stringOrRegex) { } + public StringOrRegex(System.Text.RegularExpressions.Regex regex) { } public override bool Equals(object? obj) { } public override int GetHashCode() { } public override string ToString() { } - public static Sentry.SubstringOrRegexPattern op_Implicit(string substringOrRegexPattern) { } - public static Sentry.SubstringOrRegexPattern op_Implicit(System.Text.RegularExpressions.Regex regex) { } + public static Sentry.StringOrRegex op_Implicit(string stringOrRegex) { } + public static Sentry.StringOrRegex op_Implicit(System.Text.RegularExpressions.Regex regex) { } } public class TransactionContext : Sentry.SpanContext, Sentry.ITransactionContext, Sentry.Protocol.ITraceContext { diff --git a/test/Sentry.Tests/ApiApprovalTests.Run.Net4_8.verified.txt b/test/Sentry.Tests/ApiApprovalTests.Run.Net4_8.verified.txt index 84c37bccc2..bd232912fd 100644 --- a/test/Sentry.Tests/ApiApprovalTests.Run.Net4_8.verified.txt +++ b/test/Sentry.Tests/ApiApprovalTests.Run.Net4_8.verified.txt @@ -42,19 +42,19 @@ namespace Sentry } public static class BuiltInSystemDiagnosticsMeters { - public static readonly Sentry.SubstringOrRegexPattern MicrosoftAspNetCoreDiagnostics; - public static readonly Sentry.SubstringOrRegexPattern MicrosoftAspNetCoreHeaderParsing; - public static readonly Sentry.SubstringOrRegexPattern MicrosoftAspNetCoreHosting; - public static readonly Sentry.SubstringOrRegexPattern MicrosoftAspNetCoreHttpConnections; - public static readonly Sentry.SubstringOrRegexPattern MicrosoftAspNetCoreRateLimiting; - public static readonly Sentry.SubstringOrRegexPattern MicrosoftAspNetCoreRouting; - public static readonly Sentry.SubstringOrRegexPattern MicrosoftAspNetCoreServerKestrel; - public static readonly Sentry.SubstringOrRegexPattern MicrosoftExtensionsDiagnosticsHealthChecks; - public static readonly Sentry.SubstringOrRegexPattern MicrosoftExtensionsDiagnosticsResourceMonitoring; - public static readonly Sentry.SubstringOrRegexPattern OpenTelemetryInstrumentationRuntime; - public static readonly Sentry.SubstringOrRegexPattern SystemNetHttp; - public static readonly Sentry.SubstringOrRegexPattern SystemNetNameResolution; - public static System.Collections.Generic.IList All { get; } + public static readonly Sentry.StringOrRegex MicrosoftAspNetCoreDiagnostics; + public static readonly Sentry.StringOrRegex MicrosoftAspNetCoreHeaderParsing; + public static readonly Sentry.StringOrRegex MicrosoftAspNetCoreHosting; + public static readonly Sentry.StringOrRegex MicrosoftAspNetCoreHttpConnections; + public static readonly Sentry.StringOrRegex MicrosoftAspNetCoreRateLimiting; + public static readonly Sentry.StringOrRegex MicrosoftAspNetCoreRouting; + public static readonly Sentry.StringOrRegex MicrosoftAspNetCoreServerKestrel; + public static readonly Sentry.StringOrRegex MicrosoftExtensionsDiagnosticsHealthChecks; + public static readonly Sentry.StringOrRegex MicrosoftExtensionsDiagnosticsResourceMonitoring; + public static readonly Sentry.StringOrRegex OpenTelemetryInstrumentationRuntime; + public static readonly Sentry.StringOrRegex SystemNetHttp; + public static readonly Sentry.StringOrRegex SystemNetNameResolution; + public static System.Collections.Generic.IList All { get; } } public class ByteAttachmentContent : Sentry.IAttachmentContent { @@ -105,8 +105,8 @@ namespace Sentry public class ExperimentalMetricsOptions { public ExperimentalMetricsOptions() { } - public System.Collections.Generic.IList CaptureSystemDiagnosticsInstruments { get; set; } - public System.Collections.Generic.IList CaptureSystemDiagnosticsMeters { get; set; } + public System.Collections.Generic.IList CaptureSystemDiagnosticsInstruments { get; set; } + public System.Collections.Generic.IList CaptureSystemDiagnosticsMeters { get; set; } public bool EnableCodeLocations { get; set; } } public class FileAttachmentContent : Sentry.IAttachmentContent @@ -669,7 +669,7 @@ namespace Sentry public string? Environment { get; set; } public Sentry.ExperimentalMetricsOptions? ExperimentalMetrics { get; set; } public System.Collections.Generic.IList FailedRequestStatusCodes { get; set; } - public System.Collections.Generic.IList FailedRequestTargets { get; set; } + public System.Collections.Generic.IList FailedRequestTargets { get; set; } public System.TimeSpan FlushTimeout { get; set; } public System.Net.IWebProxy? HttpProxy { get; set; } public System.TimeSpan InitCacheFlushTimeout { get; set; } @@ -695,8 +695,8 @@ namespace Sentry public System.TimeSpan ShutdownTimeout { get; set; } public string SpotlightUrl { get; set; } public Sentry.StackTraceMode StackTraceMode { get; set; } - public System.Collections.Generic.ICollection TagFilters { get; set; } - public System.Collections.Generic.IList TracePropagationTargets { get; set; } + public System.Collections.Generic.IList TagFilters { get; set; } + public System.Collections.Generic.IList TracePropagationTargets { get; set; } public double? TracesSampleRate { get; set; } public System.Func? TracesSampler { get; set; } public Sentry.Extensibility.ITransport? Transport { get; set; } @@ -1115,16 +1115,16 @@ namespace Sentry public StreamAttachmentContent(System.IO.Stream stream) { } public System.IO.Stream GetStream() { } } - [System.ComponentModel.TypeConverter(typeof(Sentry.SubstringOrRegexPatternTypeConverter))] - public class SubstringOrRegexPattern + [System.ComponentModel.TypeConverter(typeof(Sentry.StringOrRegexTypeConverter))] + public class StringOrRegex { - public SubstringOrRegexPattern(System.Text.RegularExpressions.Regex regex) { } - public SubstringOrRegexPattern(string substringOrRegexPattern, System.StringComparison comparison = 5) { } + public StringOrRegex(string stringOrRegex) { } + public StringOrRegex(System.Text.RegularExpressions.Regex regex) { } public override bool Equals(object? obj) { } public override int GetHashCode() { } public override string ToString() { } - public static Sentry.SubstringOrRegexPattern op_Implicit(string substringOrRegexPattern) { } - public static Sentry.SubstringOrRegexPattern op_Implicit(System.Text.RegularExpressions.Regex regex) { } + public static Sentry.StringOrRegex op_Implicit(string stringOrRegex) { } + public static Sentry.StringOrRegex op_Implicit(System.Text.RegularExpressions.Regex regex) { } } public class TransactionContext : Sentry.SpanContext, Sentry.ITransactionContext, Sentry.Protocol.ITraceContext { diff --git a/test/Sentry.Tests/BuiltInSystemDiagnosticsMetersTests.cs b/test/Sentry.Tests/BuiltInSystemDiagnosticsMetersTests.cs index d033049610..c9b045f776 100644 --- a/test/Sentry.Tests/BuiltInSystemDiagnosticsMetersTests.cs +++ b/test/Sentry.Tests/BuiltInSystemDiagnosticsMetersTests.cs @@ -93,12 +93,12 @@ public void SystemNetHttp_ExactString_Matches() internal static class BuiltInSystemDiagnosticsMetersTestsExtensions { - internal static void ShouldMatchOnlyExactText(this SubstringOrRegexPattern pattern, string actual) + internal static void ShouldMatchOnlyExactText(this StringOrRegex pattern, string actual) { var withPrefix = "prefix" + actual; var withSuffix = actual + "suffix"; - pattern.IsMatch(actual).Should().BeTrue(); - pattern.IsMatch(withPrefix).Should().BeFalse(); - pattern.IsMatch(withSuffix).Should().BeFalse(); + SubstringOrPatternMatcher.Default.IsMatch(pattern, actual).Should().BeTrue(); + SubstringOrPatternMatcher.Default.IsMatch(pattern, withPrefix).Should().BeFalse(); + SubstringOrPatternMatcher.Default.IsMatch(pattern, withSuffix).Should().BeFalse(); } } diff --git a/test/Sentry.Tests/FailedRequestTargetsTests.cs b/test/Sentry.Tests/FailedRequestTargetsTests.cs index d7392ea3c4..729e7cc593 100644 --- a/test/Sentry.Tests/FailedRequestTargetsTests.cs +++ b/test/Sentry.Tests/FailedRequestTargetsTests.cs @@ -26,7 +26,7 @@ public void SentryOptions_FailedRequestTargets_AddRemovesDefault() public void SentryOptions_FailedRequestTargets_SetRemovesDefault() { var options = new SentryOptions(); - var targets = new List + var targets = new List { ".*", "foo", @@ -45,9 +45,9 @@ public void SentryOptions_FailedRequestTargets_DefaultMatchesAll() { var options = new SentryOptions(); - var result1 = options.FailedRequestTargets.ContainsMatch("foo"); - var result2 = options.FailedRequestTargets.ContainsMatch(""); - var result3 = options.FailedRequestTargets.ContainsMatch(null!); + var result1 = options.FailedRequestTargets.MatchesSubstringOrRegex("foo"); + var result2 = options.FailedRequestTargets.MatchesSubstringOrRegex(""); + var result3 = options.FailedRequestTargets.MatchesSubstringOrRegex(null!); Assert.True(result1); Assert.True(result2); @@ -59,12 +59,12 @@ public void SentryOptions_FailedRequestTargets_EmptyMatchesNone() { var options = new SentryOptions { - FailedRequestTargets = new List() + FailedRequestTargets = new List() }; - var result1 = options.FailedRequestTargets.ContainsMatch("foo"); - var result2 = options.FailedRequestTargets.ContainsMatch(""); - var result3 = options.FailedRequestTargets.ContainsMatch(null!); + var result1 = options.FailedRequestTargets.MatchesSubstringOrRegex("foo"); + var result2 = options.FailedRequestTargets.MatchesSubstringOrRegex(""); + var result3 = options.FailedRequestTargets.MatchesSubstringOrRegex(null!); Assert.False(result1); Assert.False(result2); @@ -76,7 +76,7 @@ public void SentryOptions_FailedRequestTargets_OneMatch() { var options = new SentryOptions { - FailedRequestTargets = new List + FailedRequestTargets = new List { "foo", "localhost", @@ -84,7 +84,7 @@ public void SentryOptions_FailedRequestTargets_OneMatch() } }; - var result = options.FailedRequestTargets.ContainsMatch("http://localhost/abc/123"); + var result = options.FailedRequestTargets.MatchesSubstringOrRegex("http://localhost/abc/123"); Assert.True(result); } @@ -93,7 +93,7 @@ public void SentryOptions_FailedRequestTargets_MultipleMatches() { var options = new SentryOptions { - FailedRequestTargets = new List + FailedRequestTargets = new List { "foo", "localhost", @@ -101,7 +101,7 @@ public void SentryOptions_FailedRequestTargets_MultipleMatches() } }; - var result = options.FailedRequestTargets.ContainsMatch("http://localhost/foo/123"); + var result = options.FailedRequestTargets.MatchesSubstringOrRegex("http://localhost/foo/123"); Assert.True(result); } @@ -110,7 +110,7 @@ public void SentryOptions_FailedRequestTargets_NoMatches() { var options = new SentryOptions { - FailedRequestTargets = new List + FailedRequestTargets = new List { "foo", "localhost", @@ -118,7 +118,7 @@ public void SentryOptions_FailedRequestTargets_NoMatches() } }; - var result = options.FailedRequestTargets.ContainsMatch("https://sentry.io/abc/123"); + var result = options.FailedRequestTargets.MatchesSubstringOrRegex("https://sentry.io/abc/123"); Assert.False(result); } } diff --git a/test/Sentry.Tests/ScopeTests.cs b/test/Sentry.Tests/ScopeTests.cs index 6277367ca4..5815cdb68c 100644 --- a/test/Sentry.Tests/ScopeTests.cs +++ b/test/Sentry.Tests/ScopeTests.cs @@ -605,7 +605,7 @@ public void Filtered_tags_are_not_set() var scope = new Scope(new SentryOptions { - TagFilters = new[] { new SubstringOrRegexPattern("AzureFunctions_") } + TagFilters = new[] { new StringOrRegex("AzureFunctions_") } }); foreach (var (key, value) in tags) diff --git a/test/Sentry.Tests/SentryGraphQlHttpFailedRequestHandlerTests.cs b/test/Sentry.Tests/SentryGraphQlHttpFailedRequestHandlerTests.cs index 63aba9e397..65af1ae103 100644 --- a/test/Sentry.Tests/SentryGraphQlHttpFailedRequestHandlerTests.cs +++ b/test/Sentry.Tests/SentryGraphQlHttpFailedRequestHandlerTests.cs @@ -66,7 +66,7 @@ public void HandleResponse_NoMatchingTarget_DontCapture() var options = new SentryOptions { CaptureFailedRequests = true, - FailedRequestTargets = new List { "http://foo/" } + FailedRequestTargets = new List { "http://foo/" } }; var sut = new SentryGraphQLHttpFailedRequestHandler(hub, options); diff --git a/test/Sentry.Tests/SentryHttpFailedRequestHandlerTests.cs b/test/Sentry.Tests/SentryHttpFailedRequestHandlerTests.cs index 1d336e19a8..4e81fac3c6 100644 --- a/test/Sentry.Tests/SentryHttpFailedRequestHandlerTests.cs +++ b/test/Sentry.Tests/SentryHttpFailedRequestHandlerTests.cs @@ -86,7 +86,7 @@ public void HandleResponse_NoMatchingTarget_DontCapture() var options = new SentryOptions { CaptureFailedRequests = true, - FailedRequestTargets = new List { "http://foo/" } + FailedRequestTargets = new List { "http://foo/" } }; var sut = GetSut(options); diff --git a/test/Sentry.Tests/SentryHttpMessageHandlerTests.cs b/test/Sentry.Tests/SentryHttpMessageHandlerTests.cs index fc38202019..7cc372f5b9 100644 --- a/test/Sentry.Tests/SentryHttpMessageHandlerTests.cs +++ b/test/Sentry.Tests/SentryHttpMessageHandlerTests.cs @@ -41,7 +41,7 @@ public async Task SendAsync_SentryTraceHeaderNotSet_SetsHeader_WhenUrlMatchesPro var failedRequestHandler = Substitute.For(); var options = new SentryOptions { - TracePropagationTargets = new List + TracePropagationTargets = new List { new("localhost") } @@ -73,7 +73,7 @@ public async Task SendAsync_SentryTraceHeaderNotSet_DoesntSetHeader_WhenUrlDoesn var failedRequestHandler = Substitute.For(); var options = new SentryOptions { - TracePropagationTargets = new List + TracePropagationTargets = new List { new("foo") } @@ -323,7 +323,7 @@ public void Send_SentryTraceHeaderNotSet_SetsHeader_WhenUrlMatchesPropagationOpt var failedRequestHandler = Substitute.For(); var options = new SentryOptions { - TracePropagationTargets = new List + TracePropagationTargets = new List { new("localhost") } @@ -355,7 +355,7 @@ public void Send_SentryTraceHeaderNotSet_DoesntSetHeader_WhenUrlDoesntMatchesPro var failedRequestHandler = Substitute.For(); var options = new SentryOptions { - TracePropagationTargets = new List + TracePropagationTargets = new List { new("foo") } diff --git a/test/Sentry.Tests/Internals/StringOrRegexTests.cs b/test/Sentry.Tests/StringOrRegexTests.cs similarity index 78% rename from test/Sentry.Tests/Internals/StringOrRegexTests.cs rename to test/Sentry.Tests/StringOrRegexTests.cs index 407ab20d85..2799f2fffd 100644 --- a/test/Sentry.Tests/Internals/StringOrRegexTests.cs +++ b/test/Sentry.Tests/StringOrRegexTests.cs @@ -1,4 +1,4 @@ -namespace Sentry.Tests.Internals; +namespace Sentry.Tests; public class StringOrRegexTests { @@ -6,7 +6,7 @@ public class StringOrRegexTests public void StringOrRegex_ImplicitlyConvertsFromString() { StringOrRegex target = "abc"; - target._prefix.Should().Be("abc"); + target._string.Should().Be("abc"); target._regex.Should().BeNull(); } @@ -14,7 +14,7 @@ public void StringOrRegex_ImplicitlyConvertsFromString() public void StringOrRegex_ImplicitlyConvertsFromRegex() { StringOrRegex target = new Regex("^abc.*ghi$"); - target._prefix.Should().BeNull(); + target._string.Should().BeNull(); target._regex.Should().NotBeNull(); target._regex?.ToString().Should().Be("^abc.*ghi$"); } diff --git a/test/Sentry.Tests/SubstringOrPatternMatcherTests.cs b/test/Sentry.Tests/SubstringOrPatternMatcherTests.cs new file mode 100644 index 0000000000..bdea298f7c --- /dev/null +++ b/test/Sentry.Tests/SubstringOrPatternMatcherTests.cs @@ -0,0 +1,76 @@ +namespace Sentry.Tests; + +public class SubstringOrPatternMatcherTests +{ + private static class Fixture + { + public static SubstringOrPatternMatcher GetSut() => new(); + public static SubstringOrPatternMatcher GetSut(StringComparison comparison) => new(comparison); + } + + [Theory] + [InlineData("cde", "abcdef", true)] + [InlineData("cDe", "ABCdEF", true)] + [InlineData("xyz", "abcdef", false)] + public void Substring_Matches(string substring, string testString, bool expected) + { + // Arrange + var sut = Fixture.GetSut(); + + // Act + var isMatch = sut.IsMatch(substring, testString); + + // Assert + isMatch.Should().Be(expected); + } + + [Theory] + [InlineData("CdE", true)] + [InlineData("cDe", false)] + public void Substring_Matches_CaseSensitive(string testString, bool expected) + { + // Arrange + var sut = Fixture.GetSut(StringComparison.Ordinal); + + // Act + var isMatch = sut.IsMatch(testString, "ABCdEF"); + + // Assert + isMatch.Should().Be(expected); + } + + [Theory] + [InlineData("^abc.*ghi$", "abcdefghi", true)] + [InlineData("^abc.*ghi$", "aBcDeFgHi", true)] // Case insensitive + [InlineData("^abc.*ghi$", "abcdef", false)] + public void Regex_Matches(string pattern, string testString, bool expected) + { + // Arrange + var sut = Fixture.GetSut(); + var regex = new Regex(pattern, RegexOptions.IgnoreCase); + var stringOrRegex = new StringOrRegex(regex); + + // Act + var isMatch = sut.IsMatch(stringOrRegex, testString); + + // Assert + isMatch.Should().Be(expected); + } + + [Theory] + [InlineData("^aBc.*gHi$", "aBcDeFgHi", true)] + [InlineData("^abc.*ghi$", "aBcDeFgHi", false)] + public void Regex_Matches_CaseSensitive(string pattern, string testString, bool expected) + { + // Arrange + var sut = Fixture.GetSut(); + var regex = new Regex(pattern, RegexOptions.None); + var stringOrRegex = new StringOrRegex(regex); + + // Act + var isMatch = sut.IsMatch(stringOrRegex, testString); + + // Assert + isMatch.Should().Be(expected); + } +} diff --git a/test/Sentry.Tests/SubstringOrRegexPatternTests.cs b/test/Sentry.Tests/SubstringOrRegexPatternTests.cs deleted file mode 100644 index 6921e21e70..0000000000 --- a/test/Sentry.Tests/SubstringOrRegexPatternTests.cs +++ /dev/null @@ -1,110 +0,0 @@ -namespace Sentry.Tests; - -public class SubstringOrRegexPatternTests -{ - [Fact] - public void Substring_Matches() - { - var target = new SubstringOrRegexPattern("cde"); - var isMatch = target.IsMatch("abcdef"); - Assert.True(isMatch); - } - - [Fact] - public void Substring_Doesnt_Match() - { - var target = new SubstringOrRegexPattern("xyz"); - var isMatch = target.IsMatch("abcdef"); - Assert.False(isMatch); - } - - [Fact] - public void Substring_Matches_CaseInsensitive_ByDefault() - { - var target = new SubstringOrRegexPattern("cDe"); - var isMatch = target.IsMatch("ABCdEF"); - Assert.True(isMatch); - } - - [Fact] - public void Substring_Matches_CaseSensitive() - { - var target = new SubstringOrRegexPattern("CdE", StringComparison.Ordinal); - var isMatch = target.IsMatch("ABCdEF"); - Assert.True(isMatch); - } - - [Fact] - public void Substring_Doesnt_Match_WhenCaseSensitive() - { - var target = new SubstringOrRegexPattern("cDe", StringComparison.Ordinal); - var isMatch = target.IsMatch("ABCdEF"); - Assert.False(isMatch); - } - - [Fact] - public void Regex_Object_Matches() - { - var regex = new Regex("^abc.*ghi$"); - var target = new SubstringOrRegexPattern(regex); - var isMatch = target.IsMatch("abcdefghi"); - Assert.True(isMatch); - } - - [Fact] - public void Regex_Object_Doesnt_Match() - { - var regex = new Regex("^abc.*ghi$"); - var target = new SubstringOrRegexPattern(regex); - var isMatch = target.IsMatch("abcdef"); - Assert.False(isMatch); - } - - [Fact] - public void Regex_Pattern_Matches() - { - var target = new SubstringOrRegexPattern("^abc.*ghi$"); - var isMatch = target.IsMatch("abcdefghi"); - Assert.True(isMatch); - } - - [Fact] - public void Regex_Pattern_Matches_CaseInsensitive_ByDefault() - { - var target = new SubstringOrRegexPattern("^abc.*ghi$"); - var isMatch = target.IsMatch("aBcDeFgHi"); - Assert.True(isMatch); - } - - [Fact] - public void Regex_Pattern_Matches_CaseSensitive() - { - var target = new SubstringOrRegexPattern("^aBc.*gHi$", StringComparison.Ordinal); - var isMatch = target.IsMatch("aBcDeFgHi"); - Assert.True(isMatch); - } - - [Fact] - public void Regex_Pattern_Doesnt_Match_WhenCaseSensitive() - { - var target = new SubstringOrRegexPattern("^abc.*ghi$", StringComparison.Ordinal); - var isMatch = target.IsMatch("aBcDeFgHi"); - Assert.False(isMatch); - } - - [Fact] - public void SubstringOrRegexPattern_ImplicitlyConvertsFromString() - { - SubstringOrRegexPattern target = "^abc.*ghi$"; - var isMatch = target.IsMatch("abcdefghi"); - Assert.True(isMatch); - } - - [Fact] - public void SubstringOrRegexPattern_ImplicitlyConvertsFromRegex() - { - SubstringOrRegexPattern target = new Regex("^abc.*ghi$"); - var isMatch = target.IsMatch("abcdefghi"); - Assert.True(isMatch); - } -} diff --git a/test/Sentry.Tests/TracePropagationTargetTests.cs b/test/Sentry.Tests/TracePropagationTargetTests.cs index 171b3d5798..cbba80c283 100644 --- a/test/Sentry.Tests/TracePropagationTargetTests.cs +++ b/test/Sentry.Tests/TracePropagationTargetTests.cs @@ -14,8 +14,8 @@ public void SentryOptions_TracePropagationTargets_DefaultAll() public void SentryOptions_TracePropagationTargets_AddRemovesDefault() { var options = new SentryOptions(); - options.TracePropagationTargets.Add(new SubstringOrRegexPattern("foo")); - options.TracePropagationTargets.Add(new SubstringOrRegexPattern("bar")); + options.TracePropagationTargets.Add(new StringOrRegex("foo")); + options.TracePropagationTargets.Add(new StringOrRegex("bar")); Assert.Equal(2, options.TracePropagationTargets.Count); Assert.Equal("foo", options.TracePropagationTargets[0].ToString()); @@ -28,9 +28,9 @@ public void SentryOptions_TracePropagationTargets_SetRemovesDefault() var options = new SentryOptions(); var targets = new[] { - new SubstringOrRegexPattern(".*"), - new SubstringOrRegexPattern("foo"), - new SubstringOrRegexPattern("bar") + new StringOrRegex(".*"), + new StringOrRegex("foo"), + new StringOrRegex("bar") }; options.TracePropagationTargets = targets; @@ -45,9 +45,9 @@ public void SentryOptions_TracePropagationTargets_DefaultPropagatesAll() { var options = new SentryOptions(); - var result1 = options.TracePropagationTargets.ContainsMatch("foo"); - var result2 = options.TracePropagationTargets.ContainsMatch(""); - var result3 = options.TracePropagationTargets.ContainsMatch(null!); + var result1 = options.TracePropagationTargets.MatchesSubstringOrRegex("foo"); + var result2 = options.TracePropagationTargets.MatchesSubstringOrRegex(""); + var result3 = options.TracePropagationTargets.MatchesSubstringOrRegex(null!); Assert.True(result1); Assert.True(result2); @@ -59,12 +59,12 @@ public void SentryOptions_TracePropagationTargets_EmptyPropagatesNone() { var options = new SentryOptions { - TracePropagationTargets = new List() + TracePropagationTargets = new List() }; - var result1 = options.TracePropagationTargets.ContainsMatch("foo"); - var result2 = options.TracePropagationTargets.ContainsMatch(""); - var result3 = options.TracePropagationTargets.ContainsMatch(null!); + var result1 = options.TracePropagationTargets.MatchesSubstringOrRegex("foo"); + var result2 = options.TracePropagationTargets.MatchesSubstringOrRegex(""); + var result3 = options.TracePropagationTargets.MatchesSubstringOrRegex(null!); Assert.False(result1); Assert.False(result2); @@ -76,7 +76,7 @@ public void SentryOptions_TracePropagationTargets_OneMatchPropagates() { var options = new SentryOptions { - TracePropagationTargets = new List + TracePropagationTargets = new List { new("foo"), new("localhost"), @@ -84,7 +84,7 @@ public void SentryOptions_TracePropagationTargets_OneMatchPropagates() } }; - var result = options.TracePropagationTargets.ContainsMatch("http://localhost/abc/123"); + var result = options.TracePropagationTargets.MatchesSubstringOrRegex("http://localhost/abc/123"); Assert.True(result); } @@ -93,7 +93,7 @@ public void SentryOptions_TracePropagationTargets_MultipleMatchesPropagates() { var options = new SentryOptions { - TracePropagationTargets = new List + TracePropagationTargets = new List { new("foo"), new("localhost"), @@ -101,7 +101,7 @@ public void SentryOptions_TracePropagationTargets_MultipleMatchesPropagates() } }; - var result = options.TracePropagationTargets.ContainsMatch("http://localhost/foo/123"); + var result = options.TracePropagationTargets.MatchesSubstringOrRegex("http://localhost/foo/123"); Assert.True(result); } @@ -110,7 +110,7 @@ public void SentryOptions_TracePropagationTargets_NoMatchesDoesntPropagates() { var options = new SentryOptions { - TracePropagationTargets = new List + TracePropagationTargets = new List { new("foo"), new("localhost"), @@ -118,7 +118,7 @@ public void SentryOptions_TracePropagationTargets_NoMatchesDoesntPropagates() } }; - var result = options.TracePropagationTargets.ContainsMatch("https://sentry.io/abc/123"); + var result = options.TracePropagationTargets.MatchesSubstringOrRegex("https://sentry.io/abc/123"); Assert.False(result); } }