Files
watcher/Watcher/Services/MetricCleanupService.cs
2025-11-05 21:15:10 +01:00

128 lines
4.4 KiB
C#

using Microsoft.EntityFrameworkCore;
using Watcher.Data;
namespace Watcher.Services;
public class MetricCleanupService : BackgroundService
{
private readonly ILogger<MetricCleanupService> _logger;
private readonly IServiceProvider _serviceProvider;
private readonly int _retentionDays;
private readonly int _checkIntervalHours;
private readonly bool _enabled;
public MetricCleanupService(
ILogger<MetricCleanupService> logger,
IServiceProvider serviceProvider,
IConfiguration configuration)
{
_logger = logger;
_serviceProvider = serviceProvider;
// Konfiguration aus Environment Variablen laden
_retentionDays = int.TryParse(
configuration["DataRetention:MetricRetentionDays"] ??
Environment.GetEnvironmentVariable("METRIC_RETENTION_DAYS"),
out var days) ? days : 30; // Default: 30 Tage
_checkIntervalHours = int.TryParse(
configuration["DataRetention:CleanupIntervalHours"] ??
Environment.GetEnvironmentVariable("METRIC_CLEANUP_INTERVAL_HOURS"),
out var hours) ? hours : 24; // Default: 24 Stunden
_enabled = bool.TryParse(
configuration["DataRetention:Enabled"] ??
Environment.GetEnvironmentVariable("METRIC_CLEANUP_ENABLED"),
out var enabled) ? enabled : true; // Default: aktiviert
_logger.LogInformation(
"MetricCleanupService konfiguriert: Enabled={Enabled}, RetentionDays={Days}, IntervalHours={Hours}",
_enabled, _retentionDays, _checkIntervalHours);
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
if (!_enabled)
{
_logger.LogInformation("MetricCleanupService ist deaktiviert.");
return;
}
// Warte 1 Minute nach Start, bevor der erste Cleanup läuft
await Task.Delay(TimeSpan.FromMinutes(1), stoppingToken);
var timer = new PeriodicTimer(TimeSpan.FromHours(_checkIntervalHours));
while (await timer.WaitForNextTickAsync(stoppingToken))
{
try
{
await CleanupOldMetricsAsync();
}
catch (Exception ex)
{
_logger.LogError(ex, "Fehler beim Cleanup alter Metriken.");
}
// Offset nach Cleanup
await Task.Delay(TimeSpan.FromSeconds(10), stoppingToken);
}
}
private async Task CleanupOldMetricsAsync()
{
_logger.LogInformation("Starte Metric Cleanup für Daten älter als {Days} Tage...", _retentionDays);
using var scope = _serviceProvider.CreateScope();
var context = scope.ServiceProvider.GetRequiredService<AppDbContext>();
var cutoffDate = DateTime.UtcNow.AddDays(-_retentionDays);
try
{
// Anzahl der zu löschenden Einträge ermitteln
var countToDelete = await context.Metrics
.Where(m => m.Timestamp < cutoffDate)
.CountAsync();
if (countToDelete == 0)
{
_logger.LogInformation("Keine alten Metriken zum Löschen gefunden.");
return;
}
_logger.LogInformation("Lösche {Count} Metriken vor {Date}...", countToDelete, cutoffDate);
// Metriken löschen
var deletedCount = await context.Metrics
.Where(m => m.Timestamp < cutoffDate)
.ExecuteDeleteAsync();
_logger.LogInformation(
"Metric Cleanup abgeschlossen: {DeletedCount} Einträge gelöscht.",
deletedCount);
// Optional: ContainerMetrics auch bereinigen
var containerMetricsCount = await context.ContainerMetrics
.Where(cm => cm.Timestamp < cutoffDate)
.CountAsync();
if (containerMetricsCount > 0)
{
var deletedContainerMetrics = await context.ContainerMetrics
.Where(cm => cm.Timestamp < cutoffDate)
.ExecuteDeleteAsync();
_logger.LogInformation(
"ContainerMetrics Cleanup: {DeletedCount} Einträge gelöscht.",
deletedContainerMetrics);
}
}
catch (Exception ex)
{
_logger.LogError(ex, "Fehler beim Löschen alter Metriken aus der Datenbank.");
throw;
}
}
}