Update IOC x stats preliminari
This commit is contained in:
@@ -11,6 +11,8 @@ namespace MP.Data.Repository.Utils
|
||||
/// </summary>
|
||||
public interface IStatsDetailRepository
|
||||
{
|
||||
#region Public Methods
|
||||
|
||||
/// <summary>
|
||||
/// Recupera l'elenco delle statistiche di dettaglio per un periodo specifico, con filtri opzionali.
|
||||
/// </summary>
|
||||
@@ -21,6 +23,17 @@ namespace MP.Data.Repository.Utils
|
||||
/// <returns>L'elenco delle statistiche di dettaglio ordinate cronologicamente.</returns>
|
||||
Task<List<StatsDetailModel>> GetFiltAsync(DateTime dtStart, DateTime dtEnd, string sEnvir = "", string sType = "");
|
||||
|
||||
/// <summary>
|
||||
/// Elenco record in modalità pareto
|
||||
/// </summary>
|
||||
/// <param name="dtStart"></param>
|
||||
/// <param name="dtEnd"></param>
|
||||
/// <param name="maxRec"></param>
|
||||
/// <param name="sDest"></param>
|
||||
/// <param name="sType"></param>
|
||||
/// <returns></returns>
|
||||
Task<List<StatsDetailModel>> GetParetoAsync(DateTime dtStart, DateTime dtEnd, int maxRec, string sDest = "", string sType = "");
|
||||
|
||||
/// <summary>
|
||||
/// Recupera l'intervallo temporale disponibile nel database per le statistiche di dettaglio.
|
||||
/// </summary>
|
||||
@@ -36,5 +49,7 @@ namespace MP.Data.Repository.Utils
|
||||
/// <param name="removeOld">Se true, elimina preventivamente i record nel periodo richiesto.</param>
|
||||
/// <returns>Il numero di record inseriti.</returns>
|
||||
Task<int> UpsertManyAsync(List<StatsDetailModel> listRecords, bool removeOld);
|
||||
|
||||
#endregion Public Methods
|
||||
}
|
||||
}
|
||||
@@ -47,6 +47,34 @@ namespace MP.Data.Repository.Utils
|
||||
return answ;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<List<StatsDetailModel>> GetParetoAsync(DateTime dtStart, DateTime dtEnd, int maxRec, string sDest = "", string sType = "")
|
||||
{
|
||||
await using var dbCtx = await CreateContextAsync();
|
||||
List<StatsDetailModel> answ = new List<StatsDetailModel>();
|
||||
|
||||
// recupero ed ordino per data-ora
|
||||
var query = dbCtx.DbSetStatsDet
|
||||
.Where(x => x.Hour >= dtStart && x.Hour <= dtEnd);
|
||||
|
||||
if (!string.IsNullOrEmpty(sDest))
|
||||
query = query.Where(x => x.Destination == sDest);
|
||||
|
||||
if (!string.IsNullOrEmpty(sType))
|
||||
query = query.Where(x => x.Type == sType);
|
||||
|
||||
answ = await query
|
||||
.AsNoTracking()
|
||||
.OrderByDescending(x => x.RequestCount)
|
||||
.ThenBy(x => x.Hour)
|
||||
.ThenBy(x => x.Destination)
|
||||
.ThenBy(x => x.Type)
|
||||
.Take(maxRec)
|
||||
.ToListAsync();
|
||||
|
||||
return answ;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<DtUtils.Periodo> GetRangeAsync(string sEnvir, string sType)
|
||||
{
|
||||
@@ -68,7 +96,6 @@ namespace MP.Data.Repository.Utils
|
||||
return answ;
|
||||
}
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<int> UpsertManyAsync(List<StatsDetailModel> listRecords, bool removeOld)
|
||||
{
|
||||
@@ -161,6 +188,8 @@ namespace MP.Data.Repository.Utils
|
||||
}
|
||||
}
|
||||
|
||||
#endregion Public Methods
|
||||
|
||||
#if false
|
||||
/// <inheritdoc />
|
||||
public async Task<int> UpsertManyAsyncOrig(List<StatsDetailModel> listRecords, bool removeOld)
|
||||
@@ -181,7 +210,6 @@ namespace MP.Data.Repository.Utils
|
||||
DateTime startDate = firstRec.Hour;
|
||||
DateTime endDate = lastRec.Hour;
|
||||
|
||||
|
||||
var items = await dbCtx.DbSetStatsDet
|
||||
.Where(x => x.Hour >= startDate && x.Hour <= endDate)
|
||||
.ToListAsync();
|
||||
@@ -209,11 +237,9 @@ namespace MP.Data.Repository.Utils
|
||||
await tx.RollbackAsync();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#endregion Public Methods
|
||||
|
||||
#region Protected Fields
|
||||
|
||||
protected static NLog.Logger Log = LogManager.GetCurrentClassLogger();
|
||||
|
||||
@@ -16,9 +16,20 @@ namespace MP.Data.Services.Utils
|
||||
/// </summary>
|
||||
/// <param name="dtStart">Data inizio periodo</param>
|
||||
/// <param name="dtEnd">Data fine periodo</param>
|
||||
/// <param name="sEnvir">Filtro opzionale per ambiente (default: vuoto = tutti)</param>
|
||||
/// <param name="sDest">Filtro opzionale per destinazione (default: vuoto = tutti)</param>
|
||||
/// <param name="sType">Filtro opzionale per tipo (default: vuoto = tutti)</param>
|
||||
Task<List<StatsDetailModel>> GetFiltAsync(DateTime dtStart, DateTime dtEnd, string sEnvir = "", string sType = "");
|
||||
Task<List<StatsDetailModel>> GetFiltAsync(DateTime dtStart, DateTime dtEnd, string sDest = "", string sType = "");
|
||||
|
||||
/// <summary>
|
||||
/// restituisce un Pareto degli eventi più frequenti dato periodo ed eventuale filtro Destinazione/Tipo
|
||||
/// </summary>
|
||||
/// <param name="dtStart">Data inizio periodo</param>
|
||||
/// <param name="dtEnd">Data fine periodo</param>
|
||||
/// <param name="maxRec"></param>
|
||||
/// <param name="sDest">Filtro opzionale per destinazione (default: vuoto = tutti)</param>
|
||||
/// <param name="sType">Filtro opzionale per tipo (default: vuoto = tutti)</param>
|
||||
/// <returns></returns>
|
||||
Task<List<StatsDetailModel>> GetParetoAsync(DateTime dtStart, DateTime dtEnd, int maxRec, string sDest = "", string sType = "");
|
||||
|
||||
/// <summary>
|
||||
/// Recupera il range di periodi valido per le chiamate di dettaglio.
|
||||
|
||||
@@ -26,17 +26,48 @@ namespace MP.Data.Services.Utils
|
||||
#region Public Methods
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<List<StatsDetailModel>> GetFiltAsync(DateTime dtStart, DateTime dtEnd, string sEnvir = "", string sType = "")
|
||||
public async Task<List<StatsDetailModel>> GetFiltAsync(DateTime dtStart, DateTime dtEnd, string sDest = "", string sType = "")
|
||||
{
|
||||
return await TraceAsync($"{_className}.GetFilt", async (activity) =>
|
||||
{
|
||||
string cacheKey = $"{_redisBaseKey}:{_className}:DT:{dtStart:yyyyMMdd}:{dtEnd:yyyyMMdd}";
|
||||
if (!string.IsNullOrEmpty(sDest))
|
||||
{
|
||||
cacheKey += $":{sDest}";
|
||||
}
|
||||
if (!string.IsNullOrEmpty(sType))
|
||||
{
|
||||
cacheKey += $":{sType}";
|
||||
}
|
||||
return await GetOrSetCacheAsync(
|
||||
$"{_redisBaseKey}:{_className}:DT:{dtStart:yyyyMMdd}:{dtEnd:yyyyMMdd}",
|
||||
cacheKey,
|
||||
async () => await _repo.GetFiltAsync(dtStart, dtEnd),
|
||||
UltraLongCache
|
||||
);
|
||||
});
|
||||
}
|
||||
/// <inheritdoc />
|
||||
public async Task<List<StatsDetailModel>> GetParetoAsync(DateTime dtStart, DateTime dtEnd, int maxRec, string sDest = "", string sType = "")
|
||||
{
|
||||
return await TraceAsync($"{_className}.GetFilt", async (activity) =>
|
||||
{
|
||||
string cacheKey = $"{_redisBaseKey}:{_className}:PARETO:{dtStart:yyyyMMdd}:{dtEnd:yyyyMMdd}";
|
||||
if (!string.IsNullOrEmpty(sDest))
|
||||
{
|
||||
cacheKey += $":{sDest}";
|
||||
}
|
||||
if (!string.IsNullOrEmpty(sType))
|
||||
{
|
||||
cacheKey += $":{sType}";
|
||||
}
|
||||
return await GetOrSetCacheAsync(
|
||||
cacheKey,
|
||||
async () => await _repo.GetParetoAsync(dtStart, dtEnd, maxRec, sDest, sType),
|
||||
UltraLongCache
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<DtUtils.Periodo> GetRangeAsync(string sEnvir, string sType)
|
||||
|
||||
@@ -59,7 +59,7 @@
|
||||
</NavLink>
|
||||
</div> *@
|
||||
<div class="nav-item px-2">
|
||||
<NavLink class="nav-link py-0 px-2 mb-0" href="About">
|
||||
<NavLink class="nav-link py-0 px-2 mb-0" href="about">
|
||||
<span class="fas fa-info-circle fs-4 pe-2" aria-hidden="true"></span>
|
||||
@if (showText)
|
||||
{
|
||||
@@ -68,7 +68,7 @@
|
||||
</NavLink>
|
||||
</div>
|
||||
<div class="nav-item px-2">
|
||||
<NavLink class="nav-link py-0 px-2 mb-0" href="Contacts">
|
||||
<NavLink class="nav-link py-0 px-2 mb-0" href="contacts">
|
||||
<span class="fas fa-envelope fs-4 pe-2" aria-hidden="true"></span>
|
||||
@if (showText)
|
||||
{
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
@page "/"
|
||||
@page "/Home"
|
||||
@page "/Index"
|
||||
<div class="card">
|
||||
|
||||
<div class="card shadow">
|
||||
<div class="card-header bg-dark text-light">
|
||||
<div class="row">
|
||||
<div class="col-3 p-2">
|
||||
@@ -87,5 +88,47 @@
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row my-2">
|
||||
<div class="col-3">
|
||||
<ul class="list-group">
|
||||
<li class="list-group-item active d-flex justify-content-between align-items-start">
|
||||
<b>Top Call</b>
|
||||
</li>
|
||||
@foreach (var item in ListParetoCall)
|
||||
{
|
||||
<li class="list-group-item d-flex justify-content-between align-items-start small py-1">
|
||||
<div>
|
||||
@item.Destination | <b>@item.Type</b>
|
||||
</div>
|
||||
<div class="">
|
||||
<b>@($"{item.RequestCount:N0}")</b>
|
||||
</div>
|
||||
</li>
|
||||
}
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-6 text-center">
|
||||
perc IO/IOC
|
||||
</div>
|
||||
<div class="col-3">
|
||||
<ul class="list-group">
|
||||
<li class="list-group-item active d-flex justify-content-between align-items-start">
|
||||
<b>Call Processed</b>
|
||||
</li>
|
||||
@foreach (var item in ListGlobalCall)
|
||||
{
|
||||
<li class="list-group-item d-flex justify-content-between align-items-start small py-1">
|
||||
<div>
|
||||
@($"{item.Hour:yyyy-MM-dd}")
|
||||
</div>
|
||||
<div class="">
|
||||
<b>@($"{item.RequestCount:N0}")</b>
|
||||
</div>
|
||||
</li>
|
||||
}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,7 +1,33 @@
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using MP.Data.DbModels.Utils;
|
||||
using MP.Data.Services.Utils;
|
||||
|
||||
namespace MP.IOC.Components.Pages
|
||||
{
|
||||
public partial class Index
|
||||
{
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
await ReloadData();
|
||||
}
|
||||
|
||||
private async Task ReloadData()
|
||||
{
|
||||
DateTime oggi = DateTime.Today;
|
||||
DateTime adesso = DateTime.Now;
|
||||
var rawData = await StatsAggrService.GetFiltAsync(oggi.AddDays(-5), oggi);
|
||||
ListGlobalCall = rawData.OrderByDescending(x => x.Hour).ToList();
|
||||
ListParetoCall = await StatsDetService.GetParetoAsync(adesso.AddHours(-1), adesso, 5);
|
||||
}
|
||||
|
||||
private List<StatsAggregatedModel> ListGlobalCall = new();
|
||||
private List<StatsDetailModel> ListParetoCall = new();
|
||||
|
||||
|
||||
[Inject]
|
||||
private IStatsAggrService StatsAggrService { get; set; } = null!;
|
||||
[Inject]
|
||||
private IStatsDetailService StatsDetService { get; set; } = null!;
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,7 @@
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Version>6.16.2604.915</Version>
|
||||
<Version>6.16.2604.916</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -77,14 +77,6 @@ string utilsConnString = builder.Configuration.GetConnectionString("MP.Utils") ?
|
||||
builder.Services.AddDbContextFactory<MoonPro_UtilsContext>(options =>
|
||||
options.UseSqlServer(utilsConnString));
|
||||
|
||||
#if false
|
||||
// gestione generica MP
|
||||
// aggiunta helper local/session storage service
|
||||
builder.Services.AddScoped<ISessionStorageService, SessionStorageService>();
|
||||
builder.Services.AddScoped<ILocalStorageService, LocalStorageService>();
|
||||
builder.Services.AddScoped<MessageService>();
|
||||
#endif
|
||||
|
||||
// MP.Data Services Utils - Statistiche DB
|
||||
builder.Services.AddScoped<IStatsAggrRepository, StatsAggrRepository>();
|
||||
builder.Services.AddScoped<IStatsDetailRepository, StatsDetailRepository>();
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<body>
|
||||
<i>Modulo MP-IOC </i>
|
||||
<h4>Versione: 6.16.2604.915</h4>
|
||||
<h4>Versione: 6.16.2604.916</h4>
|
||||
<br /> Note di rilascio:
|
||||
<ul>
|
||||
<li>
|
||||
|
||||
@@ -1 +1 @@
|
||||
6.16.2604.915
|
||||
6.16.2604.916
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<item>
|
||||
<version>6.16.2604.915</version>
|
||||
<version>6.16.2604.916</version>
|
||||
<url>https://nexus.steamware.net/repository/SWS/MP-IOC/stable/LAST/MP.IOC.zip</url>
|
||||
<changelog>https://nexus.steamware.net/repository/SWS/MP-IOC/stable/LAST/ChangeLog.html</changelog>
|
||||
<mandatory>false</mandatory>
|
||||
|
||||
@@ -1,103 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>MP IOC</title>
|
||||
<link rel="stylesheet" href="lib/bootstrap/css/bootstrap.css" />
|
||||
<link rel="stylesheet" href="lib/font-awesome/css/all.css" />
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="container py-3">
|
||||
<div class="card">
|
||||
<div class="card-header bg-dark text-light">
|
||||
<div class="row">
|
||||
<div class="col-3 p-2">
|
||||
<img src="images/LogoMapo.png" class="image-fluid" height="64" />
|
||||
</div>
|
||||
<div class="col-6 p-2 text-center align-content-center">
|
||||
<div class="fs-1 fw-bold">MAPO MES</div>
|
||||
<div class="fs-6 text-secondary">IN/OUT module</div>
|
||||
</div>
|
||||
<div class="col-3 text-end p-2">
|
||||
<img src="images/LogoEgw.png" class="image-fluid" height="64" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<div class="col-3">
|
||||
<ul class="list-group">
|
||||
<li class="list-group-item d-flex justify-content-between align-items-start">
|
||||
<div>
|
||||
<b>Alive</b>
|
||||
</div>
|
||||
<div class="text-success">
|
||||
<i class="fa-solid fa-circle-check"></i>
|
||||
</div>
|
||||
</li>
|
||||
<li class="list-group-item d-flex justify-content-between align-items-start">
|
||||
<div>
|
||||
<b>IOB-PI</b> I/O
|
||||
</div>
|
||||
<div class="text-danger">
|
||||
<i class="fa-solid fa-circle-check"></i>
|
||||
</div>
|
||||
</li>
|
||||
<li class="list-group-item d-flex justify-content-between align-items-start">
|
||||
<div>
|
||||
<b>IOB-WIN</b> I/O
|
||||
</div>
|
||||
<div class="text-danger">
|
||||
<i class="fa-solid fa-circle-check"></i>
|
||||
</div>
|
||||
</li>
|
||||
<li class="list-group-item d-flex justify-content-between align-items-start">
|
||||
<div>
|
||||
<b>File</b> upload
|
||||
</div>
|
||||
<div class="text-danger">
|
||||
<i class="fa-solid fa-circle-check"></i>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-6 text-center">
|
||||
<h1>MP-IOC</h1>
|
||||
<h4>.net Core 8.0</h4>
|
||||
</div>
|
||||
<div class="col-3 text-end">
|
||||
<ul class="list-group">
|
||||
<li class="list-group-item d-flex justify-content-between align-items-start">
|
||||
<div>
|
||||
<b>Bench</b> test
|
||||
</div>
|
||||
<div class="text-warning">
|
||||
<i class="fa-solid fa-circle-check"></i>
|
||||
</div>
|
||||
</li>
|
||||
<li class="list-group-item d-flex justify-content-between align-items-start">
|
||||
<div>
|
||||
<b>Parameters</b> management
|
||||
</div>
|
||||
<div class="text-danger">
|
||||
<i class="fa-solid fa-circle-check"></i>
|
||||
</div>
|
||||
</li>
|
||||
<li class="list-group-item d-flex justify-content-between align-items-start">
|
||||
<div>
|
||||
<b>Recipe</b> management
|
||||
</div>
|
||||
<div class="text-success">
|
||||
<i class="fa-solid fa-circle-check"></i>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script src="lib/bootstrap/js/bootstrap.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user