ancora reviiew procedura export verso DB
This commit is contained in:
@@ -221,7 +221,10 @@ namespace EgwCoreLib.Lux.Data.Services
|
||||
});
|
||||
|
||||
// Chiave aggregata per slot orario
|
||||
var aggHourKey = Key($"stats:agg:{DateTime.UtcNow:yyyyMMddHH}");
|
||||
string dayKey = $"stats:agg:{DateTime.UtcNow:yyyyMMddHH}");
|
||||
var aggHourKey = Key($"{dayKey}");
|
||||
await _db.SetAddAsync("stats:agg:index", dayKey);
|
||||
|
||||
|
||||
// --- Aggiornamento globale (ALL|ALL) ---
|
||||
var globalKey = "ALL|ALL";
|
||||
@@ -270,6 +273,120 @@ namespace EgwCoreLib.Lux.Data.Services
|
||||
await Task.WhenAll(tasks);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Espostazione statistiche da REDIS al DB
|
||||
/// </summary>
|
||||
/// <param name="clearRedisAfterExport"></param>
|
||||
/// <returns></returns>
|
||||
public async Task ExportStatsToDbAsync(bool clearRedisAfterExport = false)
|
||||
{
|
||||
var aggregatedData = new List<StatsAggregated>();
|
||||
var detailData = new List<StatsDetail>();
|
||||
|
||||
// Recupero tutte le chiavi dall'indice (sono RedisValue)
|
||||
RedisValue[] indexValues = await _db.SetMembersAsync("stats:agg:index");
|
||||
|
||||
// Ora corrente (slot da saltare)
|
||||
string currentHourKey = $"stats:agg:{DateTime.UtcNow:yyyyMMddHH}";
|
||||
|
||||
// Lista chiavi da cancellare dopo export (uso RedisValue perché l'indice è un set di valori)
|
||||
var keysToDelete = new List<RedisValue>();
|
||||
|
||||
foreach (RedisValue indexValue in indexValues)
|
||||
{
|
||||
string keyStr = indexValue.ToString();
|
||||
if (keyStr == currentHourKey) continue; // salto slot corrente
|
||||
|
||||
// Estraggo l'ora dalla chiave
|
||||
string hourStr = keyStr.Replace("stats:agg:", "");
|
||||
if (!DateTime.TryParseExact(hourStr, "yyyyMMddHH", null,
|
||||
System.Globalization.DateTimeStyles.None, out DateTime hour))
|
||||
continue;
|
||||
|
||||
// Recupero tutti i valori dell'hash (qui serve RedisKey)
|
||||
HashEntry[] entries = await _db.HashGetAllAsync((RedisKey)keyStr);
|
||||
|
||||
// --- Globali ALL|ALL ---
|
||||
RedisValue sumGlobal = entries.FirstOrDefault(e => e.Name == "ALL|ALL:sum").Value;
|
||||
RedisValue countGlobal = entries.FirstOrDefault(e => e.Name == "ALL|ALL:count").Value;
|
||||
RedisValue maxGlobal = entries.FirstOrDefault(e => e.Name == "ALL|ALL:max").Value;
|
||||
|
||||
if (!sumGlobal.IsNull && !countGlobal.IsNull)
|
||||
{
|
||||
long count = (long)countGlobal;
|
||||
double sum = (double)sumGlobal;
|
||||
double max = maxGlobal.IsNull ? 0 : (double)maxGlobal;
|
||||
|
||||
aggregatedData.Add(new StatsAggregated
|
||||
{
|
||||
Hour = hour,
|
||||
RequestCount = count,
|
||||
AvgDuration = count > 0 ? sum / count : 0,
|
||||
MaxDuration = max
|
||||
});
|
||||
}
|
||||
|
||||
// --- Dettagli per env|tipo ---
|
||||
IEnumerable<string> grouped = entries
|
||||
.Select(e => e.Name.ToString())
|
||||
.Where(n => !n.StartsWith("ALL|ALL"))
|
||||
.Select(n => n.Split(':')[0])
|
||||
.Distinct();
|
||||
|
||||
foreach (string envTipo in grouped)
|
||||
{
|
||||
string[] envTipoSplit = envTipo.Split('|');
|
||||
if (envTipoSplit.Length != 2) continue;
|
||||
|
||||
string env = envTipoSplit[0];
|
||||
string tipo = envTipoSplit[1];
|
||||
|
||||
RedisValue sumVal = entries.FirstOrDefault(e => e.Name == $"{envTipo}:sum").Value;
|
||||
RedisValue countVal = entries.FirstOrDefault(e => e.Name == $"{envTipo}:count").Value;
|
||||
RedisValue maxVal = entries.FirstOrDefault(e => e.Name == $"{envTipo}:max").Value;
|
||||
|
||||
if (!sumVal.IsNull && !countVal.IsNull)
|
||||
{
|
||||
long count = (long)countVal;
|
||||
double sum = (double)sumVal;
|
||||
double max = maxVal.IsNull ? 0 : (double)maxVal;
|
||||
|
||||
detailData.Add(new StatsDetail
|
||||
{
|
||||
Environment = env,
|
||||
Type = tipo,
|
||||
Hour = hour,
|
||||
RequestCount = count,
|
||||
AvgDuration = count > 0 ? sum / count : 0,
|
||||
MaxDuration = max
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Se richiesto, preparo cancellazione
|
||||
if (clearRedisAfterExport)
|
||||
{
|
||||
keysToDelete.Add(indexValue); // RedisValue coerente
|
||||
}
|
||||
}
|
||||
|
||||
// Scrittura su DB
|
||||
long aggrResult = await dbController.StatsAggrUpsertAsync(aggregatedData, true);
|
||||
long detailResult = await dbController.StatsDetailUpsertAsync(detailData, true);
|
||||
|
||||
// Se entrambe hanno successo, eseguo batch di cancellazione
|
||||
if (clearRedisAfterExport && aggrResult > 0 && detailResult > 0 && keysToDelete.Any())
|
||||
{
|
||||
var batch = _db.CreateBatch();
|
||||
foreach (RedisValue indexValue in keysToDelete)
|
||||
{
|
||||
string keyStr = indexValue.ToString();
|
||||
_ = batch.KeyDeleteAsync((RedisKey)keyStr); // cancellazione hash
|
||||
_ = batch.SetRemoveAsync("stats:agg:index", indexValue); // rimozione dall'indice
|
||||
}
|
||||
batch.Execute();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public async Task<List<StatsDetail>> GetOldStatsFromRedisAsync()
|
||||
@@ -319,6 +436,7 @@ namespace EgwCoreLib.Lux.Data.Services
|
||||
return results;
|
||||
}
|
||||
|
||||
#if false
|
||||
public async Task AggregateAndSaveStatsAsync(TimeSpan? timeRange = null, bool deleteFromRedis = false)
|
||||
{
|
||||
var now = DateTime.UtcNow;
|
||||
@@ -443,7 +561,8 @@ namespace EgwCoreLib.Lux.Data.Services
|
||||
{
|
||||
Log.Info("Nessun dato da salvare sul DB");
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Metodo Recupero combinazioni envir/tipo
|
||||
|
||||
@@ -128,7 +128,7 @@
|
||||
isLoading = true;
|
||||
await InvokeAsync(StateHasChanged);
|
||||
TimeSpan defPeriod = TimeSpan.FromHours(24);
|
||||
//await Calc.ArchiveOldStatsAsync(defPeriod, false);
|
||||
await Calc.ExportStatsToDbAsync(false);
|
||||
isLoading = false;
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user