MES-ETL/MesETL.App/HostedServices/TaskMonitorService.cs

127 lines
4.9 KiB
C#

using System.Diagnostics;
using MesETL.App.Const;
using MesETL.App.Services;
using MesETL.App.Services.Loggers;
using Microsoft.Extensions.DependencyInjection;
namespace MesETL.App.HostedServices;
/// <summary>
/// 任务监控
/// </summary>
public class TaskMonitorService
{
private readonly IEnumerable<ITaskMonitorLogger> _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<ITaskMonitorLogger> 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<string, string>
{
{"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<string, string>
{
{"Input", inputCount.ToString()},
{"Transform", transformCount.ToString()},
{"Output", outputCount.ToString()}
}, ITaskMonitorLogger.LogLevel.Progress);
logger.LogStatus("Monitor: Queue", new Dictionary<string, string>
{
{"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;
}
}
}
}