You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
112 lines
3.1 KiB
112 lines
3.1 KiB
using System.Diagnostics;
|
|
using CoreAgent.Infrastructure.Options;
|
|
using System.Text;
|
|
using Microsoft.AspNetCore.Http;
|
|
using Microsoft.Extensions.Logging;
|
|
using Microsoft.Extensions.Options;
|
|
|
|
namespace CoreAgent.Infrastructure.Extensions.Logging;
|
|
|
|
/// <summary>
|
|
/// 请求日志中间件
|
|
/// </summary>
|
|
public class RequestLoggingMiddleware
|
|
{
|
|
private readonly RequestDelegate _next;
|
|
private readonly ILogger<RequestLoggingMiddleware> _logger;
|
|
private readonly RequestLoggingOptions _options;
|
|
|
|
public RequestLoggingMiddleware(
|
|
RequestDelegate next,
|
|
ILogger<RequestLoggingMiddleware> logger,
|
|
IOptions<RequestLoggingOptions> options)
|
|
{
|
|
_next = next;
|
|
_logger = logger;
|
|
_options = options.Value;
|
|
}
|
|
|
|
public async Task InvokeAsync(HttpContext context)
|
|
{
|
|
if (ShouldSkipLogging(context))
|
|
{
|
|
await _next(context);
|
|
return;
|
|
}
|
|
|
|
var sw = Stopwatch.StartNew();
|
|
var requestBody = string.Empty;
|
|
|
|
try
|
|
{
|
|
if (_options.LogRequestBody && context.Request.Body != null)
|
|
{
|
|
requestBody = await ReadRequestBodyAsync(context.Request);
|
|
}
|
|
|
|
_logger.LogInformation(
|
|
"Request started: {Method} {Path} {QueryString} {RequestBody}",
|
|
context.Request.Method,
|
|
context.Request.Path,
|
|
context.Request.QueryString,
|
|
requestBody);
|
|
|
|
await _next(context);
|
|
}
|
|
finally
|
|
{
|
|
sw.Stop();
|
|
_logger.LogInformation(
|
|
"Request completed: {Method} {Path} in {ElapsedMilliseconds}ms with status code {StatusCode}",
|
|
context.Request.Method,
|
|
context.Request.Path,
|
|
sw.ElapsedMilliseconds,
|
|
context.Response.StatusCode);
|
|
}
|
|
}
|
|
|
|
private bool ShouldSkipLogging(HttpContext context)
|
|
{
|
|
if (_options.ExcludePaths.Any(p => context.Request.Path.StartsWithSegments(p)))
|
|
{
|
|
return true;
|
|
}
|
|
|
|
if (_options.ExcludeMethods.Contains(context.Request.Method))
|
|
{
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
private async Task<string> ReadRequestBodyAsync(HttpRequest request)
|
|
{
|
|
if (!request.Body.CanRead || !request.Body.CanSeek)
|
|
{
|
|
return string.Empty;
|
|
}
|
|
|
|
var originalPosition = request.Body.Position;
|
|
request.Body.Position = 0;
|
|
|
|
try
|
|
{
|
|
using var reader = new StreamReader(
|
|
request.Body,
|
|
encoding: Encoding.UTF8,
|
|
detectEncodingFromByteOrderMarks: false,
|
|
bufferSize: 1024 * 45,
|
|
leaveOpen: true);
|
|
|
|
var body = await reader.ReadToEndAsync();
|
|
return body.Length > _options.MaxRequestBodySize
|
|
? body.Substring(0, _options.MaxRequestBodySize) + "..."
|
|
: body;
|
|
}
|
|
finally
|
|
{
|
|
request.Body.Position = originalPosition;
|
|
}
|
|
}
|
|
}
|