aspnetcore/src/Microsoft.AspNet.Hosting/Internal/HostingLoggerExtensions.cs

216 lines
7.9 KiB
C#

// 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 Microsoft.AspNet.Http;
using Microsoft.Extensions.Logging;
namespace Microsoft.AspNet.Hosting.Internal
{
internal static class HostingLoggerExtensions
{
private const long TicksPerMillisecond = 10000;
public static IDisposable RequestScope(this ILogger logger, HttpContext httpContext)
{
return logger.BeginScopeImpl(new HostingLogScope(httpContext));
}
public static void RequestStarting(this ILogger logger, HttpContext httpContext)
{
if (logger.IsEnabled(LogLevel.Information))
{
logger.Log(
logLevel: LogLevel.Information,
eventId: LoggerEventIds.RequestStarting,
state: new HostingRequestStarting(httpContext),
exception: null,
formatter: HostingRequestStarting.Callback);
}
}
public static void RequestFinished(this ILogger logger, HttpContext httpContext, int startTimeInTicks, int currentTick)
{
if (logger.IsEnabled(LogLevel.Information))
{
var elapsed = new TimeSpan(TicksPerMillisecond * (currentTick < startTimeInTicks ?
(int.MaxValue - startTimeInTicks) + (currentTick - int.MinValue) :
currentTick - startTimeInTicks));
logger.Log(
logLevel: LogLevel.Information,
eventId: LoggerEventIds.RequestFinished,
state: new HostingRequestFinished(httpContext, elapsed),
exception: null,
formatter: HostingRequestFinished.Callback);
}
}
public static void ApplicationError(this ILogger logger, Exception exception)
{
logger.LogError(
eventId: LoggerEventIds.ApplicationStartupException,
message: "Application startup exception",
error: exception);
}
public static void Starting(this ILogger logger)
{
if (logger.IsEnabled(LogLevel.Verbose))
{
logger.LogVerbose(
eventId: LoggerEventIds.Starting,
data: "Hosting starting");
}
}
public static void Started(this ILogger logger)
{
if (logger.IsEnabled(LogLevel.Verbose))
{
logger.LogVerbose(
eventId: LoggerEventIds.Started,
data: "Hosting started");
}
}
public static void Shutdown(this ILogger logger)
{
if (logger.IsEnabled(LogLevel.Verbose))
{
logger.LogVerbose(
eventId: LoggerEventIds.Shutdown,
data: "Hosting shutdown");
}
}
private class HostingLogScope : ILogValues
{
private readonly HttpContext _httpContext;
private string _cachedToString;
private IEnumerable<KeyValuePair<string, object>> _cachedGetValues;
public HostingLogScope(HttpContext httpContext)
{
_httpContext = httpContext;
}
public override string ToString()
{
if (_cachedToString == null)
{
_cachedToString = $"RequestId:{_httpContext.TraceIdentifier} RequestPath:{_httpContext.Request.Path}";
}
return _cachedToString;
}
public IEnumerable<KeyValuePair<string, object>> GetValues()
{
if (_cachedGetValues == null)
{
_cachedGetValues = new[]
{
new KeyValuePair<string, object>("RequestId", _httpContext.TraceIdentifier),
new KeyValuePair<string, object>("RequestPath", _httpContext.Request.Path.ToString()),
};
}
return _cachedGetValues;
}
}
private class HostingRequestStarting : ILogValues
{
internal static readonly Func<object, Exception, string> Callback = (state, exception) => ((HostingRequestStarting)state).ToString();
private readonly HttpRequest _request;
private string _cachedToString;
private IEnumerable<KeyValuePair<string, object>> _cachedGetValues;
public HostingRequestStarting(HttpContext httpContext)
{
_request = httpContext.Request;
}
public override string ToString()
{
if (_cachedToString == null)
{
_cachedToString = $"Request starting {_request.Protocol} {_request.Method} {_request.Scheme}://{_request.Host}{_request.PathBase}{_request.Path}{_request.QueryString} {_request.ContentType} {_request.ContentLength}";
}
return _cachedToString;
}
public IEnumerable<KeyValuePair<string, object>> GetValues()
{
if (_cachedGetValues == null)
{
_cachedGetValues = new[]
{
new KeyValuePair<string, object>("Protocol", _request.Protocol),
new KeyValuePair<string, object>("Method", _request.Method),
new KeyValuePair<string, object>("ContentType", _request.ContentType),
new KeyValuePair<string, object>("ContentLength", _request.ContentLength),
new KeyValuePair<string, object>("Scheme", _request.Scheme.ToString()),
new KeyValuePair<string, object>("Host", _request.Host.ToString()),
new KeyValuePair<string, object>("PathBase", _request.PathBase.ToString()),
new KeyValuePair<string, object>("Path", _request.Path.ToString()),
new KeyValuePair<string, object>("QueryString", _request.QueryString.ToString()),
};
}
return _cachedGetValues;
}
}
private class HostingRequestFinished
{
internal static readonly Func<object, Exception, string> Callback = (state, exception) => ((HostingRequestFinished)state).ToString();
private readonly HttpContext _httpContext;
private readonly TimeSpan _elapsed;
private IEnumerable<KeyValuePair<string, object>> _cachedGetValues;
private string _cachedToString;
public HostingRequestFinished(HttpContext httpContext, TimeSpan elapsed)
{
_httpContext = httpContext;
_elapsed = elapsed;
}
public override string ToString()
{
if (_cachedToString == null)
{
_cachedToString = $"Request finished in {_elapsed.TotalMilliseconds}ms {_httpContext.Response.StatusCode} {_httpContext.Response.ContentType}";
}
return _cachedToString;
}
public IEnumerable<KeyValuePair<string, object>> GetValues()
{
if (_cachedGetValues == null)
{
_cachedGetValues = new[]
{
new KeyValuePair<string, object>("ElapsedMilliseconds", _elapsed.TotalMilliseconds),
new KeyValuePair<string, object>("StatusCode", _httpContext.Response.StatusCode),
new KeyValuePair<string, object>("ContentType", _httpContext.Response.ContentType),
};
}
return _cachedGetValues;
}
}
}
}