public class LogMiddleware : IMiddleware
{
private readonly ILogger<LogMiddleware> _logger;
private readonly IRequestContext _requestContext;
private static readonly List<string> ActionLog = new List<string>() {
"senddiamond",
"addPropertydiamondasync",
"diamondpaymentorder",
"adddiamondorder",
"addCustomdiamondorder"
};
public LogMiddleware(IRequestContext requestContext, ILogger<LogMiddleware> logger)
{
_requestContext = requestContext;
_logger = logger;
}
public async Task InvokeAsync(HttpContext context, RequestDelegate next)
{
PMSLog log = new PMSLog();
log.StartTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:ffff");
var watch = new Stopwatch();
watch.Start();
context.Request.EnableBuffering();
var requestReader = new StreamReader(context.Request.Body);
var requestContent = requestReader.ReadToEnd();
context.Request.Body.Position = 0;
var bodyStream = context.Response.Body;
var ms = new MemoryStream();
context.Response.Body = ms;
await next.Invoke(context);
ms.Position = 0;
var responseReader = new StreamReader(ms);
log.ResponseBody = responseReader.ReadToEnd();
ms.Position = 0;
ms.CopyTo(bodyStream);
watch.Stop();
try
{
bool insertLog = false;
log.ActionName = context.GetRouteData()?.Values["action"]?.ToString();
if (!string.IsNullOrEmpty(log.ActionName))
{
if (ActionLog.Contains(log.ActionName.ToLower()))
{
insertLog = true;
}
}
if (insertLog)
{
log.ControllerName = context.GetRouteData().Values["controller"]?.ToString();
var responseTimeForCompleteRequest = watch.ElapsedMilliseconds;
log.EndTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:ffff");
log.ExecuteTime = responseTimeForCompleteRequest;
log.RequestID = context.TraceIdentifier;
var tokenInfo = _requestContext.TokenInfo;
if (tokenInfo != null)
{
log.AccountID = tokenInfo.AccountID;
log.DepartmentID = tokenInfo.CurrentDepartmentID;
log.DepartmentID = tokenInfo.CurrentDepartmentID;
log.CompanyID = tokenInfo.CompanyID;
log.Email = tokenInfo.Email;
}
log.ClientIp = _requestContext.ClientIp;
log.CityEn = _requestContext.CityEn;
log.Language = _requestContext.Language;
log.OSVersion = _requestContext.OSVersion;
log.AppVersion = _requestContext.AppVersion;
log.Platform = _requestContext.Platform.ToString();
log.Header = new List<(string, object)>();
foreach (var item in context.Request.Headers)
{
log.Header.Add((item.Key, item.Value));
}
log.RequestBody = requestContent;
_logger.LogCritical("Trace {RequestID}{StartTime}{EndTime}{ExecuteTime}{AccountID}{DepartmentI
D}{CompanyID}{Email}{ClientIp}{CityEn}{Langu log.RequestID, log.StartTime, log.EndTime, log.ExecuteTime, log.AccountID, log.DepartmentID, log.CompanyID, log.Email, log.ClientIp, log.CityEn
}
}
catch (Exception)
{
}
}
private Dictionary<string, string> GetDic(string str)
{
JObject jsonObject = JObject.Parse(str);
IEnumerable<JToken> jTokens = jsonObject.Descendants().Where(p => p.Count() == 0);
Dictionary<string, string> results = jTokens.Aggregate(new Dictionary<string, string>(), (properties, jToken) =>
{
properties.Add(jToken.Path, jToken.ToString());
return properties;
});
return results;
}
#region Request
private async Task<string> ReadRequestBodyAsync(HttpRequest request)
{
if (request.ContentLength > 0)
{
await EnableRewindAsync(request).ConfigureAwait(false);
var encoding = GetRequestEncoding(request);
return await this.ReadStreamAsync(request.Body, encoding).ConfigureAwait(false);
}
return null;
}
private Encoding GetRequestEncoding(HttpRequest request)
{
var requestContentType = request.ContentType;
var requestMediaType = requestContentType == null ? default : new MediaType(requestContentType);
var requestEncoding = requestMediaType.Encoding;
if (requestEncoding == null)
{
requestEncoding = Encoding.UTF8;
}
return requestEncoding;
}
private async Task EnableRewindAsync(HttpRequest request)
{
if (!request.Body.CanSeek)
{
request.EnableBuffering();
request.EnableBuffering();
await request.Body.DrainAsync(CancellationToken.None);
request.Body.Seek(0L, SeekOrigin.Begin);
}
}
private async Task<string> ReadStreamAsync(Stream stream, Encoding encoding)
msinfo{
using (StreamReader sr = new StreamReader(stream, encoding, true, 1024, true))//这⾥注意Body部分不能随StreamReader⼀起释放 {
var str = await sr.ReadToEndAsync();
stream.Seek(0, SeekOrigin.Begin);//内容读取完成后需要将当前位置初始化,否则后⾯的InputFormatter会⽆法读取 return str;
}
}
#endregion
#region Response
private Encoding GetEncoding(string contentType)
{
var mediaType = contentType == null ? default : new MediaType(contentType);
var encoding = mediaType.Encoding;
if (encoding == null)
{
encoding = Encoding.UTF8;
}
return encoding;
}
#endregion
public class PMSLog
{
/// <summary>
/// 请求开始时间
/// </summary>
public string StartTime { get; set; }
/// <summary>
/// 请求结束时间
/// </summary>
public string EndTime { get; set; }
/// <summary>
/// 执⾏毫秒数
/// </summary>
public long ExecuteTime { get; set; }
/// <summary>
/// 请求标识
/
// </summary>
public string RequestID { get; set; }
/// <summary>
/// 控制器名称
/// </summary>
public string ControllerName { get; set; }
public string AppVersion { get; set; }
public string OSVersion { get; set; }
/// <summary>
/// ⽅法名称
/// </summary>
/
// </summary>
public string ActionName { get; set; }
/// <summary>
/// 请求头扁平化
/// </summary>
public List<(string, object)> Header { get; set; }
/// <summary>
/// </summary>
public string RequestBody { get; set; }
/ <summary>
/
请求实体扁平化
/ </summary>
// public Dictionary<string, string> Request { get; set; } / <summary>
/ 请求路径
/ </summary>
//public string RequestPath { get; set; }
/// <summary>
/// 返回实体序列化
/// </summary>
public string ResponseBody { get; set; }
/// <summary>
/
// 返回实体扁平化
/// </summary>
public Dictionary<string, string> Response { get; set; } /// <summary>
/// PMS公司的ID
/// </summary>
public int CompanyID { get; set; }
/// <summary>
/// PMS部门的ID
/// </summary>
public int DepartmentID { get; set; }
/// <summary>
/
// 公司⽤户id
/// </summary>
public int AccountID { get; set; }
/// <summary>
/// 客户端IP
/// </summary>
public string ClientIp { get; set; }
/// <summary>
/// 城市编号
/// </summary>
public string CityEn { get; set; }
/
// <summary>
/// 平台
/// </summary>
public string Platform { get; set; }
/// <summary>
/// 语⾔
/// </summary>
public string Language { get; set; }
/// <summary>
/// 邮箱
/// </summary>
public string Email { get; set; }
}
}
public static class LogExtensions
{
public static IApplicationBuilder UseLog(this IApplicationBuilder applicationBuilder) {
return applicationBuilder.UseMiddleware<LogMiddleware>();
}
}