Files
git.stella-ops.org/src/StellaOps.Scanner.Worker/Processing/ScanProgressReporter.cs
master daa6a4ae8c
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
Build Test Deploy / build-test (push) Has been cancelled
Build Test Deploy / authority-container (push) Has been cancelled
Build Test Deploy / docs (push) Has been cancelled
Build Test Deploy / deploy (push) Has been cancelled
up
2025-10-19 10:38:55 +03:00

87 lines
3.5 KiB
C#

using System;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using StellaOps.Scanner.Worker.Diagnostics;
namespace StellaOps.Scanner.Worker.Processing;
public sealed partial class ScanProgressReporter
{
private readonly ScannerWorkerMetrics _metrics;
private readonly ILogger<ScanProgressReporter> _logger;
public ScanProgressReporter(ScannerWorkerMetrics metrics, ILogger<ScanProgressReporter> logger)
{
_metrics = metrics ?? throw new ArgumentNullException(nameof(metrics));
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
}
public async ValueTask ExecuteStageAsync(
ScanJobContext context,
string stageName,
Func<ScanJobContext, CancellationToken, ValueTask> stageWork,
CancellationToken cancellationToken)
{
ArgumentNullException.ThrowIfNull(context);
ArgumentException.ThrowIfNullOrWhiteSpace(stageName);
ArgumentNullException.ThrowIfNull(stageWork);
StageStarting(_logger, context.JobId, context.ScanId, stageName, context.Lease.Attempt);
var start = context.TimeProvider.GetUtcNow();
using var activity = ScannerWorkerInstrumentation.ActivitySource.StartActivity(
$"scanner.worker.{stageName}",
ActivityKind.Internal);
activity?.SetTag("scanner.worker.job_id", context.JobId);
activity?.SetTag("scanner.worker.scan_id", context.ScanId);
activity?.SetTag("scanner.worker.stage", stageName);
try
{
await stageWork(context, cancellationToken).ConfigureAwait(false);
var duration = context.TimeProvider.GetUtcNow() - start;
_metrics.RecordStageDuration(context, stageName, duration);
StageCompleted(_logger, context.JobId, context.ScanId, stageName, duration.TotalMilliseconds);
}
catch (OperationCanceledException) when (cancellationToken.IsCancellationRequested)
{
StageCancelled(_logger, context.JobId, context.ScanId, stageName);
throw;
}
catch (Exception ex)
{
var duration = context.TimeProvider.GetUtcNow() - start;
_metrics.RecordStageDuration(context, stageName, duration);
StageFailed(_logger, context.JobId, context.ScanId, stageName, ex);
throw;
}
}
[LoggerMessage(
EventId = 1000,
Level = LogLevel.Information,
Message = "Job {JobId} (scan {ScanId}) entering stage {Stage} (attempt {Attempt}).")]
private static partial void StageStarting(ILogger logger, string jobId, string scanId, string stage, int attempt);
[LoggerMessage(
EventId = 1001,
Level = LogLevel.Information,
Message = "Job {JobId} (scan {ScanId}) finished stage {Stage} in {ElapsedMs:F0} ms.")]
private static partial void StageCompleted(ILogger logger, string jobId, string scanId, string stage, double elapsedMs);
[LoggerMessage(
EventId = 1002,
Level = LogLevel.Warning,
Message = "Job {JobId} (scan {ScanId}) stage {Stage} cancelled by request.")]
private static partial void StageCancelled(ILogger logger, string jobId, string scanId, string stage);
[LoggerMessage(
EventId = 1003,
Level = LogLevel.Error,
Message = "Job {JobId} (scan {ScanId}) stage {Stage} failed.")]
private static partial void StageFailed(ILogger logger, string jobId, string scanId, string stage, Exception exception);
}