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.
133 lines
5.3 KiB
133 lines
5.3 KiB
10 months ago
|
using Microsoft.AspNetCore.Http.Extensions;
|
||
|
using Ocelot.RequestId;
|
||
|
using Serilog;
|
||
|
using System.Diagnostics;
|
||
|
using System.Text;
|
||
|
using Yitter.IdGenerator;
|
||
|
|
||
|
namespace HuiXin.Gateway.Ocelot.Middlewares
|
||
|
{
|
||
|
public class AccessLoggingMiddleware
|
||
|
{
|
||
|
private readonly RequestDelegate _next;
|
||
|
|
||
|
public AccessLoggingMiddleware(RequestDelegate next)
|
||
|
{
|
||
|
_next = next;
|
||
|
}
|
||
|
|
||
|
public async Task InvokeAsync(HttpContext context)
|
||
|
{
|
||
|
var traceIdKey = DefaultRequestIdKey.Value;
|
||
|
var traceId = YitIdHelper.NextId().ToString();
|
||
|
context.TraceIdentifier = traceId;
|
||
|
context.Request.Headers[traceIdKey] = traceId;
|
||
|
|
||
|
var sw = Stopwatch.StartNew();
|
||
|
sw.Start();
|
||
|
|
||
|
var sb = new StringBuilder();
|
||
|
|
||
|
sb.AppendLine();
|
||
|
sb.AppendLine("-------------------Request Start-------------------");
|
||
|
sb.AppendLine(DateTime.Now.ToString());
|
||
|
sb.AppendLine($"追踪id:{traceId}");
|
||
|
sb.AppendLine($"地址:{context.Request.GetDisplayUrl()}");
|
||
|
sb.AppendLine("请求头:");
|
||
|
foreach (var header in context.Request.Headers)
|
||
|
{
|
||
|
sb.AppendLine($"{header.Key}:{header.Value}");
|
||
|
}
|
||
|
sb.AppendLine($"数据:{await GetRequestBody(context.Request)}");
|
||
|
sb.AppendLine("===================Request End===================");
|
||
|
|
||
|
Log.Information(sb.ToString());
|
||
|
sb.Clear();
|
||
|
|
||
|
//Copy a pointer to the original response body stream
|
||
|
var originalBodyStream = context.Response.Body;
|
||
|
|
||
|
//Create a new memory stream...
|
||
|
using var responseBody = new MemoryStream();
|
||
|
//...and use that for the temporary response body
|
||
|
context.Response.Body = responseBody;
|
||
|
|
||
|
//Continue down the Middleware pipeline, eventually returning to this class
|
||
|
await _next(context);
|
||
|
|
||
|
//Format the response from the server
|
||
|
//var response = await FormatResponse(context.Response);
|
||
|
sb.AppendLine();
|
||
|
sb.AppendLine("-------------------Response Start-------------------");
|
||
|
sb.AppendLine(DateTime.Now.ToString());
|
||
|
sb.AppendLine($"追踪id:{traceId}");
|
||
|
sb.AppendLine($"耗时:{sw.ElapsedMilliseconds}毫秒");
|
||
|
sb.AppendLine($"状态码:{context.Response.StatusCode}");
|
||
|
//sb.AppendLine("Headers: ");
|
||
|
//foreach (var header in context.Response.Headers)
|
||
|
//{
|
||
|
// sb.AppendLine($"{header.Key}:{header.Value}");
|
||
|
//}
|
||
|
sb.AppendLine($"数据:{await GetResponseBody(context.Response)}");
|
||
|
sb.AppendLine("===================Response End===================");
|
||
|
|
||
|
//Save log to chosen datastore
|
||
|
Log.Information(sb.ToString());
|
||
|
|
||
|
sb.Clear();
|
||
|
|
||
|
//Copy the contents of the new memory stream (which contains the response) to the original stream, which is then returned to the client.
|
||
|
await responseBody.CopyToAsync(originalBodyStream);
|
||
|
}
|
||
|
|
||
|
private static async Task<string> GetRequestBody(HttpRequest request)
|
||
|
{
|
||
|
request.EnableBuffering();
|
||
|
// Leave the body open so the next middleware can read it.
|
||
|
using var reader = new StreamReader(
|
||
|
request.Body,
|
||
|
encoding: Encoding.UTF8,
|
||
|
detectEncodingFromByteOrderMarks: false,
|
||
|
leaveOpen: true);
|
||
|
var body = await reader.ReadToEndAsync();
|
||
|
// Do some processing with body…
|
||
|
|
||
|
//var formattedRequest = $"{request.Scheme} {request.Host}{request.Path} {request.QueryString} {body}";
|
||
|
|
||
|
// Reset the request body stream position so the next middleware can read it
|
||
|
request.Body.Position = 0;
|
||
|
|
||
|
return body;
|
||
|
}
|
||
|
|
||
|
private static async Task<string> GetResponseBody(HttpResponse response)
|
||
|
{
|
||
|
//We need to read the response stream from the beginning...
|
||
|
response.Body.Seek(0, SeekOrigin.Begin);
|
||
|
|
||
|
//...and copy it into a string
|
||
|
string text = await new StreamReader(response.Body).ReadToEndAsync();
|
||
|
|
||
|
//We need to reset the reader for the response so that the client can read it.
|
||
|
response.Body.Seek(0, SeekOrigin.Begin);
|
||
|
|
||
|
//Return the string for the response, including the status code (e.g. 200, 404, 401, etc.)
|
||
|
//return $"{response.StatusCode}: {text}";
|
||
|
return text;
|
||
|
}
|
||
|
|
||
|
static AccessLoggingMiddleware()
|
||
|
{
|
||
|
// 创建 IdGeneratorOptions 对象,可在构造函数中输入 WorkerId:
|
||
|
var options = new IdGeneratorOptions();
|
||
|
// options.WorkerIdBitLength = 10; // 默认值6,限定 WorkerId 最大值为2^6-1,即默认最多支持64个节点。
|
||
|
// options.SeqBitLength = 6; // 默认值6,限制每毫秒生成的ID个数。若生成速度超过5万个/秒,建议加大 SeqBitLength 到 10。
|
||
|
// options.BaseTime = Your_Base_Time; // 如果要兼容老系统的雪花算法,此处应设置为老系统的BaseTime。
|
||
|
// ...... 其它参数参考 IdGeneratorOptions 定义。
|
||
|
|
||
|
// 保存参数(务必调用,否则参数设置不生效):
|
||
|
YitIdHelper.SetIdGenerator(options);
|
||
|
}
|
||
|
}
|
||
|
}
|