From efd7fab27caf5f4d8767a7fda1efc5cb8b7dc6c2 Mon Sep 17 00:00:00 2001 From: Samuele Locatelli Date: Fri, 10 Apr 2026 09:55:53 +0200 Subject: [PATCH] Update display statistiche chiamata --- MP.IOC/Components/App.razor | 8 +- MP.IOC/Components/Pages/CallStats.razor | 32 +++++--- MP.IOC/Components/Pages/CallStats.razor.cs | 70 ++++++++++++++++ MP.IOC/MP.IOC.csproj | 2 +- MP.IOC/Resources/ChangeLog.html | 2 +- MP.IOC/Resources/VersNum.txt | 2 +- MP.IOC/Resources/manifest.xml | 2 +- MP.IOC/Services/MetricsCalcService.cs | 94 ---------------------- MP.IOC/Services/RedisWeightProvider.cs | 4 +- MP.IOC/appsettings.Development.json | 1 + MP.IOC/wwwroot/lib/chartBoot.js | 20 ++++- 11 files changed, 121 insertions(+), 116 deletions(-) diff --git a/MP.IOC/Components/App.razor b/MP.IOC/Components/App.razor index 60766030..50f26fdc 100644 --- a/MP.IOC/Components/App.razor +++ b/MP.IOC/Components/App.razor @@ -6,7 +6,6 @@ @* *@ - @@ -20,9 +19,10 @@ - - - + @* *@ + +@* + *@ diff --git a/MP.IOC/Components/Pages/CallStats.razor b/MP.IOC/Components/Pages/CallStats.razor index 5d1c3ed1..e45c9261 100644 --- a/MP.IOC/Components/Pages/CallStats.razor +++ b/MP.IOC/Components/Pages/CallStats.razor @@ -2,48 +2,58 @@
-

Current Call Stats

(24h) +

Current Call Stats (24h)

-
+
  • Avail Data +
  • @foreach (var item in ParetoDay) {
  • @item.Key -
  • }
-
- Pareto Chart +
+ @if (string.IsNullOrEmpty(@currSelect)) + { +
selezionare la metrica
+ } + else + { + + }
- Pie chart +
-
- lista dettaglio (5/10 pag) +
+
-
+
timeserie selezionata x num call/tempo
-
+@*
@foreach (var item in ParetoDay) {
} -
+
*@
diff --git a/MP.IOC/Components/Pages/CallStats.razor.cs b/MP.IOC/Components/Pages/CallStats.razor.cs index 042973ea..3fd46239 100644 --- a/MP.IOC/Components/Pages/CallStats.razor.cs +++ b/MP.IOC/Components/Pages/CallStats.razor.cs @@ -19,6 +19,76 @@ namespace MP.IOC.Components.Pages private Dictionary> ParetoDay = new(); + private void DoReset() + { + currSelect = ""; + currData = new(); + } + private void DoSelect(string reqKey) + { + if (ParetoDay.ContainsKey(reqKey)) + { + currSelect = reqKey; + currTitle = $"Pareto | {reqKey}"; + currData = ParetoDay[reqKey]; + } + } + private string currSelect = ""; + private string currTitle = ""; + private List currData = new(); + + private List LabelPareto + { + get => currData.Select(x => x.Label).ToList(); + } + + private List DatiPareto + { + get => currData.Select(x => x.Value).ToList(); + } + /// + /// Genera colori sfondo 33% rosso / arancione / giallo + /// + /// + /// + /// + private List semaphColors(int numRecords, string alpha) + { + List answ = new List(); + // verde... + for (int i = 0; i < numRecords / 3; i++) + { + answ.Add($"rgba(54, 235, 82, {alpha})"); + } + // arancione + for (int i = 0; i < numRecords / 3; i++) + { + answ.Add($"rgba(255, 206, 86, {alpha})"); + } + while (answ.Count < numRecords) + { + answ.Add($"rgba(255, 99, 132, {alpha}"); + } + + return answ; + } + /// + /// Genera colori sfondo 33% rosso / arancione / giallo + /// + /// + protected List bgColors + { + get => semaphColors(currData.Count, "0.3"); + } + /// + /// Genera colori sfondo 33% rosso / arancione / giallo + /// + /// + private List lineColors + { + get => semaphColors(currData.Count, "1"); + } + #endregion Private Fields #region Private Properties diff --git a/MP.IOC/MP.IOC.csproj b/MP.IOC/MP.IOC.csproj index 016342de..9c2954a2 100644 --- a/MP.IOC/MP.IOC.csproj +++ b/MP.IOC/MP.IOC.csproj @@ -4,7 +4,7 @@ net8.0 enable enable - 6.16.2604.1008 + 6.16.2604.1009 diff --git a/MP.IOC/Resources/ChangeLog.html b/MP.IOC/Resources/ChangeLog.html index dbb2f036..b71861f1 100644 --- a/MP.IOC/Resources/ChangeLog.html +++ b/MP.IOC/Resources/ChangeLog.html @@ -1,6 +1,6 @@ Modulo MP-IOC -

Versione: 6.16.2604.1008

+

Versione: 6.16.2604.1009


Note di rilascio:
  • diff --git a/MP.IOC/Resources/VersNum.txt b/MP.IOC/Resources/VersNum.txt index 47191719..4fec5777 100644 --- a/MP.IOC/Resources/VersNum.txt +++ b/MP.IOC/Resources/VersNum.txt @@ -1 +1 @@ -6.16.2604.1008 +6.16.2604.1009 diff --git a/MP.IOC/Resources/manifest.xml b/MP.IOC/Resources/manifest.xml index 25f29414..62c6e1c3 100644 --- a/MP.IOC/Resources/manifest.xml +++ b/MP.IOC/Resources/manifest.xml @@ -1,6 +1,6 @@ - 6.16.2604.1008 + 6.16.2604.1009 https://nexus.steamware.net/repository/SWS/MP-IOC/stable/LAST/MP.IOC.zip https://nexus.steamware.net/repository/SWS/MP-IOC/stable/LAST/ChangeLog.html false diff --git a/MP.IOC/Services/MetricsCalcService.cs b/MP.IOC/Services/MetricsCalcService.cs index 1ad73f02..9ec38409 100644 --- a/MP.IOC/Services/MetricsCalcService.cs +++ b/MP.IOC/Services/MetricsCalcService.cs @@ -191,100 +191,6 @@ namespace MP.IOC.Services } } } - -#if false - protected override async Task ExecuteAsync(CancellationToken stoppingToken) - { - var interval = _config.GetValue("RouteMan:MetricCalcIntervalSeconds", 20); - while (!stoppingToken.IsCancellationRequested) - { - try - { - await Task.Delay(TimeSpan.FromSeconds(interval), stoppingToken); - var snapshot = _stats.Snapshot(); - - if (snapshot.Count == 0) continue; - - var adesso = DateTime.Now; - var hourStart = new DateTime(adesso.Year, adesso.Month, adesso.Day, adesso.Hour, 0, 0); - var dayStart = new DateTime(adesso.Year, adesso.Month, adesso.Day, 0, 0, 0); - - foreach (var kv in snapshot) - { - string dest = "IO"; - string method = "NA"; - // verifico se ho chiave completo (dest+method) o parziale - string rawKey = kv.Key; - if (rawKey.Contains("|")) - { - var splitVal = rawKey.Split("|"); - dest = splitVal[0]; - method = splitVal[1]; - } - else - { - method = rawKey; - } - var stat = kv.Value; - var count = Interlocked.Read(ref stat.Count); - var totalMs = stat.TotalDuration.TotalMilliseconds; - var maxMs = stat.MaxDuration.TotalMilliseconds; - var minMs = (stat.MinDuration == TimeSpan.MaxValue) ? 0 : stat.MinDuration.TotalMilliseconds; - - Log.Info($"Dest {dest} | Method {method} | Count {count} | TotalDurationMs {totalMs} | MaxDurationMs {maxMs} | MinDurationMs {minMs}"); - - if (_db == null) continue; - - // Keys - var hourKey = HourBucketKey(dest, method, hourStart); - var hoursIndex = HoursIndexKey(dest, method); - var dayKey = DayBucketKey(dest, dayStart); - var daysIndex = DaysIndexKey(dest); - - // Use batch to reduce roundtrips - var batch = _db.CreateBatch(); - - // Increment hash fields (count and totalMs) - var taskHourCount = batch.HashIncrementAsync(hourKey, "count", count); - var taskHourTotal = batch.HashIncrementAsync(hourKey, "totalMs", totalMs); - var taskHourMax = batch.HashSetAsync(hourKey, "maxMs", maxMs.ToString()); - var taskHourMin = batch.HashSetAsync(hourKey, "minMs", minMs.ToString()); - - var taskDayCount = batch.HashIncrementAsync(dayKey, "count", count); - var taskDayTotal = batch.HashIncrementAsync(dayKey, "totalMs", totalMs); - - // For day bucket min/max: save as separate fields to be aggregated later - // Using HashSet with comparison logic handled during flush - var taskDayMax = batch.HashSetAsync(dayKey, "maxMs", maxMs.ToString()); - var taskDayMin = batch.HashSetAsync(dayKey, "minMs", minMs.ToString()); - - // Add to sorted set indices with score = epoch seconds of bucket start - var hourScore = ToEpochSeconds(hourStart); - var dayScore = ToEpochSeconds(dayStart); - - var taskZAddHour = batch.SortedSetAddAsync(hoursIndex, hourKey, hourScore); - var taskZAddDay = batch.SortedSetAddAsync(daysIndex, dayKey, dayScore); - - // Execute batch - batch.Execute(); - - // Await tasks to ensure completion - await Task.WhenAll(taskHourCount, taskHourTotal, taskHourMax, taskHourMin, - taskDayCount, taskDayTotal, taskDayMax, taskDayMin, - taskZAddHour, taskZAddDay); - } - - _stats.Clear(); - } - catch (TaskCanceledException) { } - catch (Exception ex) - { - Log.Error(ex, "Error flushing metrics"); - } - } - } -#endif - #endregion Protected Methods #region Private Fields diff --git a/MP.IOC/Services/RedisWeightProvider.cs b/MP.IOC/Services/RedisWeightProvider.cs index 3127c36e..f3fe7757 100644 --- a/MP.IOC/Services/RedisWeightProvider.cs +++ b/MP.IOC/Services/RedisWeightProvider.cs @@ -79,6 +79,7 @@ namespace MP.IOC.Services public List GetAllWeights() { var result = new List(); +#if false var keys = _db.KeyScan($"{_keyPrefix}*"); foreach (var key in keys) @@ -99,7 +100,8 @@ namespace MP.IOC.Services newW = Math.Clamp(parsedNew, 0, 100); result.Add(new WeightDTO { Method = methodName, OldWeight = oldW, NewWeight = newW }); - } + } +#endif return result; } diff --git a/MP.IOC/appsettings.Development.json b/MP.IOC/appsettings.Development.json index 0c208ae9..770d3e93 100644 --- a/MP.IOC/appsettings.Development.json +++ b/MP.IOC/appsettings.Development.json @@ -1,4 +1,5 @@ { + "DetailedErrors": true, "Logging": { "LogLevel": { "Default": "Information", diff --git a/MP.IOC/wwwroot/lib/chartBoot.js b/MP.IOC/wwwroot/lib/chartBoot.js index d934ff8f..5374f886 100644 --- a/MP.IOC/wwwroot/lib/chartBoot.js +++ b/MP.IOC/wwwroot/lib/chartBoot.js @@ -1,9 +1,25 @@ // Setup del chart desiderato con id univoco window.setup = (id, config) => { - var ctx = document.getElementById(id).getContext('2d'); + + const el = document.getElementById(id); + if (!el) { + //console.error("Elemento canvas non trovato:", id); + return; + } + // TECNICA INFALLIBILE: + // Chiediamo a Chart.js di trovare l'istanza associata a questo elemento DOM + // Indipendentemente da quale ID avesse prima. + const existingChart = Chart.getChart(el); + if (existingChart) { + existingChart.destroy(); + } + + const ctx = el.getContext('2d'); + + //var ctx = document.getElementById(id).getContext('2d'); //let currentDate = new Date(); //console.log(currentDate + " - Calling setup..."); - //console.log(id); + console.log(id); if (window['chart-' + id] instanceof Chart) { //window.myChart.destroy(); window['chart-' + id].destroy();