C# --- 使用定时任务实现日志的定时聚合
C# --- 使用定时任务实现日志的定时聚合
- Background
- Solution
Background
在项目中需要统计一个服务的资源使用情况,同时为了减少产生过多的日志,需要每十分钟根据指定字段进行聚合
Solution
Solution: 实现一个接口
public interface IOperationTracker
{void InitializeTracking(CancellationToken cancellationToken);void RecordOperationMetrics(ContextBase context, string operationCategory, RequestMetadata requestMetadata);void FlushMetricsData(object? state)
}
public class OperationTracker : IOperationTracker
{private ConcurrentDictionary<string, OperationMetrics> _metricsCache = new();private readonly ILogger<OperationTracker> _logger;private Timer _timer;public OperationTracker(ILogger<OperationTracker> logger){_logger = logger;}public void InitializeTracking(CancellationToken cancellationToken){_timer = new Timer(FlushMetricsData, null, TimeSpan.Zero,TimeSpan.FromMinutes(Constants.MetricsFlushInterval));}public void RecordOperationMetrics(ContextBase context, string operationCategory,RequestMetadata requestMetadata){var tokenHandler = new JwtSecurityTokenHandler();try{var jsonToken = (JwtSecurityToken)tokenHandler.ReadToken(context.Token.Parameter);var userIdentifier = jsonToken?.Claims?.FirstOrDefault(claim => claim.Type == "email")?.Value;var metrics = new OperationMetrics(){UserIdentifier = userIdentifier,ResourceId = requestMetadata.ResourceId,PartitionIdentifier = context.PartitionId,SourceIdentifier = requestMetadata.SourceId,ProcessId = requestMetadata.ProcessId,Timestamp = DateTime.Now,OperationCategory = operationCategory,WriteCount = context.OperationStats.WriteOperations,WriteVolume = context.OperationStats.WriteBytes,ReadCount = context.OperationStats.ReadOperations,ReadVolume = context.OperationStats.ReadBytes,};CacheMetricsData(metrics);}catch (Exception ex){_logger.Error($"Failed to record operation metrics: {ex.Message}");}}public void FlushMetricsData(object? state){var metricsData = _metricsCache.Values.ToList();_metricsCache = new();metricsData.ForEach(metric =>{var logData = metric.ToLogFormat();_logger.Track("OperationMetricsService",metric.WriteVolume + metric.ReadVolume, 0, logData);});}private void CacheMetricsData(OperationMetrics operationMetrics){var cacheKey = operationMetrics.ToString();if (_metricsCache.TryGetValue(cacheKey, out var cachedMetrics)){cachedMetrics.AggregateMetrics(operationMetrics);}else{_metricsCache.TryAdd(cacheKey, operationMetrics);}}
}
启动定时任务:
注入实现
service.AddSingleton<IResourceMonitor, ResourceMonitor>();
app初始化时启动
var monitoringService = serviceProvider.GetRequiredService<IResourceMonitor>()
monitoringService.StartMonitoringTask(CancellationToken.None)