Base solution for your next web application
Open Closed

Exception handling domain event (AbpHandledExceptionData) not working for background jobs #11811


User avatar
0
ITWebTeam created

We are implementing custom exception handling for our project. We've implemented IAsyncEventHandler<AbpHandledExceptionData> for AppServices and IAsyncExceptionFilter for Controllers and everything works fine, these areas are covered.

We also have a lot of IAsyncEventHandler governed by hangfire for different background events. The problem is that if an exception occurs inside HandleEventAsync, neither handler nor filter get triggered.

Is there any way to handle these exceptions?

We have tried following (nothing worked):

  • creating custom ExceptionFilterAttribute and attaching it to the instance of IAsyncExceptionFilter, attribute never gets called.
  • monitoring AbpHandledExceptionData, never gets called.
  • monitoring EntityCreatedEventData<AuditLog> doesn't work because audit log is not written in this case.
  • monitoring EntityCreatedEventData<SqlJob> doesn't work because Hangfire.SqlJob is not public like audit log.
  • using custom logger for hangfire doesn't do anything, the logger never gets called:

Startup:

                services.AddHangfire(config =>
                {
                    config.UseSqlServerStorage(_appConfiguration.GetConnectionString("Default"));
                    config.UseFilter(new AutomaticRetryAttribute 
                    { 
                        Attempts = 2,
                        OnAttemptsExceeded = AttemptsExceededAction.Fail,
                        LogEvents = true,
                    });
                    config.UseLogProvider(new CustomLog4NetLogProvider()); // doesn't work
                });

Custom logger:

    public class CustomLog4NetLogProvider : Log4NetLogProvider
    {
        public new ILog GetLogger(string name)
        {
            return new CustomLog4NetLogger(base.GetLogger(name));
        }
    }
    public class CustomLog4NetLogger : ILog
    {
        private readonly ILog _baseLogger;
        public CustomLog4NetLogger(ILog baseLogger)
        {
            _baseLogger = baseLogger;
        }
        public bool Log(LogLevel logLevel, Func<string> messageFunc, Exception exception = null)
        {
            // do something
            return _baseLogger.Log(logLevel, messageFunc, exception);
        }
    }

6 Answer(s)
  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi @ITWebTeam

    IAsyncEventHandler is mostly used to handle domain events, do you trigger an event when you catch an exception ? IAsyncEventHandler can be used in the same way for background jobs. If you can share the code blocks for;

    1. trowing the exception
    2. handling the exception in IAsyncEventHandler we can take a look at this.
  • User Avatar
    0
    ITWebTeam created

    Hi @ismcagdas and thank you for the reply.

    In most cases we don't catch the exceptions, we rely on the framework to handle this for us. In the case of background jobs we are depending on the exceptions details getting logged to the Audit log. We are trying to add functionality to send a notification whenever an exception is thrown. However, we are not receiving any events through AbpHandledExceptionData for background jobs wo no notifications are being sent nor are they logged in the audit log. It works for everything else. Below is an example of the workflow.

    Enqueueing event:

                // _backgroundJobManager is IBackgroundJobManager injected into an AppService's constructor.
                await _backgroundJobManager.EnqueueEventAsync(new ProductFieldApprovedEventData
                {
                    // properties
                });
    

    Handling event and throwing the exception inside:

        public class WebhookPublishProductFieldApproved : ISingletonDependency, IAsyncEventHandler<ProductFieldApprovedEventData>
        {
            // other dependencies
            public async Task HandleEventAsync(ProductFieldApprovedEventData eventData)
            {
                throw new System.Exception("test from background job"); // cannot catch this later using handlers
                // actual logic for this event's handling
            }
        }
    

    Handling the exception event:

        public class ExceptionWebhookEventHandler : ISingletonDependency, IAsyncEventHandler<AbpHandledExceptionData>
        {
            // other dependencies
            public async Task HandleEventAsync(AbpHandledExceptionData eventData)
            {
                // handling logic using eventData.Exception
            }
        }
    
  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi,

    Thanks. Could you also share ProductFieldApprovedEventData or where it throws the exception ?

  • User Avatar
    0
    ITWebTeam created

    Hi,

    You can see in the prior example we are throwing a test exception in the WebhookPublishProductFieldApprovedclass which throws this:

    throw new System.Exception("test from background job");
    

    It runs in the background. We want to handle any exception that are thrown in the background.

    Below is the ProductFieldApprovedEventData class

    public class ProductFieldApprovedEventData : WebhookEventData
        {
            public int ProductId { get; set; }
            public int ProductDetailId { get; set; }
        }
        
    public class WebhookEventData : EventData
        {
            public SchemaTypeEnum SchemaType { get; set; }
        }
    

    Thank you

  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi @ITWebTeam

    Thanks, @oguzhanagir is working on this problem and will inform you.

  • User Avatar
    0
    oguzhanagir created
    Support Team

    Hi @ITwebTeam,

    When we tested the parts you shared with us, we didn't encounter the specified problem. You can share the project with us so we can help you more. You can send the project to [email protected].