Skip to content

Commit 708c2e9

Browse files
Added SubstringOrPatternMatcher (#3566)
1 parent edd6564 commit 708c2e9

31 files changed

+446
-567
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
- 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))
1010
- `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))
1111
- `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))
12+
- The `FailedRequestTargets`, `TagFilters` and `TracePropagationTargets` options have all been changed from `SubstringOrRegexPattern` to `IList<StringOrRegex>` ([#3566](https://github.com/getsentry/sentry-dotnet/pull/3566))
1213

1314
## 4.10.2
1415

src/Sentry/BindableSentryOptions.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ public void ApplyTo(SentryOptions options)
5555
{
5656
options.IsGlobalModeEnabled = IsGlobalModeEnabled ?? options.IsGlobalModeEnabled;
5757
options.EnableScopeSync = EnableScopeSync ?? options.EnableScopeSync;
58-
options.TagFilters = TagFilters?.Select(s => new SubstringOrRegexPattern(s)).ToList() ?? options.TagFilters;
58+
options.TagFilters = TagFilters?.Select(s => new StringOrRegex(s)).ToList() ?? options.TagFilters;
5959
options.SendDefaultPii = SendDefaultPii ?? options.SendDefaultPii;
6060
options.IsEnvironmentUser = IsEnvironmentUser ?? options.IsEnvironmentUser;
6161
options.ServerName = ServerName ?? options.ServerName;
@@ -80,12 +80,12 @@ public void ApplyTo(SentryOptions options)
8080
options.DeduplicateMode = DeduplicateMode ?? options.DeduplicateMode;
8181
options.CacheDirectoryPath = CacheDirectoryPath ?? options.CacheDirectoryPath;
8282
options.CaptureFailedRequests = CaptureFailedRequests ?? options.CaptureFailedRequests;
83-
options.FailedRequestTargets = FailedRequestTargets?.Select(s => new SubstringOrRegexPattern(s)).ToList() ?? options.FailedRequestTargets;
83+
options.FailedRequestTargets = FailedRequestTargets?.Select(s => new StringOrRegex(s)).ToList() ?? options.FailedRequestTargets;
8484
options.InitCacheFlushTimeout = InitCacheFlushTimeout ?? options.InitCacheFlushTimeout;
8585
options.DefaultTags = DefaultTags ?? options.DefaultTags;
8686
options.TracesSampleRate = TracesSampleRate ?? options.TracesSampleRate;
8787
options.ProfilesSampleRate = ProfilesSampleRate ?? options.ProfilesSampleRate;
88-
options.TracePropagationTargets = TracePropagationTargets?.Select(s => new SubstringOrRegexPattern(s)).ToList() ?? options.TracePropagationTargets;
88+
options.TracePropagationTargets = TracePropagationTargets?.Select(s => new StringOrRegex(s)).ToList() ?? options.TracePropagationTargets;
8989
options.StackTraceMode = StackTraceMode ?? options.StackTraceMode;
9090
options.MaxAttachmentSize = MaxAttachmentSize ?? options.MaxAttachmentSize;
9191
options.DetectStartupTime = DetectStartupTime ?? options.DetectStartupTime;
Lines changed: 42 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1+
using Sentry.Internal;
2+
13
namespace Sentry;
24

35
/// <summary>
4-
/// Well known values for built in metrics that can be configured for
6+
/// Well known values for built-in metrics that can be configured for
57
/// <see cref="ExperimentalMetricsOptions.CaptureSystemDiagnosticsMeters"/>
68
/// </summary>
79
public static partial class BuiltInSystemDiagnosticsMeters
@@ -20,150 +22,150 @@ public static partial class BuiltInSystemDiagnosticsMeters
2022
private const string SystemNetHttpPattern = @"^System\.Net\.Http$";
2123

2224
/// <summary>
23-
/// Matches the built in Microsoft.AspNetCore.Hosting metrics
25+
/// Matches the built-in Microsoft.AspNetCore.Hosting metrics
2426
/// </summary>
2527
#if NET8_0_OR_GREATER
26-
public static readonly SubstringOrRegexPattern MicrosoftAspNetCoreHosting = MicrosoftAspNetCoreHostingRegex();
28+
public static readonly StringOrRegex MicrosoftAspNetCoreHosting = MicrosoftAspNetCoreHostingRegex();
2729

2830
[GeneratedRegex(MicrosoftAspNetCoreHostingPattern, RegexOptions.Compiled)]
2931
private static partial Regex MicrosoftAspNetCoreHostingRegex();
3032
#else
31-
public static readonly SubstringOrRegexPattern MicrosoftAspNetCoreHosting = new Regex(MicrosoftAspNetCoreHostingPattern, RegexOptions.Compiled);
33+
public static readonly StringOrRegex MicrosoftAspNetCoreHosting = new Regex(MicrosoftAspNetCoreHostingPattern, RegexOptions.Compiled);
3234
#endif
3335

3436
/// <summary>
35-
/// Matches the built in Microsoft.AspNetCore.Routing metrics
37+
/// Matches the built-in Microsoft.AspNetCore.Routing metrics
3638
/// </summary>
3739
#if NET8_0_OR_GREATER
38-
public static readonly SubstringOrRegexPattern MicrosoftAspNetCoreRouting = MicrosoftAspNetCoreRoutingRegex();
40+
public static readonly StringOrRegex MicrosoftAspNetCoreRouting = MicrosoftAspNetCoreRoutingRegex();
3941

4042
[GeneratedRegex(MicrosoftAspNetCoreRoutingPattern, RegexOptions.Compiled)]
4143
private static partial Regex MicrosoftAspNetCoreRoutingRegex();
4244
#else
43-
public static readonly SubstringOrRegexPattern MicrosoftAspNetCoreRouting = new Regex(MicrosoftAspNetCoreRoutingPattern, RegexOptions.Compiled);
45+
public static readonly StringOrRegex MicrosoftAspNetCoreRouting = new Regex(MicrosoftAspNetCoreRoutingPattern, RegexOptions.Compiled);
4446
#endif
4547

4648
/// <summary>
47-
/// Matches the built in Microsoft.AspNetCore.Diagnostics metrics
49+
/// Matches the built-in Microsoft.AspNetCore.Diagnostics metrics
4850
/// </summary>
4951
#if NET8_0_OR_GREATER
50-
public static readonly SubstringOrRegexPattern MicrosoftAspNetCoreDiagnostics = MicrosoftAspNetCoreDiagnosticsRegex();
52+
public static readonly StringOrRegex MicrosoftAspNetCoreDiagnostics = MicrosoftAspNetCoreDiagnosticsRegex();
5153

5254
[GeneratedRegex(MicrosoftAspNetCoreDiagnosticsPattern, RegexOptions.Compiled)]
5355
private static partial Regex MicrosoftAspNetCoreDiagnosticsRegex();
5456
#else
55-
public static readonly SubstringOrRegexPattern MicrosoftAspNetCoreDiagnostics = new Regex(MicrosoftAspNetCoreDiagnosticsPattern, RegexOptions.Compiled);
57+
public static readonly StringOrRegex MicrosoftAspNetCoreDiagnostics = new Regex(MicrosoftAspNetCoreDiagnosticsPattern, RegexOptions.Compiled);
5658
#endif
5759

5860
/// <summary>
59-
/// Matches the built in Microsoft.AspNetCore.RateLimiting metrics
61+
/// Matches the built-in Microsoft.AspNetCore.RateLimiting metrics
6062
/// </summary>
6163
#if NET8_0_OR_GREATER
62-
public static readonly SubstringOrRegexPattern MicrosoftAspNetCoreRateLimiting = MicrosoftAspNetCoreRateLimitingRegex();
64+
public static readonly StringOrRegex MicrosoftAspNetCoreRateLimiting = MicrosoftAspNetCoreRateLimitingRegex();
6365

6466
[GeneratedRegex(MicrosoftAspNetCoreRateLimitingPattern, RegexOptions.Compiled)]
6567
private static partial Regex MicrosoftAspNetCoreRateLimitingRegex();
6668
#else
67-
public static readonly SubstringOrRegexPattern MicrosoftAspNetCoreRateLimiting = new Regex(MicrosoftAspNetCoreRateLimitingPattern, RegexOptions.Compiled);
69+
public static readonly StringOrRegex MicrosoftAspNetCoreRateLimiting = new Regex(MicrosoftAspNetCoreRateLimitingPattern, RegexOptions.Compiled);
6870
#endif
6971

7072
/// <summary>
71-
/// Matches the built in Microsoft.AspNetCore.HeaderParsing metrics
73+
/// Matches the built-in Microsoft.AspNetCore.HeaderParsing metrics
7274
/// </summary>
7375
#if NET8_0_OR_GREATER
74-
public static readonly SubstringOrRegexPattern MicrosoftAspNetCoreHeaderParsing = MicrosoftAspNetCoreHeaderParsingRegex();
76+
public static readonly StringOrRegex MicrosoftAspNetCoreHeaderParsing = MicrosoftAspNetCoreHeaderParsingRegex();
7577

7678
[GeneratedRegex(MicrosoftAspNetCoreHeaderParsingPattern, RegexOptions.Compiled)]
7779
private static partial Regex MicrosoftAspNetCoreHeaderParsingRegex();
7880
#else
79-
public static readonly SubstringOrRegexPattern MicrosoftAspNetCoreHeaderParsing = new Regex(MicrosoftAspNetCoreHeaderParsingPattern, RegexOptions.Compiled);
81+
public static readonly StringOrRegex MicrosoftAspNetCoreHeaderParsing = new Regex(MicrosoftAspNetCoreHeaderParsingPattern, RegexOptions.Compiled);
8082
#endif
8183

8284
/// <summary>
83-
/// Matches the built in Microsoft.AspNetCore.Server.Kestrel metrics
85+
/// Matches the built-in Microsoft.AspNetCore.Server.Kestrel metrics
8486
/// </summary>
8587
#if NET8_0_OR_GREATER
86-
public static readonly SubstringOrRegexPattern MicrosoftAspNetCoreServerKestrel = MicrosoftAspNetCoreServerKestrelRegex();
88+
public static readonly StringOrRegex MicrosoftAspNetCoreServerKestrel = MicrosoftAspNetCoreServerKestrelRegex();
8789

8890
[GeneratedRegex(MicrosoftAspNetCoreServerKestrelPattern, RegexOptions.Compiled)]
8991
private static partial Regex MicrosoftAspNetCoreServerKestrelRegex();
9092
#else
91-
public static readonly SubstringOrRegexPattern MicrosoftAspNetCoreServerKestrel = new Regex(MicrosoftAspNetCoreServerKestrelPattern, RegexOptions.Compiled);
93+
public static readonly StringOrRegex MicrosoftAspNetCoreServerKestrel = new Regex(MicrosoftAspNetCoreServerKestrelPattern, RegexOptions.Compiled);
9294
#endif
9395

9496
/// <summary>
95-
/// Matches the built in Microsoft.AspNetCore.Http.Connections metrics
97+
/// Matches the built-in Microsoft.AspNetCore.Http.Connections metrics
9698
/// </summary>
9799
#if NET8_0_OR_GREATER
98-
public static readonly SubstringOrRegexPattern MicrosoftAspNetCoreHttpConnections = MicrosoftAspNetCoreHttpConnectionsRegex();
100+
public static readonly StringOrRegex MicrosoftAspNetCoreHttpConnections = MicrosoftAspNetCoreHttpConnectionsRegex();
99101

100102
[GeneratedRegex(MicrosoftAspNetCoreHttpConnectionsPattern, RegexOptions.Compiled)]
101103
private static partial Regex MicrosoftAspNetCoreHttpConnectionsRegex();
102104
#else
103-
public static readonly SubstringOrRegexPattern MicrosoftAspNetCoreHttpConnections = new Regex(MicrosoftAspNetCoreHttpConnectionsPattern, RegexOptions.Compiled);
105+
public static readonly StringOrRegex MicrosoftAspNetCoreHttpConnections = new Regex(MicrosoftAspNetCoreHttpConnectionsPattern, RegexOptions.Compiled);
104106
#endif
105107

106108
/// <summary>
107-
/// Matches the built in Microsoft.Extensions.Diagnostics.HealthChecks metrics
109+
/// Matches the built-in Microsoft.Extensions.Diagnostics.HealthChecks metrics
108110
/// </summary>
109111
#if NET8_0_OR_GREATER
110-
public static readonly SubstringOrRegexPattern MicrosoftExtensionsDiagnosticsHealthChecks = MicrosoftExtensionsDiagnosticsHealthChecksRegex();
112+
public static readonly StringOrRegex MicrosoftExtensionsDiagnosticsHealthChecks = MicrosoftExtensionsDiagnosticsHealthChecksRegex();
111113

112114
[GeneratedRegex(MicrosoftExtensionsDiagnosticsHealthChecksPattern, RegexOptions.Compiled)]
113115
private static partial Regex MicrosoftExtensionsDiagnosticsHealthChecksRegex();
114116
#else
115-
public static readonly SubstringOrRegexPattern MicrosoftExtensionsDiagnosticsHealthChecks = new Regex(MicrosoftExtensionsDiagnosticsHealthChecksPattern, RegexOptions.Compiled);
117+
public static readonly StringOrRegex MicrosoftExtensionsDiagnosticsHealthChecks = new Regex(MicrosoftExtensionsDiagnosticsHealthChecksPattern, RegexOptions.Compiled);
116118
#endif
117119

118120
/// <summary>
119-
/// Matches the built in Microsoft.Extensions.Diagnostics.ResourceMonitoring metrics
121+
/// Matches the built-in Microsoft.Extensions.Diagnostics.ResourceMonitoring metrics
120122
/// </summary>
121123
#if NET8_0_OR_GREATER
122-
public static readonly SubstringOrRegexPattern MicrosoftExtensionsDiagnosticsResourceMonitoring = MicrosoftExtensionsDiagnosticsResourceMonitoringRegex();
124+
public static readonly StringOrRegex MicrosoftExtensionsDiagnosticsResourceMonitoring = MicrosoftExtensionsDiagnosticsResourceMonitoringRegex();
123125

124126
[GeneratedRegex(MicrosoftExtensionsDiagnosticsResourceMonitoringPattern, RegexOptions.Compiled)]
125127
private static partial Regex MicrosoftExtensionsDiagnosticsResourceMonitoringRegex();
126128
#else
127-
public static readonly SubstringOrRegexPattern MicrosoftExtensionsDiagnosticsResourceMonitoring = new Regex(MicrosoftExtensionsDiagnosticsResourceMonitoringPattern, RegexOptions.Compiled);
129+
public static readonly StringOrRegex MicrosoftExtensionsDiagnosticsResourceMonitoring = new Regex(MicrosoftExtensionsDiagnosticsResourceMonitoringPattern, RegexOptions.Compiled);
128130
#endif
129131

130132
/// <summary>
131-
/// Matches the built in System.Net.NameResolution metrics
133+
/// Matches the built-in System.Net.NameResolution metrics
132134
/// </summary>
133135
#if NET8_0_OR_GREATER
134-
public static readonly SubstringOrRegexPattern OpenTelemetryInstrumentationRuntime = OpenTelemetryInstrumentationRuntimeRegex();
136+
public static readonly StringOrRegex OpenTelemetryInstrumentationRuntime = OpenTelemetryInstrumentationRuntimeRegex();
135137

136138
[GeneratedRegex(OpenTelemetryInstrumentationRuntimePattern, RegexOptions.Compiled)]
137139
private static partial Regex OpenTelemetryInstrumentationRuntimeRegex();
138140
#else
139-
public static readonly SubstringOrRegexPattern OpenTelemetryInstrumentationRuntime = new Regex(OpenTelemetryInstrumentationRuntimePattern, RegexOptions.Compiled);
141+
public static readonly StringOrRegex OpenTelemetryInstrumentationRuntime = new Regex(OpenTelemetryInstrumentationRuntimePattern, RegexOptions.Compiled);
140142
#endif
141143

142144
/// <summary>
143-
/// Matches the built in System.Net.NameResolution metrics
145+
/// Matches the built-in System.Net.NameResolution metrics
144146
/// </summary>
145147
#if NET8_0_OR_GREATER
146-
public static readonly SubstringOrRegexPattern SystemNetNameResolution = SystemNetNameResolutionRegex();
148+
public static readonly StringOrRegex SystemNetNameResolution = SystemNetNameResolutionRegex();
147149

148150
[GeneratedRegex(SystemNetNameResolutionPattern, RegexOptions.Compiled)]
149151
private static partial Regex SystemNetNameResolutionRegex();
150152
#else
151-
public static readonly SubstringOrRegexPattern SystemNetNameResolution = new Regex(SystemNetNameResolutionPattern, RegexOptions.Compiled);
153+
public static readonly StringOrRegex SystemNetNameResolution = new Regex(SystemNetNameResolutionPattern, RegexOptions.Compiled);
152154
#endif
153155

154156
/// <summary>
155-
/// Matches the built in <see cref="System.Net.Http"/> metrics
157+
/// Matches the built-in <see cref="System.Net.Http"/> metrics
156158
/// </summary>
157159
#if NET8_0_OR_GREATER
158-
public static readonly SubstringOrRegexPattern SystemNetHttp = SystemNetHttpRegex();
160+
public static readonly StringOrRegex SystemNetHttp = SystemNetHttpRegex();
159161

160162
[GeneratedRegex(SystemNetHttpPattern, RegexOptions.Compiled)]
161163
private static partial Regex SystemNetHttpRegex();
162164
#else
163-
public static readonly SubstringOrRegexPattern SystemNetHttp = new Regex(SystemNetHttpPattern, RegexOptions.Compiled);
165+
public static readonly StringOrRegex SystemNetHttp = new Regex(SystemNetHttpPattern, RegexOptions.Compiled);
164166
#endif
165167

166-
private static readonly Lazy<IList<SubstringOrRegexPattern>> LazyAll = new(() => new List<SubstringOrRegexPattern>
168+
private static readonly Lazy<IList<StringOrRegex>> LazyAll = new(() => new List<StringOrRegex>
167169
{
168170
MicrosoftAspNetCoreHosting,
169171
MicrosoftAspNetCoreRouting,
@@ -180,8 +182,8 @@ public static partial class BuiltInSystemDiagnosticsMeters
180182
});
181183

182184
/// <summary>
183-
/// Matches all built in metrics
185+
/// Matches all built-in metrics
184186
/// </summary>
185187
/// <returns></returns>
186-
public static IList<SubstringOrRegexPattern> All => LazyAll.Value;
188+
public static IList<StringOrRegex> All => LazyAll.Value;
187189
}

src/Sentry/ExperimentalMetricsOptions.cs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
using Sentry.Internal;
2+
13
namespace Sentry;
24

35
/// <summary>
@@ -11,21 +13,21 @@ public class ExperimentalMetricsOptions
1113
/// </summary>
1214
public bool EnableCodeLocations { get; set; } = true;
1315

14-
private IList<SubstringOrRegexPattern> _captureSystemDiagnosticsInstruments = new List<SubstringOrRegexPattern>();
16+
private IList<StringOrRegex> _captureSystemDiagnosticsInstruments = new List<StringOrRegex>();
1517

1618
/// <summary>
1719
/// <para>
1820
/// A list of Substrings or Regular Expressions. Any `System.Diagnostics.Metrics.Instrument` whose name
1921
/// matches one of the items in this list will be collected and reported to Sentry.
2022
/// </para>
2123
/// <para>
22-
/// These can be either custom Instruments that you have created or any of the built in metrics that are available.
24+
/// These can be either custom Instruments that you have created or any of the built-in metrics that are available.
2325
/// </para>
2426
/// <para>
2527
/// See https://learn.microsoft.com/en-us/dotnet/core/diagnostics/built-in-metrics for more information.
2628
/// </para>
2729
/// </summary>
28-
public IList<SubstringOrRegexPattern> CaptureSystemDiagnosticsInstruments
30+
public IList<StringOrRegex> CaptureSystemDiagnosticsInstruments
2931
{
3032
// NOTE: During configuration binding, .NET 6 and lower used to just call Add on the existing item.
3133
// .NET 7 changed this to call the setter with an array that already starts with the old value.
@@ -34,21 +36,21 @@ public IList<SubstringOrRegexPattern> CaptureSystemDiagnosticsInstruments
3436
set => _captureSystemDiagnosticsInstruments = value.WithConfigBinding();
3537
}
3638

37-
private IList<SubstringOrRegexPattern> _captureSystemDiagnosticsMeters = BuiltInSystemDiagnosticsMeters.All;
39+
private IList<StringOrRegex> _captureSystemDiagnosticsMeters = BuiltInSystemDiagnosticsMeters.All;
3840

3941
/// <summary>
4042
/// <para>
4143
/// A list of Substrings or Regular Expressions. Instruments for any `System.Diagnostics.Metrics.Meter`
4244
/// whose name matches one of the items in this list will be collected and reported to Sentry.
4345
/// </para>
4446
/// <para>
45-
/// These can be either custom Instruments that you have created or any of the built in metrics that are available.
47+
/// These can be either custom Instruments that you have created or any of the built-in metrics that are available.
4648
/// </para>
4749
/// <para>
4850
/// See https://learn.microsoft.com/en-us/dotnet/core/diagnostics/built-in-metrics for more information.
4951
/// </para>
5052
/// </summary>
51-
public IList<SubstringOrRegexPattern> CaptureSystemDiagnosticsMeters
53+
public IList<StringOrRegex> CaptureSystemDiagnosticsMeters
5254
{
5355
// NOTE: During configuration binding, .NET 6 and lower used to just call Add on the existing item.
5456
// .NET 7 changed this to call the setter with an array that already starts with the old value.

src/Sentry/Internal/DelimitedPrefixOrPatternMatcher.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,11 @@ internal class DelimitedPrefixOrPatternMatcher(char delimiter = '.', StringCompa
77
{
88
public bool IsMatch(StringOrRegex stringOrRegex, string value)
99
{
10-
if (stringOrRegex._prefix is not null)
10+
if (stringOrRegex._string is not null)
1111
{
1212
// Check for a prefix followed by the separator
13-
return stringOrRegex._prefix != null && value.StartsWith(stringOrRegex._prefix, comparison) &&
14-
value.Length > stringOrRegex._prefix.Length && value[stringOrRegex._prefix.Length] == delimiter;
13+
return stringOrRegex._string != null && value.StartsWith(stringOrRegex._string, comparison) &&
14+
value.Length > stringOrRegex._string.Length && value[stringOrRegex._string.Length] == delimiter;
1515
}
1616

1717
// Check for any regex match followed by the separator

src/Sentry/Internal/IStringOrRegexMatcher.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,8 @@ namespace Sentry.Internal;
22

33
internal interface IStringOrRegexMatcher
44
{
5+
/// <summary>
6+
/// Evaluates if the given value matches the string or regex.
7+
/// </summary>
58
bool IsMatch(StringOrRegex stringOrRegex, string value);
69
}

src/Sentry/Internal/PrefixOrPatternMatcher.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ internal class PrefixOrPatternMatcher(StringComparison comparison = StringCompar
77
{
88
public bool IsMatch(StringOrRegex stringOrRegex, string value)
99
{
10-
return (stringOrRegex._prefix != null && value.StartsWith(stringOrRegex._prefix, comparison)) ||
10+
return (stringOrRegex._string != null && value.StartsWith(stringOrRegex._string, comparison)) ||
1111
stringOrRegex?._regex?.IsMatch(value) == true;
1212
}
1313
}

0 commit comments

Comments
 (0)