From a7ff46ca99b43221ecbdd6d5f971f4b34e1bfe07 Mon Sep 17 00:00:00 2001 From: Samuele Locatelli Date: Mon, 11 May 2026 10:38:39 +0200 Subject: [PATCH] Completo modifiche x test SIMULA nuove statistiche cone rrori --- MP.RIOC/Services/MetricsDbFlushService.cs | 97 +++++++++++++++++------ 1 file changed, 74 insertions(+), 23 deletions(-) diff --git a/MP.RIOC/Services/MetricsDbFlushService.cs b/MP.RIOC/Services/MetricsDbFlushService.cs index ba6444b2..4d2cbd71 100644 --- a/MP.RIOC/Services/MetricsDbFlushService.cs +++ b/MP.RIOC/Services/MetricsDbFlushService.cs @@ -27,7 +27,7 @@ namespace MP.RIOC.Services protected override async Task ExecuteAsync(CancellationToken stoppingToken) { - var interval = _config.GetValue("RouteMan:MetricFlushIntervalSeconds", 180); + var interval = _config.GetValue("RouteMan:MetricFlushIntervalSeconds", 240); while (!stoppingToken.IsCancellationRequested) { @@ -79,7 +79,7 @@ namespace MP.RIOC.Services DateTime now = DateTime.Now; // Confini temporali per proteggere i dati in corso - DateTime currentDayStart = new DateTime(now.Year, now.Month, now.Day, 0, 0, 0); + DateTime currentDayStart = DateTime.Today; var endpoints = _mux.GetEndPoints(); @@ -110,17 +110,14 @@ namespace MP.RIOC.Services foreach (var statKey in memberKeys) { var sKey = (RedisKey)$"{statKey}"; +#if false if (!TryParseKeyMetadata(sKey, out string dest, out string method, out string machId, out DateTime timestamp, out bool isHourType)) - continue; - - // Verifica se la chiave fosse scaduta rispetto all'orario corrente - bool isExpired = isHourType - //? timestamp < currentHourStart - ? false - : timestamp < currentDayStart; + continue; +#endif + if (!TryParseKeyMetadata(sKey, out var meta) || meta.IsHourType) continue; // Se fosse scaduta e abbiamo il permesso, segnamola per la cancellazione - if (isExpired && deleteConfirmed) + if (meta.Timestamp < currentDayStart && deleteConfirmed) { // 1. Segna la chiave Hash (Dati) per l'eliminazione keysToDelete.Add(sKey); @@ -152,16 +149,23 @@ namespace MP.RIOC.Services if (count <= 0) continue; + // recupero se presente noReply + long noReply = 0; + if (dict.TryGetValue("noReply", out var sNoReply)) + { + noReply = long.Parse(sNoReply); + } + aggrRecordsToInsert.Add(new StatsAggregatedModel { - Destination = dest, - MachineId = machId, - Hour = timestamp, + Destination = meta.Dest, + MachineId = meta.MachId, + Hour = meta.Timestamp, RequestCount = count, AvgDuration = totalMs / count, MinDuration = minMs, MaxDuration = maxMs, - NoReply = 0 + NoReply = noReply }); } } @@ -171,7 +175,7 @@ namespace MP.RIOC.Services } // --- FASE UPSERT DB --- - if (aggrRecordsToInsert.Count > 0) + if (aggrRecordsToInsert.Any()) { await using var scope = _scopeFactory.CreateAsyncScope(); var aggrService = scope.ServiceProvider.GetRequiredService(); @@ -180,7 +184,7 @@ namespace MP.RIOC.Services } // --- FASE PULIZIA REDIS --- - if (deleteConfirmed && keysToDelete.Count > 0) + if (deleteConfirmed && keysToDelete.Any()) { var batch = _db.CreateBatch(); int deletedCount = 0; @@ -239,17 +243,20 @@ namespace MP.RIOC.Services foreach (var statKey in memberKeys) { var sKey = (RedisKey)$"{statKey}"; + if (!TryParseKeyMetadata(sKey, out var meta) || !meta.IsHourType) continue; +#if false if (!TryParseKeyMetadata(sKey, out string dest, out string method, out string machId, out DateTime timestamp, out bool isHourType)) - continue; + continue; // Verifica se la chiave fosse scaduta rispetto all'orario corrente bool isExpired = isHourType ? timestamp < currentHourStart - : false; + : false; //: timestamp < currentDayStart; +#endif // Se fosse scaduta e abbiamo il permesso, segnamola per la cancellazione - if (isExpired && deleteConfirmed) + if (meta.Timestamp < currentHourStart && deleteConfirmed) { // 1. Segna la chiave Hash (Dati) per l'eliminazione keysToDelete.Add(sKey); @@ -280,17 +287,23 @@ namespace MP.RIOC.Services if (maxMs >= SentinelValue) maxMs = SentinelValue; if (count <= 0) continue; + // recupero se presente noReply + long noReply = 0; + if (dict.TryGetValue("noReply", out var sNoReply)) + { + noReply = long.Parse(sNoReply); + } detailRecordsToInsert.Add(new StatsDetailModel { - Destination = dest, - Type = method, - Hour = timestamp, + Destination = meta.Dest, + Type = meta.Method, + Hour = meta.Timestamp, RequestCount = count, AvgDuration = totalMs / count, MinDuration = minMs, MaxDuration = maxMs, - NoReply = 0 + NoReply = noReply }); } } @@ -322,7 +335,35 @@ namespace MP.RIOC.Services Log.Info($"[CLEANUP HOUR] Deleted {deletedCount} expired metric keys from Redis"); } } + private bool TryParseKeyMetadata(RedisKey key, out KeyMeta meta) + { + meta = new KeyMeta(); + try + { + string k = key.ToString(); + string relativeKey = k.Replace($"{_redisBaseKey}:", ""); + var p = relativeKey.Split(':'); + if (p.Length < 4) return false; + meta.IsHourType = p[1].Equals("hour", StringComparison.InvariantCultureIgnoreCase); + meta.Dest = p[2]; + if (meta.IsHourType) + { + meta.Method = p[3]; + if (p.Length >= 5) DateTime.TryParseExact(p[4], "yyyyMMddHH", CultureInfo.InvariantCulture, DateTimeStyles.None, out meta.Timestamp); + } + else + { + meta.Method = "DAILY"; + meta.MachId = p[3]; + if (p.Length >= 5) DateTime.TryParseExact(p[4], "yyyyMMdd", CultureInfo.InvariantCulture, DateTimeStyles.None, out meta.Timestamp); + } + return meta.Timestamp != DateTime.MinValue; + } + catch { return false; } + } + +#if false private bool TryParseKeyMetadata(RedisKey key, out string dest, out string method, out string machId, out DateTime timestamp, out bool isHourType) { dest = "NA"; @@ -374,6 +415,16 @@ namespace MP.RIOC.Services } catch { } return false; + } +#endif + + private record KeyMeta + { + public string Dest = "NA"; + public string Method = "NA"; + public string MachId = "ALL"; + public DateTime Timestamp = DateTime.MinValue; + public bool IsHourType = true; } #endregion Private Methods