* Move logging to new style

This commit is contained in:
ryanbrandenburg 2015-10-21 16:06:56 -07:00
parent 3c46662d91
commit 5763eb580a
27 changed files with 422 additions and 166 deletions

View File

@ -13,6 +13,7 @@ using Microsoft.AspNet.Mvc.Filters;
using Microsoft.AspNet.Mvc.Formatters; using Microsoft.AspNet.Mvc.Formatters;
using Microsoft.AspNet.Mvc.Infrastructure; using Microsoft.AspNet.Mvc.Infrastructure;
using Microsoft.AspNet.Mvc.Internal; using Microsoft.AspNet.Mvc.Internal;
using Microsoft.AspNet.Mvc.Logging;
using Microsoft.AspNet.Mvc.ModelBinding; using Microsoft.AspNet.Mvc.ModelBinding;
using Microsoft.AspNet.Mvc.ModelBinding.Validation; using Microsoft.AspNet.Mvc.ModelBinding.Validation;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
@ -48,17 +49,6 @@ namespace Microsoft.AspNet.Mvc.Controllers
private ResultExecutingContext _resultExecutingContext; private ResultExecutingContext _resultExecutingContext;
private ResultExecutedContext _resultExecutedContext; private ResultExecutedContext _resultExecutedContext;
private const string AuthorizationFailureLogMessage =
"Authorization failed for the request at filter '{AuthorizationFilter}'.";
private const string ResourceFilterShortCircuitLogMessage =
"Request was short circuited at resource filter '{ResourceFilter}'.";
private const string ActionFilterShortCircuitLogMessage =
"Request was short circuited at action filter '{ActionFilter}'.";
private const string ExceptionFilterShortCircuitLogMessage =
"Request was short circuited at exception filter '{ExceptionFilter}'.";
private const string ResultFilterShortCircuitLogMessage =
"Request was short circuited at result filter '{ResultFilter}'.";
public FilterActionInvoker( public FilterActionInvoker(
ActionContext actionContext, ActionContext actionContext,
@ -306,7 +296,7 @@ namespace Microsoft.AspNet.Mvc.Controllers
} }
else else
{ {
Logger.LogWarning(AuthorizationFailureLogMessage, current.FilterAsync.GetType().FullName); Logger.AuthorizationFailure(current.FilterAsync);
} }
} }
else if (current.Filter != null) else if (current.Filter != null)
@ -328,7 +318,7 @@ namespace Microsoft.AspNet.Mvc.Controllers
} }
else else
{ {
Logger.LogWarning(AuthorizationFailureLogMessage, current.Filter.GetType().FullName); Logger.AuthorizationFailure(current.Filter);
} }
} }
else else
@ -393,9 +383,7 @@ namespace Microsoft.AspNet.Mvc.Controllers
// If we get here then the filter didn't call 'next' indicating a short circuit // If we get here then the filter didn't call 'next' indicating a short circuit
if (_resourceExecutingContext.Result != null) if (_resourceExecutingContext.Result != null)
{ {
Logger.LogVerbose( Logger.ResourceFilterShortCircuited(item.FilterAsync);
ResourceFilterShortCircuitLogMessage,
item.FilterAsync.GetType().FullName);
await InvokeResultAsync(_resourceExecutingContext.Result); await InvokeResultAsync(_resourceExecutingContext.Result);
} }
@ -422,8 +410,8 @@ namespace Microsoft.AspNet.Mvc.Controllers
if (_resourceExecutingContext.Result != null) if (_resourceExecutingContext.Result != null)
{ {
// Short-circuited by setting a result. // Short-circuited by setting a result.
Logger.LogVerbose(ResourceFilterShortCircuitLogMessage, item.Filter.GetType().FullName); Logger.ResourceFilterShortCircuited(item.Filter);
await InvokeResultAsync(_resourceExecutingContext.Result); await InvokeResultAsync(_resourceExecutingContext.Result);
_resourceExecutedContext = new ResourceExecutedContext(_resourceExecutingContext, _filters) _resourceExecutedContext = new ResourceExecutedContext(_resourceExecutingContext, _filters)
@ -558,9 +546,7 @@ namespace Microsoft.AspNet.Mvc.Controllers
if (_exceptionContext.Exception == null) if (_exceptionContext.Exception == null)
{ {
Logger.LogVerbose( Logger.ExceptionFilterShortCircuited(current.FilterAsync);
ExceptionFilterShortCircuitLogMessage,
current.FilterAsync.GetType().FullName);
} }
} }
} }
@ -587,9 +573,7 @@ namespace Microsoft.AspNet.Mvc.Controllers
if (_exceptionContext.Exception == null) if (_exceptionContext.Exception == null)
{ {
Logger.LogVerbose( Logger.ExceptionFilterShortCircuited(current.Filter);
ExceptionFilterShortCircuitLogMessage,
current.Filter.GetType().FullName);
} }
} }
} }
@ -676,8 +660,7 @@ namespace Microsoft.AspNet.Mvc.Controllers
if (_actionExecutedContext == null) if (_actionExecutedContext == null)
{ {
// If we get here then the filter didn't call 'next' indicating a short circuit // If we get here then the filter didn't call 'next' indicating a short circuit
Logger.ActionFilterShortCircuited(item.FilterAsync);
Logger.LogVerbose(ActionFilterShortCircuitLogMessage, item.FilterAsync.GetType().FullName);
_actionExecutedContext = new ActionExecutedContext( _actionExecutedContext = new ActionExecutedContext(
_actionExecutingContext, _actionExecutingContext,
@ -704,8 +687,7 @@ namespace Microsoft.AspNet.Mvc.Controllers
if (_actionExecutingContext.Result != null) if (_actionExecutingContext.Result != null)
{ {
// Short-circuited by setting a result. // Short-circuited by setting a result.
Logger.ActionFilterShortCircuited(item.Filter);
Logger.LogVerbose(ActionFilterShortCircuitLogMessage, item.Filter.GetType().FullName);
_actionExecutedContext = new ActionExecutedContext( _actionExecutedContext = new ActionExecutedContext(
_actionExecutingContext, _actionExecutingContext,
@ -834,7 +816,7 @@ namespace Microsoft.AspNet.Mvc.Controllers
if (_resultExecutedContext == null || _resultExecutingContext.Cancel == true) if (_resultExecutedContext == null || _resultExecutingContext.Cancel == true)
{ {
// Short-circuited by not calling next || Short-circuited by setting Cancel == true // Short-circuited by not calling next || Short-circuited by setting Cancel == true
Logger.LogVerbose(ResourceFilterShortCircuitLogMessage, item.FilterAsync.GetType().FullName); Logger.ResourceFilterShortCircuited(item.FilterAsync);
_resultExecutedContext = new ResultExecutedContext( _resultExecutedContext = new ResultExecutedContext(
_resultExecutingContext, _resultExecutingContext,
@ -861,7 +843,7 @@ namespace Microsoft.AspNet.Mvc.Controllers
if (_resultExecutingContext.Cancel == true) if (_resultExecutingContext.Cancel == true)
{ {
// Short-circuited by setting Cancel == true // Short-circuited by setting Cancel == true
Logger.LogVerbose(ResourceFilterShortCircuitLogMessage, item.Filter.GetType().FullName); Logger.ResourceFilterShortCircuited(item.Filter);
_resultExecutedContext = new ResultExecutedContext( _resultExecutedContext = new ResultExecutedContext(
_resultExecutingContext, _resultExecutingContext,

View File

@ -9,6 +9,7 @@ using Microsoft.AspNet.Http;
using Microsoft.AspNet.Mvc.Abstractions; using Microsoft.AspNet.Mvc.Abstractions;
using Microsoft.AspNet.Mvc.ActionConstraints; using Microsoft.AspNet.Mvc.ActionConstraints;
using Microsoft.AspNet.Mvc.Core; using Microsoft.AspNet.Mvc.Core;
using Microsoft.AspNet.Mvc.Logging;
using Microsoft.AspNet.Mvc.Routing; using Microsoft.AspNet.Mvc.Routing;
using Microsoft.AspNet.Routing; using Microsoft.AspNet.Routing;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
@ -87,8 +88,7 @@ namespace Microsoft.AspNet.Mvc.Infrastructure
Environment.NewLine, Environment.NewLine,
finalMatches.Select(a => a.DisplayName)); finalMatches.Select(a => a.DisplayName));
_logger.LogError("Request matched multiple actions resulting in ambiguity. " + _logger.AmbiguousActions(actionNames);
"Matching actions: {AmbiguousActions}", actionNames);
var message = Resources.FormatDefaultActionSelector_AmbiguousActions( var message = Resources.FormatDefaultActionSelector_AmbiguousActions(
Environment.NewLine, Environment.NewLine,
@ -170,14 +170,10 @@ namespace Microsoft.AspNet.Mvc.Infrastructure
if (!constraint.Accept(constraintContext)) if (!constraint.Accept(constraintContext))
{ {
isMatch = false; isMatch = false;
_logger.ConstraintMismatch(
_logger.LogVerbose(
"Action '{ActionDisplayName}' with id '{ActionId}' did not match the " +
"constraint '{ActionConstraint}'",
candidate.Action.DisplayName, candidate.Action.DisplayName,
candidate.Action.Id, candidate.Action.Id,
constraint); constraint);
break; break;
} }
} }

View File

@ -128,18 +128,13 @@ namespace Microsoft.AspNet.Mvc.Infrastructure
if (selectedFormatter == null) if (selectedFormatter == null)
{ {
// No formatter supports this. // No formatter supports this.
Logger.LogWarning("No output formatter was found to write the response."); Logger.NoFormatter(formatterContext);
context.HttpContext.Response.StatusCode = StatusCodes.Status406NotAcceptable; context.HttpContext.Response.StatusCode = StatusCodes.Status406NotAcceptable;
return TaskCache.CompletedTask; return TaskCache.CompletedTask;
} }
Logger.LogVerbose( Logger.FormatterSelected(selectedFormatter, formatterContext);
"Selected output formatter '{OutputFormatter}' and content type " +
"'{ContentType}' to write the response.",
selectedFormatter.GetType().FullName,
formatterContext.ContentType);
Logger.ObjectResultExecuting(context); Logger.ObjectResultExecuting(context);
result.OnFormatting(context); result.OnFormatting(context);
@ -183,9 +178,7 @@ namespace Microsoft.AspNet.Mvc.Infrastructure
// or URL path extension mapping). If yes, then ignore content-negotiation and use this content-type. // or URL path extension mapping). If yes, then ignore content-negotiation and use this content-type.
if (contentTypes.Count == 1) if (contentTypes.Count == 1)
{ {
Logger.LogVerbose( Logger.SkippedContentNegotiation(contentTypes[0]);
"Skipped content negotiation as content type '{ContentType}' is explicitly set for the response.",
contentTypes[0]);
return SelectFormatterUsingAnyAcceptableContentType(formatterContext, formatters, contentTypes); return SelectFormatterUsingAnyAcceptableContentType(formatterContext, formatters, contentTypes);
} }
@ -200,7 +193,7 @@ namespace Microsoft.AspNet.Mvc.Infrastructure
// which can write the type. Let the formatter choose the Content-Type. // which can write the type. Let the formatter choose the Content-Type.
if (acceptValues == null || acceptValues.Count == 0) if (acceptValues == null || acceptValues.Count == 0)
{ {
Logger.LogVerbose("No information found on request to perform content negotiation."); Logger.NoAcceptForNegotiation();
return SelectFormatterNotUsingAcceptHeaders(formatterContext, formatters); return SelectFormatterNotUsingAcceptHeaders(formatterContext, formatters);
} }
@ -219,7 +212,7 @@ namespace Microsoft.AspNet.Mvc.Infrastructure
// the type. Let the formatter choose the Content-Type. // the type. Let the formatter choose the Content-Type.
if (selectedFormatter == null) if (selectedFormatter == null)
{ {
Logger.LogVerbose("Could not find an output formatter based on content negotiation."); Logger.NoFormatterFromNegotiation(acceptValues);
// Set this flag to indicate that content-negotiation has failed to let formatters decide // Set this flag to indicate that content-negotiation has failed to let formatters decide
// if they want to write the response or not. // if they want to write the response or not.

View File

@ -8,9 +8,9 @@ using Microsoft.Extensions.Logging;
namespace Microsoft.AspNet.Mvc.Logging namespace Microsoft.AspNet.Mvc.Logging
{ {
public static class ChallengeResultLoggerExtenstions internal static class ChallengeResultLoggerExtenstions
{ {
private static Action<ILogger, string[], Exception> _challengeResultExecuting; private static readonly Action<ILogger, string[], Exception> _challengeResultExecuting;
static ChallengeResultLoggerExtenstions() static ChallengeResultLoggerExtenstions()
{ {

View File

@ -7,9 +7,9 @@ using Microsoft.Net.Http.Headers;
namespace Microsoft.AspNet.Mvc.Logging namespace Microsoft.AspNet.Mvc.Logging
{ {
public static class ContentResultLoggerExtensions internal static class ContentResultLoggerExtensions
{ {
private static Action<ILogger, string, Exception> _contentResultExecuting; private static readonly Action<ILogger, string, Exception> _contentResultExecuting;
static ContentResultLoggerExtensions() static ContentResultLoggerExtensions()
{ {

View File

@ -8,10 +8,10 @@ using Microsoft.Extensions.Logging;
namespace Microsoft.AspNet.Mvc.Logging namespace Microsoft.AspNet.Mvc.Logging
{ {
public static class ControllerActionInvokerLoggerExtensions internal static class ControllerActionInvokerLoggerExtensions
{ {
private static Action<ILogger, string, string[], ModelValidationState, Exception> _actionMethodExecuting; private static readonly Action<ILogger, string, string[], ModelValidationState, Exception> _actionMethodExecuting;
private static Action<ILogger, string, string, Exception> _actionMethodExecuted; private static readonly Action<ILogger, string, string, Exception> _actionMethodExecuted;
static ControllerActionInvokerLoggerExtensions() static ControllerActionInvokerLoggerExtensions()
{ {

View File

@ -0,0 +1,41 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using Microsoft.AspNet.Mvc.ActionConstraints;
using Microsoft.Extensions.Logging;
namespace Microsoft.AspNet.Mvc.Logging
{
internal static class DefaultActionSelectorLoggerExtensions
{
private static readonly Action<ILogger, string, Exception> _ambiguousActions;
private static readonly Action<ILogger, string, string, IActionConstraint, Exception> _constraintMismatch;
static DefaultActionSelectorLoggerExtensions()
{
_ambiguousActions = LoggerMessage.Define<string>(
LogLevel.Error,
1,
"Request matched multiple actions resulting in ambiguity. Matching actions: {AmbiguousActions}");
_constraintMismatch = LoggerMessage.Define<string, string, IActionConstraint>(
LogLevel.Verbose,
2,
"Action '{ActionName}' with id '{ActionId}' did not match the constraint '{ActionConstraint}'");
}
public static void AmbiguousActions(this ILogger logger, string actionNames)
{
_ambiguousActions(logger, actionNames, null);
}
public static void ConstraintMismatch(
this ILogger logger,
string actionName,
string actionId,
IActionConstraint actionConstraint)
{
_constraintMismatch(logger, actionName, actionId, actionConstraint, null);
}
}
}

View File

@ -6,9 +6,9 @@ using Microsoft.Extensions.Logging;
namespace Microsoft.AspNet.Mvc.Logging namespace Microsoft.AspNet.Mvc.Logging
{ {
public static class FileResultLoggerExtensions internal static class FileResultLoggerExtensions
{ {
private static Action<ILogger, string, Exception> _fileResultExecuting; private static readonly Action<ILogger, string, Exception> _fileResultExecuting;
static FileResultLoggerExtensions() static FileResultLoggerExtensions()
{ {

View File

@ -0,0 +1,65 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using Microsoft.AspNet.Mvc.Filters;
using Microsoft.Extensions.Logging;
namespace Microsoft.AspNet.Mvc.Logging
{
internal static class FilterActionInvokerLoggerExtensions
{
private static readonly Action<ILogger, object, Exception> _authorizationFailure;
private static readonly Action<ILogger, object, Exception> _resourceFilterShortCircuit;
private static readonly Action<ILogger, object, Exception> _actionFilterShortCircuit;
private static readonly Action<ILogger, object, Exception> _exceptionFilterShortCircuit;
static FilterActionInvokerLoggerExtensions()
{
_authorizationFailure = LoggerMessage.Define<object>(
LogLevel.Warning,
1,
"Authorization failed for the request at filter '{AuthorizationFilter}'.");
_resourceFilterShortCircuit = LoggerMessage.Define<object>(
LogLevel.Verbose,
2,
"Request was short circuited at resource filter '{ResourceFilter}'.");
_actionFilterShortCircuit = LoggerMessage.Define<object>(
LogLevel.Verbose,
3,
"Request was short circuited at action filter '{ActionFilter}'.");
_exceptionFilterShortCircuit = LoggerMessage.Define<object>(
LogLevel.Verbose,
4,
"Request was short circuited at exception filter '{ExceptionFilter}'.");
}
public static void AuthorizationFailure(
this ILogger logger,
IFilterMetadata filter)
{
_authorizationFailure(logger, filter, null);
}
public static void ResourceFilterShortCircuited(
this ILogger logger,
IFilterMetadata filter)
{
_resourceFilterShortCircuit(logger, filter, null);
}
public static void ExceptionFilterShortCircuited(
this ILogger logger,
IFilterMetadata filter)
{
_exceptionFilterShortCircuit(logger, filter, null);
}
public static void ActionFilterShortCircuited(
this ILogger logger,
IFilterMetadata filter)
{
_actionFilterShortCircuit(logger, filter, null);
}
}
}

View File

@ -6,9 +6,9 @@ using Microsoft.Extensions.Logging;
namespace Microsoft.AspNet.Mvc.Logging namespace Microsoft.AspNet.Mvc.Logging
{ {
public static class HttpStatusCodeLoggerExtensions internal static class HttpStatusCodeLoggerExtensions
{ {
private static Action<ILogger, int, Exception> _httpStatusCodeResultExecuting; private static readonly Action<ILogger, int, Exception> _httpStatusCodeResultExecuting;
static HttpStatusCodeLoggerExtensions() static HttpStatusCodeLoggerExtensions()
{ {

View File

@ -0,0 +1,26 @@
using System;
using Microsoft.Extensions.Logging;
namespace Microsoft.AspNet.Mvc.Logging
{
internal static class InnerAttributeRouteLoggerExtensions
{
private static readonly Action<ILogger, string, string, Exception> _matchedRouteName;
static InnerAttributeRouteLoggerExtensions()
{
_matchedRouteName = LoggerMessage.Define<string, string>(
LogLevel.Verbose,
1,
"Request successfully matched the route with name '{RouteName}' and template '{RouteTemplate}'.");
}
public static void MatchedRouteName(
this ILogger logger,
string routeName,
string routeTemplate)
{
_matchedRouteName(logger, routeName, routeTemplate, null);
}
}
}

View File

@ -6,9 +6,9 @@ using Microsoft.Extensions.Logging;
namespace Microsoft.AspNet.Mvc.Logging namespace Microsoft.AspNet.Mvc.Logging
{ {
public static class LocalRedirectResultLoggerExtensions internal static class LocalRedirectResultLoggerExtensions
{ {
private static Action<ILogger, string, Exception> _localRedirectResultExecuting; private static readonly Action<ILogger, string, Exception> _localRedirectResultExecuting;
static LocalRedirectResultLoggerExtensions() static LocalRedirectResultLoggerExtensions()
{ {

View File

@ -10,8 +10,8 @@ namespace Microsoft.AspNet.Mvc.Logging
{ {
internal static class MvcRouteHandlerLoggerExtensions internal static class MvcRouteHandlerLoggerExtensions
{ {
private static Action<ILogger, string, Exception> _actionExecuting; private static readonly Action<ILogger, string, Exception> _actionExecuting;
private static Action<ILogger, string, double, Exception> _actionExecuted; private static readonly Action<ILogger, string, double, Exception> _actionExecuted;
static MvcRouteHandlerLoggerExtensions() static MvcRouteHandlerLoggerExtensions()
{ {

View File

@ -1,26 +1,85 @@
// Copyright (c) .NET Foundation. All rights reserved. // Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System; using System;
using System.Collections.Generic;
using Microsoft.AspNet.Mvc.Formatters;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.Net.Http.Headers;
namespace Microsoft.AspNet.Mvc.Logging namespace Microsoft.AspNet.Mvc.Logging
{ {
public static class ObjectResultExecutorLoggerExtensions internal static class ObjectResultExecutorLoggerExtensions
{ {
private static Action<ILogger, string, Exception> _objectResultExecuting; private static readonly Action<ILogger, string, Exception> _objectResultExecuting;
private static readonly Action<ILogger, string, Exception> _noFormatter;
private static readonly Action<ILogger, IOutputFormatter, string, Exception> _formatterSelected;
private static readonly Action<ILogger, string, Exception> _skippedContentNegotiation;
private static readonly Action<ILogger, string, Exception> _noAcceptForNegotiation;
private static readonly Action<ILogger, IEnumerable<MediaTypeHeaderValue>, Exception> _noFormatterFromNegotiation;
static ObjectResultExecutorLoggerExtensions() static ObjectResultExecutorLoggerExtensions()
{ {
_noFormatter = LoggerMessage.Define<string>(
LogLevel.Warning,
1,
"No output formatter was found for content type '{ContentType}' to write the response.");
_objectResultExecuting = LoggerMessage.Define<string>( _objectResultExecuting = LoggerMessage.Define<string>(
LogLevel.Information, LogLevel.Information,
1, 1,
"Executing ObjectResult, writing value {Value}."); "Executing ObjectResult, writing value {Value}.");
_formatterSelected = LoggerMessage.Define<IOutputFormatter, string>(
LogLevel.Verbose,
2,
"Selected output formatter '{OutputFormatter}' and content type '{ContentType}' to write the response.");
_skippedContentNegotiation = LoggerMessage.Define<string>(
LogLevel.Verbose,
3,
"Skipped content negotiation as content type '{ContentType}' is explicitly set for the response.");
_noAcceptForNegotiation = LoggerMessage.Define<string>(
LogLevel.Verbose,
4,
"No information found on request to perform content negotiation.");
_noFormatterFromNegotiation = LoggerMessage.Define<IEnumerable<MediaTypeHeaderValue>>(
LogLevel.Verbose,
5,
"Could not find an output formatter based on content negotiation. Accepted types were ({AcceptTypes})");
} }
public static void ObjectResultExecuting(this ILogger logger, object value) public static void ObjectResultExecuting(this ILogger logger, object value)
{ {
_objectResultExecuting(logger, Convert.ToString(value), null); _objectResultExecuting(logger, Convert.ToString(value), null);
} }
public static void NoFormatter(
this ILogger logger,
OutputFormatterWriteContext formatterContext)
{
_noFormatter(logger, Convert.ToString(formatterContext.ContentType), null);
}
public static void FormatterSelected(
this ILogger logger,
IOutputFormatter outputFormatter,
OutputFormatterWriteContext context)
{
var contentType = Convert.ToString(context.ContentType);
_formatterSelected(logger, outputFormatter, contentType, null);
}
public static void SkippedContentNegotiation(this ILogger logger, MediaTypeHeaderValue contentType)
{
_skippedContentNegotiation(logger, Convert.ToString(contentType), null);
}
public static void NoAcceptForNegotiation(this ILogger logger)
{
_noAcceptForNegotiation(logger, null, null);
}
public static void NoFormatterFromNegotiation(this ILogger logger, IEnumerable<MediaTypeHeaderValue> acceptTypes)
{
_noFormatterFromNegotiation(logger, acceptTypes, null);
}
} }
} }

View File

@ -6,9 +6,9 @@ using Microsoft.Extensions.Logging;
namespace Microsoft.AspNet.Mvc.Logging namespace Microsoft.AspNet.Mvc.Logging
{ {
public static class RedirectResultLoggerExtensions internal static class RedirectResultLoggerExtensions
{ {
private static Action<ILogger, string, Exception> _redirectResultExecuting; private static readonly Action<ILogger, string, Exception> _redirectResultExecuting;
static RedirectResultLoggerExtensions() static RedirectResultLoggerExtensions()
{ {

View File

@ -6,9 +6,9 @@ using Microsoft.Extensions.Logging;
namespace Microsoft.AspNet.Mvc.Logging namespace Microsoft.AspNet.Mvc.Logging
{ {
public static class RedirectToActionResultLoggerExtensions internal static class RedirectToActionResultLoggerExtensions
{ {
private static Action<ILogger, string, Exception> _redirectToActionResultExecuting; private static readonly Action<ILogger, string, Exception> _redirectToActionResultExecuting;
static RedirectToActionResultLoggerExtensions() static RedirectToActionResultLoggerExtensions()
{ {

View File

@ -6,9 +6,9 @@ using Microsoft.Extensions.Logging;
namespace Microsoft.AspNet.Mvc.Logging namespace Microsoft.AspNet.Mvc.Logging
{ {
public static class RedirectToRouteResultLoggerExtensions internal static class RedirectToRouteResultLoggerExtensions
{ {
private static Action<ILogger, string, string, Exception> _redirectToRouteResultExecuting; private static readonly Action<ILogger, string, string, Exception> _redirectToRouteResultExecuting;
static RedirectToRouteResultLoggerExtensions() static RedirectToRouteResultLoggerExtensions()
{ {

View File

@ -0,0 +1,37 @@
using System;
using System.Collections.Generic;
using Microsoft.Extensions.Logging;
namespace Microsoft.AspNet.Mvc.Logging
{
internal static class ViewResultExecutorLoggerExtensions
{
private static readonly Action<ILogger, string, Exception> _viewFound;
private static readonly Action<ILogger, string, IEnumerable<string>, Exception> _viewNotFound;
static ViewResultExecutorLoggerExtensions()
{
_viewFound = LoggerMessage.Define<string>(
LogLevel.Verbose,
1,
"The view '{ViewName}' was found.");
_viewNotFound = LoggerMessage.Define<string, IEnumerable<string>>(
LogLevel.Error,
2,
"The view '{ViewName}' was not found. Searched locations: {SearchedViewLocations}");
}
public static void ViewFound(this ILogger logger, string viewName)
{
_viewFound(logger, viewName, null);
}
public static void ViewNotFound(
this ILogger logger,
string viewName,
IEnumerable<string> searchedLocations)
{
_viewNotFound(logger, viewName, searchedLocations, null);
}
}
}

View File

@ -7,6 +7,7 @@ using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNet.Mvc.Core; using Microsoft.AspNet.Mvc.Core;
using Microsoft.AspNet.Mvc.Internal.Routing; using Microsoft.AspNet.Mvc.Internal.Routing;
using Microsoft.AspNet.Mvc.Logging;
using Microsoft.AspNet.Routing; using Microsoft.AspNet.Routing;
using Microsoft.AspNet.Routing.Template; using Microsoft.AspNet.Routing.Template;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
@ -156,8 +157,7 @@ namespace Microsoft.AspNet.Mvc.Routing
continue; continue;
} }
_logger.LogVerbose( _logger.MatchedRouteName(
"Request successfully matched the route with name '{RouteName}' and template '{RouteTemplate}'.",
matchingEntry.RouteName, matchingEntry.RouteName,
matchingEntry.RouteTemplate); matchingEntry.RouteTemplate);

View File

@ -6,9 +6,9 @@ using Microsoft.Extensions.Logging;
namespace Microsoft.AspNet.Mvc.Logging namespace Microsoft.AspNet.Mvc.Logging
{ {
public static class JsonResultLoggerExtensions internal static class JsonResultLoggerExtensions
{ {
private static Action<ILogger, string, Exception> _jsonResultExecuting; private static readonly Action<ILogger, string, Exception> _jsonResultExecuting;
static JsonResultLoggerExtensions() static JsonResultLoggerExtensions()
{ {

View File

@ -4,7 +4,8 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Reflection; using Microsoft.AspNet.Mvc.Logging;
using Microsoft.AspNet.Mvc.TagHelpers.Logging;
using Microsoft.AspNet.Razor.TagHelpers; using Microsoft.AspNet.Razor.TagHelpers;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
@ -63,17 +64,15 @@ namespace Microsoft.AspNet.Mvc.TagHelpers.Internal
match => match.PresentAttributes.Any( match => match.PresentAttributes.Any(
attribute => PartiallyMatchedAttributes.Contains( attribute => PartiallyMatchedAttributes.Contains(
attribute, StringComparer.OrdinalIgnoreCase))); attribute, StringComparer.OrdinalIgnoreCase)));
logger.TagHelperPartialMatches<TMode>(uniqueId, viewPath, partialOnlyMatches);
logger.LogWarning(new PartialModeMatchLogValues<TMode>(uniqueId, viewPath, partialOnlyMatches));
} }
if (logger.IsEnabled(LogLevel.Verbose) && !FullMatches.Any()) if (logger.IsEnabled(LogLevel.Verbose) && !FullMatches.Any())
{ {
logger.LogVerbose( logger.TagHelperSkippingProcessing(
"Skipping processing for tag helper '{TagHelper}' with id '{TagHelperId}'.", tagHelper,
tagHelper.GetType().GetTypeInfo().FullName,
uniqueId); uniqueId);
} }
} }
} }
} }

View File

@ -1,63 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Extensions.Logging;
namespace Microsoft.AspNet.Mvc.TagHelpers.Internal
{
/// <summary>
/// Log values for <see cref="AspNet.Razor.TagHelpers.ITagHelper"/> instances that opt out of
/// processing due to missing attributes for one of several possible modes.
/// </summary>
public class PartialModeMatchLogValues<TMode> : ILogValues
{
private readonly string _uniqueId;
private readonly string _viewPath;
private readonly IEnumerable<ModeMatchAttributes<TMode>> _partialMatches;
/// <summary>
/// Creates a new <see cref="PartialModeMatchLogValues{TMode}"/>.
/// </summary>
/// <param name="uniqueId">The unique ID of the HTML element this message applies to.</param>
/// <param name="viewPath">The path to the view.</param>
/// <param name="partialMatches">The set of modes with partial required attributes.</param>
public PartialModeMatchLogValues(
string uniqueId,
string viewPath,
IEnumerable<ModeMatchAttributes<TMode>> partialMatches)
{
if (partialMatches == null)
{
throw new ArgumentNullException(nameof(partialMatches));
}
_uniqueId = uniqueId;
_viewPath = viewPath;
_partialMatches = partialMatches;
}
public override string ToString()
{
var newLine = Environment.NewLine;
return string.Format(
$"Tag Helper with ID '{_uniqueId}' in view '{_viewPath}' had partial matches " +
$"while determining mode:{newLine}\t{{0}}",
string.Join($"{newLine}\t", _partialMatches.Select(partial =>
string.Format($"Mode '{partial.Mode}' missing attributes:{newLine}\t\t{{0}} ",
string.Join($"{newLine}\t\t", partial.MissingAttributes)))));
}
public IEnumerable<KeyValuePair<string, object>> GetValues()
{
yield return new KeyValuePair<string, object>(
"Message",
"Tag helper had partial matches while determining mode.");
yield return new KeyValuePair<string, object>("UniqueId", _uniqueId);
yield return new KeyValuePair<string, object>("ViewPath", _viewPath);
yield return new KeyValuePair<string, object>("PartialMatches", _partialMatches);
}
}
}

View File

@ -0,0 +1,103 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNet.Mvc.TagHelpers.Internal;
using Microsoft.AspNet.Razor.TagHelpers;
using Microsoft.Extensions.Logging;
namespace Microsoft.AspNet.Mvc.TagHelpers.Logging
{
internal static class ModeMatchResultLoggerExtensions
{
private static readonly Action<ILogger, ITagHelper, string, Exception> _skippingProcessing;
static ModeMatchResultLoggerExtensions()
{
_skippingProcessing = LoggerMessage.Define<ITagHelper, string>(
LogLevel.Verbose,
1,
"Skipping processing for tag helper '{TagHelper}' with id '{TagHelperId}'.");
}
public static void TagHelperPartialMatches<TMode>(
this ILogger logger,
string uniqueId,
string viewPath,
IEnumerable<ModeMatchAttributes<TMode>> partialMatches)
{
var logValues = new PartialModeMatchLogValues<TMode>(
uniqueId,
viewPath,
partialMatches);
logger.LogWarning(logValues);
}
public static void TagHelperSkippingProcessing(
this ILogger logger,
ITagHelper tagHelper,
string uniqueId)
{
_skippingProcessing(
logger,
tagHelper,
uniqueId,
null);
}
/// <summary>
/// Log values for <see cref="AspNet.Razor.TagHelpers.ITagHelper"/> instances that opt out
/// of processing due to missing attributes for one of several possible modes.
/// </summary>
private class PartialModeMatchLogValues<TMode> : ILogValues
{
private readonly IEnumerable<ModeMatchAttributes<TMode>> _partialMatches;
private readonly string _uniqueId;
private readonly string _viewPath;
/// <summary>
/// Creates a new <see cref="PartialModeMatchLogValues{TMode}"/>.
/// </summary>
/// <param name="uniqueId">
/// The unique ID of the HTML element this message applies to.
/// </param>
/// <param name="viewPath">The path to the view.</param>
/// <param name="partialMatches">The set of modes with partial required attributes.</param>
public PartialModeMatchLogValues(
string uniqueId,
string viewPath,
IEnumerable<ModeMatchAttributes<TMode>> partialMatches)
{
if (partialMatches == null)
{
throw new ArgumentNullException(nameof(partialMatches));
}
_uniqueId = uniqueId;
_viewPath = viewPath;
_partialMatches = partialMatches;
}
public IEnumerable<KeyValuePair<string, object>> GetValues()
{
yield return new KeyValuePair<string, object>(
"Message",
"Tag helper had partial matches while determining mode.");
yield return new KeyValuePair<string, object>("UniqueId", _uniqueId);
yield return new KeyValuePair<string, object>("ViewPath", _viewPath);
yield return new KeyValuePair<string, object>("PartialMatches", _partialMatches);
}
public override string ToString()
{
var newLine = Environment.NewLine;
return string.Format(
$"Tag Helper with ID '{_uniqueId}' in view '{_viewPath}' had partial matches " +
$"while determining mode:{newLine}\t{{0}}",
string.Join($"{newLine}\t", _partialMatches.Select(partial =>
string.Format($"Mode '{partial.Mode}' missing attributes:{newLine}\t\t{{0}} ",
string.Join($"{newLine}\t\t", partial.MissingAttributes)))));
}
}
}
}

View File

@ -2,14 +2,17 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System; using System;
using System.Collections.Generic;
using Microsoft.AspNet.Mvc.ViewEngines; using Microsoft.AspNet.Mvc.ViewEngines;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
namespace Microsoft.AspNet.Mvc.Logging namespace Microsoft.AspNet.Mvc.ViewFeatures.Logging
{ {
public static class PartialViewResultExecutorLoggerExtensions internal static class PartialViewResultExecutorLoggerExtensions
{ {
private static Action<ILogger, string, Exception> _partialViewResultExecuting; private static readonly Action<ILogger, string, Exception> _partialViewFound;
private static readonly Action<ILogger, string, IEnumerable<string>, Exception> _partialViewNotFound;
private static readonly Action<ILogger, string, Exception> _partialViewResultExecuting;
static PartialViewResultExecutorLoggerExtensions() static PartialViewResultExecutorLoggerExtensions()
{ {
@ -17,6 +20,29 @@ namespace Microsoft.AspNet.Mvc.Logging
LogLevel.Information, LogLevel.Information,
1, 1,
"Executing PartialViewResult, running view at path {Path}."); "Executing PartialViewResult, running view at path {Path}.");
_partialViewFound = LoggerMessage.Define<string>(
LogLevel.Verbose,
2,
"The partial view '{PartialViewName}' was found.");
_partialViewNotFound = LoggerMessage.Define<string, IEnumerable<string>>(
LogLevel.Error,
3,
"The partial view '{PartialViewName}' was not found. Searched locations: {SearchedViewLocations}");
}
public static void PartialViewFound(
this ILogger logger,
string partialViewName)
{
_partialViewFound(logger, partialViewName, null);
}
public static void PartialViewNotFound(
this ILogger logger,
string partialViewName,
IEnumerable<string> searchedLocations)
{
_partialViewNotFound(logger, partialViewName, searchedLocations, null);
} }
public static void PartialViewResultExecuting(this ILogger logger, IView view) public static void PartialViewResultExecuting(this ILogger logger, IView view)

View File

@ -8,6 +8,7 @@ using Microsoft.AspNet.Mvc.Diagnostics;
using Microsoft.AspNet.Mvc.Infrastructure; using Microsoft.AspNet.Mvc.Infrastructure;
using Microsoft.AspNet.Mvc.Logging; using Microsoft.AspNet.Mvc.Logging;
using Microsoft.AspNet.Mvc.ViewEngines; using Microsoft.AspNet.Mvc.ViewEngines;
using Microsoft.AspNet.Mvc.ViewFeatures.Logging;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.Extensions.OptionsModel; using Microsoft.Extensions.OptionsModel;
@ -73,16 +74,13 @@ namespace Microsoft.AspNet.Mvc.ViewFeatures
{ {
DiagnosticSource.ViewFound(actionContext, true, viewResult, viewName, result.View); DiagnosticSource.ViewFound(actionContext, true, viewResult, viewName, result.View);
Logger.LogVerbose("The partial view '{PartialViewName}' was found.", viewName); Logger.PartialViewFound(viewName);
} }
else else
{ {
DiagnosticSource.ViewNotFound(actionContext, true, viewResult, viewName, result.SearchedLocations); DiagnosticSource.ViewNotFound(actionContext, true, viewResult, viewName, result.SearchedLocations);
Logger.LogError( Logger.PartialViewNotFound(viewName, result.SearchedLocations);
"The partial view '{PartialViewName}' was not found. Searched locations: {SearchedViewLocations}",
viewName,
result.SearchedLocations);
} }
return result; return result;

View File

@ -7,6 +7,7 @@ using System.Threading.Tasks;
using Microsoft.AspNet.Mvc.Infrastructure; using Microsoft.AspNet.Mvc.Infrastructure;
using Microsoft.AspNet.Mvc.Logging; using Microsoft.AspNet.Mvc.Logging;
using Microsoft.AspNet.Mvc.ViewEngines; using Microsoft.AspNet.Mvc.ViewEngines;
using Microsoft.AspNet.Mvc.ViewFeatures.Logging;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.Extensions.OptionsModel; using Microsoft.Extensions.OptionsModel;
@ -84,7 +85,7 @@ namespace Microsoft.AspNet.Mvc.ViewFeatures
}); });
} }
Logger.LogVerbose("The view '{ViewName}' was found.", viewName); Logger.PartialViewFound(viewName);
} }
else else
{ {
@ -101,11 +102,7 @@ namespace Microsoft.AspNet.Mvc.ViewFeatures
searchedLocations = result.SearchedLocations searchedLocations = result.SearchedLocations
}); });
} }
Logger.PartialViewNotFound(viewName, result.SearchedLocations);
Logger.LogError(
"The view '{ViewName}' was not found. Searched locations: {SearchedViewLocations}",
viewName,
result.SearchedLocations);
} }
return result; return result;
@ -135,7 +132,6 @@ namespace Microsoft.AspNet.Mvc.ViewFeatures
throw new ArgumentNullException(nameof(viewResult)); throw new ArgumentNullException(nameof(viewResult));
} }
Logger.ViewResultExecuting(view); Logger.ViewResultExecuting(view);
return ExecuteAsync( return ExecuteAsync(

View File

@ -330,8 +330,7 @@ namespace Microsoft.AspNet.Mvc.Razor.Test
// Arrange // Arrange
var source = new RazorTextWriter(TextWriter.Null, Encoding.UTF8, new CommonTestEncoder()); var source = new RazorTextWriter(TextWriter.Null, Encoding.UTF8, new CommonTestEncoder());
var target = new StringWriter(); var target = new StringWriter();
var expected = @"Hello world var expected = "Hello world" + Environment.NewLine + "abc";
abc";
// Act // Act
source.WriteLine("Hello world"); source.WriteLine("Hello world");
@ -390,8 +389,7 @@ abc";
// Arrange // Arrange
var source = new RazorTextWriter(TextWriter.Null, Encoding.UTF8, new CommonTestEncoder()); var source = new RazorTextWriter(TextWriter.Null, Encoding.UTF8, new CommonTestEncoder());
var target = new StringWriter(); var target = new StringWriter();
var expected = @"Hello world var expected = "Hello world" + Environment.NewLine;
";
// Act // Act
source.Write("Hello "); source.Write("Hello ");