Logging errors in NServiceBus

NServiceBus logs a generic error message when a message is sent to the error queue, and a generic warning message is logged when a message is sent to first level retry. The problem is that these log messages don’t contain the original exception messages and stack traces. However, the exception details are stored in the message header data, but it may be cumbersome to inspect the message headers instead of just viewing the exception in the log output.

The recommended solution to this issue from Particular Software is to use ServicePulse for health monitoring. 

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.

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.

Etiketter: