Skip to content

RabbitMQActivitySource.Deliver cannot be used by types that implement Consumer #1621

@Tornhoof

Description

@Tornhoof

Describe the bug

Currently RabbitMQActivitySource.Deliver is only called in the derived types AsyncEventingBasicConsumer and EventingBasicConsumer and the method itself is marked as internal.

private async Task BasicDeliverWrapper(BasicDeliverEventArgs eventArgs)
{
using (Activity activity = RabbitMQActivitySource.Deliver(eventArgs))
{
await _receivedWrapper.InvokeAsync(this, eventArgs).ConfigureAwait(false);
}
}

This means, if a dev is deriving from the base types DefaultBasicConsumer or AsyncDefaultBasicConsumer or implements the appropriate interfaces, the Deliver method can't be invoked.

All the other relevant ActivitySource methods are called from within ChannelBase, so these should be fine.

I think the easiest way forward is to make a public RabbitMQActivitySource.Deliver method with the args from the eventArgs:

Current:

internal static Activity Deliver(BasicDeliverEventArgs deliverEventArgs)
{
if (!s_subscriberSource.HasListeners())
{
return null;
}
// Extract the PropagationContext of the upstream parent from the message headers.
Activity activity = s_subscriberSource.StartLinkedRabbitMQActivity(
UseRoutingKeyAsOperationName ? $"{deliverEventArgs.RoutingKey} deliver" : "deliver",
ActivityKind.Consumer, ContextExtractor(deliverEventArgs.BasicProperties));
if (activity != null && activity.IsAllDataRequested)
{
PopulateMessagingTags("deliver", deliverEventArgs.RoutingKey, deliverEventArgs.Exchange,
deliverEventArgs.DeliveryTag, deliverEventArgs.BasicProperties, deliverEventArgs.Body.Length,
activity);
}
return activity;
}

Proposed change:

        internal static Activity Deliver(BasicDeliverEventArgs deliverEventArgs)
        {
            return Deliver(deliverEventArgs.RoutingKey, deliverEventArgs.Exchange, deliverEventArgs.DeliveryTag,
                deliverEventArgs.BasicProperties, deliverEventArgs.Body.Length);
        }

        public static Activity Deliver(string routingKey, string exchange, ulong deliveryTag,
            in ReadOnlyBasicProperties readOnlyBasicProperties, int bodySize)
        {
            if (!s_subscriberSource.HasListeners())
            {
                return null;
            }

            // Extract the PropagationContext of the upstream parent from the message headers.
            Activity activity = s_subscriberSource.StartLinkedRabbitMQActivity(
                UseRoutingKeyAsOperationName ? $"{routingKey} deliver" : "deliver",
                ActivityKind.Consumer, ContextExtractor(readOnlyBasicProperties));
            if (activity != null && activity.IsAllDataRequested)
            {
                PopulateMessagingTags("deliver", routingKey, exchange,
                    deliveryTag, readOnlyBasicProperties, bodySize,
                    activity);
            }

            return activity;
        }

Then the dev can call it in their own implementation of HandleBasicDeliver. I don't see any easy way to do it automatically, like for the other methods, that would be preferable.

Reproduction steps

Expected behavior

Additional context

Maybe @stebet has a better idea, he wrote the original PR.

Metadata

Metadata

Labels

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions