2021-11-10 14:23:53 +05:00
|
|
|
|
using AsbCloudApp.Data;
|
|
|
|
|
using AsbCloudApp.Services;
|
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Collections.Concurrent;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Text;
|
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
|
|
|
|
|
namespace AsbCloudInfrastructure.Services
|
|
|
|
|
{
|
2022-02-08 13:03:56 +05:00
|
|
|
|
public class RequestTrackerService : IRequerstTrackerService
|
2021-11-10 14:23:53 +05:00
|
|
|
|
{
|
|
|
|
|
const int fastRequestsCount = 1000;
|
|
|
|
|
const int slowRequestsCount = 1000;
|
|
|
|
|
const int errorRequestsCount = 1000;
|
|
|
|
|
const int span = 100;
|
|
|
|
|
|
|
|
|
|
const int fastLimitMs = 500;
|
|
|
|
|
static readonly char[] stackTraceSeparators = "\r\n".ToCharArray();
|
2021-12-07 11:34:06 +05:00
|
|
|
|
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 ConcurrentDictionary<string, RequestLogUserDto> users = new ConcurrentDictionary<string, RequestLogUserDto>();
|
2021-12-17 16:24:54 +05:00
|
|
|
|
|
2021-12-07 11:34:06 +05:00
|
|
|
|
private static IEnumerable<RequestLogDto> Get(IEnumerable<RequestLogDto> list, int take = -1)
|
2021-11-10 14:23:53 +05:00
|
|
|
|
{
|
|
|
|
|
IEnumerable<RequestLogDto> orderedlist = list.OrderByDescending(r => r.Date);
|
|
|
|
|
if (take > 0)
|
|
|
|
|
orderedlist = orderedlist.Take(take);
|
|
|
|
|
return orderedlist;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public IEnumerable<RequestLogUserDto> GetUsersStat(int take = -1)
|
|
|
|
|
{
|
|
|
|
|
IEnumerable<RequestLogUserDto> result = users.Values.OrderByDescending(u => u.LastDate);
|
|
|
|
|
if (take > 0)
|
2021-12-17 16:24:54 +05:00
|
|
|
|
result = result.Take(take);
|
2021-11-10 14:23:53 +05:00
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public IEnumerable<RequestLogDto> GetAll(int take = -1)
|
|
|
|
|
{
|
|
|
|
|
var result = fastRequests
|
|
|
|
|
.Union(slowRequests)
|
|
|
|
|
.Union(errorRequests);
|
|
|
|
|
|
|
|
|
|
return Get(result, take);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public IEnumerable<RequestLogDto> GetFast(int take = -1)
|
|
|
|
|
=> Get(fastRequests, take);
|
|
|
|
|
|
|
|
|
|
public IEnumerable<RequestLogDto> GetSlow(int take = -1)
|
|
|
|
|
=> Get(slowRequests, take);
|
|
|
|
|
|
|
|
|
|
public IEnumerable<RequestLogDto> GetError(int take = -1)
|
|
|
|
|
=> Get(errorRequests, take);
|
|
|
|
|
|
|
|
|
|
public void RegisterRequest(RequestLogDto requestLog)
|
|
|
|
|
{
|
|
|
|
|
if (requestLog.Status < 200)
|
|
|
|
|
return;
|
|
|
|
|
requestLog.Date = DateTime.Now;
|
|
|
|
|
if (requestLog.ElapsedMilliseconds > fastLimitMs)
|
|
|
|
|
RegisterSlowRequest(requestLog);
|
|
|
|
|
else
|
|
|
|
|
RegisterFastRequest(requestLog);
|
|
|
|
|
|
|
|
|
|
UpdateUserStat(requestLog);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void RegisterFastRequest(RequestLogDto requestLog)
|
|
|
|
|
{
|
|
|
|
|
fastRequests.Enqueue(requestLog);
|
|
|
|
|
if (fastRequests.Count > fastRequestsCount + span)
|
|
|
|
|
while (fastRequests.Count > fastRequestsCount)
|
|
|
|
|
fastRequests.TryDequeue(out _);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void RegisterSlowRequest(RequestLogDto requestLog)
|
|
|
|
|
{
|
|
|
|
|
slowRequests.Enqueue(requestLog);
|
|
|
|
|
if (slowRequests.Count > slowRequestsCount + span)
|
|
|
|
|
while (slowRequests.Count > slowRequestsCount)
|
|
|
|
|
slowRequests.TryDequeue(out _);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void RegisterRequestError(RequestLogDto requestLog, Exception ex)
|
|
|
|
|
{
|
|
|
|
|
requestLog.Date = DateTime.Now;
|
|
|
|
|
requestLog.ExceptionMessage = ex.InnerException?.InnerException?.Message
|
|
|
|
|
?? ex.InnerException?.Message
|
|
|
|
|
?? ex.Message;
|
|
|
|
|
requestLog.ExceptionStack = ex.StackTrace?.Split(stackTraceSeparators)[0];
|
|
|
|
|
errorRequests.Enqueue(requestLog);
|
|
|
|
|
if (errorRequests.Count > errorRequestsCount + span)
|
|
|
|
|
while (errorRequests.Count > errorRequestsCount)
|
|
|
|
|
errorRequests.TryDequeue(out _);
|
|
|
|
|
|
|
|
|
|
UpdateUserStat(requestLog);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void UpdateUserStat(RequestLogDto requestLog)
|
|
|
|
|
{
|
|
|
|
|
if (!string.IsNullOrEmpty(requestLog.UserLogin))
|
|
|
|
|
{
|
|
|
|
|
var key = $"{requestLog?.UserId}>{requestLog?.UserIp}";
|
|
|
|
|
if (!users.ContainsKey(key))
|
|
|
|
|
users[key] = new RequestLogUserDto
|
|
|
|
|
{
|
2021-12-17 16:24:54 +05:00
|
|
|
|
UserId = requestLog.UserId,
|
2021-11-10 14:23:53 +05:00
|
|
|
|
Ip = requestLog.UserIp,
|
|
|
|
|
Login = requestLog.UserLogin,
|
2021-12-17 16:24:54 +05:00
|
|
|
|
//User = userService.Get(requestLog.UserId),
|
2021-11-10 14:23:53 +05:00
|
|
|
|
};
|
|
|
|
|
users[key].ElapsedMs += requestLog.ElapsedMilliseconds;
|
|
|
|
|
users[key].LastDate = requestLog.Date;
|
|
|
|
|
users[key].Requests++;
|
|
|
|
|
if(!string.IsNullOrEmpty(requestLog.ExceptionMessage))
|
|
|
|
|
users[key].Errors++;
|
|
|
|
|
|
|
|
|
|
if(users.Count > 1000)
|
|
|
|
|
{
|
|
|
|
|
var count = 900 - users.Count;
|
|
|
|
|
var toRemove = users.OrderBy(kv => kv.Value.LastDate).Take(count);
|
|
|
|
|
foreach (var kv in toRemove)
|
|
|
|
|
users.TryRemove(kv);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|