如何为api所有的请求和响应做一个统一的日志记录
1.创建日志类
public class RequestResponseLog {
public string Url { get; set; }
public IDictionary<string, string> Headers { get; set; } = new Dictionary<string, string>();
public string Method { get; set; }
public string RequestBody { get; set; }
public string ResponseBody { get; set; }
public DateTime ExcuteStartTime { get; set; }
public DateTime ExcuteEndTime { get; set; }
public override string ToString()
{
string headers = "[" + string.Join(",", this.Headers.Select(i => "{" + $"\"{i.Key}\":\"{i.Value}\"" + "}")) + "]";
return $"\r\n***********************************************************************\r\nUrl: {this.Url},\r\nHeaders: {headers},\r\nMethod: {this.Method},\r\nRequestBody: {this.RequestBody},\r\nResponseBody: {this.ResponseBody},\r\nExcuteStartTime: {this.ExcuteStartTime.ToString("yyyy-MM-dd HH:mm:ss.fff")},\r\nExcuteEndTime: {this.ExcuteEndTime.ToString("yyyy-MM-dd HH:mm:ss.fff")}";
}
}
2.创建日志中间件
public class RequestResponseLoggingMiddleware {
private readonly RequestDelegate _next;
private RequestResponseLog _logInfo;
public RequestResponseLoggingMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task Invoke(HttpContext context)
{
_logInfo = new RequestResponseLog();
HttpRequest request = context.Request;
_logInfo.Url = request.Path.ToString();
_logInfo.Headers = request.Headers.ToDictionary(k => k.Key, v => string.Join(";", v.Value.ToList()));
_logInfo.Method = request.Method;
_logInfo.ExcuteStartTime = DateTime.Now;
if (request.Method.ToLower().Equals("post"))
{
request.EnableBuffering();
Stream stream = request.Body;
byte[] buffer = new byte[request.ContentLength.Value];
stream.ReadAsync(buffer, 0, buffer.Length);
_logInfo.RequestBody = Encoding.UTF8.GetString(buffer);
request.Body.Position = 0;
}
else if (request.Method.ToLower().Equals("get"))
{
_logInfo.RequestBody = request.QueryString.Value;
}
var originalBodyStream = context.Response.Body;
using (var responseBody = new MemoryStream())
{
context.Response.Body = responseBody;
await _next(context);
_logInfo.ResponseBody = await FormatResponse(context.Response);
_logInfo.ExcuteEndTime = DateTime.Now;
LogA.SaveInfoToTxtFile($"VisitLog: {_logInfo.ToString()}");
await responseBody.CopyToAsync(originalBodyStream);
}
}
private async Task<string> FormatResponse(HttpResponse response)
{
response.Body.Seek(0, SeekOrigin.Begin);
var text = await new StreamReader(response.Body).ReadToEndAsync();
response.Body.Seek(0, SeekOrigin.Begin);
return text;
}
}
public static class RequestResponseLoggingMiddlewareExtensions {
public static IApplicationBuilder UseRequestResponseLogging(this IApplicationBuilder builder)
{
return builder.UseMiddleware<RequestResponseLoggingMiddleware>();
}
}
3.日志书写类
public static class LogA {
public static void SaveInfoToTxtFile(string info)
{
string bPath = AppContext.BaseDirectory;
if (Directory.Exists(bPath+@".\Log") == false)
{
Directory.CreateDirectory(bPath+@".\Log");
}
if (Directory.Exists(bPath+@".\Log\" + DateTime.Now.ToString("yyyyMM")) == false)
{
Directory.CreateDirectory(bPath+@".\Log\" + DateTime.Now.ToString("yyyyMM"));
}
string fileName = bPath+@".\Log\" + DateTime.Now.ToString("yyyyMM") + "\\" + DateTime.Now.ToString("yyyyMMddHH") + ".txt";
StreamWriter sWriter = null;
try
{
sWriter = new StreamWriter(fileName, true, Encoding.Default);
sWriter.Write(info);
}
catch (Exception err)
{
Console.WriteLine("\r\n保存控制台显示的信息 出现异常!" + err.Message);
}
finally
{
if (sWriter != null)
sWriter.Close();
}
}
}
4.在starpup.cs中注册中间件
app.UseRequestResponseLogging();
5.完成,收工
|