Is there a global exception handler for NServiceBus?
Asked Answered
L

5

5

The current advice on handling exceptions in NServiceBus is to use the built in facilities. Errored out messages go to the error message queue, and a log is written to disk.

But what if I want to send my errors to a service like AirBrake which has better functionality for grouping similar exceptions, metrics, and other good stuff? Is there a global exception handler I can tap into?

Livvi answered 17/4, 2013 at 19:51 Comment(0)
W
4

As mentioned in the original post the recommended solution is to use ServicePulse for monitoring errors. The client I currently work for is using a custom made centralized logger, and we want NServiceBus to log to this log store when messages are forwarded to the error queue.

We could have achieved this by just editing the log4net config if the exception from NServiceBus had included the original exception, currently NServiceBus just logs a generic error message with no details about what caused the failure.

NServiceBus has a class named NServiceBus.Faults.ErrorsNotifications which contains the following observables:

  • MessageSentToErrorQueue
  • MessageHasFailedAFirstLevelRetryAttempt
  • MessageHasBeenSentToSecondLevelRetries

You can subscribe to these observables when the endpoint starts, like in the following example which logs an error when messages are sent to the error queue:

public class GlobalErrorHandler : IWantToRunWhenBusStartsAndStops
{
    private readonly ILogger _logger;
    private readonly BusNotifications _busNotifications;
    readonly List<IDisposable> _notificationSubscriptions = new List<IDisposable>();

    public GlobalErrorHandler(ILogger logger, BusNotifications busNotifications)
    {
        _logger = logger;
        _busNotifications = busNotifications;
    }

    public void Start()
    {
        _notificationSubscriptions.Add(_busNotifications.Errors.MessageSentToErrorQueue.Subscribe(LogWhenMessageSentToErrorQueue));
    }

    public void Stop()
    {
        foreach (var subscription in _notificationSubscriptions)
        {
            subscription.Dispose();
        }
    }

    private void LogWhenMessageSentToErrorQueue(FailedMessage message)
    {
        var properties = new
        {
            MessageType = message.Headers["NServiceBus.EnclosedMessageTypes"],
            MessageId = message.Headers["NServiceBus.MessageId"],
            OriginatingMachine = message.Headers["NServiceBus.OriginatingMachine"],
            OriginatingEndpoint = message.Headers["NServiceBus.OriginatingEndpoint"],
            ExceptionType = message.Headers["NServiceBus.ExceptionInfo.ExceptionType"],
            ExceptionMessage = message.Headers["NServiceBus.ExceptionInfo.Message"],
            ExceptionSource = message.Headers["NServiceBus.ExceptionInfo.Source"],
            TimeSent = message.Headers["NServiceBus.TimeSent"]
        };

        _logger.Error("Message sent to error queue. " + properties, message.Exception);
    }
}

The observable is implemented by using Reactive Extensions, so you will have to install the NuGet package Rx-Core for this to work.

Woll answered 13/4, 2015 at 8:42 Comment(0)
L
1

Could you maybe use a custom log4net configuration to do it?

http://help.airbrake.io/discussions/suggestions/157-net-plug-in-for-api-v2

Latium answered 18/4, 2013 at 11:35 Comment(0)
Z
1

There is an interface in NServiceBus called IManageMessageFailures, but I don't believe you can use it in conjucntion with the Second Level Retries so you would probably lose that if you did go for your own.

You could write the errors to SQL Server with log4net and the from there you could forward them to AirBrake using their API marking each error in the error table as sent afterwards maybe?

Zealand answered 18/4, 2013 at 13:22 Comment(1)
That really sucks if you can't use it with second level retries. Thanks, though!Livvi
L
1

I would suggest that you create a custom endpoint that feeds off the error queue and uploads the data to AirBrake.

Side note: v4.0|4.1 will come with a nice Rest-Api that gives you nice management/querying capabilities for the errors. Tools like the Profiler and Ops will use this api to present the data to you in various ways.

http://particular.net/service-platform

Lydell answered 18/4, 2013 at 15:38 Comment(1)
This question/answer is kinda old, but I've since learned that the reason this doesn't exist as a global handler is because each failure should be considered in the context of the business requirements.Livvi
A
1

We switched to Serilog, it has perfect logging ans tracing support for NServiceBus. Creating a custom Serilog sink that will send your log events wherever you want is quite easy.

Acetylene answered 14/4, 2015 at 13:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.