diff --git a/MP.Core/DTO/StatInfoDto.cs b/MP.Core/DTO/StatInfoDto.cs
new file mode 100644
index 00000000..e2d96a99
--- /dev/null
+++ b/MP.Core/DTO/StatInfoDto.cs
@@ -0,0 +1,80 @@
+namespace MP.Core.DTO
+{
+ public class StatInfoDto
+ {
+ #region Public Enums
+
+ ///
+ /// Modalità di aggregwzione del dato
+ ///
+ public enum AggrLevel
+ {
+ ///
+ /// Non specificato
+ ///
+ None,
+
+ ///
+ /// Aggregazione x server (IO/IOC)
+ ///
+ Service,
+
+ ///
+ /// Aggregazione x metodo chiamato
+ ///
+ Method,
+
+ ///
+ /// Aggregazione x Macchina chiamante
+ ///
+ Machine
+ }
+
+ ///
+ /// Tipologia del dato collezionato
+ ///
+ public enum DataType
+ {
+ ///
+ /// Non specificato
+ ///
+ None,
+
+ ///
+ /// Conteggio
+ ///
+ Count,
+
+ ///
+ /// Durata temporale (Avg)
+ ///
+ AvgDuration
+ }
+
+ #endregion Public Enums
+
+ #region Public Properties
+
+ ///
+ /// Titolo della statistica
+ ///
+ public string Title { get; set; } = "";
+
+ ///
+ /// Livello di aggregazione delle statistiche collezionate
+ ///
+ public AggrLevel Grouping { get; set; } = AggrLevel.None;
+
+ ///
+ /// Tipologia di dato della statistica
+ ///
+ public DataType Type { get; set; } = DataType.None;
+
+ ///
+ /// Dati statistici ordinati in logica Pareto
+ ///
+ public List DataCollection { get; set; } = new();
+
+ #endregion Public Properties
+ }
+}
\ No newline at end of file
diff --git a/MP.Data/Services/Utils/IStatsAggrService.cs b/MP.Data/Services/Utils/IStatsAggrService.cs
index 77e2c4e1..a1905070 100644
--- a/MP.Data/Services/Utils/IStatsAggrService.cs
+++ b/MP.Data/Services/Utils/IStatsAggrService.cs
@@ -1,6 +1,7 @@
using EgwCoreLib.Utils;
using MP.Core.DTO;
using MP.Data.DbModels.Utils;
+using MP.Data.DTO;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
@@ -46,6 +47,14 @@ namespace MP.Data.Services.Utils
/// Elenco dei record da inserire/aggiornare
/// Se true elimina preventivamente i record nel periodo richiesto
Task UpsertManyAsync(List listRecords, bool removeOld);
+ ///
+ /// Helper conversione dati aggregati in statistiche da inviare a ChartJS
+ ///
+ ///
+ /// raggruppamento per macchina/server
+ /// metrica conteggio/avgDuration
+ ///
+ List GetTimeSeriesData(List rawData, bool groupMach, bool getCount);
#endregion Public Methods
}
diff --git a/MP.Data/Services/Utils/IStatsDetailService.cs b/MP.Data/Services/Utils/IStatsDetailService.cs
index 31cb4da1..364a44a4 100644
--- a/MP.Data/Services/Utils/IStatsDetailService.cs
+++ b/MP.Data/Services/Utils/IStatsDetailService.cs
@@ -38,7 +38,9 @@ namespace MP.Data.Services.Utils
/// Ogni elaborazione contiene Dictionary in forma pareto per una data statistica
///
///
- Task>> GetParetoStatsDayAsync();
+ //Task>> GetParetoStatsDayAsync();
+ Task> GetParetoStatsDayAsync();
+
///
/// Recupera il range di periodi valido per le chiamate di dettaglio.
diff --git a/MP.Data/Services/Utils/StatsAggrService.cs b/MP.Data/Services/Utils/StatsAggrService.cs
index 088b40fd..012031e9 100644
--- a/MP.Data/Services/Utils/StatsAggrService.cs
+++ b/MP.Data/Services/Utils/StatsAggrService.cs
@@ -2,6 +2,7 @@
using Microsoft.Extensions.Configuration;
using MP.Core.DTO;
using MP.Data.DbModels.Utils;
+using MP.Data.DTO;
using MP.Data.Repository.Utils;
using StackExchange.Redis;
using System;
@@ -41,18 +42,6 @@ namespace MP.Data.Services.Utils
});
}
- ///
- public async Task>> GetParetoStatsWeekAsync()
- {
- return await TraceAsync($"{_className}.GetParetoStatsWeekAsync", async (activity) =>
- {
- return await GetOrSetCacheAsync(
- $"{_redisBaseKey}:{_className}:ParetoWeek",
- async () => await GetParetoDataAsync(),
- LongCache
- );
- });
- }
///
public async Task>> GetParetoStatsDayAsync(int numDay)
{
@@ -66,6 +55,19 @@ namespace MP.Data.Services.Utils
});
}
+ ///
+ public async Task>> GetParetoStatsWeekAsync()
+ {
+ return await TraceAsync($"{_className}.GetParetoStatsWeekAsync", async (activity) =>
+ {
+ return await GetOrSetCacheAsync(
+ $"{_redisBaseKey}:{_className}:ParetoWeek",
+ async () => await GetParetoDataAsync(),
+ LongCache
+ );
+ });
+ }
+
///
public async Task GetRangeAsync()
{
@@ -79,6 +81,59 @@ namespace MP.Data.Services.Utils
});
}
+ ///
+ public List GetTimeSeriesData(List rawData, bool groupMach, bool getCount)
+ {
+ List series = new();
+ // a seconda della richiesta cambio il group by...
+ if (groupMach)
+ {
+ series = rawData
+ .GroupBy(s => new { s.Destination, s.MachineId }) // Raggruppiamo per la chiave composta
+ .Select(group => new ChartSeriesDto
+ {
+ // Creiamo un nome leggibile per la legenda del grafico
+ SeriesName = $"{group.Key.Destination}|{group.Key.MachineId}",
+
+ // Per ogni gruppo, creiamo la lista dei punti temporali
+ DataPoints = group
+ .OrderBy(p => p.Hour) // Fondamentale: l'asse X deve essere cronologico
+ .Select(p => new chartJsData.chartJsTSerie
+ {
+ x = p.Hour,
+ y = getCount ? p.RequestCount : p.AvgDuration * p.RequestCount // La metrica richiesta
+ })
+ .ToList()
+ })
+ .OrderBy(s => s.SeriesName) // Opzionale: ordina le serie alfabeticamente
+ .ToList();
+ }
+ else
+ {
+ series = rawData
+ .GroupBy(s => new { s.MachineId, s.Destination }) // Raggruppiamo per la chiave composta
+ .Select(group => new ChartSeriesDto
+ {
+ // Creiamo un nome leggibile per la legenda del grafico
+ SeriesName = $"{group.Key.MachineId}|{group.Key.Destination}",
+
+ // Per ogni gruppo, creiamo la lista dei punti temporali
+ DataPoints = group
+ .OrderBy(p => p.Hour) // Fondamentale: l'asse X deve essere cronologico
+ .Select(p => new chartJsData.chartJsTSerie
+ {
+ x = p.Hour,
+ y = getCount ? p.RequestCount : p.AvgDuration // La metrica richiesta
+ })
+ .ToList()
+ })
+ .OrderBy(s => s.SeriesName) // Opzionale: ordina le serie alfabeticamente
+ .ToList();
+ }
+
+ return series;
+ }
+
///
public async Task UpsertManyAsync(List listRecords, bool removeOld)
{
diff --git a/MP.Data/Services/Utils/StatsDetailService.cs b/MP.Data/Services/Utils/StatsDetailService.cs
index 3f253562..14c9dd53 100644
--- a/MP.Data/Services/Utils/StatsDetailService.cs
+++ b/MP.Data/Services/Utils/StatsDetailService.cs
@@ -74,7 +74,7 @@ namespace MP.Data.Services.Utils
}
///
- public async Task>> GetParetoStatsDayAsync()
+ public async Task> GetParetoStatsDayAsync()
{
return await TraceAsync($"{_className}.GetDailyParetoStats", async (activity) =>
{
@@ -152,8 +152,80 @@ namespace MP.Data.Services.Utils
/// metodo locale per recupero e trasformazione dati da includere con processo generare di tracking & cache
///
///
- protected async Task>> GetParetoDataAsync()
+ protected async Task> GetParetoDataAsync()
{
+ List result = new();
+ DateTime adesso = DateTime.Now;
+ var rawData = await GetFiltAsync(adesso.AddDays(-1), adesso);
+
+ // calcolo le varie statistiche...
+ var pDestRequest = rawData.GroupBy(x => x.Destination)
+ .Select(g => new StatDataDTO
+ {
+ Label = g.Key,
+ Value = g.Sum(x => x.RequestCount)
+ })
+ .OrderByDescending(x => x.Value)
+ .ToList();
+ result.Add(new StatInfoDto()
+ {
+ Title = "Dest.Request (#)",
+ DataCollection = pDestRequest,
+ Grouping = StatInfoDto.AggrLevel.Service,
+ Type = StatInfoDto.DataType.Count
+ });
+
+ var pDestDuration = rawData.GroupBy(x => x.Destination)
+ .Select(g => new StatDataDTO
+ {
+ Label = g.Key,
+ Value = g.Sum(x => x.RequestCount * x.AvgDuration)
+ })
+ .OrderByDescending(x => x.Value)
+ .ToList();
+ result.Add(new StatInfoDto()
+ {
+ Title = "Dest.Duration (ms)",
+ DataCollection = pDestDuration,
+ Grouping = StatInfoDto.AggrLevel.Service,
+ Type = StatInfoDto.DataType.AvgDuration
+ });
+
+ var pTypeRequest = rawData.GroupBy(x => x.Type)
+ .Select(g => new StatDataDTO
+ {
+ Label = g.Key,
+ Value = g.Sum(x => x.RequestCount)
+ })
+ .OrderByDescending(x => x.Value)
+ .ToList();
+ result.Add(new StatInfoDto()
+ {
+ Title = "Type.Request (#)",
+ DataCollection = pTypeRequest,
+ Grouping = StatInfoDto.AggrLevel.Method,
+ Type = StatInfoDto.DataType.Count
+ });
+
+ var pTypeDuration = rawData.GroupBy(x => x.Type)
+ .Select(g => new StatDataDTO
+ {
+ Label = g.Key,
+ Value = g.Sum(x => x.RequestCount * x.AvgDuration)
+ })
+ .OrderByDescending(x => x.Value)
+ .ToList();
+
+ result.Add(new StatInfoDto()
+ {
+ Title = "Type.Duration (ms)",
+ DataCollection = pTypeDuration,
+ Grouping = StatInfoDto.AggrLevel.Method,
+ Type = StatInfoDto.DataType.AvgDuration
+ });
+
+ return result;
+#if false
Dictionary> result = new();
DateTime adesso = DateTime.Now;
var rawData = await GetFiltAsync(adesso.AddDays(-1), adesso);
@@ -217,8 +289,10 @@ namespace MP.Data.Services.Utils
//result.Add("DestType.Duration (ms)", pDestTypeDuration);
return result;
+#endif
}
+
#endregion Protected Methods
#region Private Fields
diff --git a/MP.IOC/Components/Pages/CallStats.razor b/MP.IOC/Components/Pages/CallStats.razor
index a6ff3ac0..eff4482b 100644
--- a/MP.IOC/Components/Pages/CallStats.razor
+++ b/MP.IOC/Components/Pages/CallStats.razor
@@ -22,9 +22,9 @@
@foreach (var item in ParetoDay)
{
- -
- @item.Key
-