using Microsoft.AspNetCore.Connections; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Logging; using System; using System.Diagnostics; using System.Text; using System.Threading.Tasks; namespace FastGithub.HttpServer.HttpMiddlewares { /// /// 请求日志中间件 /// sealed class RequestLoggingMiddleware { private readonly ILogger logger; /// /// 请求日志中间件 /// /// public RequestLoggingMiddleware(ILogger logger) { this.logger = logger; } /// /// 执行请求 /// /// /// /// public async Task InvokeAsync(HttpContext context, RequestDelegate next) { var feature = new RequestLoggingFeature(); context.Features.Set(feature); var stopwatch = Stopwatch.StartNew(); try { await next(context); } finally { stopwatch.Stop(); } if (feature.Enable == false) { return; } var request = context.Request; var response = context.Response; var exception = context.GetForwarderErrorFeature()?.Exception; if (exception == null) { logger.LogInformation($"{request.Method} {request.Scheme}://{request.Host}{request.Path} responded {response.StatusCode} in {stopwatch.Elapsed.TotalMilliseconds} ms"); } else if (IsError(exception)) { logger.LogError($"{request.Method} {request.Scheme}://{request.Host}{request.Path} responded {response.StatusCode} in {stopwatch.Elapsed.TotalMilliseconds} ms{Environment.NewLine}{exception}"); } else { logger.LogWarning($"{request.Method} {request.Scheme}://{request.Host}{request.Path} responded {response.StatusCode} in {stopwatch.Elapsed.TotalMilliseconds} ms{Environment.NewLine}{GetMessage(exception)}"); } } /// /// 是否为错误 /// /// /// private static bool IsError(Exception exception) { if (exception is OperationCanceledException) { return false; } if (HasInnerException(exception)) { return false; } return true; } /// /// 是否有内部异常异常 /// /// /// /// private static bool HasInnerException(Exception exception) where TInnerException : Exception { var inner = exception.InnerException; while (inner != null) { if (inner is TInnerException) { return true; } inner = inner.InnerException; } return false; } /// /// 获取异常信息 /// /// /// private static string GetMessage(Exception exception) { var ex = exception; var builder = new StringBuilder(); while (ex != null) { var type = ex.GetType(); builder.Append(type.Namespace).Append('.').Append(type.Name).Append(": ").AppendLine(ex.Message); ex = ex.InnerException; } return builder.ToString(); } private class RequestLoggingFeature : IRequestLoggingFeature { public bool Enable { get; set; } = true; } } }