arcus-azure/arcus.messaging

Add message correlation to Azure Service Bus client

Closed this issue · 1 comments

Is your feature request related to a problem? Please describe.
Currently, users are responsible for their own creation of the Service Bus message, setting the correct correlation information, and placing that information in the tracking of the a Service Bus dependency.
Just like we helped with the HTTP tracking, we could do better and register our own wrapper for the Azure client which takes care of correlation under the hood.

Describe the solution you'd like
Create an extension for the AddServiceBusClient which creates a new client with message correlation.

Additional context
https://docs.microsoft.com/en-us/dotnet/api/overview/azure/microsoft.extensions.azure-readme-pre

Doesn't seem like there's a way to introduce message correlation tracking in the said extension bc the client/sender is not available for extension (either internal or not available in the constructor while building the client/sender).

An option would be to introduce extensions on the ServiceBusSender (like we did on the HttpClient).

public static class ServiceBusSenderExtensions
{
        public static async Task SendMessagesAsync(
            this ServiceBusSender sender, 
            IEnumerable<ServiceBusMessage> messages, 
            MessageCorrelationInfo correlationInfo,
            Action<ServiceBusSenderMessageCorrelationOptions> configureOptions,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            var options = new ServiceBusSenderMessageCorrelationOptions();
            configureOptions?.Invoke(options);

            AddMessageCorrelationProperties(messages, options, correlationInfo);
            bool isSuccessful = false;           

            using (var measurement = DurationMeasurement.Start())
            {
                try
                {
                    await sender.SendMessagesAsync(messages, cancellationToken);
                    isSuccessful = true;
                }
               finally
               {
                   _logger.LogServiceBusDependency(...);
               }
            }
        }

        private static void AddMessageCorrelationProperties(
            IEnumerable<ServiceBusMessage> messages, 
            ServiceBusSenderMessageCorrelationOptions options, 
            MessageCorrelationInfo correlation)
        {
            foreach (ServiceBusMessage message in messages)
            {
                message.ApplicationProperties[options.OperationIdPropertyName] = "new operation ID";
                message.ApplicationProperties[options.TransactionIdPropertyName] = correlation.TransactionId;
                message.ApplicationProperties[options.OperationParentIdPropertyName] = "new operation parent ID";
            }
        }
}

Or do we ignore this and solely rely on the fact that developers should use the correct extensions on the ServiceBusMessageBuilder, like .WithOperationId, but then they should also know that they should pass-in new operation and operation parent ID's, and use the correct transaction ID.
And also set this new operation parent ID as the dependency ID in the dependency tracking.