-
Notifications
You must be signed in to change notification settings - Fork 0
Replace static parameters in route pattern for telemetry #5
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: qodo_only-issues-20260113-qodo-grep-copilot_base_replace_static_parameters_in_route_pattern_for_telemetry_pr20
Are you sure you want to change the base?
Changes from all commits
1e2153b
f1f3274
ec8c576
6fd922c
f6fbcf8
89ee7c9
bc94108
4404a33
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,103 @@ | ||
| // Licensed to the .NET Foundation under one or more agreements. | ||
| // The .NET Foundation licenses this file to you under the MIT license. | ||
|
|
||
| using System.Diagnostics.CodeAnalysis; | ||
|
|
||
| namespace Microsoft.AspNetCore.Routing.Patterns; | ||
|
|
||
| internal static class RoutePatternDebugStringFormatter | ||
| { | ||
| private const char Separator = '/'; | ||
| private const string SeparatorString = "/"; | ||
|
|
||
| public static string Format(RoutePattern pattern) | ||
| { | ||
| // If there are no required values that match parameters, use the simple approach | ||
| if (pattern.RawText is { Length: > 0 } rawText && !HasMatchingRequiredValues(pattern)) | ||
| { | ||
| return rawText; | ||
| } | ||
|
|
||
| // Build the string replacing parameters with their required values when available | ||
| var segments = new string[pattern.PathSegments.Count]; | ||
| for (var i = 0; i < pattern.PathSegments.Count; i++) | ||
| { | ||
| var segment = pattern.PathSegments[i]; | ||
| var segmentString = GetSegmentDebuggerToString(pattern, segment); | ||
| segments[i] = segmentString; | ||
| } | ||
|
|
||
| var result = string.Join(SeparatorString, segments); | ||
|
|
||
| // Preserve leading slash from raw text | ||
| if (pattern.RawText is { Length: > 0 } rt && rt[0] == Separator) | ||
| { | ||
| result = Separator + result; | ||
| } | ||
|
Comment on lines
+32
to
+36
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 2. Drops tilde-slash prefix • When RequiredValues match parameters, RoutePatternDebugStringFormatter rebuilds the string from segments and only re-adds a leading '/' (not "~/"). • For patterns whose RawText starts with "~/" (supported by RoutePatternParser), this means the returned debug string loses that prefix only in the rebuild/substitution path. Agent Prompt
|
||
|
|
||
| // Return "/" for empty results | ||
| if (result.Length == 0) | ||
| { | ||
| return SeparatorString; | ||
| } | ||
|
|
||
| return result; | ||
| } | ||
|
|
||
| private static bool HasMatchingRequiredValues(RoutePattern pattern) | ||
| { | ||
| if (pattern.RequiredValues.Count == 0) | ||
| { | ||
| return false; | ||
| } | ||
|
|
||
| for (var i = 0; i < pattern.Parameters.Count; i++) | ||
| { | ||
| if (TryGetRequiredValue(pattern, pattern.Parameters[i].Name, out _)) | ||
| { | ||
| return true; | ||
| } | ||
| } | ||
|
|
||
| return false; | ||
| } | ||
|
|
||
| private static string GetSegmentDebuggerToString(RoutePattern pattern, RoutePatternPathSegment segment) | ||
| { | ||
| // Simple segment with single parameter that has a required value - just return the required value | ||
| if (segment.IsSimple && segment.Parts[0] is RoutePatternParameterPart parameter) | ||
| { | ||
| if (TryGetRequiredValue(pattern, parameter.Name, out var requiredValue)) | ||
| { | ||
| return requiredValue; | ||
| } | ||
| return parameter.DebuggerToString(); | ||
| } | ||
|
|
||
| // For complex segments, build the string part by part | ||
| var parts = new string[segment.Parts.Count]; | ||
| for (var i = 0; i < segment.Parts.Count; i++) | ||
| { | ||
| var part = segment.Parts[i]; | ||
| parts[i] = part is RoutePatternParameterPart paramPart && TryGetRequiredValue(pattern, paramPart.Name, out var value) | ||
| ? value | ||
| : part.DebuggerToString(); | ||
| } | ||
|
|
||
| return string.Join(string.Empty, parts); | ||
| } | ||
|
|
||
| private static bool TryGetRequiredValue(RoutePattern pattern, string parameterName, [NotNullWhen(true)] out string? value) | ||
| { | ||
| if (pattern.RequiredValues.TryGetValue(parameterName, out var requiredValue) && | ||
| !RoutePattern.IsRequiredValueAny(requiredValue) && | ||
| requiredValue?.ToString() is { Length: > 0 } v) | ||
| { | ||
| value = v; | ||
| return true; | ||
| } | ||
|
Comment on lines
+92
to
+98
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 3. Required value culture drift • Required value substitution uses requiredValue.ToString(), which is culture-dependent for non-string values and may produce different endpoint display names/route metadata across environments. • Routing already normalizes values with Convert.ToString(..., CultureInfo.InvariantCulture) elsewhere; using object.ToString() here is inconsistent and can also surface unexpected ToString() exceptions into endpoint construction. Agent Prompt
|
||
|
|
||
| value = null; | ||
| return false; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -99,10 +99,23 @@ internal override string DebuggerToString() | |
| foreach (var constraint in ParameterPolicies) | ||
| { | ||
| builder.Append(':'); | ||
| builder.Append(constraint.ParameterPolicy); | ||
| if (constraint.Content is not null) | ||
| { | ||
| builder.Append(constraint.Content); | ||
| } | ||
| else if (constraint.ParameterPolicy is Constraints.RegexRouteConstraint regexConstraint) | ||
| { | ||
| builder.Append("regex("); | ||
| builder.Append(regexConstraint.Constraint.ToString()); | ||
| builder.Append(')'); | ||
| } | ||
|
Comment on lines
+106
to
+111
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 1. Regex compiled in debug • RoutePatternParameterPart.DebuggerToString now formats RegexRouteConstraint by reading regexConstraint.Constraint, which forces the lazily-created Regex instance to be created/compiled. • DebuggerToString is executed during endpoint construction for both RouteEndpoint.DisplayName and default IRouteDiagnosticsMetadata, so this can regress startup performance for apps using regex-based constraints/policies. Agent Prompt
|
||
| else if (constraint.ParameterPolicy is not null) | ||
| { | ||
| builder.Append(constraint.ParameterPolicy); | ||
| } | ||
| } | ||
|
|
||
| if (Default != null) | ||
| if (Default is not null) | ||
| { | ||
| builder.Append('='); | ||
| builder.Append(Default); | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
4. Metrics tag cardinality
🐞 BugAgent Prompt
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools