Add logging of elapsed time for the action.

This commit is contained in:
Ryan Nowak 2015-10-22 16:26:48 -07:00
parent cea8d019f1
commit ec2abc8ae0
3 changed files with 49 additions and 8 deletions

View File

@ -59,7 +59,7 @@ namespace Microsoft.AspNet.Mvc.Infrastructure
var actionDescriptor = await _actionSelector.SelectAsync(context); var actionDescriptor = await _actionSelector.SelectAsync(context);
if (actionDescriptor == null) if (actionDescriptor == null)
{ {
_logger.LogVerbose("No actions matched the current request."); _logger.NoActionsMatched();
return; return;
} }
@ -90,10 +90,13 @@ namespace Microsoft.AspNet.Mvc.Infrastructure
using (_logger.ActionScope(actionDescriptor)) using (_logger.ActionScope(actionDescriptor))
{ {
_logger.LogVerbose("Executing action {ActionDisplayName}", actionDescriptor.DisplayName); _logger.ExecutingAction(actionDescriptor);
var startTime = Environment.TickCount;
await InvokeActionAsync(context, actionDescriptor); await InvokeActionAsync(context, actionDescriptor);
context.IsHandled = true; context.IsHandled = true;
_logger.ExecutedAction(actionDescriptor, startTime);
} }
} }
finally finally

View File

@ -10,11 +10,43 @@ namespace Microsoft.AspNet.Mvc.Logging
{ {
internal static class MvcRouteHandlerLoggerExtensions internal static class MvcRouteHandlerLoggerExtensions
{ {
private static Action<ILogger, string, Exception> _actionExecuting;
private static Action<ILogger, string, double, Exception> _actionExecuted;
static MvcRouteHandlerLoggerExtensions()
{
_actionExecuting = LoggerMessage.Define<string>(
LogLevel.Verbose,
1,
"Executing action {ActionName}");
_actionExecuted = LoggerMessage.Define<string, double>(
LogLevel.Information,
2,
"Executed action {ActionName} in {ElapsedMilliseconds}ms");
}
public static IDisposable ActionScope(this ILogger logger, ActionDescriptor action) public static IDisposable ActionScope(this ILogger logger, ActionDescriptor action)
{ {
return logger.BeginScopeImpl(new ActionLogScope(action)); return logger.BeginScopeImpl(new ActionLogScope(action));
} }
public static void ExecutingAction(this ILogger logger, ActionDescriptor action)
{
_actionExecuting(logger, action.DisplayName, null);
}
public static void ExecutedAction(this ILogger logger, ActionDescriptor action, int startTicks)
{
var elapsed = new TimeSpan(Environment.TickCount - startTicks);
_actionExecuted(logger, action.DisplayName, elapsed.TotalMilliseconds, null);
}
public static void NoActionsMatched(this ILogger logger)
{
logger.LogVerbose(3, "No actions matched the current request");
}
private class ActionLogScope : ILogValues private class ActionLogScope : ILogValues
{ {
private readonly ActionDescriptor _action; private readonly ActionDescriptor _action;

View File

@ -25,13 +25,16 @@ namespace Microsoft.AspNet.Mvc.Infrastructure
// Arrange // Arrange
var sink = new TestSink(); var sink = new TestSink();
var loggerFactory = new TestLoggerFactory(sink, enabled: true); var loggerFactory = new TestLoggerFactory(sink, enabled: true);
var displayName = "A.B.C"; var displayName = "A.B.C";
var actionDescriptor = new Mock<ActionDescriptor>(); var actionDescriptor = new Mock<ActionDescriptor>();
actionDescriptor.SetupGet(ad => ad.DisplayName) actionDescriptor
.Returns(displayName); .SetupGet(ad => ad.DisplayName)
.Returns(displayName);
var context = CreateRouteContext(actionDescriptor: actionDescriptor.Object, loggerFactory: loggerFactory); var context = CreateRouteContext(actionDescriptor: actionDescriptor.Object, loggerFactory: loggerFactory);
var handler = new MvcRouteHandler(); var handler = new MvcRouteHandler();
var expectedMessage = $"Executing action {displayName}";
// Act // Act
await handler.RouteAsync(context); await handler.RouteAsync(context);
@ -39,8 +42,11 @@ namespace Microsoft.AspNet.Mvc.Infrastructure
// Assert // Assert
Assert.Single(sink.Scopes); Assert.Single(sink.Scopes);
Assert.Equal(displayName, sink.Scopes[0].Scope?.ToString()); Assert.Equal(displayName, sink.Scopes[0].Scope?.ToString());
Assert.Single(sink.Writes);
Assert.Equal(expectedMessage, sink.Writes[0].State?.ToString()); Assert.Equal(2, sink.Writes.Count);
Assert.Equal($"Executing action {displayName}", sink.Writes[0].State?.ToString());
// This message has the execution time embedded, which we don't want to verify.
Assert.StartsWith($"Executed action {displayName} ", sink.Writes[1].State?.ToString());
} }
[Fact] [Fact]
@ -59,7 +65,7 @@ namespace Microsoft.AspNet.Mvc.Infrastructure
loggerFactory: loggerFactory); loggerFactory: loggerFactory);
var handler = new MvcRouteHandler(); var handler = new MvcRouteHandler();
var expectedMessage = "No actions matched the current request."; var expectedMessage = "No actions matched the current request";
// Act // Act
await handler.RouteAsync(context); await handler.RouteAsync(context);