Conversation
A lot of the warnings for this rule appear from logging. Given this is going to be replaced by a source generator, this change soft enables the rule while fixing warnings that appear in non-logging code
| _endpointsFound(logger, endpoints.Select(e => e.DisplayName), address, null); | ||
| } | ||
| } | ||
| [LoggerMessage(EventId = 100, EventName = "EndpointsFound", Level = LogLevel.Debug, Message = "Found the endpoints {Endpoints} for address {Address}")] |
There was a problem hiding this comment.
@maryamariyan / @eerhardt could you have a look at this and let me know if I'm doing this correctly?
FYI @JamesNK / @davidfowl
There was a problem hiding this comment.
The previous EndpointsFound method would check whether logging was enabled and then use LINQ to get endpoint names. I believe that is missing post your changes.
Follow the pattern you used with TemplateFailedRequiredValues?
| <ItemGroup> | ||
| <Reference Include="Microsoft.AspNetCore.Http.Features" /> | ||
| <Reference Include="Microsoft.Net.Http.Headers" /> | ||
| <Reference Include="Microsoft.Extensions.Logging.Abstractions" PrivateAssets="All" /> |
There was a problem hiding this comment.
Why is this private assets?
There was a problem hiding this comment.
I had to add a reference for the source generator. Our build complains if you add new references and I didn't want to deal with it.
| } | ||
|
|
||
| private static class Log | ||
| internal static partial class Log |
There was a problem hiding this comment.
I can revert it. I was fiddling around with making the source generator work.
| } | ||
| } | ||
| [LoggerMessage(EventId = 100, EventName = "EndpointsFound", Level = LogLevel.Debug, Message = "Found the endpoints {Endpoints} for address {Address}")] | ||
| public static partial void EndpointsFound(ILogger logger, object address, IEnumerable<Endpoint> endpoints); |
There was a problem hiding this comment.
Does the order of {Endpoints} and {Address} need to match in the string with how it is ordered in the method signature?
If not, do the names need to match? Here they differ by case.
There was a problem hiding this comment.
I think the generator looks them up by name (case insensitively).
There was a problem hiding this comment.
Here's the dope code it generates: https://gist.github.com/pranavkm/dba57e845227045d8e3651b0d49d3418
| _endpointsFound(logger, endpoints.Select(e => e.DisplayName), address, null); | ||
| } | ||
| } | ||
| [LoggerMessage(EventId = 100, EventName = "EndpointsFound", Level = LogLevel.Debug, Message = "Found the endpoints {Endpoints} for address {Address}")] |
There was a problem hiding this comment.
The previous EndpointsFound method would check whether logging was enabled and then use LINQ to get endpoint names. I believe that is missing post your changes.
Follow the pattern you used with TemplateFailedRequiredValues?
| } | ||
| } | ||
| [LoggerMessage(EventId = 100, EventName = "EndpointsFound", Level = LogLevel.Debug, Message = "Found the endpoints {Endpoints} for address {Address}")] | ||
| public static partial void EndpointsFound(ILogger logger, object address, IEnumerable<Endpoint> endpoints); |
| Message = "Failed to process the template {Template} for {Endpoint}. " + | ||
| "A required route value is missing, or has a different value from the required default values. " + | ||
| "Supplied ambient values {AmbientValues} and {Values} with default values {Defaults}")] | ||
| public static partial void TemplateFailedRequiredValues(ILogger logger, string template, string endpoint, string ambientValues, string values, string defaults); |
There was a problem hiding this comment.
Do partial methods on log generators always have to be public? Looks like this would only be called from the overload so it could be private.
| Message = "Failed to process the template {Template} for {Endpoint}. " + | ||
| "The failure occurred while expanding the template with values {Values} " + | ||
| "This is usually due to a missing or empty value in a complex segment")] | ||
| public static partial void TemplateFailedExpansion(ILogger logger, string template, string endpoint, string values); |
There was a problem hiding this comment.
Is skip log level check added yet? Can add it to attribute when method is called from an overload that already checks for IsEnabled.
There was a problem hiding this comment.
Not yet but close: dotnet/runtime#54305
Add comments to attributes where it should be added once supported.
| <MicrosoftExtensionsHostingVersion>6.0.0-preview.6.21314.2</MicrosoftExtensionsHostingVersion> | ||
| <MicrosoftExtensionsHttpVersion>6.0.0-preview.6.21314.2</MicrosoftExtensionsHttpVersion> | ||
| <MicrosoftExtensionsLoggingAbstractionsVersion>6.0.0-preview.6.21314.2</MicrosoftExtensionsLoggingAbstractionsVersion> | ||
| <MicrosoftExtensionsLoggingAbstractionsVersion>6.0.0-preview.7.21316.3</MicrosoftExtensionsLoggingAbstractionsVersion> |
There was a problem hiding this comment.
This will simply cause conflicts or be overwritten the next time we get versions from dotnet/runtime. Suggest retrying after #33560 is in.
| private static class Log | ||
| { | ||
| private static readonly Action<ILogger, string, Exception> _unhandledExceptionRenderingComponent; | ||
| private static readonly Action<ILogger, string, Exception> _unhandledExceptionRenderingComponent = LoggerMessage.Define<string>( |
There was a problem hiding this comment.
or maybe something like below?
[LoggerMessage(EventId = EventIds.UnhandledExceptionRenderingComponent, Level = LogLevel.Critical, Message = "Unhandled exception rendering component: {Message}")]
public static partial void UnhandledExceptionRenderingComponent(ILogger logger, string message);| { | ||
| _listeningOnAddress(logger, address, null); | ||
| } | ||
| [LoggerMessage(EventId = LoggerEventIds.ServerListeningOnAddresses, EventName = "ServerListeningOnAddresses", Level = LogLevel.Information, Message = "Now listening on: {address}")] |
There was a problem hiding this comment.
Note, when you don't specify EventName, it would take the method name as the event name for the log method.
Instead of setting EventName, I would rename this method from ListeningOnAddress to ServerListeningOnAddresses.
There was a problem hiding this comment.
We want to be explicit about the event name. It is easy for someone to unknowingly change the event name by renaming a method. That would introduce a breaking change.
That is the reason why we have strings today instead of using nameof(MethodName).
| { | ||
| _samesiteNotSecure(logger, name, null); | ||
| } | ||
| [LoggerMessage(EventId = 1, EventName = "SameSiteNotSecure", Level = LogLevel.Warning, Message = "The cookie '{name}' has set 'SameSite=None' and must also set 'Secure'.")] |
There was a problem hiding this comment.
When you don't set EventName explicitly the generator uses the log method's name as the event name. So you if you prefer, just remove , EventName = "SameSiteNotSecure" and rename SameSiteCookieNotSecure(..) to SameSiteNotSecure.
| { | ||
| _failedToReadStackFrameInfo(logger, exception); | ||
| } | ||
| [LoggerMessage(EventId = 0, EventName = "FailedToReadStackTraceInfo", Level = LogLevel.Debug, Message = "Failed to read stack trace information for exception.")] |
There was a problem hiding this comment.
| [LoggerMessage(EventId = 0, EventName = "FailedToReadStackTraceInfo", Level = LogLevel.Debug, Message = "Failed to read stack trace information for exception.")] | |
| [LoggerMessage(EventId = 0, Level = LogLevel.Debug, Message = "Failed to read stack trace information for exception.")] |
| { | ||
| _writeCancelled(logger, ex); | ||
| } | ||
| [LoggerMessage(EventId = 14, EventName = "WriteCancelled", Level = LogLevel.Debug, Message = "The file transmission was cancelled")] |
There was a problem hiding this comment.
| [LoggerMessage(EventId = 14, EventName = "WriteCancelled", Level = LogLevel.Debug, Message = "The file transmission was cancelled")] | |
| [LoggerMessage(EventId = 14, Level = LogLevel.Debug, Message = "The file transmission was cancelled")] |
| LogLevel.Information, | ||
| new EventId(6, "OriginNotAllowed"), | ||
| "Request origin {origin} does not have permission to access the resource."); | ||
| [LoggerMessage(EventId = 7, EventName = "AccessControlMethodNotAllowed", Level = LogLevel.Information, Message = "Request method {accessControlRequestMethod} not allowed in CORS policy.")] |
There was a problem hiding this comment.
| [LoggerMessage(EventId = 7, EventName = "AccessControlMethodNotAllowed", Level = LogLevel.Information, Message = "Request method {accessControlRequestMethod} not allowed in CORS policy.")] | |
| [LoggerMessage(EventId = 7, Level = LogLevel.Information, Message = "Request method {accessControlRequestMethod} not allowed in CORS policy.")] |
| LogLevel.Information, | ||
| new EventId(7, "AccessControlMethodNotAllowed"), | ||
| "Request method {accessControlRequestMethod} not allowed in CORS policy."); | ||
| [LoggerMessage(EventId = 8, EventName = "RequestHeaderNotAllowed", Level = LogLevel.Information, Message = "Request header '{requestHeader}' not allowed in CORS policy.")] |
There was a problem hiding this comment.
| [LoggerMessage(EventId = 8, EventName = "RequestHeaderNotAllowed", Level = LogLevel.Information, Message = "Request header '{requestHeader}' not allowed in CORS policy.")] | |
| [LoggerMessage(EventId = 8, Level = LogLevel.Information, Message = "Request header '{requestHeader}' not allowed in CORS policy.")] |
| LogLevel.Information, | ||
| new EventId(8, "RequestHeaderNotAllowed"), | ||
| "Request header '{requestHeader}' not allowed in CORS policy."); | ||
| [LoggerMessage(EventId = 9, EventName = "FailedToSetCorsHeaders", Level = LogLevel.Warning, Message = "Failed to apply CORS Response headers.")] |
There was a problem hiding this comment.
| [LoggerMessage(EventId = 9, EventName = "FailedToSetCorsHeaders", Level = LogLevel.Warning, Message = "Failed to apply CORS Response headers.")] | |
| [LoggerMessage(EventId = 9, Level = LogLevel.Warning, Message = "Failed to apply CORS Response headers.")] |
| LogLevel.Warning, | ||
| new EventId(9, "FailedToSetCorsHeaders"), | ||
| "Failed to apply CORS Response headers."); | ||
| [LoggerMessage(EventId = 10, EventName = "NoCorsPolicyFound", Level = LogLevel.Information, Message = "No CORS policy found for the specified request.")] |
There was a problem hiding this comment.
| [LoggerMessage(EventId = 10, EventName = "NoCorsPolicyFound", Level = LogLevel.Information, Message = "No CORS policy found for the specified request.")] | |
| [LoggerMessage(EventId = 10, Level = LogLevel.Information, Message = "No CORS policy found for the specified request.")] |
| { | ||
| _isNotPreflightRequest(logger, null); | ||
| } | ||
| [LoggerMessage(EventId = 12, EventName = "IsNotPreflightRequest", Level = LogLevel.Debug, |
There was a problem hiding this comment.
| [LoggerMessage(EventId = 12, EventName = "IsNotPreflightRequest", Level = LogLevel.Debug, | |
| [LoggerMessage(EventId = 12, Level = LogLevel.Debug, |
| { | ||
| _requestBodyIOException(GetLogger(httpContext), exception); | ||
| } | ||
| [LoggerMessage(EventId = 1, EventName = "RequestBodyIOException", Level = LogLevel.Debug, Message = "Reading the request body failed with an IOException.")] |
There was a problem hiding this comment.
| [LoggerMessage(EventId = 1, EventName = "RequestBodyIOException", Level = LogLevel.Debug, Message = "Reading the request body failed with an IOException.")] | |
| [LoggerMessage(EventId = 1, Level = LogLevel.Debug, Message = "Reading the request body failed with an IOException.")] |
| } | ||
| => RequestBodyInvalidDataException(GetLogger(httpContext), exception); | ||
|
|
||
| [LoggerMessage(EventId = 2, EventName = "RequestBodyInvalidDataException", Level = LogLevel.Debug, Message = "Reading the request body failed with an InvalidDataException.")] |
There was a problem hiding this comment.
| [LoggerMessage(EventId = 2, EventName = "RequestBodyInvalidDataException", Level = LogLevel.Debug, Message = "Reading the request body failed with an InvalidDataException.")] | |
| [LoggerMessage(EventId = 2, Level = LogLevel.Debug, Message = "Reading the request body failed with an InvalidDataException.")] |
| => ParameterBindingFailed(GetLogger(httpContext), parameterTypeName, parameterName, sourceValue); | ||
|
|
||
| [LoggerMessage(EventId = 3, EventName = "ParamaterBindingFailed", Level = LogLevel.Debug, Message = @"Failed to bind parameter ""{ParameterType} {ParameterName}"" from ""{SourceValue}"".")] | ||
| public static partial void ParameterBindingFailed(ILogger logger, string parameterType, string parameterName, string sourceValue); |
There was a problem hiding this comment.
ParamaterBindingFailed vs. ParameterBindingFailed
|
Closing this. Will work on converting to LoggerMessage in independent PRs. |
A lot of the warnings for this rule appear from logging. Given this is going
to be replaced by a source generator, this change soft enables the rule while
fixing warnings that appear in non-logging code
Contributes to #24055