Files
lux/Lux.UI/Components/Compo/Stats/RealTimeStats.razor.cs
T
2025-12-18 15:03:57 +01:00

245 lines
7.9 KiB
C#

using EgwCoreLib.Lux.Core.Stats;
using EgwCoreLib.Lux.Data.Services;
using Microsoft.AspNetCore.Components;
using Microsoft.JSInterop;
using Newtonsoft.Json.Linq;
using System.CodeDom;
using System.Net.Cache;
using static System.Runtime.InteropServices.JavaScript.JSType;
namespace Lux.UI.Components.Compo.Stats
{
public partial class RealTimeStats : IDisposable
{
#region Public Methods
public void Dispose()
{
_cts?.Cancel();
_cts?.Dispose();
}
#endregion Public Methods
#region Protected Properties
[Inject]
protected CalcRuidService Calc { get; set; } = null!;
[Inject]
protected IJSRuntime JSRuntime { get; set; } = null!;
#endregion Protected Properties
#region Protected Methods
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
await InitCharts();
_cts = new CancellationTokenSource();
_ = UpdateLoop(_cts.Token);
}
}
protected override async Task OnInitializedAsync()
{
InitConfig();
await ReloadStatsRT();
}
#endregion Protected Methods
#region Private Fields
private CancellationTokenSource? _cts;
private StatsRealtimeDto? stats;
private List<RealtimeProcDto> rtProcStats = new List<RealtimeProcDto>();
#endregion Private Fields
#region Private Methods
private async Task InitCharts()
{
await JSRuntime.InvokeVoidAsync("chartsInterop.createChart", "chartRequestsMinute", new
{
type = "line",
data = new
{
labels = new[] { "Now" },
datasets = new[]
{
new {
label = "Richieste/minuto",
data = new[] { 0 },
borderColor = "blue"
}
}
}
});
await JSRuntime.InvokeVoidAsync("chartsInterop.createChart", "chartRequestsHour", new
{
type = "bar",
data = new
{
labels = new[] { "Now" },
datasets = new[]
{
new {
label = "Richieste/ora",
data = new[] { 0 },
backgroundColor = "green"
}
}
}
});
await JSRuntime.InvokeVoidAsync("chartsInterop.createChart", "chartAvgProcessing", new
{
type = "line",
data = new
{
labels = new[] { "Now" },
datasets = new[]
{
new {
label = "Tempo medio (s)",
data = new[] { 0 },
borderColor = "orange"
}
}
}
});
await JSRuntime.InvokeVoidAsync("chartsInterop.createChart", "chartMaxProcessing", new
{
type = "line",
data = new
{
labels = new[] { "Now" },
datasets = new[]
{
new {
label = "Tempo massimo (s)",
data = new[] { 0 },
borderColor = "red"
}
}
}
});
}
private void InitConfig()
{
PieColors.Clear();
PieColors.Add("WINDOW", "rgba(54,162,235,0.6)");
PieColors.Add("BEAM", "rgba(69,195,132,0.6)");
DatasetCount.Clear();
DatasetCount.Add("NONE", 0);
DataseElapsed.Clear();
DataseElapsed.Add("NONE", 0);
}
private Dictionary<string, string> PieColors = new Dictionary<string, string>();
private Dictionary<string, double> DatasetCount = new Dictionary<string, double>();
private Dictionary<string, double> DataseElapsed = new Dictionary<string, double>();
private List<string> ListX = new List<string>();
private Dictionary<string, List<decimal>> DictY = new Dictionary<string, List<decimal>>();
private async Task UpdateLoop(CancellationToken token)
{
try
{
while (!token.IsCancellationRequested)
{
stats = await Calc.GetStatsAsync();
await ReloadStatsRT();
await JSRuntime.InvokeVoidAsync("chartsInterop.updateChart",
"chartRequestsMinute",
DateTime.Now.ToString("HH:mm:ss"),
stats.RequestsLastMinute);
await JSRuntime.InvokeVoidAsync("chartsInterop.updateBarChart",
"chartRequestsHour",
DateTime.Now.ToString("HH:mm:ss"),
stats.RequestsLastHour);
await JSRuntime.InvokeVoidAsync("chartsInterop.updateChart",
"chartAvgProcessing",
DateTime.Now.ToString("HH:mm:ss"),
stats.ProcessingAvgLastHour);
await JSRuntime.InvokeVoidAsync("chartsInterop.updateChart",
"chartMaxProcessing",
DateTime.Now.ToString("HH:mm:ss"),
stats.ProcessingMaxLastHour);
// attesa 5 secondi, rispettando il token
await Task.Delay(TimeSpan.FromSeconds(5), token);
}
}
catch (OperationCanceledException)
{
// loop fermato
}
}
private async Task ReloadStatsRT()
{
rtProcStats = await Calc.RealTimeDataStats(CalcRuidService.GroupMode.Hour, CalcRuidService.TagMode.Envir, DateTime.Today.AddDays(-1));
// calcolo i valori da mostrare...
if (rtProcStats != null && rtProcStats.Count > 0)
{
DatasetCount = rtProcStats
.GroupBy(p => p.TagClass)
.ToDictionary(
g => g.Key,
g => (double)g.Sum(p => p.EventCount)
);
DataseElapsed = rtProcStats
.GroupBy(p => p.TagClass)
.ToDictionary(
g => g.Key,
g => g.Sum(p => p.Elapsed)
);
// 1. Definiamo le etichette dell'asse X (es. le ultime 24 ore o quelle presenti nei dati)
ListX = rtProcStats
.Select(p => p.Hour.ToString("HH:mm"))
.Distinct()
.OrderBy(t => t)
.ToList();
// 2. Identifichiamo tutti i TagClass unici (saranno i nostri dataset)
var allTags = rtProcStats.Select(p => p.TagClass).Distinct().ToList();
// 3. Costruiamo il DictY: per ogni Tag, creiamo una lista di valori allineata a ListX
DictY = allTags.ToDictionary(
tag => tag,
tag => ListX.Select(hour =>
{
// Cerchiamo il valore per quel tag in quell'ora specifica
return (decimal)(rtProcStats
.FirstOrDefault(p => p.TagClass == tag && p.Hour.ToString("HH:mm") == hour)
?.EventCount ?? 0); // Se non esiste, mettiamo 0
}).ToList()
);
// forzatura update
await InvokeAsync(StateHasChanged);
}
}
#endregion Private Methods
}
}