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

View File

@ -2,6 +2,7 @@
namespace AsbCloudApp.Data
{
#nullable enable
/// <summary>
/// DTO статистики запросов по пользователю
/// </summary>
@ -15,12 +16,12 @@ namespace AsbCloudApp.Data
/// <summary>
/// логин
/// </summary>
public string Login { get; set; }
public string Login { get; set; } = string.Empty;
/// <summary>
/// IP адрес пользователя
/// </summary>
public string Ip { get; set; }
public string? Ip { get; set; }
/// <summary>
/// время выполнения запроса
@ -45,6 +46,7 @@ namespace AsbCloudApp.Data
/// <summary>
/// DTO пользователя
/// </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
{
// TODO: make this nullable
#nullable enable
/// <summary>
/// Отслеживание и сбор статистики по запросам
@ -29,34 +29,35 @@ namespace AsbCloudApp.Services
/// </summary>
/// <param name="take"></param>
/// <returns></returns>
IEnumerable<RequestLogDto> GetAll(int take = -1);
IEnumerable<RequestLogDto> GetAll(int? take);
/// <summary>
/// запросы которые выполнялись быстро
/// </summary>
/// <param name="take"></param>
/// <returns></returns>
IEnumerable<RequestLogDto> GetFast(int take = -1);
IEnumerable<RequestLogDto> GetFast(int? take);
/// <summary>
/// запросы, которые выполнялись медленно
/// </summary>
/// <param name="take"></param>
/// <returns></returns>
IEnumerable<RequestLogDto> GetSlow(int take = -1);
IEnumerable<RequestLogDto> GetSlow(int? take);
/// <summary>
/// запросы, которые завершились ошибкой
/// </summary>
/// <param name="take"></param>
/// <returns></returns>
IEnumerable<RequestLogDto> GetError(int take = -1);
IEnumerable<RequestLogDto> GetError(int? take);
/// <summary>
/// Статистика посещений пользователей
/// </summary>
/// <param name="take"></param>
/// <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
{
#nullable enable
public class RequestTrackerService : IRequerstTrackerService
{
const int fastRequestsCount = 1000;
@ -16,28 +17,28 @@ namespace AsbCloudInfrastructure.Services
const int fastLimitMs = 500;
static readonly char[] stackTraceSeparators = "\r\n".ToCharArray();
private readonly ConcurrentQueue<RequestLogDto> fastRequests = new ConcurrentQueue<RequestLogDto>();
private readonly ConcurrentQueue<RequestLogDto> slowRequests = new ConcurrentQueue<RequestLogDto>();
private readonly ConcurrentQueue<RequestLogDto> errorRequests = new ConcurrentQueue<RequestLogDto>();
private readonly ConcurrentQueue<RequestLogDto> fastRequests = new ();
private readonly ConcurrentQueue<RequestLogDto> slowRequests = new ();
private readonly ConcurrentQueue<RequestLogDto> errorRequests = new ();
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);
if (take > 0)
orderedlist = orderedlist.Take(take);
orderedlist = orderedlist.Take(take.Value);
return orderedlist;
}
public IEnumerable<RequestLogUserDto> GetUsersStat(int take = -1)
public IEnumerable<RequestLogUserDto> GetUsersStat(int? take)
{
IEnumerable<RequestLogUserDto> result = users.Values.OrderByDescending(u => u.LastDate);
if (take > 0)
result = result.Take(take);
result = result.Take(take.Value);
return result;
}
public IEnumerable<RequestLogDto> GetAll(int take = -1)
public IEnumerable<RequestLogDto> GetAll(int? take)
{
var result = fastRequests
.Union(slowRequests)
@ -46,13 +47,13 @@ namespace AsbCloudInfrastructure.Services
return Get(result, take);
}
public IEnumerable<RequestLogDto> GetFast(int take = -1)
public IEnumerable<RequestLogDto> GetFast(int? take)
=> Get(fastRequests, take);
public IEnumerable<RequestLogDto> GetSlow(int take = -1)
public IEnumerable<RequestLogDto> GetSlow(int? take)
=> Get(slowRequests, take);
public IEnumerable<RequestLogDto> GetError(int take = -1)
public IEnumerable<RequestLogDto> GetError(int? take)
=> Get(errorRequests, take);
public void RegisterRequest(RequestLogDto requestLog)
@ -103,14 +104,13 @@ namespace AsbCloudInfrastructure.Services
{
if (!string.IsNullOrEmpty(requestLog.UserLogin))
{
var key = $"{requestLog?.UserId}>{requestLog?.UserIp}";
var key = $"{requestLog.UserId}>{requestLog.UserIp}";
if (!users.ContainsKey(key))
users[key] = new RequestLogUserDto
{
UserId = requestLog.UserId,
Ip = requestLog.UserIp,
Login = requestLog.UserLogin,
//User = userService.Get(requestLog.UserId),
};
users[key].ElapsedMs += requestLog.ElapsedMilliseconds;
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
{
#nullable enable
/// <summary>
/// Мониторинг запросов, ошибок, пользователей
/// </summary>
@ -87,4 +88,5 @@ namespace AsbCloudWebApi.Controllers
return Ok(result);
}
}
#nullable disable
}

View File

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