public static ICustomOperationSpanBuilder BeginConsumerCustomOperationSpan(this ITracer tracer, string operationName) { var spanBuilder = tracer.BeginCustomOperationSpan(operationName); spanBuilder.SetOperationStatus(null, WellKnownStatuses.Success); spanBuilder.SetAnnotation(WellKnownAnnotations.Common.Component, "Hercules.Consumers"); return(spanBuilder); }
private async Task ExecutePayloadAsync(DateTimeOffset executionTime, IScheduler scheduler, CancellationToken token) { if (token.IsCancellationRequested) { return; } var nextExecution = GetNextExecutionTime(executionTime).time; var timeBudget = nextExecution.HasValue ? TimeBudget.StartNew(TimeSpanArithmetics.Max(TimeSpan.Zero, nextExecution.Value - executionTime)) : TimeBudget.Infinite; var context = new ScheduledActionContext(executionTime, timeBudget, scheduler, token); if (!(scheduler is PeriodicalWithConstantPauseScheduler)) { log.Info("Executing with time budget = {TimeBudget}.", timeBudget.Total.ToPrettyString()); } else { log.Info("Executing.."); } async Task ExecutePayload() { monitor.OnIterationStarted(); var span = tracer.BeginCustomOperationSpan(action.Name); try { var watch = Stopwatch.StartNew(); await action.Payload(context); watch.Stop(); log.Info( "Executed in {ExecutionTime}.", new { ExecutionTime = watch.Elapsed.ToPrettyString(), ExecutionTimeMs = watch.Elapsed.TotalMilliseconds }); if (watch.Elapsed > timeBudget.Total && !(scheduler is PeriodicalWithConstantPauseScheduler)) { log.Warn("Execution did not fit into the time budget before the next planned execution."); } action.Scheduler.OnSuccessfulIteration(scheduler); span.SetOperationStatus(null, WellKnownStatuses.Success); monitor.OnIterationSucceeded(); } catch (Exception error) { action.Scheduler.OnFailedIteration(scheduler, error); span.SetOperationStatus(null, WellKnownStatuses.Error); monitor.OnIterationFailed(error); if (action.Options.CrashOnPayloadException || error is OperationCanceledException) { throw; } log.Error(error, "Scheduled action threw an exception."); } finally { span.Dispose(); monitor.OnIterationCompleted(); } } var payloadTask = action.Options.PreferSeparateThread ? Task.Factory.StartNew(ExecutePayload, TaskCreationOptions.LongRunning) : Task.Run(ExecutePayload); if (action.Options.AllowOverlappingExecution) { return; } await payloadTask; }