Skip to content

Commit 72a13f5

Browse files
author
Liudmila Molkova
authored
Add id to log AmqpChannelProcessor.ChannelSubscriber lifetime (Azure#29738)
* Add id to log AmqpChannelProcessor.ChannelSubscriber lifetime * add subscriber id to reactor subscriber context
1 parent e1b53f9 commit 72a13f5

File tree

6 files changed

+116
-57
lines changed

6 files changed

+116
-57
lines changed

sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/AmqpChannelProcessor.java

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030

3131
import static com.azure.core.amqp.implementation.ClientConstants.ENTITY_PATH_KEY;
3232
import static com.azure.core.amqp.implementation.ClientConstants.INTERVAL_KEY;
33+
import static com.azure.core.amqp.implementation.ClientConstants.SUBSCRIBER_ID_KEY;
3334

3435
public class AmqpChannelProcessor<T> extends Mono<T> implements Processor<T, T>, CoreSubscriber<T>, Disposable {
3536
@SuppressWarnings("rawtypes")
@@ -66,7 +67,6 @@ public AmqpChannelProcessor(String fullyQualifiedNamespace, String entityPath,
6667
this.endpointStatesFunction = Objects.requireNonNull(endpointStatesFunction,
6768
"'endpointStates' cannot be null.");
6869
this.retryPolicy = Objects.requireNonNull(retryPolicy, "'retryPolicy' cannot be null.");
69-
7070
Map<String, Object> loggingContext = new HashMap<>(1);
7171
loggingContext.put(ENTITY_PATH_KEY, Objects.requireNonNull(entityPath, "'entityPath' cannot be null."));
7272
this.logger = new ClientLogger(getClass(), loggingContext);
@@ -77,6 +77,7 @@ public AmqpChannelProcessor(String fullyQualifiedNamespace, Function<T, Flux<Amq
7777
this.endpointStatesFunction = Objects.requireNonNull(endpointStatesFunction,
7878
"'endpointStates' cannot be null.");
7979
this.retryPolicy = Objects.requireNonNull(retryPolicy, "'retryPolicy' cannot be null.");
80+
8081
this.logger = new ClientLogger(getClass(), Objects.requireNonNull(loggingContext, "'loggingContext' cannot be null."));
8182
this.errorContext = new AmqpErrorContext(fullyQualifiedNamespace);
8283
}
@@ -107,8 +108,6 @@ public void onNext(T amqpChannel) {
107108
currentChannel = amqpChannel;
108109

109110
final ConcurrentLinkedDeque<ChannelSubscriber<T>> currentSubscribers = subscribers;
110-
logger.info("Next AMQP channel received, updating {} current subscribers", subscribers.size());
111-
112111
currentSubscribers.forEach(subscription -> subscription.onNext(amqpChannel));
113112

114113
connectionSubscription = endpointStatesFunction.apply(amqpChannel).subscribe(
@@ -227,8 +226,6 @@ public void onError(Throwable throwable) {
227226
synchronized (lock) {
228227
final ConcurrentLinkedDeque<ChannelSubscriber<T>> currentSubscribers = subscribers;
229228
subscribers = new ConcurrentLinkedDeque<>();
230-
logger.info("Error in AMQP channel processor. Notifying {} subscribers.", currentSubscribers.size());
231-
232229
currentSubscribers.forEach(subscriber -> subscriber.onError(throwable));
233230
}
234231
}
@@ -242,7 +239,6 @@ public void onComplete() {
242239
synchronized (lock) {
243240
final ConcurrentLinkedDeque<ChannelSubscriber<T>> currentSubscribers = subscribers;
244241
subscribers = new ConcurrentLinkedDeque<>();
245-
logger.info("AMQP channel processor completed. Notifying {} subscribers.", currentSubscribers.size());
246242
currentSubscribers.forEach(subscriber -> subscriber.onComplete());
247243
}
248244
}
@@ -270,8 +266,8 @@ public void subscribe(CoreSubscriber<? super T> actual) {
270266
}
271267
}
272268

269+
subscriber.onAdd();
273270
subscribers.add(subscriber);
274-
logger.atVerbose().addKeyValue("subscribers", subscribers.size()).log("Added a subscriber.");
275271

276272
if (!isRetryPending.get()) {
277273
requestUpstream();
@@ -370,17 +366,37 @@ private void close(T channel) {
370366
* which removes itself from the tracking list, then propagates the notification to the wrapped subscriber.
371367
*/
372368
private static final class ChannelSubscriber<T> extends Operators.MonoSubscriber<T, T> {
369+
373370
private final AmqpChannelProcessor<T> processor;
371+
// subscriberId is only needed for logging and not every subscriber is logged, so let's make it lazy.
372+
private String subscriberId = null;
374373

375374
private ChannelSubscriber(CoreSubscriber<? super T> actual, AmqpChannelProcessor<T> processor) {
376375
super(actual);
377376
this.processor = processor;
378377
}
379378

379+
void onAdd() {
380+
Object subscriberIdObj = actual.currentContext().getOrDefault(SUBSCRIBER_ID_KEY, null);
381+
if (subscriberIdObj != null) {
382+
subscriberId = subscriberIdObj.toString();
383+
} else {
384+
subscriberId = StringUtil.getRandomString("un");
385+
}
386+
387+
// most subscribers never get here and will be completed immediately after they are created.
388+
processor.logger.atVerbose()
389+
.addKeyValue(SUBSCRIBER_ID_KEY, subscriberId)
390+
.log("Added subscriber.");
391+
}
392+
380393
@Override
381394
public void cancel() {
382395
processor.subscribers.remove(this);
383396
super.cancel();
397+
processor.logger.atVerbose()
398+
.addKeyValue(SUBSCRIBER_ID_KEY, subscriberId)
399+
.log("Canceled subscriber");
384400
}
385401

386402
@Override
@@ -389,6 +405,9 @@ public void onComplete() {
389405
// first untrack before calling into external code.
390406
processor.subscribers.remove(this);
391407
actual.onComplete();
408+
processor.logger.atInfo()
409+
.addKeyValue(SUBSCRIBER_ID_KEY, subscriberId)
410+
.log("AMQP channel processor completed.");
392411
}
393412
}
394413

@@ -397,6 +416,10 @@ public void onNext(T channel) {
397416
if (!isCancelled()) {
398417
processor.subscribers.remove(this);
399418
super.complete(channel);
419+
420+
processor.logger.atInfo()
421+
.addKeyValue(SUBSCRIBER_ID_KEY, subscriberId)
422+
.log("Next AMQP channel received.");
400423
}
401424
}
402425

@@ -405,6 +428,9 @@ public void onError(Throwable throwable) {
405428
if (!isCancelled()) {
406429
processor.subscribers.remove(this);
407430
actual.onError(throwable);
431+
processor.logger.atInfo()
432+
.addKeyValue(SUBSCRIBER_ID_KEY, subscriberId)
433+
.log("Error in AMQP channel processor.");
408434
} else {
409435
Operators.onErrorDropped(throwable, currentContext());
410436
}

sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ClientConstants.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ public final class ClientConstants {
2424
public static final String SIGNAL_TYPE_KEY = "signalType";
2525
public static final String HOSTNAME_KEY = "hostName";
2626
public static final String INTERVAL_KEY = "interval_ms";
27+
public static final String SUBSCRIBER_ID_KEY = "subscriberId";
2728

2829
/**
2930
* The default maximum allowable size, in bytes, for a batch to be sent.

0 commit comments

Comments
 (0)