Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a global exception handler for NServiceBus?

Tags:

nservicebus

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?

like image 386
Josh Kodroff Avatar asked Apr 17 '13 19:04

Josh Kodroff


People also ask

How many global exception handlers are there?

Only one Global Exception Handler can be set per automation project.

How do you handle exceptions globally?

The Controller Advice class to handle the exception globally is given below. We can define any Exception Handler methods in this class file. The Product Service API controller file is given below to update the Product. If the Product is not found, then it throws the ProductNotFoundException class.

What is Nservicebus endpoint?

An endpoint is a logical component that communicates with other components using messages. Each endpoint has an identifying name, contains a collection of message handlers and/or sagas, and is deployed to a given environment (e.g. development, testing, production).

What does an exception handler do?

An exception handler is code that stipulates what a program will do when an anomalous event disrupts the normal flow of that program's instructions. An exception, in a computer context, is an unplanned event that occurs while a program is executing and disrupts the flow of its instructions.


2 Answers

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

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

like image 34
mackie Avatar answered Sep 19 '22 14:09

mackie


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.

like image 113
sverrehundeide Avatar answered Sep 22 '22 14:09

sverrehundeide