Getting Started
Architecture
NServiceBus
Transports
Persistence
ServiceInsight
ServicePulse
ServiceControl
Monitoring
Samples

Notifications

Component: NServiceBus
NuGet Package: NServiceBus (9.x)

Introduction

This sample shows how to use the recoverability error notifications to capture the following:

Custom Settings in this sample

This sample uses several non-standard settings.

Logging

All errors below Fatal are suppressed to reduce the noise related to raising multiple exceptions

var defaultFactory = LogManager.Use<DefaultFactory>();
defaultFactory.Level(LogLevel.Fatal);

Delayed Retry Time increase

The time to increase changed to 1 second so the wait for all retries to occur is reduced.

var recoverability = endpointConfiguration.Recoverability();
recoverability.Delayed(
    customizations: delayed =>
    {
        delayed.TimeIncrease(TimeSpan.FromSeconds(1));
    });

Plugging into the API

The notifications API is exposed as follows.

var endpointConfiguration = new EndpointConfiguration("Samples.Notifications");
SubscribeToNotifications.Subscribe(endpointConfiguration);
public static class SubscribeToNotifications
{
    static ILog log = LogManager.GetLogger(typeof(SubscribeToNotifications));

    public static void Subscribe(EndpointConfiguration endpointConfiguration)
    {
        var recoverability = endpointConfiguration.Recoverability();
        recoverability.Immediate(settings => settings.OnMessageBeingRetried(Log));
        recoverability.Delayed(settings => settings.OnMessageBeingRetried(Log));
        recoverability.Failed(settings => settings.OnMessageSentToErrorQueue(Log));
    }

    static string GetMessageString(ReadOnlyMemory<byte> body)
    {
        return Encoding.UTF8.GetString(body.ToArray());
    }

    static Task Log(FailedMessage failed, CancellationToken cancellationToken)
    {
        log.Fatal($@"Message sent to error queue.
        Body:
        {GetMessageString(failed.Body)}");
        return Task.CompletedTask;
    }

    static Task Log(DelayedRetryMessage retry, CancellationToken cancellationToken)
    {
        log.Fatal($@"Message sent to Delayed Retries.
        RetryAttempt:{retry.RetryAttempt}
        Body:
        {GetMessageString(retry.Body)}");
        return Task.CompletedTask;
    }

    static Task Log(ImmediateRetryMessage retry, CancellationToken cancellationToken)
    {
        log.Fatal($@"Message sent to Immediate Retry.
        RetryAttempt:{retry.RetryAttempt}
        Body:
        {GetMessageString(retry.Body)}");
        return Task.CompletedTask;
    }
}

Notifications are manipulated at configuration time.

Notifications are executed on the same thread as the NServiceBus pipeline. If long running work needs to be done it should be executed on another thread otherwise the message processing performance can be impacted.

Message Body

Since the message could have failed due to a deserialization exception, it is not possible for the API to provide the instance of the message. For the same reason is it recommended that consumers of this API do not attempt to deserialize the message instance. If the message contents are required for debugging purposes, convert the message body to a string using the .NET Encoding APIs.

Related Articles

  • Recoverability
    Explains how exceptions are handled, and actions retried, during message processing.