78 lines
3.4 KiB
C#
78 lines
3.4 KiB
C#
using Microsoft.Extensions.Hosting;
|
|
using Microsoft.Extensions.Logging;
|
|
|
|
namespace Monitor.Backend.Application;
|
|
|
|
/// <summary>保留清理:原始段文件(持续任务与按需测试保留期不同)、各层指标、事件。保留期来自 settings,可以在线修改。</summary>
|
|
public sealed partial class RetentionService : BackgroundService
|
|
{
|
|
private static readonly TimeSpan s_interval = TimeSpan.FromHours(1);
|
|
|
|
private readonly IRawStore _raw;
|
|
private readonly IMetricStore _metrics;
|
|
private readonly IEventStore _events;
|
|
private readonly IAuthStore _auth;
|
|
private readonly IHostStore _hosts;
|
|
private readonly SettingsService _settings;
|
|
private readonly LoginRateLimiter _limiter;
|
|
private readonly TimeProvider _time;
|
|
private readonly ILogger<RetentionService> _logger;
|
|
|
|
public RetentionService(IRawStore raw, IMetricStore metrics, IEventStore events, IHostStore hosts, IAuthStore auth, SettingsService settings, LoginRateLimiter limiter, TimeProvider time, ILogger<RetentionService> logger)
|
|
{
|
|
_raw = raw;
|
|
_metrics = metrics;
|
|
_events = events;
|
|
_hosts = hosts;
|
|
_auth = auth;
|
|
_settings = settings;
|
|
_limiter = limiter;
|
|
_time = time;
|
|
_logger = logger;
|
|
}
|
|
|
|
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
|
|
{
|
|
while (!stoppingToken.IsCancellationRequested)
|
|
{
|
|
try
|
|
{
|
|
await RunOnceAsync(stoppingToken);
|
|
await Task.Delay(s_interval, _time, stoppingToken);
|
|
}
|
|
catch (OperationCanceledException) when (stoppingToken.IsCancellationRequested)
|
|
{
|
|
return;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
// 后台循环不能因为一次失败而退出
|
|
LogFailed(ex);
|
|
await Task.Delay(TimeSpan.FromMinutes(5), _time, stoppingToken);
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>执行一轮清理(也供测试直接调用)。</summary>
|
|
public async Task RunOnceAsync(CancellationToken ct)
|
|
{
|
|
DateTimeOffset now = _time.GetUtcNow();
|
|
long nowMs = now.ToUnixTimeMilliseconds();
|
|
DateOnly today = DateOnly.FromDateTime(now.UtcDateTime);
|
|
int rawDays = await _settings.GetIntAsync(SettingsService.RawDays, ct);
|
|
int testDays = await _settings.GetIntAsync(SettingsService.TestRawDays, ct);
|
|
|
|
await _raw.DeleteExpiredAsync(today.AddDays(-rawDays), today.AddDays(-testDays), ct);
|
|
await _metrics.DeleteOlderThanAsync(MetricLevel.S10, nowMs - (await _settings.GetIntAsync(SettingsService.Metric10sHours, ct) * Steps.Hour), ct);
|
|
await _metrics.DeleteOlderThanAsync(MetricLevel.M1, nowMs - (await _settings.GetIntAsync(SettingsService.Metric1mDays, ct) * Steps.Day), ct);
|
|
await _metrics.DeleteOlderThanAsync(MetricLevel.M5, nowMs - (await _settings.GetIntAsync(SettingsService.Metric5mDays, ct) * Steps.Day), ct);
|
|
await _events.DeleteOlderThanAsync(nowMs - (await _settings.GetIntAsync(SettingsService.EventDays, ct) * Steps.Day), ct);
|
|
await _hosts.DeleteOlderThanAsync(nowMs - (await _settings.GetIntAsync(SettingsService.HostDays, ct) * Steps.Day), ct);
|
|
await _auth.DeleteExpiredSessionsAsync(nowMs, ct);
|
|
_limiter.Prune();
|
|
}
|
|
|
|
[LoggerMessage(Level = LogLevel.Error, Message = "retention pass failed")]
|
|
private partial void LogFailed(Exception exception);
|
|
}
|