|
31 | 31 |
|
32 | 32 | using System;
|
33 | 33 | using System.Collections.Generic;
|
| 34 | +using System.Diagnostics; |
34 | 35 | using System.Threading.Tasks;
|
35 | 36 | using RabbitMQ.Client.client.impl;
|
36 | 37 |
|
@@ -86,17 +87,58 @@ public static Task<string> BasicConsumeAsync(this IChannel channel, string queue
|
86 | 87 | /// <remarks>
|
87 | 88 | /// The publication occurs with mandatory=false and immediate=false.
|
88 | 89 | /// </remarks>
|
89 |
| - public static ValueTask BasicPublishAsync<T>(this IChannel channel, PublicationAddress addr, in T basicProperties, ReadOnlyMemory<byte> body) |
| 90 | + public static async ValueTask BasicPublishAsync<T>(this IChannel channel, PublicationAddress addr, T basicProperties, ReadOnlyMemory<byte> body) |
90 | 91 | where T : IReadOnlyBasicProperties, IAmqpHeader
|
91 | 92 | {
|
92 |
| - return channel.BasicPublishAsync(addr.ExchangeName, addr.RoutingKey, basicProperties, body); |
| 93 | + using Activity? sendActivity = RabbitMQActivitySource.PublisherHasListeners |
| 94 | + ? RabbitMQActivitySource.Send(addr.RoutingKey, addr.ExchangeName, body.Length) |
| 95 | + : default; |
| 96 | + |
| 97 | + if (sendActivity != null) |
| 98 | + { |
| 99 | + BasicProperties props = PopulateActivityAndPropagateTraceId(EmptyBasicProperty.Empty, sendActivity); |
| 100 | + await channel.BasicPublishAsync(addr.ExchangeName, addr.RoutingKey, props, body); |
| 101 | + } |
| 102 | + else |
| 103 | + { |
| 104 | + await channel.BasicPublishAsync(addr.ExchangeName, addr.RoutingKey, basicProperties, body); |
| 105 | + } |
| 106 | + } |
| 107 | + |
| 108 | + public static async ValueTask BasicPublishAsync(this IChannel channel, string exchange, string routingKey, ReadOnlyMemory<byte> body = default, bool mandatory = false) |
| 109 | + { |
| 110 | + using Activity? sendActivity = RabbitMQActivitySource.PublisherHasListeners |
| 111 | + ? RabbitMQActivitySource.Send(routingKey, exchange, body.Length) |
| 112 | + : default; |
| 113 | + |
| 114 | + if (sendActivity != null) |
| 115 | + { |
| 116 | + BasicProperties props = PopulateActivityAndPropagateTraceId(EmptyBasicProperty.Empty, sendActivity); |
| 117 | + await channel.BasicPublishAsync(exchange, routingKey, props, body, mandatory); |
| 118 | + } |
| 119 | + else |
| 120 | + { |
| 121 | + await channel.BasicPublishAsync(exchange, routingKey, EmptyBasicProperty.Empty, body, mandatory); |
| 122 | + } |
93 | 123 | }
|
94 | 124 |
|
95 |
| - public static ValueTask BasicPublishAsync(this IChannel channel, string exchange, string routingKey, ReadOnlyMemory<byte> body = default, bool mandatory = false) |
96 |
| - => channel.BasicPublishAsync(exchange, routingKey, EmptyBasicProperty.Empty, body, mandatory); |
| 125 | + public static async ValueTask BasicPublishAsync(this IChannel channel, CachedString exchange, |
| 126 | + CachedString routingKey, ReadOnlyMemory<byte> body = default, bool mandatory = false) |
| 127 | + { |
| 128 | + using Activity? sendActivity = RabbitMQActivitySource.PublisherHasListeners |
| 129 | + ? RabbitMQActivitySource.Send(routingKey.Value, exchange.Value, body.Length) |
| 130 | + : default; |
97 | 131 |
|
98 |
| - public static ValueTask BasicPublishAsync(this IChannel channel, CachedString exchange, CachedString routingKey, ReadOnlyMemory<byte> body = default, bool mandatory = false) |
99 |
| - => channel.BasicPublishAsync(exchange, routingKey, EmptyBasicProperty.Empty, body, mandatory); |
| 132 | + if (sendActivity != null) |
| 133 | + { |
| 134 | + BasicProperties props = PopulateActivityAndPropagateTraceId(EmptyBasicProperty.Empty, sendActivity); |
| 135 | + await channel.BasicPublishAsync(exchange, routingKey, props, body, mandatory); |
| 136 | + } |
| 137 | + else |
| 138 | + { |
| 139 | + await channel.BasicPublishAsync(exchange, routingKey, EmptyBasicProperty.Empty, body, mandatory); |
| 140 | + } |
| 141 | + } |
100 | 142 |
|
101 | 143 | #nullable disable
|
102 | 144 |
|
@@ -185,5 +227,34 @@ public static Task CloseAsync(this IChannel channel, ushort replyCode, string re
|
185 | 227 | {
|
186 | 228 | return channel.CloseAsync(replyCode, replyText, false);
|
187 | 229 | }
|
| 230 | + |
| 231 | + private static BasicProperties PopulateActivityAndPropagateTraceId<TProperties>(TProperties basicProperties, |
| 232 | + Activity sendActivity) where TProperties : IReadOnlyBasicProperties, IAmqpHeader |
| 233 | + { |
| 234 | + // This activity is marked as recorded, so let's propagate the trace and span ids. |
| 235 | + if (sendActivity.IsAllDataRequested) |
| 236 | + { |
| 237 | + if (!string.IsNullOrEmpty(basicProperties.CorrelationId)) |
| 238 | + { |
| 239 | + sendActivity.SetTag(RabbitMQActivitySource.MessageConversationId, basicProperties.CorrelationId); |
| 240 | + } |
| 241 | + } |
| 242 | + |
| 243 | + BasicProperties props = default; |
| 244 | + if (basicProperties is BasicProperties properties) |
| 245 | + { |
| 246 | + props = properties; |
| 247 | + } |
| 248 | + else if (basicProperties is EmptyBasicProperty) |
| 249 | + { |
| 250 | + props = new BasicProperties(); |
| 251 | + } |
| 252 | + |
| 253 | + var headers = props.Headers ?? new Dictionary<string, object>(); |
| 254 | + // Inject the ActivityContext into the message headers to propagate trace context to the receiving service. |
| 255 | + RabbitMQActivitySource.ContextInjector(sendActivity, headers); |
| 256 | + props.Headers = headers; |
| 257 | + return props; |
| 258 | + } |
188 | 259 | }
|
189 | 260 | }
|
0 commit comments