RequerstTracker Add nullable

This commit is contained in:
ngfrolov 2022-12-26 18:03:26 +05:00
parent b91093b2e4
commit 8e896a887d
6 changed files with 46 additions and 37 deletions

View File

@ -2,6 +2,7 @@
namespace AsbCloudApp.Data namespace AsbCloudApp.Data
{ {
#nullable enable
/// <summary> /// <summary>
/// DTO журнала запросов /// DTO журнала запросов
/// </summary> /// </summary>
@ -10,7 +11,7 @@ namespace AsbCloudApp.Data
/// <summary> /// <summary>
/// логин пользователя /// логин пользователя
/// </summary> /// </summary>
public string UserLogin { get; set; } public string UserLogin { get; set; } = string.Empty;
/// <summary> /// <summary>
/// Id пользователя /// Id пользователя
@ -20,22 +21,22 @@ namespace AsbCloudApp.Data
/// <summary> /// <summary>
/// IP адрес пользователя /// IP адрес пользователя
/// </summary> /// </summary>
public string UserIp { get; set; } public string? UserIp { get; set; }
/// <summary> /// <summary>
/// метод запроса (GET, POST,..) /// метод запроса (GET, POST,..)
/// </summary> /// </summary>
public string RequestMethod { get; set; } public string RequestMethod { get; set; } = null!;
/// <summary> /// <summary>
/// url /// url
/// </summary> /// </summary>
public string RequestPath { get; set; } public string? RequestPath { get; set; }
/// <summary> /// <summary>
/// Referer /// Referer
/// </summary> /// </summary>
public string Referer { get; set; } public string Referer { get; set; } = string.Empty;
/// <summary> /// <summary>
/// продолжительность выполнения /// продолжительность выполнения
@ -47,19 +48,20 @@ namespace AsbCloudApp.Data
/// </summary> /// </summary>
public int Status { get; set; } public int Status { get; set; }
/// <summary>
/// сообщение об ошибке, если она произошла
/// </summary>
public string ExceptionMessage { get; set; }
/// <summary> /// <summary>
/// метка времени запроса /// метка времени запроса
/// </summary> /// </summary>
public DateTime Date { get; set; } public DateTime Date { get; set; }
/// <summary>
/// сообщение об ошибке, если она произошла
/// </summary>
public string? ExceptionMessage { get; set; } = null!;
/// <summary> /// <summary>
/// стек вызовов /// стек вызовов
/// </summary> /// </summary>
public string ExceptionStack { get; set; } public string? ExceptionStack { get; set; } = null!;
} }
#nullable disable
} }

View File

@ -2,6 +2,7 @@
namespace AsbCloudApp.Data namespace AsbCloudApp.Data
{ {
#nullable enable
/// <summary> /// <summary>
/// DTO статистики запросов по пользователю /// DTO статистики запросов по пользователю
/// </summary> /// </summary>
@ -15,12 +16,12 @@ namespace AsbCloudApp.Data
/// <summary> /// <summary>
/// логин /// логин
/// </summary> /// </summary>
public string Login { get; set; } public string Login { get; set; } = string.Empty;
/// <summary> /// <summary>
/// IP адрес пользователя /// IP адрес пользователя
/// </summary> /// </summary>
public string Ip { get; set; } public string? Ip { get; set; }
/// <summary> /// <summary>
/// время выполнения запроса /// время выполнения запроса
@ -45,6 +46,7 @@ namespace AsbCloudApp.Data
/// <summary> /// <summary>
/// DTO пользователя /// DTO пользователя
/// </summary> /// </summary>
public UserDto User { get; set; } public UserDto User { get; set; } = null!;
} }
#nullable disable
} }

View File

@ -4,7 +4,7 @@ using System.Collections.Generic;
namespace AsbCloudApp.Services namespace AsbCloudApp.Services
{ {
// TODO: make this nullable #nullable enable
/// <summary> /// <summary>
/// Отслеживание и сбор статистики по запросам /// Отслеживание и сбор статистики по запросам
@ -29,34 +29,35 @@ namespace AsbCloudApp.Services
/// </summary> /// </summary>
/// <param name="take"></param> /// <param name="take"></param>
/// <returns></returns> /// <returns></returns>
IEnumerable<RequestLogDto> GetAll(int take = -1); IEnumerable<RequestLogDto> GetAll(int? take);
/// <summary> /// <summary>
/// запросы которые выполнялись быстро /// запросы которые выполнялись быстро
/// </summary> /// </summary>
/// <param name="take"></param> /// <param name="take"></param>
/// <returns></returns> /// <returns></returns>
IEnumerable<RequestLogDto> GetFast(int take = -1); IEnumerable<RequestLogDto> GetFast(int? take);
/// <summary> /// <summary>
/// запросы, которые выполнялись медленно /// запросы, которые выполнялись медленно
/// </summary> /// </summary>
/// <param name="take"></param> /// <param name="take"></param>
/// <returns></returns> /// <returns></returns>
IEnumerable<RequestLogDto> GetSlow(int take = -1); IEnumerable<RequestLogDto> GetSlow(int? take);
/// <summary> /// <summary>
/// запросы, которые завершились ошибкой /// запросы, которые завершились ошибкой
/// </summary> /// </summary>
/// <param name="take"></param> /// <param name="take"></param>
/// <returns></returns> /// <returns></returns>
IEnumerable<RequestLogDto> GetError(int take = -1); IEnumerable<RequestLogDto> GetError(int? take);
/// <summary> /// <summary>
/// Статистика посещений пользователей /// Статистика посещений пользователей
/// </summary> /// </summary>
/// <param name="take"></param> /// <param name="take"></param>
/// <returns></returns> /// <returns></returns>
IEnumerable<RequestLogUserDto> GetUsersStat(int take = -1); IEnumerable<RequestLogUserDto> GetUsersStat(int? take);
} }
#nullable disable
} }

View File

@ -7,6 +7,7 @@ using System.Linq;
namespace AsbCloudInfrastructure.Services namespace AsbCloudInfrastructure.Services
{ {
#nullable enable
public class RequestTrackerService : IRequerstTrackerService public class RequestTrackerService : IRequerstTrackerService
{ {
const int fastRequestsCount = 1000; const int fastRequestsCount = 1000;
@ -16,28 +17,28 @@ namespace AsbCloudInfrastructure.Services
const int fastLimitMs = 500; const int fastLimitMs = 500;
static readonly char[] stackTraceSeparators = "\r\n".ToCharArray(); static readonly char[] stackTraceSeparators = "\r\n".ToCharArray();
private readonly ConcurrentQueue<RequestLogDto> fastRequests = new ConcurrentQueue<RequestLogDto>(); private readonly ConcurrentQueue<RequestLogDto> fastRequests = new ();
private readonly ConcurrentQueue<RequestLogDto> slowRequests = new ConcurrentQueue<RequestLogDto>(); private readonly ConcurrentQueue<RequestLogDto> slowRequests = new ();
private readonly ConcurrentQueue<RequestLogDto> errorRequests = new ConcurrentQueue<RequestLogDto>(); private readonly ConcurrentQueue<RequestLogDto> errorRequests = new ();
private readonly ConcurrentDictionary<string, RequestLogUserDto> users = new ConcurrentDictionary<string, RequestLogUserDto>(); private readonly ConcurrentDictionary<string, RequestLogUserDto> users = new ConcurrentDictionary<string, RequestLogUserDto>();
private static IEnumerable<RequestLogDto> Get(IEnumerable<RequestLogDto> list, int take = -1) private static IEnumerable<RequestLogDto> Get(IEnumerable<RequestLogDto> list, int? take)
{ {
IEnumerable<RequestLogDto> orderedlist = list.OrderByDescending(r => r.Date); IEnumerable<RequestLogDto> orderedlist = list.OrderByDescending(r => r.Date);
if (take > 0) if (take > 0)
orderedlist = orderedlist.Take(take); orderedlist = orderedlist.Take(take.Value);
return orderedlist; return orderedlist;
} }
public IEnumerable<RequestLogUserDto> GetUsersStat(int take = -1) public IEnumerable<RequestLogUserDto> GetUsersStat(int? take)
{ {
IEnumerable<RequestLogUserDto> result = users.Values.OrderByDescending(u => u.LastDate); IEnumerable<RequestLogUserDto> result = users.Values.OrderByDescending(u => u.LastDate);
if (take > 0) if (take > 0)
result = result.Take(take); result = result.Take(take.Value);
return result; return result;
} }
public IEnumerable<RequestLogDto> GetAll(int take = -1) public IEnumerable<RequestLogDto> GetAll(int? take)
{ {
var result = fastRequests var result = fastRequests
.Union(slowRequests) .Union(slowRequests)
@ -46,13 +47,13 @@ namespace AsbCloudInfrastructure.Services
return Get(result, take); return Get(result, take);
} }
public IEnumerable<RequestLogDto> GetFast(int take = -1) public IEnumerable<RequestLogDto> GetFast(int? take)
=> Get(fastRequests, take); => Get(fastRequests, take);
public IEnumerable<RequestLogDto> GetSlow(int take = -1) public IEnumerable<RequestLogDto> GetSlow(int? take)
=> Get(slowRequests, take); => Get(slowRequests, take);
public IEnumerable<RequestLogDto> GetError(int take = -1) public IEnumerable<RequestLogDto> GetError(int? take)
=> Get(errorRequests, take); => Get(errorRequests, take);
public void RegisterRequest(RequestLogDto requestLog) public void RegisterRequest(RequestLogDto requestLog)
@ -103,14 +104,13 @@ namespace AsbCloudInfrastructure.Services
{ {
if (!string.IsNullOrEmpty(requestLog.UserLogin)) if (!string.IsNullOrEmpty(requestLog.UserLogin))
{ {
var key = $"{requestLog?.UserId}>{requestLog?.UserIp}"; var key = $"{requestLog.UserId}>{requestLog.UserIp}";
if (!users.ContainsKey(key)) if (!users.ContainsKey(key))
users[key] = new RequestLogUserDto users[key] = new RequestLogUserDto
{ {
UserId = requestLog.UserId, UserId = requestLog.UserId,
Ip = requestLog.UserIp, Ip = requestLog.UserIp,
Login = requestLog.UserLogin, Login = requestLog.UserLogin,
//User = userService.Get(requestLog.UserId),
}; };
users[key].ElapsedMs += requestLog.ElapsedMilliseconds; users[key].ElapsedMs += requestLog.ElapsedMilliseconds;
users[key].LastDate = requestLog.Date; users[key].LastDate = requestLog.Date;
@ -128,4 +128,5 @@ namespace AsbCloudInfrastructure.Services
} }
} }
} }
#nullable disable
} }

View File

@ -6,6 +6,7 @@ using System.Collections.Generic;
namespace AsbCloudWebApi.Controllers namespace AsbCloudWebApi.Controllers
{ {
#nullable enable
/// <summary> /// <summary>
/// Мониторинг запросов, ошибок, пользователей /// Мониторинг запросов, ошибок, пользователей
/// </summary> /// </summary>
@ -87,4 +88,5 @@ namespace AsbCloudWebApi.Controllers
return Ok(result); return Ok(result);
} }
} }
#nullable disable
} }

View File

@ -4,6 +4,7 @@ using System.Threading.Tasks;
namespace AsbCloudWebApi.Middlewares namespace AsbCloudWebApi.Middlewares
{ {
#nullable enable
public class RequerstTrackerMiddleware public class RequerstTrackerMiddleware
{ {
private readonly RequestDelegate next; private readonly RequestDelegate next;
@ -18,8 +19,8 @@ namespace AsbCloudWebApi.Middlewares
var service = context.RequestServices.GetRequiredService<AsbCloudApp.Services.IRequerstTrackerService>(); var service = context.RequestServices.GetRequiredService<AsbCloudApp.Services.IRequerstTrackerService>();
var requestLog = new AsbCloudApp.Data.RequestLogDto var requestLog = new AsbCloudApp.Data.RequestLogDto
{ {
UserLogin = context.User?.Identity.Name, UserLogin = context.User.Identity?.Name ?? string.Empty,
UserIp = context.Connection.RemoteIpAddress.ToString(), UserIp = context.Connection?.RemoteIpAddress?.ToString(),
RequestMethod = context.Request.Method, RequestMethod = context.Request.Method,
RequestPath = context.Request.Path.Value, RequestPath = context.Request.Path.Value,
Referer = context.Request.Headers["Referer"].ToString(), Referer = context.Request.Headers["Referer"].ToString(),
@ -32,7 +33,7 @@ namespace AsbCloudWebApi.Middlewares
var sw = System.Diagnostics.Stopwatch.StartNew(); var sw = System.Diagnostics.Stopwatch.StartNew();
try try
{ {
await next?.Invoke(context); await next.Invoke(context);
sw.Stop(); sw.Stop();
requestLog.ElapsedMilliseconds = sw.ElapsedMilliseconds; requestLog.ElapsedMilliseconds = sw.ElapsedMilliseconds;
requestLog.Status = context.Response.StatusCode; requestLog.Status = context.Response.StatusCode;
@ -43,10 +44,10 @@ namespace AsbCloudWebApi.Middlewares
sw.Stop(); sw.Stop();
requestLog.ElapsedMilliseconds = sw.ElapsedMilliseconds; requestLog.ElapsedMilliseconds = sw.ElapsedMilliseconds;
requestLog.Status = context.Response.StatusCode; requestLog.Status = context.Response.StatusCode;
// TODO: Add request params and body size.
service.RegisterRequestError(requestLog, ex); service.RegisterRequestError(requestLog, ex);
throw; throw;
} }
} }
} }
#nullable disable
} }