private void ProcessException(WorkflowErrorEventArgs args, WorkflowRuntime runtime) { if (!String.IsNullOrEmpty(args.ProcessInstance.ExecutedTimer)) { Log.Error($"Exception::: Timer: {args.Exception.Message}"); args.ProcessStatus = ProcessStatus.Idled; } else { Log.Error($"Exception::: Command: {args.Exception.Message}"); runtime.SetActivityWithExecution( identityId: null, impersonatedIdentityId: null, parameters: new Dictionary <string, object>(), activityToSet: args.ProcessInstance.ProcessScheme.InitialActivity, processInstance: args.ProcessInstance, doNotSetRunningStatus: true ); } }
private void ProcessException(WorkflowErrorEventArgs args, WorkflowRuntime runtime) { // Follow recommendation // https://workflowengine.io/documentation/scheme/timers/ var isTimerTriggeredTransitionChain = !string.IsNullOrEmpty(args.ProcessInstance.ExecutedTimer) || //for timers executed from main branch (args.ProcessInstance.MergedSubprocessParameters != null && //for timers executed from subprocess !string.IsNullOrEmpty(args.ProcessInstance.MergedSubprocessParameters.GetParameter(DefaultDefinitions.ParameterExecutedTimer.Name)?.Value?.ToString())); // We have to delay creation of the Bugsnag Client until runtime instead // of constructor dependency injection due to crashing on startup using (var scope = ServiceProvider.CreateScope()) { var client = scope.ServiceProvider.GetRequiredService <Bugsnag.IClient>(); client.Notify(args.Exception, (report) => { report.Event.Metadata.Add("details", new Dictionary <string, object> { { "handler", "OnWorkflowError" }, { "timer", isTimerTriggeredTransitionChain }, { "process-id", args.ProcessInstance.ProcessId }, { "schema-code", args.ProcessInstance.SchemeCode }, { "schema-id", args.ProcessInstance.SchemeId } }); if (args.Exception is ResponseException responseException) { var contentType = new ContentType(responseException.ContentType); var charset = contentType.CharSet ?? "UTF-8"; var encoding = Encoding.GetEncoding(charset); var content = encoding.GetString(responseException.RawBytes, 0, responseException.RawBytes.Length); report.Event.Metadata.Add("response", new Dictionary <string, object> { { "content", content }, { "content-length", responseException.ContentLength }, { "content-type", responseException.ContentType } }); } }); } if (isTimerTriggeredTransitionChain) { Log.Error($"Exception::: Timer: {args.Exception.Message}"); args.SuppressThrow = true; } else { Log.Error($"Exception::: Command: {args.Exception.Message}"); runtime.SetActivityWithExecution( identityId: null, impersonatedIdentityId: null, parameters: new Dictionary <string, object>(), activityToSet: args.ProcessInstance.ProcessScheme.InitialActivity, processInstance: args.ProcessInstance, doNotSetRunningStatus: true ); } }