229 lines
8.4 KiB
C#
229 lines
8.4 KiB
C#
/// <summary>
|
|
/// StatsCollector fornisce statistiche in tempo reale sulle prestazioni e sulle attività dell'applicazione.
|
|
///
|
|
/// Questa classe raccoglie e traccia i metri di esecuzione (ad esempio, durata, frequenza, ultima chiamata) per diverse funzioni.
|
|
/// Viene utilizzata per generare report dettagliati sul comportamento dell'applicazione, inclusi il tempo di avvio, l'uptime e le prestazioni delle funzioni.
|
|
///
|
|
/// Caratteristiche principali:
|
|
/// - Traccia la durata e la frequenza delle esecuzioni delle funzioni (ad esempio, controlli di servizio, scansione dati).
|
|
/// - Calcola l'uptime e il timestamp di avvio.
|
|
/// - Formatta i tempi in unità leggibili (ns, ms, sec, min).
|
|
/// - Utilizza dizionari concorrenti per garantire l'accesso sicuro in ambienti multithread.
|
|
/// - Esprime un dizionario di statistiche utilizzabile per report o logging.
|
|
/// </summary>
|
|
using System.Collections.Concurrent;
|
|
|
|
namespace IOB_MAN.Core
|
|
{
|
|
/// <summary>
|
|
/// Oggetto responsabile della raccolta e del reporting delle statistiche a livello di applicazione.
|
|
/// Utilizzato per monitorare i tempi di esecuzione, la frequenza e il comportamento in tempo reale delle funzioni.
|
|
/// </summary>
|
|
public class StatsCollector
|
|
{
|
|
#region Public Properties
|
|
|
|
/// <summary>
|
|
/// Calcola e restituisce l'uptime attuale dell'applicazione.
|
|
///
|
|
/// Formato:
|
|
/// - Se superiore a 1 giorno: "GG d HHh MMm"
|
|
/// - Altrimenti: "HHh MMm SS s"
|
|
///
|
|
/// Esempio: "2d 3h 45m" o "1h 23m 15 s"
|
|
/// </summary>
|
|
public static string UptimeCurr
|
|
{
|
|
get
|
|
{
|
|
string answ = "ND";
|
|
var upT = DateTime.Now.Subtract(StartTime);
|
|
|
|
// Formattazione in base alla durata
|
|
if (upT.TotalDays > 1)
|
|
{
|
|
answ = $"{upT.Days:00} d {upT.Hours:00}h {upT.Minutes:00}m";
|
|
}
|
|
else
|
|
{
|
|
answ = $"{upT.Hours:00}h {upT.Minutes:00}m {upT.Seconds:00} s";
|
|
}
|
|
return answ;
|
|
}
|
|
}
|
|
|
|
#endregion Public Properties
|
|
|
|
#region Public Methods
|
|
|
|
/// <summary>
|
|
/// Restituisce un dizionario contenente tutte le statistiche raccolte per ogni funzione.
|
|
///
|
|
/// Ogni voce include:
|
|
/// - Il numero di esecuzioni.
|
|
/// - La durata media dell'esecuzione (formattata).
|
|
/// - Il timestamp dell'ultima esecuzione.
|
|
///
|
|
/// Esempio:
|
|
/// {
|
|
/// "ScanIOB": "15 x 2.345 sec",
|
|
/// "ScanIOBLast": "2025-04-05 10:30:22",
|
|
/// "Startup": "2025-04-05 09:00:00",
|
|
/// "Uptime": "2d 3h 45m"
|
|
/// }
|
|
/// </summary>
|
|
/// <returns>Un dizionario delle statistiche a livello di funzione.</returns>
|
|
public static Dictionary<string, string> CurrentInfo()
|
|
{
|
|
Dictionary<string, string> result = new Dictionary<string, string>();
|
|
|
|
// Itera su tutte le funzioni tracciate
|
|
foreach (var item in Counter)
|
|
{
|
|
string executionCount = $"{Counter[item.Key]} x {formElaps((Duration[item.Key]) / Counter[item.Key])}";
|
|
result.Add(item.Key, executionCount);
|
|
result.Add($"{item.Key}Last", $"{LastCall[item.Key]:yyyy-MM-dd HH:mm:ss}");
|
|
}
|
|
|
|
// Aggiunge metadati di avvio e uptime
|
|
result.Add("Startup", $"{StartTime:yyyy-MM-dd HH:mm:ss}");
|
|
result.Add("Uptime", UptimeCurr);
|
|
|
|
return result;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Resetta tutte le statistiche interne allo stato iniziale.
|
|
///
|
|
/// Azioni:
|
|
/// - Imposta il nuovo timestamp di avvio al momento attuale.
|
|
/// - Pulisce tutti i contatori, i tempi totali e i timestamp degli ultimi chiamati.
|
|
///
|
|
/// Caso d'uso: chiamato durante un riavvio dell'applicazione, un ricarico della configurazione o un reset per debug.
|
|
/// </summary>
|
|
public static void ResetData()
|
|
{
|
|
StartTime = DateTime.Now;
|
|
Counter = new ConcurrentDictionary<string, long>();
|
|
Duration = new ConcurrentDictionary<string, TimeSpan>();
|
|
LastCall = new ConcurrentDictionary<string, DateTime>();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Aggiorna le statistiche di esecuzione per una funzione specifica.
|
|
///
|
|
/// Parametri:
|
|
/// - functionName: Nome della funzione (es. "DoScan", "CheckMemory").
|
|
/// - elaps: Durata dell'esecuzione della funzione (es. 123.45 ms).
|
|
///
|
|
/// Comportamento:
|
|
/// - Accumula la durata totale e il contatore di esecuzioni.
|
|
/// - Salva il timestamp attuale come ultima chiamata.
|
|
///
|
|
/// Sicurezza multithread:
|
|
/// - Utilizza dizionari concorrenti per garantire l'accesso sicuro da più thread.
|
|
/// </summary>
|
|
/// <param name="functionName">Il nome della funzione in esecuzione.</param>
|
|
/// <param name="elaps">Il tempo trascorso durante l'esecuzione della funzione.</param>
|
|
public static void UpdateStat(string functionName, TimeSpan elaps)
|
|
{
|
|
// Accumula la durata totale
|
|
if (!Duration.ContainsKey(functionName))
|
|
{
|
|
Duration.TryAdd(functionName, elaps);
|
|
}
|
|
else
|
|
{
|
|
Duration[functionName] += elaps;
|
|
}
|
|
|
|
// Incrementa il contatore di esecuzioni
|
|
if (!Counter.ContainsKey(functionName))
|
|
{
|
|
Counter.TryAdd(functionName, 1);
|
|
}
|
|
else
|
|
{
|
|
Counter[functionName]++;
|
|
}
|
|
|
|
// Salva il timestamp dell'ultima esecuzione
|
|
DateTime adesso = DateTime.Now;
|
|
if (!LastCall.ContainsKey(functionName))
|
|
{
|
|
LastCall.TryAdd(functionName, adesso);
|
|
}
|
|
else
|
|
{
|
|
LastCall[functionName] = adesso;
|
|
}
|
|
}
|
|
|
|
#endregion Public Methods
|
|
|
|
#region Private Fields
|
|
|
|
/// <summary>
|
|
/// Dizionario thread-safe che traccia quante volte è stata eseguita ogni funzione.
|
|
/// </summary>
|
|
private static ConcurrentDictionary<string, long> Counter = new ConcurrentDictionary<string, long>();
|
|
|
|
/// <summary>
|
|
/// Dizionario thread-safe che contiene la durata totale (somma) delle esecuzioni di ogni funzione.
|
|
/// </summary>
|
|
private static ConcurrentDictionary<string, TimeSpan> Duration = new ConcurrentDictionary<string, TimeSpan>();
|
|
|
|
/// <summary>
|
|
/// Dizionario thread-safe che memorizza il timestamp dell'ultima esecuzione di ogni funzione.
|
|
/// </summary>
|
|
private static ConcurrentDictionary<string, DateTime> LastCall = new ConcurrentDictionary<string, DateTime>();
|
|
|
|
/// <summary>
|
|
/// Timestamp dell'avvio dell'applicazione.
|
|
/// Utilizzato per calcolare l'uptime e il tempo di avvio.
|
|
/// </summary>
|
|
private static DateTime StartTime = DateTime.Now;
|
|
|
|
#endregion Private Fields
|
|
|
|
#region Private Methods
|
|
|
|
/// <summary>
|
|
/// Formatta un intervallo di tempo in una stringa leggibile in base alla grandezza.
|
|
///
|
|
/// Logica di formattazione:
|
|
/// - Inferiore a 1 ms → "X.XXX ns"
|
|
/// - Da 1 ms a 1 secondo → "X.X ms"
|
|
/// - Da 1 secondo a 300 secondi → "X.X sec"
|
|
/// - Superiore a 300 secondi → "X.X min"
|
|
///
|
|
/// Esempio: 123.456 ms → "123.456 ms", 1.234 sec → "1.234 sec", 360 sec → "6.0 min"
|
|
/// </summary>
|
|
/// <param name="ts">L'intervallo di tempo da formattare.</param>
|
|
/// <returns>Stringa formattata del tempo.</returns>
|
|
private static string formElaps(TimeSpan ts)
|
|
{
|
|
string answ = "";
|
|
if (ts.Milliseconds < 1)
|
|
{
|
|
answ = $"{ts.TotalMilliseconds:N3} ns";
|
|
}
|
|
else if (ts.TotalSeconds < 1)
|
|
{
|
|
answ = $"{ts.TotalMilliseconds:N1} ms";
|
|
}
|
|
else if (ts.TotalSeconds < 300)
|
|
{
|
|
answ = $"{ts.TotalSeconds:N1} sec";
|
|
}
|
|
else
|
|
{
|
|
answ = $"{ts.TotalMinutes:N1} min";
|
|
}
|
|
return answ;
|
|
}
|
|
|
|
#endregion Private Methods
|
|
}
|
|
}
|