Log inner exceptions
This commit is contained in:
parent
d0523439ad
commit
59cdcdad6c
|
|
@ -1,14 +1,21 @@
|
|||
using System;
|
||||
using Elsa.Services.Models;
|
||||
|
||||
namespace Elsa.ActivityResults
|
||||
{
|
||||
public class FaultResult : ActivityExecutionResult
|
||||
{
|
||||
public FaultResult(Exception exception) => Exception = exception;
|
||||
public FaultResult(string message) => Message = message;
|
||||
public string Message { get; set; }
|
||||
public string? StackTrace { get; set; }
|
||||
|
||||
protected override void Execute(ActivityExecutionContext activityExecutionContext) =>
|
||||
activityExecutionContext.WorkflowExecutionContext.Fault(activityExecutionContext.ActivityBlueprint.Id, Message, StackTrace, activityExecutionContext.Input, activityExecutionContext.Resuming);
|
||||
public Exception Exception { get; } = default!;
|
||||
public string Message { get; } = default!;
|
||||
|
||||
protected override void Execute(ActivityExecutionContext activityExecutionContext)
|
||||
{
|
||||
if(Exception != null!)
|
||||
activityExecutionContext.WorkflowExecutionContext.Fault(Exception, activityExecutionContext.ActivityBlueprint.Id, activityExecutionContext.Input, activityExecutionContext.Resuming);
|
||||
else
|
||||
activityExecutionContext.WorkflowExecutionContext.Fault(Message!, activityExecutionContext.ActivityBlueprint.Id, activityExecutionContext.Input, activityExecutionContext.Resuming);
|
||||
}
|
||||
}
|
||||
}
|
||||
20
src/core/Elsa.Abstractions/Models/SimpleException.cs
Normal file
20
src/core/Elsa.Abstractions/Models/SimpleException.cs
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
using System;
|
||||
|
||||
namespace Elsa.Models
|
||||
{
|
||||
public record SimpleException(Type Type, string Message, string StackTrace, SimpleException? InnerException = default)
|
||||
{
|
||||
public static SimpleException? FromException(Exception? ex)
|
||||
{
|
||||
if (ex == null)
|
||||
return null;
|
||||
|
||||
var simpleException = new SimpleException(ex.GetType(), ex.Message, ex.StackTrace);
|
||||
|
||||
if (ex.InnerException != null)
|
||||
simpleException = simpleException with { InnerException = FromException(ex.InnerException) };
|
||||
|
||||
return simpleException;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
namespace Elsa.Models
|
||||
{
|
||||
public record WorkflowFault(string? FaultedActivityId, string? Message, string? StackTrace, object? ActivityInput, bool Resuming);
|
||||
public record WorkflowFault(SimpleException? Exception, string Message, string? FaultedActivityId, object? ActivityInput, bool Resuming);
|
||||
}
|
||||
|
|
@ -46,6 +46,7 @@ namespace Elsa.Services
|
|||
protected ScheduleActivitiesResult Schedule(IEnumerable<ScheduledActivity> activities) => new(activities);
|
||||
protected CombinedResult Combine(IEnumerable<IActivityExecutionResult> results) => new(results);
|
||||
protected CombinedResult Combine(params IActivityExecutionResult[] results) => new(results);
|
||||
protected FaultResult Fault(Exception exception) => new(exception);
|
||||
protected FaultResult Fault(string message) => new(message);
|
||||
|
||||
protected T? GetState<T>([CallerMemberName] string name = null!) => Data.GetState<T>(name);
|
||||
|
|
|
|||
|
|
@ -111,13 +111,15 @@ namespace Elsa.Services.Models
|
|||
public void Begin() => WorkflowInstance.WorkflowStatus = WorkflowStatus.Running;
|
||||
public void Resume() => WorkflowInstance.WorkflowStatus = WorkflowStatus.Running;
|
||||
public void Suspend() => WorkflowInstance.WorkflowStatus = WorkflowStatus.Suspended;
|
||||
|
||||
public void Fault(string? activityId, string? message, string? stackTrace, object? activityInput, bool resuming)
|
||||
public void Fault(Exception ex, string? activityId, object? activityInput, bool resuming) => Fault(ex, ex.Message, activityId, activityInput, resuming);
|
||||
public void Fault(string message, string? activityId, object? activityInput, bool resuming) => Fault(null, message, activityId, activityInput, resuming);
|
||||
|
||||
public void Fault(Exception? exception, string message, string? activityId, object? activityInput, bool resuming)
|
||||
{
|
||||
var clock = ServiceProvider.GetRequiredService<IClock>();
|
||||
WorkflowInstance.WorkflowStatus = WorkflowStatus.Faulted;
|
||||
WorkflowInstance.FaultedAt = clock.GetCurrentInstant();
|
||||
WorkflowInstance.Fault = new WorkflowFault(activityId, message, stackTrace, activityInput, resuming);
|
||||
WorkflowInstance.Fault = new WorkflowFault(SimpleException.FromException(exception), message, activityId, activityInput, resuming);
|
||||
}
|
||||
|
||||
public void Complete() => WorkflowInstance.WorkflowStatus = WorkflowStatus.Finished;
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ using System.Threading;
|
|||
using System.Threading.Tasks;
|
||||
using Elsa.ActivityResults;
|
||||
using Elsa.Attributes;
|
||||
using Elsa.Exceptions;
|
||||
using Elsa.Models;
|
||||
using Elsa.Services;
|
||||
using Elsa.Services.Models;
|
||||
|
|
|
|||
|
|
@ -176,10 +176,10 @@ namespace Elsa.Services
|
|||
var loadContext = new LoadWorkflowContext(workflowExecutionContext);
|
||||
workflowExecutionContext.WorkflowContext = await _workflowContextManager.LoadContext(loadContext, cancellationToken);
|
||||
}
|
||||
|
||||
|
||||
// If the workflow instance has a CurrentActivity, it means the workflow instance is being retried.
|
||||
var currentActivity = workflowInstance.CurrentActivity;
|
||||
|
||||
|
||||
if (currentActivity != null)
|
||||
{
|
||||
activityId = currentActivity.ActivityId;
|
||||
|
|
@ -187,7 +187,7 @@ namespace Elsa.Services
|
|||
}
|
||||
|
||||
var activity = activityId != null ? workflowBlueprint.GetActivity(activityId) : default;
|
||||
|
||||
|
||||
// Give application a chance to prevent workflow from executing.
|
||||
var validateWorkflowExecution = new ValidateWorkflowExecution(workflowExecutionContext, activity);
|
||||
await _mediator.Publish(validateWorkflowExecution, cancellationToken);
|
||||
|
|
@ -309,7 +309,7 @@ namespace Elsa.Services
|
|||
catch (Exception e)
|
||||
{
|
||||
_logger.LogWarning(e, "Failed to run workflow {WorkflowInstanceId}", workflowExecutionContext.WorkflowInstance.Id);
|
||||
workflowExecutionContext.Fault(null, e.Message, e.StackTrace, null, activityOperation == Resume);
|
||||
workflowExecutionContext.Fault(e, null, null, activityOperation == Resume);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -371,7 +371,7 @@ namespace Elsa.Services
|
|||
catch (Exception e)
|
||||
{
|
||||
_logger.LogWarning(e, "Failed to run activity {ActivityId} of workflow {WorkflowInstanceId}", activity.Id, activityExecutionContext.WorkflowInstance.Id);
|
||||
activityExecutionContext.WorkflowExecutionContext.Fault(activity.Id, e.Message, e.StackTrace, activityExecutionContext.Input, activityExecutionContext.Resuming);
|
||||
activityExecutionContext.WorkflowExecutionContext.Fault(e, activity.Id, activityExecutionContext.Input, activityExecutionContext.Resuming);
|
||||
await _mediator.Publish(new ActivityFaulted(e, activityExecutionContext), cancellationToken);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using System.Net;
|
||||
using Elsa.Activities.Console;
|
||||
using Elsa.Activities.Timers;
|
||||
using Elsa.Builders;
|
||||
|
|
@ -13,7 +14,7 @@ namespace Elsa.Samples.Faulting.Workflows
|
|||
builder
|
||||
.StartIn(Duration.FromSeconds(1))
|
||||
.WriteLine("Catch this!")
|
||||
.Then(() => throw new ArithmeticException("Does not compute"));
|
||||
.Then(() => throw new ArithmeticException("Does not compute", new ArgumentException("Incorrect argument", new ArgumentOutOfRangeException("This is the root problem", default(Exception)))));
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue