using System.Diagnostics; using MesETL.App.Const; using MesETL.App.Services; using MesETL.App.Services.Loggers; using Microsoft.Extensions.DependencyInjection; namespace MesETL.App.HostedServices; /// /// 任务监控 /// public class TaskMonitorService { private readonly IEnumerable _monitorLoggers; private readonly ProcessContext _context; private readonly DataRecordQueue _producerQueue; private readonly RecordQueuePool _queuePool; public TaskMonitorService(ProcessContext context, [FromKeyedServices(ProcessStep.Produce)] DataRecordQueue producerQueue, RecordQueuePool queuePool, IEnumerable monitorLoggers) { _context = context; _producerQueue = producerQueue; _queuePool = queuePool; _monitorLoggers = monitorLoggers; } public async Task Monitor(CancellationToken stoppingToken) { var sw = Stopwatch.StartNew(); var lastTime = sw.ElapsedMilliseconds; var lastInputCount = _context.InputCount; var lastTransformCount = _context.TransformCount; var lastOutputCount = _context.OutputCount; bool endCheck = false; while (!stoppingToken.IsCancellationRequested) { EndCheck: // var running = 0; // var error = 0; // var completed = 0; // var canceled = 0; // foreach (var task in _taskManager.Tasks) // { // switch (task.Status) // { // case TaskStatus.Canceled: // canceled++; // break; // case TaskStatus.Faulted: // error++; // break; // case TaskStatus.RanToCompletion: // completed++; // break; // default: // running++; // break; // } // } var time = sw.ElapsedMilliseconds; var inputCount = _context.InputCount; var transformCount = _context.TransformCount; var outputCount = _context.OutputCount; var elapseTime = (time - lastTime) / 1000f; var inputSpeed = (inputCount - lastInputCount) / elapseTime; var transformSpeed = (transformCount - lastTransformCount) / elapseTime; var outputSpeed = (outputCount - lastOutputCount) / elapseTime; // _logger.LogInformation( // "Task monitor: running: {Running}, error: {Error}, completed: {Completed}, canceled: {Canceled}, outputSpeed: {Speed} records/s", // running, error, completed, canceled, outputSpeed); foreach (var logger in _monitorLoggers) { logger.LogStatus("Monitor: Progress status", new Dictionary { {"Input",_context.IsInputCompleted ? "completed" : $"running {inputSpeed:F2} records/s" }, {"Transform", _context.IsTransformCompleted ? "completed" : $"running {transformSpeed:F2} records/s" }, {"Output", _context.IsOutputCompleted ? "completed" : $"running {outputSpeed:F2} records/s" } }); logger.LogStatus("Monitor: Table output progress", _context.TableProgress .ToDictionary(kv => kv.Key, kv => kv.Value.ToString()), ITaskMonitorLogger.LogLevel.Progress); logger.LogStatus("Monitor: Process count", new Dictionary { {"Input", inputCount.ToString()}, {"Transform", transformCount.ToString()}, {"Output", outputCount.ToString()} }, ITaskMonitorLogger.LogLevel.Progress); logger.LogStatus("Monitor: Queue", new Dictionary { {"Producer queue records", _producerQueue.Count.ToString() }, {"Output queues", _queuePool.Queues.Count.ToString() }, {"Output queue records", _queuePool.Queues.Values.Sum(queue => queue.Count).ToString()}, }); } await Task.Delay(5000, stoppingToken); lastTime = time; lastInputCount = inputCount; lastTransformCount = transformCount; lastOutputCount = outputCount; if (_context is { IsInputCompleted: true, IsTransformCompleted: true, IsOutputCompleted: true }) { if (!endCheck) { endCheck = true; goto EndCheck; } break; } } } }