DD.WellWorkover.Cloud/AsbCloudInfrastructure/Services/RequestTrackerService.cs

134 lines
5.0 KiB
C#
Raw Normal View History

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
{
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-07 11:34:06 +05:00
private static IEnumerable<RequestLogDto> Get(IEnumerable<RequestLogDto> list, int take = -1)
{
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)
result = result.Take(take);
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
{
UserId = requestLog.UserId,
Ip = requestLog.UserIp,
Login = requestLog.UserLogin,
//User = userService.Get(requestLog.UserId),
};
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);
}
}
}
}
}