From 60bc8b8e5efa97c7b7c7e24da2a8cc0e92403259 Mon Sep 17 00:00:00 2001
From: Liudmila Molkova
Date: Sat, 20 Nov 2021 21:47:26 -0800
Subject: [PATCH 01/17] Switch to structured logging in amqp-core
---
.../azure/core/amqp/AmqpShutdownSignal.java | 13 +-
.../ActiveClientTokenManager.java | 69 +++++---
.../implementation/AmqpChannelProcessor.java | 69 ++++----
.../implementation/AmqpExceptionHandler.java | 4 +-
.../amqp/implementation/AmqpLoggingUtils.java | 33 ++++
.../AzureTokenManagerProvider.java | 7 +-
.../amqp/implementation/ClientConstants.java | 12 ++
.../implementation/ManagementChannel.java | 16 +-
.../implementation/ReactorConnection.java | 147 +++++++++--------
.../implementation/ReactorDispatcher.java | 40 ++---
.../amqp/implementation/ReactorExecutor.java | 42 +++--
.../amqp/implementation/ReactorReceiver.java | 100 ++++++++----
.../amqp/implementation/ReactorSender.java | 113 ++++++-------
.../amqp/implementation/ReactorSession.java | 153 +++++++++++-------
.../RequestResponseChannel.java | 98 +++++------
.../handler/ConnectionHandler.java | 67 ++++----
.../handler/CustomIOHandler.java | 16 +-
.../amqp/implementation/handler/Handler.java | 26 +--
.../implementation/handler/LinkHandler.java | 32 ++--
.../handler/ReactorHandler.java | 12 +-
.../handler/ReceiveLinkHandler.java | 83 ++++++----
.../handler/SendLinkHandler.java | 74 ++++++---
.../handler/SessionHandler.java | 82 +++++-----
.../handler/WebSocketsConnectionHandler.java | 14 +-
.../WebSocketsProxyConnectionHandler.java | 38 +++--
.../AmqpChannelProcessorTest.java | 3 +-
.../implementation/ManagementChannelTest.java | 3 +-
.../implementation/ReactorSenderTest.java | 1 +
.../implementation/handler/HandlerTest.java | 11 +-
.../handler/LinkHandlerTest.java | 14 +-
.../java/com/azure/core/util/FluxUtil.java | 13 ++
31 files changed, 829 insertions(+), 576 deletions(-)
create mode 100644 sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/AmqpLoggingUtils.java
diff --git a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/AmqpShutdownSignal.java b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/AmqpShutdownSignal.java
index a105e8416fb2..e9e3c9665b2a 100644
--- a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/AmqpShutdownSignal.java
+++ b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/AmqpShutdownSignal.java
@@ -3,6 +3,8 @@
package com.azure.core.amqp;
+import com.azure.core.util.logging.LoggingEventBuilder;
+
import java.util.Locale;
/**
@@ -46,8 +48,17 @@ public boolean isInitiatedByClient() {
return isInitiatedByClient;
}
+ public LoggingEventBuilder addContext(LoggingEventBuilder logBuilder) {
+ return logBuilder
+ .addKeyValue("isTransient", isTransient)
+ .addKeyValue("isInitiatedByClient", isInitiatedByClient)
+ .addKeyValue("shutdownMessage", message);
+ }
+
/**
- * {@inheritDoc}
+ * Returns String representing this {@code AmqpShutdownSignal} signal.
+ *
+ * To write logs, please use {@link AmqpShutdownSignal#addContext} instead.
*/
@Override
public String toString() {
diff --git a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ActiveClientTokenManager.java b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ActiveClientTokenManager.java
index 3270a2f8f8ef..e9e3dce79ee8 100644
--- a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ActiveClientTokenManager.java
+++ b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ActiveClientTokenManager.java
@@ -19,11 +19,14 @@
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
+import static com.azure.core.amqp.implementation.AmqpLoggingUtils.addErrorCondition;
+import static com.azure.core.amqp.implementation.AmqpLoggingUtils.addSignalTypeAndResult;
+
/**
* Manages the re-authorization of the client to the token audience against the CBS node.
*/
public class ActiveClientTokenManager implements TokenManager {
- private final ClientLogger logger = new ClientLogger(ActiveClientTokenManager.class);
+ private final ClientLogger logger;
private final AtomicBoolean hasScheduled = new AtomicBoolean();
private final AtomicBoolean hasDisposed = new AtomicBoolean();
private final Mono cbsNode;
@@ -39,6 +42,7 @@ public ActiveClientTokenManager(Mono cbsNode, String to
this.cbsNode = cbsNode;
this.tokenAudience = tokenAudience;
this.scopes = scopes;
+ this.logger = new ClientLogger(ActiveClientTokenManager.class);
}
/**
@@ -76,12 +80,14 @@ public Mono authorize() {
// If this is the first time authorize is called, the task will not have been scheduled yet.
if (!hasScheduled.getAndSet(true)) {
- logger.info("Scheduling refresh token task. scopes[{}]", scopes);
+ logger.atInfo()
+ .addKeyValue("scopes", scopes)
+ .log("Scheduling refresh token task.");
final Duration firstInterval = Duration.ofMillis(refreshIntervalMS);
lastRefreshInterval.set(firstInterval);
authorizationResults.emitNext(AmqpResponseCode.ACCEPTED, (signalType, emitResult) -> {
- logger.verbose("signalType[{}] result[{}] Could not emit ACCEPTED.", signalType, emitResult);
+ addSignalTypeAndResult(logger.atVerbose(), signalType, emitResult).log("Could not emit ACCEPTED.");
return false;
});
@@ -99,11 +105,13 @@ public void close() {
}
authorizationResults.emitComplete((signalType, emitResult) -> {
- logger.verbose("signalType[{}] result[{}] Could not close authorizationResults.", signalType, emitResult);
+ addSignalTypeAndResult(logger.atVerbose(), signalType, emitResult).log("Could not close authorizationResults.");
+
return false;
});
durationSource.emitComplete((signalType, emitResult) -> {
- logger.verbose("signalType[{}] result[{}] Could not close durationSource.", signalType, emitResult);
+ addSignalTypeAndResult(logger.atVerbose(), signalType, emitResult).log("Could not close durationSource.");
+
return false;
});
@@ -115,15 +123,19 @@ public void close() {
private Disposable scheduleRefreshTokenTask(Duration initialRefresh) {
// EmitterProcessor can queue up an initial refresh interval before any subscribers are received.
durationSource.emitNext(initialRefresh, (signalType, emitResult) -> {
- logger.verbose("signalType[{}] result[{}] Could not emit initial refresh interval.", signalType,
- emitResult);
+ addSignalTypeAndResult(logger.atVerbose(), signalType, emitResult).log(" Could not emit initial refresh interval.");
+
return false;
});
return Flux.switchOnNext(durationSource.asFlux().map(Flux::interval))
.takeUntil(duration -> hasDisposed.get())
.flatMap(delay -> {
- logger.info("Refreshing token. scopes[{}] ", scopes);
+
+ logger.atInfo()
+ .addKeyValue("scopes", scopes)
+ .log("Refreshing token.");
+
return authorize();
})
.onErrorContinue(
@@ -131,20 +143,26 @@ private Disposable scheduleRefreshTokenTask(Duration initialRefresh) {
(amqpException, interval) -> {
final Duration lastRefresh = lastRefreshInterval.get();
- logger.error("Error is transient. Rescheduling authorization task at interval {} ms. scopes[{}]",
- lastRefresh.toMillis(), scopes, amqpException);
+ logger.atError()
+ .addKeyValue("scopes", scopes)
+ .log("Error is transient. Rescheduling authorization task at interval {} ms", lastRefresh.toMillis(), amqpException);
+
durationSource.emitNext(lastRefresh, (signalType, emitResult) -> {
- logger.verbose("signalType[{}] result[{}] Could not emit lastRefresh[{}].", signalType,
- emitResult, lastRefresh);
+ addSignalTypeAndResult(logger.atVerbose(), signalType, emitResult)
+ .addKeyValue("lastRefresh", lastRefresh)
+ .log("Could not emit.");
return false;
});
})
.subscribe(interval -> {
- logger.verbose("Authorization successful. Refreshing token in {} ms. scopes[{}]", interval, scopes);
+ logger.atVerbose()
+ .addKeyValue("scopes", scopes)
+ .log("Authorization successful. Refreshing token in {} ms.", interval);
+
authorizationResults.emitNext(AmqpResponseCode.ACCEPTED, (signalType, emitResult) -> {
- logger.verbose("signalType[{}] result[{}] Could not emit ACCEPTED after refresh.", signalType,
- emitResult);
+ addSignalTypeAndResult(logger.atVerbose(), signalType, emitResult)
+ .log("Could not emit ACCEPTED after refresh.");
return false;
});
@@ -152,29 +170,32 @@ private Disposable scheduleRefreshTokenTask(Duration initialRefresh) {
lastRefreshInterval.set(nextRefresh);
durationSource.emitNext(nextRefresh, (signalType, emitResult) -> {
- logger.verbose("signalType[{}] result[{}] Could not emit nextRefresh[{}].", signalType,
- emitResult, nextRefresh);
+ addSignalTypeAndResult(logger.atVerbose(), signalType, emitResult)
+ .addKeyValue("nextRefresh", nextRefresh)
+ .log("Could not emit nextRefresh.");
return false;
});
}, error -> {
- logger.error("Error occurred while refreshing token that is not retriable. Not scheduling"
- + " refresh task. Use ActiveClientTokenManager.authorize() to schedule task again. audience[{}]"
- + " scopes[{}]", tokenAudience, scopes, error);
+ logger.atError()
+ .addKeyValue("scopes", scopes)
+ .addKeyValue("audience", tokenAudience)
+ .log("Error occurred while refreshing token that is not retriable. Not scheduling"
+ + " refresh task. Use ActiveClientTokenManager.authorize() to schedule task again.", error);
// This hasn't been disposed yet.
if (!hasDisposed.getAndSet(true)) {
hasScheduled.set(false);
durationSource.emitComplete((signalType, emitResult) -> {
- logger.verbose("signalType[{}] result[{}] Could not close durationSource.", signalType,
- emitResult);
+ addSignalTypeAndResult(logger.atVerbose(), signalType, emitResult)
+ .log("Could not close durationSource.");
return false;
});
authorizationResults.emitError(error, (signalType, emitResult) -> {
- logger.verbose("signalType[{}] result[{}] Could not emit authorization error.", signalType,
- emitResult, error);
+ addSignalTypeAndResult(logger.atVerbose(), signalType, emitResult)
+ .log("Could not emit authorization error.", error);
return false;
});
diff --git a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/AmqpChannelProcessor.java b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/AmqpChannelProcessor.java
index 7273b753fead..0f95feaec32a 100644
--- a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/AmqpChannelProcessor.java
+++ b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/AmqpChannelProcessor.java
@@ -9,6 +9,7 @@
import com.azure.core.amqp.exception.AmqpException;
import com.azure.core.util.AsyncCloseable;
import com.azure.core.util.logging.ClientLogger;
+import com.azure.core.util.logging.ClientLogger;
import org.reactivestreams.Processor;
import org.reactivestreams.Subscription;
import reactor.core.CoreSubscriber;
@@ -18,6 +19,7 @@
import reactor.core.publisher.Operators;
import java.time.Duration;
+import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentLinkedDeque;
import java.util.concurrent.RejectedExecutionException;
@@ -26,6 +28,9 @@
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
import java.util.function.Function;
+import static com.azure.core.amqp.implementation.ClientConstants.ENTITY_PATH_KEY;
+import static com.azure.core.amqp.implementation.ClientConstants.FULLY_QUALIFIED_NAMESPACE_KEY;
+
public class AmqpChannelProcessor extends Mono implements Processor, CoreSubscriber, Disposable {
@SuppressWarnings("rawtypes")
private static final AtomicReferenceFieldUpdater UPSTREAM =
@@ -40,8 +45,6 @@ public class AmqpChannelProcessor extends Mono implements Processor,
private final Object lock = new Object();
private final AmqpRetryPolicy retryPolicy;
- private final String fullyQualifiedNamespace;
- private final String entityPath;
private final Function> endpointStatesFunction;
private final AmqpErrorContext errorContext;
@@ -53,14 +56,13 @@ public class AmqpChannelProcessor extends Mono implements Processor,
private volatile Disposable retrySubscription;
public AmqpChannelProcessor(String fullyQualifiedNamespace, String entityPath,
- Function> endpointStatesFunction, AmqpRetryPolicy retryPolicy, ClientLogger logger) {
- this.fullyQualifiedNamespace = Objects
- .requireNonNull(fullyQualifiedNamespace, "'fullyQualifiedNamespace' cannot be null.");
- this.entityPath = Objects.requireNonNull(entityPath, "'entityPath' cannot be null.");
+ Function> endpointStatesFunction, AmqpRetryPolicy retryPolicy, String loggerName) {
this.endpointStatesFunction = Objects.requireNonNull(endpointStatesFunction,
"'endpointStates' cannot be null.");
this.retryPolicy = Objects.requireNonNull(retryPolicy, "'retryPolicy' cannot be null.");
- this.logger = Objects.requireNonNull(logger, "'logger' cannot be null.");
+ this.logger = new ClientLogger(loggerName, Map.of(
+ FULLY_QUALIFIED_NAMESPACE_KEY, Objects.requireNonNull(fullyQualifiedNamespace, "'fullyQualifiedNamespace' cannot be null."),
+ ENTITY_PATH_KEY, Objects.requireNonNull(entityPath, "'entityPath' cannot be null.")));
this.errorContext = new AmqpErrorContext(fullyQualifiedNamespace);
}
@@ -77,7 +79,7 @@ public void onSubscribe(Subscription subscription) {
@Override
public void onNext(T amqpChannel) {
- logger.info("namespace[{}] entityPath[{}]: Setting next AMQP channel.", fullyQualifiedNamespace, entityPath);
+ logger.info("Setting next AMQP channel.");
Objects.requireNonNull(amqpChannel, "'amqpChannel' cannot be null.");
@@ -90,8 +92,7 @@ public void onNext(T amqpChannel) {
currentChannel = amqpChannel;
final ConcurrentLinkedDeque> currentSubscribers = subscribers;
- logger.info("namespace[{}] entityPath[{}]: Next AMQP channel received, updating {} current "
- + "subscribers", fullyQualifiedNamespace, entityPath, subscribers.size());
+ logger.info("Next AMQP channel received, updating {} current subscribers", subscribers.size());
currentSubscribers.forEach(subscription -> subscription.onNext(amqpChannel));
@@ -100,8 +101,7 @@ public void onNext(T amqpChannel) {
// Connection was successfully opened, we can reset the retry interval.
if (state == AmqpEndpointState.ACTIVE) {
retryAttempts.set(0);
- logger.info("namespace[{}] entityPath[{}]: Channel is now active.",
- fullyQualifiedNamespace, entityPath);
+ logger.info("Channel is now active.");
}
},
error -> {
@@ -110,11 +110,9 @@ public void onNext(T amqpChannel) {
},
() -> {
if (isDisposed()) {
- logger.info("namespace[{}] entityPath[{}]: Channel is disposed.",
- fullyQualifiedNamespace, entityPath);
+ logger.info("Channel is disposed.");
} else {
- logger.info("namespace[{}] entityPath[{}]: Channel is closed. Requesting upstream. ",
- fullyQualifiedNamespace, entityPath);
+ logger.info("Channel is closed. Requesting upstream.");
setAndClearChannel();
requestUpstream();
}
@@ -140,8 +138,7 @@ public void onError(Throwable throwable) {
Objects.requireNonNull(throwable, "'throwable' is required.");
if (isRetryPending.get() && retryPolicy.calculateRetryDelay(throwable, retryAttempts.get()) != null) {
- logger.warning("namespace[{}] entityPath[{}]: Retry is already pending. Ignoring transient error.",
- fullyQualifiedNamespace, entityPath, throwable);
+ logger.warning("Retry is already pending. Ignoring transient error.", throwable);
return;
}
@@ -183,24 +180,20 @@ public void onError(Throwable throwable) {
return;
}
- logger.info("namespace[{}] entityPath[{}]: Retry #{}. Transient error occurred. Retrying after {} ms.",
- fullyQualifiedNamespace, entityPath, attempts, retryInterval.toMillis(), throwable);
+ logger.info("Retry #{}. Transient error occurred. Retrying after {} ms.", attempts, retryInterval.toMillis(), throwable);
retrySubscription = Mono.delay(retryInterval).subscribe(i -> {
if (isDisposed()) {
- logger.info("namespace[{}] entityPath[{}]: Retry #{}. Not requesting from upstream. Processor is disposed.",
- fullyQualifiedNamespace, entityPath, attempts);
+ logger.info("Retry #{}. Not requesting from upstream. Processor is disposed.", attempts);
} else {
- logger.info("namespace[{}] entityPath[{}]: Retry #{}. Requesting from upstream.",
- fullyQualifiedNamespace, entityPath, attempts);
+ logger.info("Retry #{}. Requesting from upstream.", attempts);
requestUpstream();
isRetryPending.set(false);
}
});
} else {
- logger.warning("namespace[{}] entityPath[{}]: Retry #{}. Retry attempts exhausted or exception was not retriable.",
- fullyQualifiedNamespace, entityPath, attempts, throwable);
+ logger.warning("Retry #{}. Retry attempts exhausted or exception was not retriable.", attempts, throwable);
lastError = throwable;
isDisposed.set(true);
@@ -209,8 +202,7 @@ public void onError(Throwable throwable) {
synchronized (lock) {
final ConcurrentLinkedDeque> currentSubscribers = subscribers;
subscribers = new ConcurrentLinkedDeque<>();
- logger.info("namespace[{}] entityPath[{}]: Error in AMQP channel processor. Notifying {} subscribers.",
- fullyQualifiedNamespace, entityPath, currentSubscribers.size());
+ logger.info("Error in AMQP channel processor. Notifying {} subscribers.", currentSubscribers.size());
currentSubscribers.forEach(subscriber -> subscriber.onError(throwable));
}
@@ -225,8 +217,7 @@ public void onComplete() {
synchronized (lock) {
final ConcurrentLinkedDeque> currentSubscribers = subscribers;
subscribers = new ConcurrentLinkedDeque<>();
- logger.info("namespace[{}] entityPath[{}]: AMQP channel processor completed. Notifying {} "
- + "subscribers.", fullyQualifiedNamespace, entityPath, currentSubscribers.size());
+ logger.info("AMQP channel processor completed. Notifying {} subscribers.", currentSubscribers.size());
currentSubscribers.forEach(subscriber -> subscriber.onComplete());
}
}
@@ -238,9 +229,7 @@ public void subscribe(CoreSubscriber super T> actual) {
actual.onSubscribe(Operators.emptySubscription());
actual.onError(lastError);
} else {
- Operators.error(actual, logger.logExceptionAsError(new IllegalStateException(
- String.format("namespace[%s] entityPath[%s]: Cannot subscribe. Processor is already terminated.",
- fullyQualifiedNamespace, entityPath))));
+ Operators.error(actual, logger.atError().log(new IllegalStateException("Cannot subscribe. Processor is already terminated.")));
}
return;
@@ -257,8 +246,7 @@ public void subscribe(CoreSubscriber super T> actual) {
}
subscribers.add(subscriber);
- logger.verbose("namespace[{}] entityPath[{}] subscribers[{}]: Added a subscriber.",
- fullyQualifiedNamespace, entityPath, subscribers.size());
+ logger.atVerbose().addKeyValue("subscribers", subscribers.size()).log("Added a subscriber.");
if (!isRetryPending.get()) {
requestUpstream();
@@ -289,25 +277,22 @@ public boolean isDisposed() {
private void requestUpstream() {
if (currentChannel != null) {
- logger.verbose("namespace[{}] entityPath[{}]: Connection exists, not requesting another.",
- fullyQualifiedNamespace, entityPath);
+ logger.verbose("Connection exists, not requesting another.");
return;
} else if (isDisposed()) {
- logger.verbose("namespace[{}] entityPath[{}]: Is already disposed.", fullyQualifiedNamespace, entityPath);
+ logger.verbose("Is already disposed.");
return;
}
final Subscription subscription = UPSTREAM.get(this);
if (subscription == null) {
- logger.warning("namespace[{}] entityPath[{}]: There is no upstream subscription.",
- fullyQualifiedNamespace, entityPath);
+ logger.warning("There is no upstream subscription.");
return;
}
// subscribe(CoreSubscriber) may have requested a subscriber already.
if (!isRequested.getAndSet(true)) {
- logger.info("namespace[{}] entityPath[{}]: Connection not requested, yet. Requesting one.",
- fullyQualifiedNamespace, entityPath);
+ logger.info("Connection not requested, yet. Requesting one.");
subscription.request(1);
}
}
diff --git a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/AmqpExceptionHandler.java b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/AmqpExceptionHandler.java
index 88ee6c052f83..fa02f50883bd 100644
--- a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/AmqpExceptionHandler.java
+++ b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/AmqpExceptionHandler.java
@@ -5,6 +5,7 @@
import com.azure.core.amqp.AmqpShutdownSignal;
import com.azure.core.util.logging.ClientLogger;
+import com.azure.core.util.logging.ClientLogger;
/**
* Handles exceptions generated by AMQP connections, sessions, and/or links.
@@ -33,6 +34,7 @@ void onConnectionError(Throwable exception) {
* @param shutdownSignal The shutdown signal that was received.
*/
void onConnectionShutdown(AmqpShutdownSignal shutdownSignal) {
- logger.info("Shutdown received: {}", shutdownSignal);
+ shutdownSignal
+ .addContext(logger.atInfo()).log("Shutdown received");
}
}
diff --git a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/AmqpLoggingUtils.java b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/AmqpLoggingUtils.java
new file mode 100644
index 000000000000..d00d778047b7
--- /dev/null
+++ b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/AmqpLoggingUtils.java
@@ -0,0 +1,33 @@
+package com.azure.core.amqp.implementation;
+
+import com.azure.core.util.logging.LoggingEventBuilder;
+import org.apache.qpid.proton.amqp.transport.ErrorCondition;
+import reactor.core.publisher.SignalType;
+import reactor.core.publisher.Sinks;
+
+import static com.azure.core.amqp.implementation.ClientConstants.EMIT_RESULT_KEY;
+import static com.azure.core.amqp.implementation.ClientConstants.ERROR_CONDITION_KEY;
+import static com.azure.core.amqp.implementation.ClientConstants.ERROR_DESCRIPTION_KEY;
+import static com.azure.core.amqp.implementation.ClientConstants.NOT_APPLICABLE;
+import static com.azure.core.amqp.implementation.ClientConstants.SIGNAL_TYPE_KEY;
+
+public class AmqpLoggingUtils {
+ public static LoggingEventBuilder addSignalTypeAndResult(LoggingEventBuilder logBuilder, SignalType signalType, Sinks.EmitResult result) {
+ return logBuilder
+ .addKeyValue(SIGNAL_TYPE_KEY, signalType)
+ .addKeyValue(EMIT_RESULT_KEY, result);
+ }
+
+ public static LoggingEventBuilder addErrorCondition(LoggingEventBuilder logBuilder, ErrorCondition errorCondition) {
+ if (errorCondition == null) {
+ return logBuilder
+ .addKeyValue(ERROR_CONDITION_KEY, NOT_APPLICABLE)
+ .addKeyValue(ERROR_DESCRIPTION_KEY, NOT_APPLICABLE);
+ }
+
+ return logBuilder
+ .addKeyValue(ERROR_CONDITION_KEY, errorCondition.getCondition())
+ .addKeyValue(ERROR_DESCRIPTION_KEY, errorCondition.getDescription());
+ }
+}
+
diff --git a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/AzureTokenManagerProvider.java b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/AzureTokenManagerProvider.java
index 9641fb0ef688..fe4488f92fc1 100644
--- a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/AzureTokenManagerProvider.java
+++ b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/AzureTokenManagerProvider.java
@@ -48,7 +48,10 @@ public TokenManager getTokenManager(Mono cbsNodeMono, S
final String scopes = getScopesFromResource(resource);
final String tokenAudience = String.format(Locale.US, TOKEN_AUDIENCE_FORMAT, fullyQualifiedNamespace, resource);
- logger.verbose("Creating new token manager for audience[{}], resource[{}]", tokenAudience, resource);
+ logger.atVerbose()
+ .addKeyValue("audience", tokenAudience)
+ .addKeyValue("resource", resource)
+ .log("Creating new token manager.");
return new ActiveClientTokenManager(cbsNodeMono, tokenAudience, scopes);
}
@@ -63,7 +66,7 @@ public String getScopesFromResource(String resource) {
} else if (CbsAuthorizationType.SHARED_ACCESS_SIGNATURE.equals(authorizationType)) {
return String.format(Locale.US, TOKEN_AUDIENCE_FORMAT, fullyQualifiedNamespace, resource);
} else {
- throw logger.logExceptionAsError(new IllegalArgumentException(String.format(Locale.US,
+ throw logger.atError().log(new IllegalArgumentException(String.format(Locale.US,
"'%s' is not supported authorization type for token audience.", authorizationType)));
}
}
diff --git a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ClientConstants.java b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ClientConstants.java
index 885d70d3b14d..04210a669653 100644
--- a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ClientConstants.java
+++ b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ClientConstants.java
@@ -12,6 +12,18 @@ public final class ClientConstants {
// Base sleep wait time.
public static final Duration SERVER_BUSY_WAIT_TIME = Duration.ofSeconds(4);
+ // Logging context keys
+ public final static String CONNECTION_ID_KEY = "connectionId";
+ public final static String LINK_NAME_KEY = "linkName";
+ public final static String ENTITY_PATH_KEY = "entityPath";
+ public final static String SESSION_NAME_KEY = "sessionName";
+ public final static String FULLY_QUALIFIED_NAMESPACE_KEY = "namespace";
+ public final static String ERROR_CONDITION_KEY = "errorCondition";
+ public final static String ERROR_DESCRIPTION_KEY = "errorDescription";
+ public final static String EMIT_RESULT_KEY = "emitResult";
+ public final static String SIGNAL_TYPE_KEY = "signalType";
+ public final static String HOSTNAME_KEY = "hostName";
+
/**
* The default maximum allowable size, in bytes, for a batch to be sent.
*/
diff --git a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ManagementChannel.java b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ManagementChannel.java
index 23b560745666..853a99384519 100644
--- a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ManagementChannel.java
+++ b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ManagementChannel.java
@@ -12,13 +12,20 @@
import com.azure.core.amqp.models.AmqpAnnotatedMessage;
import com.azure.core.amqp.models.DeliveryOutcome;
import com.azure.core.util.logging.ClientLogger;
+import com.azure.core.util.logging.ClientLogger;
import org.apache.qpid.proton.amqp.transport.DeliveryState;
import org.apache.qpid.proton.message.Message;
+import org.slf4j.LoggerFactory;
import reactor.core.publisher.Mono;
import reactor.core.publisher.SynchronousSink;
+import java.util.Map;
import java.util.Objects;
+import static com.azure.core.amqp.implementation.ClientConstants.ENTITY_PATH_KEY;
+import static com.azure.core.amqp.implementation.ClientConstants.ERROR_CONDITION_KEY;
+import static com.azure.core.amqp.implementation.ClientConstants.ERROR_DESCRIPTION_KEY;
+
/**
* AMQP node responsible for performing management and metadata operations on an Azure AMQP message broker.
*/
@@ -34,8 +41,8 @@ public ManagementChannel(AmqpChannelProcessor createChan
this.createChannel = Objects.requireNonNull(createChannel, "'createChannel' cannot be null.");
this.fullyQualifiedNamespace = Objects.requireNonNull(fullyQualifiedNamespace,
"'fullyQualifiedNamespace' cannot be null.");
- this.logger = new ClientLogger(String.format("%s<%s>", ManagementChannel.class.getName(), entityPath));
this.entityPath = Objects.requireNonNull(entityPath, "'entityPath' cannot be null.");
+ this.logger = new ClientLogger(ManagementChannel.class, Map.of(ENTITY_PATH_KEY, entityPath));
this.tokenManager = Objects.requireNonNull(tokenManager, "'tokenManager' cannot be null.");
}
@@ -104,8 +111,11 @@ private void handleResponse(Message response, SynchronousSink sessionMap = new ConcurrentHashMap<>();
private final ConcurrentHashMap managementNodes = new ConcurrentHashMap<>();
@@ -101,6 +113,7 @@ public ReactorConnection(String connectionId, ConnectionOptions connectionOption
this.connectionOptions = connectionOptions;
this.reactorProvider = reactorProvider;
this.connectionId = connectionId;
+ this.logger = new ClientLogger(ReactorConnection.class, Map.of(CONNECTION_ID_KEY, connectionId));
this.handlerProvider = handlerProvider;
this.tokenManagerProvider = Objects.requireNonNull(tokenManagerProvider,
"'tokenManagerProvider' cannot be null.");
@@ -123,38 +136,33 @@ public ReactorConnection(String connectionId, ConnectionOptions connectionOption
return activeEndpoint.thenReturn(reactorConnection);
})
.doOnError(error -> {
- final String message = String.format(
- "connectionId[%s] Error occurred while connection was starting. Error: %s", connectionId, error);
-
if (isDisposed.getAndSet(true)) {
- logger.verbose("connectionId[{}] was already disposed. {}", connectionId, message);
+ logger.atVerbose()
+ .log("Connection was already disposed: Error occurred while connection was starting.", error);
} else {
- closeAsync(new AmqpShutdownSignal(false, false, message)).subscribe();
+ closeAsync(new AmqpShutdownSignal(false, false, String.format(
+ "Error occurred while connection was starting. Error: %s", error))).subscribe();
}
});
this.endpointStates = this.handler.getEndpointStates()
.takeUntilOther(shutdownSignalSink.asMono())
.map(state -> {
- logger.verbose("connectionId[{}]: State {}", connectionId, state);
+ logger.verbose("State {}", state);
return AmqpEndpointStateUtil.getConnectionState(state);
})
.onErrorResume(error -> {
if (!isDisposed.getAndSet(true)) {
- logger.verbose("connectionId[{}]: Disposing of active sessions due to error.", connectionId);
- return closeAsync(new AmqpShutdownSignal(false, false,
- error.getMessage())).then(Mono.error(error));
+ logger.verbose("Disposing of active sessions due to error.");
+ return closeAsync(new AmqpShutdownSignal(false, false, error.getMessage())).then(Mono.error(error));
} else {
return Mono.error(error);
}
})
.doOnComplete(() -> {
if (!isDisposed.getAndSet(true)) {
- logger.verbose("connectionId[{}]: Disposing of active sessions due to connection close.",
- connectionId);
-
- closeAsync(new AmqpShutdownSignal(false, false,
- "Connection handler closed.")).subscribe();
+ logger.verbose("Disposing of active sessions due to connection close.");
+ closeAsync(new AmqpShutdownSignal(false, false, "Connection handler closed.")).subscribe();
}
})
.cache(1);
@@ -185,9 +193,7 @@ public Flux getShutdownSignals() {
public Mono getManagementNode(String entityPath) {
return Mono.defer(() -> {
if (isDisposed()) {
- return Mono.error(logger.logExceptionAsError(new IllegalStateException(String.format(
- "connectionId[%s]: Connection is disposed. Cannot get management instance for '%s'",
- connectionId, entityPath))));
+ return monoError(logger.atError().addKeyValue(ENTITY_PATH_KEY, entityPath), new IllegalStateException("Connection is disposed. Cannot get management instance."));
}
final AmqpManagementNode existing = managementNodes.get(entityPath);
@@ -201,7 +207,7 @@ public Mono getManagementNode(String entityPath) {
return tokenManager.authorize().thenReturn(managementNodes.compute(entityPath, (key, current) -> {
if (current != null) {
- logger.info("A management node exists already, returning it.");
+ logger.atInfo().addKeyValue(ENTITY_PATH_KEY, entityPath).log("A management node exists already, returning it.");
// Close the token manager we had created during this because it is unneeded now.
tokenManager.close();
@@ -212,8 +218,11 @@ public Mono getManagementNode(String entityPath) {
final String linkName = entityPath + "-" + MANAGEMENT_LINK_NAME;
final String address = entityPath + "/" + MANAGEMENT_ADDRESS;
- logger.info("Creating management node. entityPath[{}], address[{}], linkName[{}]",
- entityPath, address, linkName);
+ logger.atInfo()
+ .addKeyValue(ENTITY_PATH_KEY, entityPath)
+ .addKeyValue(LINK_NAME_KEY, linkName)
+ .addKeyValue("address", address)
+ .log("Creating management node.");
final AmqpChannelProcessor requestResponseChannel =
createRequestResponseChannel(sessionName, linkName, address);
@@ -281,8 +290,9 @@ public Mono createSession(String sessionName) {
return;
}
- logger.info("connectionId[{}] sessionName[{}]: Error occurred. Removing and disposing"
- + " session.", connectionId, sessionName, error);
+ logger.atInfo()
+ .addKeyValue(SESSION_NAME_KEY, sessionName)
+ .log("Error occurred. Removing and disposing session", error);
removeSession(key);
}, () -> {
// If we were already disposing of the connection, the session would be removed.
@@ -290,8 +300,9 @@ public Mono createSession(String sessionName) {
return;
}
- logger.verbose("connectionId[{}] sessionName[{}]: Complete. Removing and disposing session.",
- connectionId, sessionName);
+ logger.atVerbose()
+ .addKeyValue(SESSION_NAME_KEY, sessionName)
+ .log("connectionId[{}] sessionName[{}]: Complete. Removing and disposing session.");
removeSession(key);
});
@@ -389,35 +400,37 @@ protected AmqpChannelProcessor createRequestResponseChan
entityPath, reactorSession.session(), connectionOptions.getRetry(), handlerProvider, reactorProvider,
messageSerializer, senderSettleMode, receiverSettleMode))
.doOnNext(e -> {
- logger.info("connectionId[{}] entityPath[{}] linkName[{}] Emitting new response channel.",
- getId(), entityPath, linkName);
+ logger.atInfo()
+ .addKeyValue(ENTITY_PATH_KEY, entityPath)
+ .addKeyValue(LINK_NAME_KEY, linkName)
+ .log("Emitting new response channel.");
})
.repeat();
return createChannel
.subscribeWith(new AmqpChannelProcessor<>(connectionId, entityPath,
- channel -> channel.getEndpointStates(), retryPolicy,
- new ClientLogger(RequestResponseChannel.class.getName() + ":" + entityPath)));
+ channel -> channel.getEndpointStates(), retryPolicy, RequestResponseChannel.class.getName()));
}
@Override
public Mono closeAsync() {
if (isDisposed.getAndSet(true)) {
- logger.verbose("connectionId[{}] Was already closed. Not disposing again.", connectionId);
+ logger.verbose("Connection was already closed. Not disposing again.");
return isClosedMono.asMono();
}
- return closeAsync(new AmqpShutdownSignal(false, true,
- "Disposed by client."));
+ return closeAsync(new AmqpShutdownSignal(false, true, "Disposed by client."));
}
Mono closeAsync(AmqpShutdownSignal shutdownSignal) {
- logger.info("connectionId[{}] signal[{}]: Disposing of ReactorConnection.", connectionId, shutdownSignal);
-
+ shutdownSignal.addContext(logger.atInfo()).log("Disposing of ReactorConnection.");
final Sinks.EmitResult result = shutdownSignalSink.tryEmitValue(shutdownSignal);
+
if (result.isFailure()) {
// It's possible that another one was already emitted, so it's all good.
- logger.info("connectionId[{}] signal[{}] result[{}] Unable to emit shutdown signal.", connectionId, result);
+ shutdownSignal.addContext(logger.atInfo())
+ .addKeyValue(EMIT_RESULT_KEY, result)
+ .log("Unable to emit shutdown signal.");
}
final Mono cbsCloseOperation;
@@ -431,21 +444,19 @@ Mono closeAsync(AmqpShutdownSignal shutdownSignal) {
Flux.fromStream(managementNodes.values().stream()).flatMap(node -> node.closeAsync()));
final Mono closeReactor = Mono.fromRunnable(() -> {
- logger.verbose("connectionId[{}] Scheduling closeConnection work.", connectionId);
+ logger.verbose("Scheduling closeConnection work.");
final ReactorDispatcher dispatcher = reactorProvider.getReactorDispatcher();
if (dispatcher != null) {
try {
dispatcher.invoke(() -> closeConnectionWork());
} catch (IOException e) {
- logger.warning("connectionId[{}] IOException while scheduling closeConnection work. Manually "
- + "disposing.", connectionId, e);
+ logger.warning("IOException while scheduling closeConnection work. Manually disposing", e);
closeConnectionWork();
} catch (RejectedExecutionException e) {
// Not logging error here again because we have to log the exception when we throw it.
- logger.info("connectionId[{}] Could not schedule closeConnection work. Manually disposing.",
- connectionId);
+ logger.info("Could not schedule closeConnection work. Manually disposing.");
closeConnectionWork();
}
@@ -456,23 +467,24 @@ Mono closeAsync(AmqpShutdownSignal shutdownSignal) {
return Mono.whenDelayError(
cbsCloseOperation.doFinally(signalType ->
- logger.verbose("connectionId[{}] signalType[{}] Closed CBS node.", connectionId, signalType)),
+ logger.atVerbose()
+ .addKeyValue(SIGNAL_TYPE_KEY, signalType)
+ .log("Closed CBS node.")),
managementNodeCloseOperations.doFinally(signalType ->
- logger.verbose("connectionId[{}] signalType[{}] Closed management nodes.", connectionId,
- signalType)))
-
-
+ logger.atVerbose()
+ .log("Closed management nodes.")))
.then(closeReactor.doFinally(signalType ->
- logger.verbose("connectionId[{}] signalType[{}] Closed reactor dispatcher.", connectionId,
- signalType)))
+ logger.atVerbose()
+ .addKeyValue(SIGNAL_TYPE_KEY, signalType)
+ .log("Closed reactor dispatcher.")))
.then(isClosedMono.asMono());
}
private synchronized void closeConnectionWork() {
if (connection == null) {
isClosedMono.emitEmpty((signalType, emitResult) -> {
- logger.info("connectionId[{}] signal[{}] result[{}] Unable to complete closeMono.",
- connectionId, signalType, emitResult);
+ addSignalTypeAndResult(logger.atInfo(), signalType, emitResult)
+ .log("Unable to complete closeMono.");
return false;
});
@@ -490,7 +502,7 @@ private synchronized void closeConnectionWork() {
// remaining work after OperationTimeout has elapsed and closes afterwards.
final Mono closedExecutor = executor != null ? Mono.defer(() -> {
synchronized (this) {
- logger.info("connectionId[{}] Closing executor.", connectionId);
+ logger.info("Closing executor.");
return executor.closeAsync();
}
}) : Mono.empty();
@@ -499,14 +511,14 @@ private synchronized void closeConnectionWork() {
final Mono closeSessionAndExecutorMono = Mono.when(closingSessions)
.timeout(operationTimeout)
.onErrorResume(error -> {
- logger.info("connectionId[{}]: Timed out waiting for all sessions to close.", connectionId);
+ logger.info("Timed out waiting for all sessions to close.");
return Mono.empty();
})
.then(closedExecutor)
.then(Mono.fromRunnable(() -> {
isClosedMono.emitEmpty((signalType, result) -> {
- logger.warning("connectionId[{}] signal[{}] result[{}]: Unable to emit connection closed signal",
- connectionId, signalType, result);
+ addSignalTypeAndResult(logger.atWarning(), signalType, result)
+ .log("Unable to emit connection closed signal.");
return false;
});
@@ -531,8 +543,10 @@ private synchronized ClaimsBasedSecurityNode getOrCreateCBSNode() {
private synchronized Connection getOrCreateConnection() throws IOException {
if (connection == null) {
- logger.info("connectionId[{}]: Creating and starting connection to {}:{}", connectionId,
- handler.getHostname(), handler.getProtocolPort());
+ logger.atInfo()
+ .addKeyValue(HOSTNAME_KEY, handler.getHostname())
+ .addKeyValue("port", handler.getProtocolPort())
+ .log("Creating and starting connection.");
final Reactor reactor = reactorProvider.createReactor(connectionId, handler.getMaxFrameSize());
connection = reactor.connectionToHost(handler.getHostname(), handler.getProtocolPort(), handler);
@@ -587,13 +601,15 @@ private ReactorExceptionHandler() {
@Override
public void onConnectionError(Throwable exception) {
- logger.info(
- "onConnectionError connectionId[{}], hostName[{}], message[Starting new reactor], error[{}]",
- getId(), getFullyQualifiedNamespace(), exception.getMessage(), exception);
+ logger.atInfo()
+ .addKeyValue(FULLY_QUALIFIED_NAMESPACE_KEY, getFullyQualifiedNamespace())
+ .log("onConnectionError, Starting new reactor", exception);
if (!isDisposed.getAndSet(true)) {
- logger.verbose("onReactorError connectionId[{}], hostName[{}]: Disposing.", connectionId,
- getFullyQualifiedNamespace());
+ logger.atVerbose()
+ .addKeyValue(FULLY_QUALIFIED_NAMESPACE_KEY, getFullyQualifiedNamespace())
+ .log("onReactorError: Disposing.");
+
closeAsync(new AmqpShutdownSignal(false, false,
"onReactorError: " + exception.toString()))
.subscribe();
@@ -602,12 +618,15 @@ public void onConnectionError(Throwable exception) {
@Override
void onConnectionShutdown(AmqpShutdownSignal shutdownSignal) {
- logger.info(
- "onConnectionShutdown connectionId[{}], hostName[{}], message[Shutting down], shutdown signal[{}]",
- getId(), getFullyQualifiedNamespace(), shutdownSignal.isInitiatedByClient(), shutdownSignal);
+ shutdownSignal.addContext(logger.atInfo())
+ .addKeyValue(FULLY_QUALIFIED_NAMESPACE_KEY, getFullyQualifiedNamespace())
+ .log("onConnectionShutdown. Shutting down.");
if (!isDisposed.getAndSet(true)) {
- logger.verbose("onConnectionShutdown connectionId[{}], hostName[{}]: disposing.");
+ logger.atVerbose()
+ .addKeyValue(FULLY_QUALIFIED_NAMESPACE_KEY, getFullyQualifiedNamespace())
+ .log("onConnectionShutdown: disposing.");
+
closeAsync(shutdownSignal).subscribe();
}
}
diff --git a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ReactorDispatcher.java b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ReactorDispatcher.java
index 3607803eba10..ac4ce4baefb3 100644
--- a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ReactorDispatcher.java
+++ b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ReactorDispatcher.java
@@ -6,6 +6,7 @@
import com.azure.core.amqp.AmqpShutdownSignal;
import com.azure.core.amqp.implementation.handler.DispatchHandler;
import com.azure.core.util.logging.ClientLogger;
+import com.azure.core.util.logging.ClientLogger;
import org.apache.qpid.proton.Proton;
import org.apache.qpid.proton.reactor.Reactor;
import org.apache.qpid.proton.reactor.Selectable;
@@ -18,11 +19,14 @@
import java.nio.channels.ClosedChannelException;
import java.nio.channels.Pipe;
import java.time.Duration;
+import java.util.Map;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
+import static com.azure.core.amqp.implementation.ClientConstants.CONNECTION_ID_KEY;
+
/**
* The following utility class is used to generate an event to hook into {@link Reactor}'s event delegation pattern. It
* uses a {@link Pipe} as the IO on which Reactor listens to.
@@ -40,7 +44,7 @@
*
*/
public final class ReactorDispatcher {
- private final ClientLogger logger = new ClientLogger(ReactorDispatcher.class);
+ private final ClientLogger logger;
private final CloseHandler onClose;
private final String connectionId;
private final Reactor reactor;
@@ -65,7 +69,7 @@ public ReactorDispatcher(final String connectionId, final Reactor reactor, final
this.workQueue = new ConcurrentLinkedQueue<>();
this.onClose = new CloseHandler();
this.workScheduler = new WorkScheduler();
-
+ this.logger = new ClientLogger(ReactorDispatcher.class , Map.of(CONNECTION_ID_KEY, connectionId));
// The Proton-J reactor goes quiescent when there is no work to do, and it only wakes up when a Selectable (by
// default, the network connection) signals that data is available.
//
@@ -125,7 +129,7 @@ private void throwIfSchedulerError() {
final RejectedExecutionException rejectedException = this.reactor.attachments()
.get(RejectedExecutionException.class, RejectedExecutionException.class);
if (rejectedException != null) {
- throw logger.logExceptionAsWarning(new RejectedExecutionException(
+ throw logger.atWarning().log(new RejectedExecutionException(
"Underlying Reactor was already disposed. Should not continue dispatching work to this. "
+ rejectedException.getMessage(), rejectedException));
}
@@ -133,7 +137,7 @@ private void throwIfSchedulerError() {
// throw when the pipe is in closed state - in which case,
// signalling the new event-dispatch will fail
if (!this.ioSignal.sink().isOpen()) {
- throw logger.logExceptionAsWarning(new RejectedExecutionException(
+ throw logger.atWarning().log(new RejectedExecutionException(
"ReactorDispatcher instance is closed. Should not continue dispatching work to this reactor."));
}
}
@@ -146,14 +150,13 @@ private void signalWorkQueue() throws IOException {
}
} catch (ClosedChannelException ignorePipeClosedDuringReactorShutdown) {
if (!isClosed.get()) {
- logger.warning("connectionId[{}] signalWorkQueue failed before reactor closed.",
- connectionId, ignorePipeClosedDuringReactorShutdown);
+ logger.atWarning()
+ .log("signalWorkQueue failed before reactor closed.", ignorePipeClosedDuringReactorShutdown);
shutdownSignal.emitError(new RuntimeException(String.format(
"connectionId[%s] IO Sink was interrupted before reactor closed.", connectionId),
ignorePipeClosedDuringReactorShutdown), Sinks.EmitFailureHandler.FAIL_FAST);
} else {
- logger.verbose("connectionId[{}] signalWorkQueue failed with an error after closed. Can be ignored.",
- connectionId, ignorePipeClosedDuringReactorShutdown);
+ logger.verbose("signalWorkQueue failed with an error after closed. Can be ignored.", ignorePipeClosedDuringReactorShutdown);
}
}
}
@@ -179,21 +182,20 @@ public void run(Selectable selectable) {
}
} catch (ClosedChannelException ignorePipeClosedDuringReactorShutdown) {
if (!isClosed.get()) {
- logger.warning("connectionId[{}] WorkScheduler.run() failed before reactor was closed.",
- connectionId, ignorePipeClosedDuringReactorShutdown);
+ logger.atWarning()
+ .log("WorkScheduler.run() failed before reactor was closed.", ignorePipeClosedDuringReactorShutdown);
shutdownSignal.emitError(new RuntimeException(String.format(
"connectionId[%s] IO Source was interrupted before reactor closed.", connectionId),
ignorePipeClosedDuringReactorShutdown), Sinks.EmitFailureHandler.FAIL_FAST);
} else {
- logger.verbose("connectionId[{}] WorkScheduler.run() failed with an error. Can be ignored.",
- connectionId, ignorePipeClosedDuringReactorShutdown);
+ logger.atVerbose()
+ .log("WorkScheduler.run() failed with an error. Can be ignored.", ignorePipeClosedDuringReactorShutdown);
}
break;
} catch (IOException ioException) {
- shutdownSignal.emitError(logger.logExceptionAsError(new RuntimeException(
- String.format("connectionId[%s] WorkScheduler.run() failed with an error.", connectionId),
- ioException)), Sinks.EmitFailureHandler.FAIL_FAST);
+ shutdownSignal.emitError(logger.atError().log(new RuntimeException(
+ "WorkScheduler.run() failed with an error.", ioException)), Sinks.EmitFailureHandler.FAIL_FAST);
break;
}
@@ -221,7 +223,7 @@ public void run(Selectable selectable) {
return;
}
- logger.info("connectionId[{}] Reactor selectable is being disposed.", connectionId);
+ logger.info("Reactor selectable is being disposed.");
shutdownSignal.emitValue(new AmqpShutdownSignal(false, false,
String.format("connectionId[%s] Reactor selectable is disposed.", connectionId)),
@@ -232,8 +234,7 @@ public void run(Selectable selectable) {
ioSignal.sink().close();
}
} catch (IOException ioException) {
- logger.error("connectionId[{}] CloseHandler.sink().close() failed with an error.",
- connectionId, ioException);
+ logger.atError().log("CloseHandler.sink().close() failed with an error.", ioException);
}
workScheduler.run(null);
@@ -243,8 +244,7 @@ public void run(Selectable selectable) {
ioSignal.source().close();
}
} catch (IOException ioException) {
- logger.error("connectionId[{}] CloseHandler.source().close() failed with an error.",
- connectionId, ioException);
+ logger.atError().log("CloseHandler.source().close() failed with an error.", ioException);
}
}
}
diff --git a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ReactorExecutor.java b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ReactorExecutor.java
index 6a7d80476ea1..8aee5ae47dbc 100644
--- a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ReactorExecutor.java
+++ b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ReactorExecutor.java
@@ -18,18 +18,20 @@
import java.nio.channels.UnresolvedAddressException;
import java.time.Duration;
import java.util.Locale;
+import java.util.Map;
import java.util.Objects;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
+import static com.azure.core.amqp.implementation.AmqpLoggingUtils.addSignalTypeAndResult;
+import static com.azure.core.amqp.implementation.ClientConstants.CONNECTION_ID_KEY;
+
/**
* Schedules the proton-j reactor to continuously run work.
*/
class ReactorExecutor implements AsyncCloseable {
- private static final String LOG_MESSAGE = "connectionId[{}] message[{}]";
-
- private final ClientLogger logger = new ClientLogger(ReactorExecutor.class);
+ private final ClientLogger logger;
private final AtomicBoolean hasStarted = new AtomicBoolean();
private final AtomicBoolean isDisposed = new AtomicBoolean();
private final Sinks.Empty isClosedMono = Sinks.empty();
@@ -37,7 +39,6 @@ class ReactorExecutor implements AsyncCloseable {
private final Object lock = new Object();
private final Reactor reactor;
private final Scheduler scheduler;
- private final String connectionId;
private final Duration timeout;
private final AmqpExceptionHandler exceptionHandler;
private final String hostname;
@@ -46,10 +47,10 @@ class ReactorExecutor implements AsyncCloseable {
Duration timeout, String hostname) {
this.reactor = Objects.requireNonNull(reactor, "'reactor' cannot be null.");
this.scheduler = Objects.requireNonNull(scheduler, "'scheduler' cannot be null.");
- this.connectionId = Objects.requireNonNull(connectionId, "'connectionId' cannot be null.");
this.timeout = Objects.requireNonNull(timeout, "'timeout' cannot be null.");
this.exceptionHandler = Objects.requireNonNull(exceptionHandler, "'exceptionHandler' cannot be null.");
this.hostname = Objects.requireNonNull(hostname, "'hostname' cannot be null.");
+ this.logger = new ClientLogger(ReactorExecutor.class, Map.of(CONNECTION_ID_KEY, Objects.requireNonNull(connectionId, "'connectionId' cannot be null.")));
}
/**
@@ -67,7 +68,7 @@ void start() {
return;
}
- logger.info(LOG_MESSAGE, connectionId, "Starting reactor.");
+ logger.info("Starting reactor.");
reactor.start();
scheduler.schedule(this::run);
}
@@ -79,8 +80,7 @@ void start() {
private void run() {
// If this hasn't been disposed of, and we're trying to run work items on it, log a warning and return.
if (!isDisposed.get() && !hasStarted.get()) {
- logger.warning(LOG_MESSAGE, connectionId,
- "Cannot run work items on ReactorExecutor if ReactorExecutor.start() has not been invoked.");
+ logger.warning("Cannot run work items on ReactorExecutor if ReactorExecutor.start() has not been invoked.");
return;
}
@@ -97,8 +97,7 @@ private void run() {
scheduler.schedule(this::run);
rescheduledReactor = true;
} catch (RejectedExecutionException exception) {
- logger.warning(LOG_MESSAGE, connectionId,
- "Scheduling reactor failed because the scheduler has been shut down.", exception);
+ logger.warning("Scheduling reactor failed because the scheduler has been shut down.", exception);
this.reactor.attachments()
.set(RejectedExecutionException.class, RejectedExecutionException.class, exception);
@@ -109,8 +108,7 @@ private void run() {
? handlerException
: handlerException.getCause();
- logger.warning(LOG_MESSAGE, connectionId,
- "Unhandled exception while processing events in reactor, report this error.", handlerException);
+ logger.warning("Unhandled exception while processing events in reactor, report this error.", handlerException);
final String message = !CoreUtils.isNullOrEmpty(cause.getMessage())
? cause.getMessage()
@@ -137,14 +135,14 @@ private void run() {
} finally {
if (!rescheduledReactor) {
if (hasStarted.getAndSet(false)) {
- logger.verbose(LOG_MESSAGE, connectionId, "Scheduling reactor to complete pending tasks.");
+ logger.verbose("Scheduling reactor to complete pending tasks.");
scheduleCompletePendingTasks();
} else {
final String reason =
"Stopping the reactor because thread was interrupted or the reactor has no more events to "
+ "process.";
- logger.info(LOG_MESSAGE, connectionId, reason);
+ logger.info(reason);
close(reason, true);
}
}
@@ -156,18 +154,15 @@ private void run() {
*/
private void scheduleCompletePendingTasks() {
final Runnable work = () -> {
- logger.info(LOG_MESSAGE, connectionId, "Processing all pending tasks and closing old reactor.");
+ logger.info("Processing all pending tasks and closing old reactor.");
try {
if (reactor.process()) {
- logger.verbose(LOG_MESSAGE, connectionId,
- "Had more tasks to process on reactor but it is shutting down.");
+ logger.verbose("Had more tasks to process on reactor but it is shutting down.");
}
reactor.stop();
} catch (HandlerException e) {
- logger.warning(LOG_MESSAGE, connectionId,
- StringUtil.toStackTraceString(e, "scheduleCompletePendingTasks - exception occurred while "
- + "processing events."));
+ logger.atWarning().log(() -> StringUtil.toStackTraceString(e, "scheduleCompletePendingTasks - exception occurred while processing events."));
} finally {
try {
reactor.free();
@@ -183,17 +178,16 @@ private void scheduleCompletePendingTasks() {
try {
this.scheduler.schedule(work, timeout.toMillis(), TimeUnit.MILLISECONDS);
} catch (RejectedExecutionException e) {
- logger.warning(LOG_MESSAGE, connectionId, "Scheduler was already closed. Manually releasing reactor.");
+ logger.warning("Scheduler was already closed. Manually releasing reactor.");
work.run();
}
}
private void close(String reason, boolean initiatedByClient) {
- logger.verbose(LOG_MESSAGE, connectionId, "Completing close and disposing scheduler. {}", reason);
+ logger.verbose("Completing close and disposing scheduler. {}", reason);
scheduler.dispose();
isClosedMono.emitEmpty((signalType, emitResult) -> {
- logger.verbose("connectionId[{}] signalType[{}] emitResult[{}]: Unable to emit close event on reactor",
- connectionId, signalType, emitResult);
+ addSignalTypeAndResult(logger.atVerbose(), signalType, emitResult).log("Unable to emit close event on reactor");
return false;
});
exceptionHandler.onConnectionShutdown(new AmqpShutdownSignal(false, initiatedByClient, reason));
diff --git a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ReactorReceiver.java b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ReactorReceiver.java
index 086a395fc8e7..b34abf0d85d8 100644
--- a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ReactorReceiver.java
+++ b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ReactorReceiver.java
@@ -6,10 +6,13 @@
import com.azure.core.amqp.AmqpConnection;
import com.azure.core.amqp.AmqpEndpointState;
import com.azure.core.amqp.AmqpRetryOptions;
+import com.azure.core.amqp.AmqpShutdownSignal;
import com.azure.core.amqp.exception.AmqpErrorCondition;
import com.azure.core.amqp.implementation.handler.ReceiveLinkHandler;
import com.azure.core.util.AsyncCloseable;
import com.azure.core.util.logging.ClientLogger;
+import com.azure.core.util.logging.ClientLogger;
+import com.azure.core.util.logging.LoggingEventBuilder;
import org.apache.qpid.proton.Proton;
import org.apache.qpid.proton.amqp.Symbol;
import org.apache.qpid.proton.amqp.transport.ErrorCondition;
@@ -19,6 +22,7 @@
import org.apache.qpid.proton.message.Message;
import reactor.core.Disposable;
import reactor.core.Disposables;
+import reactor.core.Exceptions;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.core.publisher.Sinks;
@@ -26,12 +30,19 @@
import java.io.IOException;
import java.io.UncheckedIOException;
+import java.util.Map;
import java.util.Objects;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Supplier;
+import static com.azure.core.amqp.implementation.AmqpLoggingUtils.addSignalTypeAndResult;
+import static com.azure.core.amqp.implementation.ClientConstants.CONNECTION_ID_KEY;
+import static com.azure.core.amqp.implementation.ClientConstants.ENTITY_PATH_KEY;
+import static com.azure.core.amqp.implementation.ClientConstants.LINK_NAME_KEY;
+import static com.azure.core.amqp.implementation.AmqpLoggingUtils.addErrorCondition;
+import static com.azure.core.amqp.implementation.AmqpLoggingUtils.addErrorCondition;
import static com.azure.core.amqp.implementation.ClientConstants.NOT_APPLICABLE;
import static com.azure.core.util.FluxUtil.monoError;
@@ -49,7 +60,7 @@ public class ReactorReceiver implements AmqpReceiveLink, AsyncCloseable, AutoClo
private final Sinks.Empty isClosedMono = Sinks.empty();
private final Flux messagesProcessor;
private final AmqpRetryOptions retryOptions;
- private final ClientLogger logger = new ClientLogger(ReactorReceiver.class);
+ private final ClientLogger logger;
private final Flux endpointStates;
private final AtomicReference> creditSupplier = new AtomicReference<>();
@@ -62,6 +73,7 @@ protected ReactorReceiver(AmqpConnection amqpConnection, String entityPath, Rece
this.handler = handler;
this.tokenManager = tokenManager;
this.dispatcher = dispatcher;
+ this.logger = new ClientLogger(ReactorReceiver.class, Map.of(CONNECTION_ID_KEY, handler.getConnectionId(), LINK_NAME_KEY, this.handler.getLinkName()));
// Delivered messages are not published on another scheduler because we want the settlement method that happens
// in decodeDelivery to take place and since proton-j is not thread safe, it could end up with hundreds of
// backed up deliveries waiting to be settled. (Which, consequently, ends up in a FAIL_OVERFLOW error from
@@ -83,12 +95,14 @@ protected ReactorReceiver(AmqpConnection amqpConnection, String entityPath, Rece
final Integer credits = supplier.get();
if (credits != null && credits > 0) {
- logger.info("connectionId[{}] linkName[{}] credits[{}] Adding credits.",
- handler.getConnectionId(), getLinkName(), credits);
+ logger.atInfo()
+ .addKeyValue("credits", credits)
+ .log("Adding credits.");
receiver.flow(credits);
} else {
- logger.verbose("connectionId[{}] linkName[{}] credits[{}] There are no credits to add.",
- handler.getConnectionId(), getLinkName(), credits);
+ logger.atVerbose()
+ .addKeyValue("credits", credits)
+ .log("There are no credits to add.");
}
sink.success(message);
@@ -102,16 +116,19 @@ protected ReactorReceiver(AmqpConnection amqpConnection, String entityPath, Rece
this.retryOptions = retryOptions;
this.endpointStates = this.handler.getEndpointStates()
.map(state -> {
- logger.verbose("connectionId[{}] entityPath[{}] linkName[{}] State {}", handler.getConnectionId(),
- entityPath, getLinkName(), state);
+ logger.atVerbose()
+ .addKeyValue(ENTITY_PATH_KEY, entityPath)
+ .log("State {}", state);
return AmqpEndpointStateUtil.getConnectionState(state);
})
.doOnError(error -> {
final String message = isDisposed.getAndSet(true)
? "This was already disposed. Dropping error."
: "Freeing resources due to error.";
- logger.warning("connectionId[{}] entityPath[{}] linkName[{}] {}",
- handler.getConnectionId(), entityPath, getLinkName(), message, error);
+
+ logger.atInfo()
+ .addKeyValue(ENTITY_PATH_KEY, entityPath)
+ .log(message);
completeClose();
})
@@ -119,8 +136,10 @@ protected ReactorReceiver(AmqpConnection amqpConnection, String entityPath, Rece
final String message = isDisposed.getAndSet(true)
? "This was already disposed."
: "Freeing resources.";
- logger.verbose("connectionId[{}] entityPath[{}] linkName[{}] {}", handler.getConnectionId(),
- entityPath, getLinkName(), message);
+
+ logger.atVerbose()
+ .addKeyValue(ENTITY_PATH_KEY, entityPath)
+ .log(message);
completeClose();
})
@@ -133,28 +152,27 @@ protected ReactorReceiver(AmqpConnection amqpConnection, String entityPath, Rece
.onErrorResume(error -> {
// When we encounter an error refreshing authorization results, close the receive link.
final Mono operation =
- closeAsync(String.format(
- "connectionId[%s] linkName[%s] Token renewal failure. Disposing receive link.",
- amqpConnection.getId(), getLinkName()),
+ closeAsync("Token renewal failure. Disposing receive link.",
new ErrorCondition(Symbol.getSymbol(AmqpErrorCondition.NOT_ALLOWED.getErrorCondition()),
error.getMessage()));
return operation.then(Mono.empty());
- }).subscribe(response -> {
- logger.verbose("connectionId[{}] linkName[{}] response[{}] Token refreshed.",
- handler.getConnectionId(), getLinkName(), response);
- }, error -> {
+ }).subscribe(response ->
+ logger.atVerbose()
+ .addKeyValue("response", response)
+ .log("Token refreshed.")
+ , error -> {
}, () -> {
- logger.verbose("connectionId[{}] entityPath[{}] linkName[{}] Authorization completed.",
- handler.getConnectionId(), entityPath, getLinkName());
+ logger.atVerbose()
+ .addKeyValue(ENTITY_PATH_KEY, entityPath)
+ .log("Authorization completed.");
closeAsync("Authorization completed. Disposing.", null).subscribe();
}),
amqpConnection.getShutdownSignals().flatMap(signal -> {
- logger.verbose("connectionId[{}] linkName[{}] Shutdown signal received.", handler.getConnectionId(),
- getLinkName());
-
+ logger.atVerbose()
+ .log("Shutdown signal received.");
return closeAsync("Connection shutdown.", null);
}).subscribe());
//@formatter:on
@@ -173,7 +191,7 @@ public Flux receive() {
@Override
public Mono addCredits(int credits) {
if (isDisposed()) {
- return monoError(logger, new IllegalStateException("Cannot add credits to closed link: " + getLinkName()));
+ return monoError(logger.atError(), Exceptions.propagate(new IllegalStateException("Cannot add credits to closed link: " + getLinkName())));
}
return Mono.create(sink -> {
@@ -262,10 +280,9 @@ Mono closeAsync(String message, ErrorCondition errorCondition) {
return isClosedMono.asMono().publishOn(Schedulers.boundedElastic());
}
- final String condition = errorCondition != null ? errorCondition.toString() : NOT_APPLICABLE;
- logger.verbose("connectionId[{}], path[{}], linkName[{}] errorCondition[{}]: Setting error condition and "
- + "disposing. {}",
- handler.getConnectionId(), entityPath, getLinkName(), condition, message);
+ addErrorCondition(logger.atVerbose(), errorCondition)
+ .addKeyValue(ENTITY_PATH_KEY, entityPath)
+ .log("Setting error condition and disposing. {}", message);
final Runnable closeReceiver = () -> {
if (receiver.getLocalState() != EndpointState.CLOSED) {
@@ -281,16 +298,15 @@ Mono closeAsync(String message, ErrorCondition errorCondition) {
try {
dispatcher.invoke(closeReceiver);
} catch (IOException e) {
- logger.warning("connectionId[{}] linkName[{}] IO sink was closed when scheduling work. Manually "
- + "invoking and completing close.", handler.getConnectionId(), getLinkName(), e);
+ logger.atWarning()
+ .log("IO sink was closed when scheduling work. Manually invoking and completing close.", e);
closeReceiver.run();
completeClose();
} catch (RejectedExecutionException e) {
// Not logging error here again because we have to log the exception when we throw it.
- logger.info("connectionId[{}] linkName[{}] RejectedExecutionException when scheduling on "
- + "ReactorDispatcher. Manually invoking and completing close.", handler.getConnectionId(),
- getLinkName());
+ logger.atInfo()
+ .log("RejectedExecutionException when scheduling on ReactorDispatcher. Manually invoking and completing close.");
closeReceiver.run();
completeClose();
@@ -302,9 +318,11 @@ Mono closeAsync(String message, ErrorCondition errorCondition) {
* Takes care of disposing of subscriptions, reactor resources after they've been closed.
*/
private void completeClose() {
+
isClosedMono.emitEmpty((signalType, result) -> {
- logger.warning("connectionId[{}], signal[{}], result[{}]. Unable to emit shutdown signal.",
- handler.getConnectionId(), signalType, result);
+ addSignalTypeAndResult(logger.atWarning(), signalType, result)
+ .addKeyValue(ENTITY_PATH_KEY, entityPath)
+ .log("Unable to emit shutdown signal.");
return false;
});
@@ -318,6 +336,18 @@ private void completeClose() {
receiver.free();
}
+ public LoggingEventBuilder addContext(LoggingEventBuilder logBuilder) {
+ return logBuilder
+ .addKeyValue(CONNECTION_ID_KEY, receiver.getName())
+ .addKeyValue(ENTITY_PATH_KEY, entityPath)
+ .addKeyValue(LINK_NAME_KEY, getLinkName());
+ }
+
+ /**
+ * Returns String representing this {@code ReactorReceiver} signal.
+ *
+ * To write logs, please use {@link ReactorReceiver#addContext} instead.
+ */
@Override
public String toString() {
return String.format("connectionId: [%s] entity path: [%s] linkName: [%s]", receiver.getName(), entityPath,
diff --git a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ReactorSender.java b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ReactorSender.java
index ab3946443719..8048c1e0ab2f 100644
--- a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ReactorSender.java
+++ b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ReactorSender.java
@@ -46,6 +46,7 @@
import java.util.Comparator;
import java.util.List;
import java.util.Locale;
+import java.util.Map;
import java.util.Objects;
import java.util.PriorityQueue;
import java.util.UUID;
@@ -56,6 +57,10 @@
import java.util.concurrent.atomic.AtomicInteger;
import static com.azure.core.amqp.exception.AmqpErrorCondition.NOT_ALLOWED;
+import static com.azure.core.amqp.implementation.AmqpLoggingUtils.addErrorCondition;
+import static com.azure.core.amqp.implementation.ClientConstants.CONNECTION_ID_KEY;
+import static com.azure.core.amqp.implementation.ClientConstants.ENTITY_PATH_KEY;
+import static com.azure.core.amqp.implementation.ClientConstants.LINK_NAME_KEY;
import static com.azure.core.amqp.implementation.ClientConstants.MAX_AMQP_HEADER_SIZE_BYTES;
import static com.azure.core.amqp.implementation.ClientConstants.NOT_APPLICABLE;
import static com.azure.core.amqp.implementation.ClientConstants.SERVER_BUSY_BASE_SLEEP_TIME_IN_SECS;
@@ -65,6 +70,7 @@
* Handles scheduling and transmitting events through proton-j to Event Hubs service.
*/
class ReactorSender implements AmqpSendLink, AsyncCloseable, AutoCloseable {
+ private static final String DELIVERY_TAG_KEY = "deliveryTag";
private final String entityPath;
private final Sender sender;
private final SendLinkHandler handler;
@@ -80,7 +86,7 @@ class ReactorSender implements AmqpSendLink, AsyncCloseable, AutoCloseable {
private final ConcurrentHashMap pendingSendsMap = new ConcurrentHashMap<>();
private final PriorityQueue pendingSendsQueue =
new PriorityQueue<>(1000, new DeliveryTagComparator());
- private final ClientLogger logger = new ClientLogger(ReactorSender.class);
+ private final ClientLogger logger;
private final Flux endpointStates;
private final TokenManager tokenManager;
@@ -123,14 +129,16 @@ class ReactorSender implements AmqpSendLink, AsyncCloseable, AutoCloseable {
this.retry = RetryUtil.getRetryPolicy(retryOptions);
this.tokenManager = tokenManager;
+ String connectionId = handler.getConnectionId() == null ? NOT_APPLICABLE : handler.getConnectionId();
+ String linkName = getLinkName() == null ? NOT_APPLICABLE : getLinkName();
+ this.logger = new ClientLogger(ReactorSender.class, Map.of(CONNECTION_ID_KEY, connectionId, ENTITY_PATH_KEY, entityPath, LINK_NAME_KEY, linkName));
this.activeTimeoutMessage = String.format(
"ReactorSender connectionId[%s] linkName[%s]: Waiting for send and receive handler to be ACTIVE",
handler.getConnectionId(), handler.getLinkName());
this.endpointStates = this.handler.getEndpointStates()
.map(state -> {
- logger.verbose("connectionId[{}] entityPath[{}] linkName[{}]: State {}", handler.getConnectionId(),
- entityPath, getLinkName(), state);
+ logger.verbose("State {}", state);
this.hasConnected.set(state == EndpointState.ACTIVE);
return AmqpEndpointStateUtil.getConnectionState(state);
})
@@ -150,14 +158,13 @@ class ReactorSender implements AmqpSendLink, AsyncCloseable, AutoCloseable {
this.handler.getDeliveredMessages().subscribe(this::processDeliveredMessage),
this.handler.getLinkCredits().subscribe(credit -> {
- logger.verbose("connectionId[{}] entityPath[{}] linkName[{}] credits[{}] Credits on link.",
- handler.getConnectionId(), entityPath, getLinkName(), credit);
+ logger.atVerbose().addKeyValue("credits", credit)
+ .log("Credits on link.");
this.scheduleWorkOnDispatcher();
}),
amqpConnection.getShutdownSignals().flatMap(signal -> {
- logger.verbose("connectionId[{}] linkName[{}]: Shutdown signal received.", handler.getConnectionId(),
- getLinkName());
+ logger.verbose("Shutdown signal received.");
hasConnected.set(false);
return closeAsync("Connection shutdown.", null);
@@ -175,12 +182,11 @@ class ReactorSender implements AmqpSendLink, AsyncCloseable, AutoCloseable {
return operation.then(Mono.empty());
}).subscribe(response -> {
- logger.verbose("connectionId[{}] linkName[{}] response[{}] Token refreshed.",
- handler.getConnectionId(), getLinkName(), response);
+ logger.atVerbose().addKeyValue("response", response)
+ .log("Token refreshed.");
}, error -> {
}, () -> {
- logger.verbose("connectionId[{}] entityPath[{}] linkName[{}] Authorization completed. Disposing.",
- handler.getConnectionId(), entityPath, getLinkName());
+ logger.verbose(" Authorization completed. Disposing.");
closeAsync("Authorization completed. Disposing.", null).subscribe();
}));
@@ -332,9 +338,7 @@ public Mono getLinkSize() {
if (remoteMaxMessageSize != null) {
linkSize = remoteMaxMessageSize.intValue();
} else {
- logger.warning("connectionId[{}], linkName[{}]: Could not get the getRemoteMaxMessageSize."
- + " Returning current link size: {}", handler.getConnectionId(), handler.getLinkName(),
- linkSize);
+ logger.warning("Could not get the getRemoteMaxMessageSize. Returning current link size: {}",linkSize);
}
return linkSize;
@@ -385,10 +389,8 @@ Mono closeAsync(String message, ErrorCondition errorCondition) {
return isClosedMono.asMono();
}
- final String condition = errorCondition != null ? errorCondition.toString() : NOT_APPLICABLE;
- logger.verbose("connectionId[{}], path[{}], linkName[{}] errorCondition[{}]. Setting error condition and "
- + "disposing. {}",
- handler.getConnectionId(), entityPath, getLinkName(), condition, message);
+ addErrorCondition(logger.atVerbose(), errorCondition)
+ .log("Setting error condition and disposing. {}", message);
final Runnable closeWork = () -> {
if (errorCondition != null && sender.getCondition() == null) {
@@ -404,14 +406,12 @@ Mono closeAsync(String message, ErrorCondition errorCondition) {
try {
reactorProvider.getReactorDispatcher().invoke(closeWork);
} catch (IOException e) {
- logger.warning("connectionId[{}] entityPath[{}] linkName[{}]: Could not schedule close work. Running"
- + " manually. And completing close.", handler.getConnectionId(), entityPath, getLinkName(), e);
+ logger.warning("Could not schedule close work. Running manually. And completing close.", e);
closeWork.run();
handleClose();
} catch (RejectedExecutionException e) {
- logger.info("connectionId[{}] entityPath[{}] linkName[{}]: RejectedExecutionException scheduling close"
- + " work. And completing close.", handler.getConnectionId(), entityPath, getLinkName());
+ logger.info("RejectedExecutionException scheduling close work. And completing close.");
closeWork.run();
handleClose();
@@ -488,9 +488,9 @@ private void processSendWork() {
if (workItem == null) {
if (deliveryTag != null) {
- logger.verbose(
- "clientId[{}]. path[{}], linkName[{}], deliveryTag[{}]: sendData not found for this delivery.",
- handler.getConnectionId(), entityPath, getLinkName(), deliveryTag);
+ logger.atVerbose()
+ .addKeyValue(DELIVERY_TAG_KEY, deliveryTag)
+ .log("sendData not found for this delivery.");
}
//TODO (conniey): Should we update to continue rather than break?
@@ -519,18 +519,19 @@ private void processSendWork() {
}
if (linkAdvance) {
- logger.verbose("entityPath[{}], linkName[{}], deliveryTag[{}]: Sent message", entityPath,
- getLinkName(), deliveryTag);
+ logger.atVerbose()
+ .addKeyValue(DELIVERY_TAG_KEY, deliveryTag)
+ .log("Sent message.");
workItem.setWaitingForAck();
scheduler.schedule(new SendTimeout(deliveryTag), retryOptions.getTryTimeout().toMillis(),
TimeUnit.MILLISECONDS);
} else {
- logger.verbose(
- "clientId[{}]. path[{}], linkName[{}], deliveryTag[{}], sentMessageSize[{}], "
- + "payloadActualSize[{}]: sendlink advance failed",
- handler.getConnectionId(), entityPath, getLinkName(), deliveryTag, sentMsgSize,
- workItem.getEncodedMessageSize());
+ logger.atVerbose()
+ .addKeyValue(DELIVERY_TAG_KEY, deliveryTag)
+ .addKeyValue("sentMessageSize", sentMsgSize)
+ .addKeyValue("payloadActualSize", workItem.getEncodedMessageSize())
+ .log("Sendlink advance failed.");
if (delivery != null) {
delivery.free();
@@ -554,14 +555,17 @@ private void processDeliveredMessage(Delivery delivery) {
final DeliveryState outcome = delivery.getRemoteState();
final String deliveryTag = new String(delivery.getTag(), UTF_8);
- logger.verbose("entityPath[{}], linkName[{}], deliveryTag[{}]: process delivered message",
- entityPath, getLinkName(), deliveryTag);
+ logger.atVerbose()
+ .addKeyValue(DELIVERY_TAG_KEY, deliveryTag)
+ .log("Process delivered message.");
final RetriableWorkItem workItem = pendingSendsMap.remove(deliveryTag);
if (workItem == null) {
- logger.verbose("clientId[{}]. path[{}], linkName[{}], delivery[{}] - mismatch (or send timed out)",
- handler.getConnectionId(), entityPath, getLinkName(), deliveryTag);
+ logger.atVerbose()
+ .addKeyValue(DELIVERY_TAG_KEY, deliveryTag)
+ .log("Mismatch (or send timed out.");
+
return;
} else if (workItem.isDeliveryStateProvided()) {
workItem.success(outcome);
@@ -582,8 +586,10 @@ private void processDeliveredMessage(Delivery delivery) {
final Exception exception = ExceptionUtil.toException(error.getCondition().toString(),
error.getDescription(), handler.getErrorContext(sender));
- logger.warning("entityPath[{}], linkName[{}], deliveryTag[{}]: Delivery rejected. [{}]",
- entityPath, getLinkName(), deliveryTag, rejected);
+ logger.atWarning()
+ .addKeyValue(DELIVERY_TAG_KEY, deliveryTag)
+ .addKeyValue("rejected", rejected)
+ .log("Delivery rejected.");
final int retryAttempt;
if (isGeneralSendError(error.getCondition())) {
@@ -630,11 +636,10 @@ private void scheduleWorkOnDispatcher() {
try {
reactorProvider.getReactorDispatcher().invoke(this::processSendWork);
} catch (IOException e) {
- logger.warning("connectionId[{}] linkName[{}]: Error scheduling work on reactor.",
- handler.getConnectionId(), getLinkName(), e);
+ logger.warning("Error scheduling work on reactor.", e);
+
} catch (RejectedExecutionException e) {
- logger.info("connectionId[{}] linkName[{}]: Error scheduling work on reactor because of"
- + " RejectedExecutionException.", handler.getConnectionId(), getLinkName());
+ logger.info("Error scheduling work on reactor because of RejectedExecutionException.");
}
}
@@ -645,8 +650,7 @@ private void cleanupFailedSend(final RetriableWorkItem workItem, final Exception
private void completeClose() {
isClosedMono.emitEmpty((signalType, result) -> {
- logger.warning("connectionId[{}], signal[{}], result[{}]. Unable to emit shutdown signal.",
- handler.getConnectionId(), signalType, result);
+ logger.warning("Unable to emit shutdown signal.");
return false;
});
@@ -664,11 +668,11 @@ private void completeClose() {
*/
private void handleError(Throwable error) {
synchronized (pendingSendLock) {
- final String logMessage = isDisposed.getAndSet(true)
- ? "This was already disposed. Dropping error."
- : String.format("Disposing of '%d' pending sends with error.", pendingSendsMap.size());
- logger.verbose("connectionId[{}] entityPath[{}] linkName[{}] {}", handler.getConnectionId(), entityPath,
- getLinkName(), logMessage);
+ if (isDisposed.getAndSet(true)) {
+ logger.verbose("This was already disposed. Dropping error.");
+ } else {
+ logger.verbose("Disposing of '{}' pending sends with error.", pendingSendsMap.size());
+ }
pendingSendsMap.forEach((key, value) -> value.error(error));
pendingSendsMap.clear();
@@ -684,12 +688,11 @@ private void handleClose() {
final AmqpErrorContext context = handler.getErrorContext(sender);
synchronized (pendingSendLock) {
- final String logMessage = isDisposed.getAndSet(true)
- ? "This was already disposed."
- : String.format("Disposing of '%d' pending sends.", pendingSendsMap.size());
-
- logger.verbose("connectionId[{}] entityPath[{}] linkName[{}] {}", handler.getConnectionId(), entityPath,
- getLinkName(), logMessage);
+ if (isDisposed.getAndSet(true)) {
+ logger.verbose("This was already disposed.");
+ } else {
+ logger.verbose("Disposing of '{}' pending sends.", pendingSendsMap.size());
+ }
pendingSendsMap.forEach((key, value) -> value.error(new AmqpException(true, message, context)));
pendingSendsMap.clear();
diff --git a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ReactorSession.java b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ReactorSession.java
index 3048850cd041..5e71fef941a6 100644
--- a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ReactorSession.java
+++ b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ReactorSession.java
@@ -18,6 +18,7 @@
import com.azure.core.amqp.implementation.handler.SendLinkHandler;
import com.azure.core.amqp.implementation.handler.SessionHandler;
import com.azure.core.util.logging.ClientLogger;
+import com.azure.core.util.logging.LoggingEventBuilder;
import org.apache.qpid.proton.amqp.Symbol;
import org.apache.qpid.proton.amqp.messaging.Source;
import org.apache.qpid.proton.amqp.messaging.Target;
@@ -50,7 +51,14 @@
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Consumer;
+import static com.azure.core.amqp.implementation.AmqpLoggingUtils.addSignalTypeAndResult;
+import static com.azure.core.amqp.implementation.ClientConstants.CONNECTION_ID_KEY;
+import static com.azure.core.amqp.implementation.ClientConstants.ENTITY_PATH_KEY;
+import static com.azure.core.amqp.implementation.ClientConstants.LINK_NAME_KEY;
+import static com.azure.core.amqp.implementation.AmqpLoggingUtils.addErrorCondition;
import static com.azure.core.amqp.implementation.ClientConstants.NOT_APPLICABLE;
+import static com.azure.core.amqp.implementation.ClientConstants.SESSION_NAME_KEY;
+import static com.azure.core.util.FluxUtil.monoError;
/**
* Represents an AMQP session using proton-j reactor.
@@ -69,7 +77,7 @@ public class ReactorSession implements AmqpSession {
*/
private final Sinks.Empty isClosedMono = Sinks.empty();
- private final ClientLogger logger = new ClientLogger(ReactorSession.class);
+ private final ClientLogger logger;
private final Flux endpointStates;
private final AmqpConnection amqpConnection;
@@ -120,10 +128,15 @@ public ReactorSession(AmqpConnection amqpConnection, Session session, SessionHan
"ReactorSession connectionId[%s], session[%s]: Retries exhausted waiting for ACTIVE endpoint state.",
sessionHandler.getConnectionId(), sessionName);
+ this.logger = new ClientLogger(ReactorSession.class, Map.of(CONNECTION_ID_KEY, this.sessionHandler.getConnectionId()));
+
this.endpointStates = sessionHandler.getEndpointStates()
.map(state -> {
- logger.verbose("connectionId[{}], sessionName[{}], state[{}]", sessionHandler.getConnectionId(),
- sessionName, state);
+ logger.atVerbose()
+ .addKeyValue(SESSION_NAME_KEY, sessionName)
+ .addKeyValue("state", state)
+ .log("Got endpoint state.");
+
return AmqpEndpointStateUtil.getConnectionState(state);
})
.doOnError(error -> handleError(error))
@@ -210,9 +223,7 @@ public Mono rollbackTransaction(AmqpTransaction transaction) {
@Override
public Mono createProducer(String linkName, String entityPath, Duration timeout, AmqpRetryPolicy retry) {
return createProducer(linkName, entityPath, timeout, retry, null)
- .or(onClosedError(String.format(
- "connectionId[%s] entityPath[%s] linkName[%s] Connection closed while waiting for new producer link.",
- sessionHandler.getConnectionId(), entityPath, linkName)));
+ .or(onClosedError("Connection closed while waiting for new producer link.", entityPath, linkName));
}
/**
@@ -222,9 +233,7 @@ public Mono createProducer(String linkName, String entityPath, Duratio
public Mono createConsumer(String linkName, String entityPath, Duration timeout, AmqpRetryPolicy retry) {
return createConsumer(linkName, entityPath, timeout, retry, null, null, null,
SenderSettleMode.UNSETTLED, ReceiverSettleMode.SECOND)
- .or(onClosedError(String.format(
- "connectionId[%s] entityPath[%s] linkName[%s] Connection closed while waiting for new receive link.",
- sessionHandler.getConnectionId(), entityPath, linkName)))
+ .or(onClosedError("Connection closed while waiting for new receive link.", entityPath, linkName))
.cast(AmqpLink.class);
}
@@ -255,22 +264,23 @@ Mono closeAsync(String message, ErrorCondition errorCondition, boolean dis
return isClosedMono.asMono();
}
- final String condition = errorCondition != null ? errorCondition.toString() : NOT_APPLICABLE;
- logger.verbose("connectionId[{}], sessionName[{}], errorCondition[{}]. Setting error condition and "
- + "disposing session. {}",
- sessionHandler.getConnectionId(), sessionName, condition, message != null ? message : "");
+ addErrorCondition(logger.atVerbose(), errorCondition)
+ .addKeyValue(SESSION_NAME_KEY, sessionName)
+ .log("Disposing session. {}", message != null ? message : "");
return Mono.fromRunnable(() -> {
try {
provider.getReactorDispatcher().invoke(() -> disposeWork(errorCondition, disposeLinks));
} catch (IOException e) {
- logger.info("connectionId[{}] sessionName[{}] Error while scheduling work. Manually disposing.",
- sessionHandler.getConnectionId(), sessionName, e);
+ addErrorCondition(logger.atInfo(), errorCondition)
+ .addKeyValue(SESSION_NAME_KEY, sessionName)
+ .log("Error while scheduling work. Manually disposing.", e);
disposeWork(errorCondition, disposeLinks);
} catch (RejectedExecutionException e) {
- logger.info("connectionId[{}] sessionName[{}] RejectedExecutionException when scheduling work.",
- sessionHandler.getConnectionId(), sessionName);
+ logger.atInfo()
+ .addKeyValue(SESSION_NAME_KEY, sessionName)
+ .log("RejectedExecutionException when scheduling work.");
disposeWork(errorCondition, disposeLinks);
}
@@ -283,16 +293,18 @@ Mono closeAsync(String message, ErrorCondition errorCondition, boolean dis
@Override
public Mono extends AmqpTransactionCoordinator> getOrCreateTransactionCoordinator() {
if (isDisposed()) {
- return Mono.error(logger.logExceptionAsError(new AmqpException(true, String.format(
- "connectionId[%s] sessionName[%s] Cannot create coordinator send link '%s' from a closed session.",
- sessionHandler.getConnectionId(), sessionName, TRANSACTION_LINK_NAME),
- sessionHandler.getErrorContext())));
+ return Mono.error(logger.atError()
+ .addKeyValue(SESSION_NAME_KEY, sessionName)
+ .log(new AmqpException(true,
+ String.format("Cannot create coordinator send link %s from a closed session.", TRANSACTION_LINK_NAME),
+ sessionHandler.getErrorContext())));
}
final TransactionCoordinator existing = transactionCoordinator.get();
if (existing != null) {
- logger.verbose("connectionId[{}] coordinator[{}]: Returning existing transaction coordinator.",
- sessionHandler.getConnectionId(), TRANSACTION_LINK_NAME);
+ logger.atVerbose()
+ .addKeyValue("coordinator", TRANSACTION_LINK_NAME)
+ .log("Returning existing transaction coordinator.");
return Mono.just(existing);
}
@@ -306,9 +318,7 @@ public Mono extends AmqpTransactionCoordinator> getOrCreateTransactionCoordina
return transactionCoordinator.get();
}
})
- .or(onClosedError(String.format(
- "connectionId[%s] Connection closed while waiting for transaction coordinator creation.",
- sessionHandler.getConnectionId())));
+ .or(onClosedError("Connection closed while waiting for transaction coordinator creation.", NOT_APPLICABLE, NOT_APPLICABLE));
}
/**
@@ -338,15 +348,20 @@ protected Mono createConsumer(String linkName, String entityPat
ReceiverSettleMode receiverSettleMode) {
if (isDisposed()) {
- return Mono.error(logger.logExceptionAsError(new AmqpException(true, String.format(
- "connectionId[%s] sessionName[%s] entityPath[%s] linkName[%s] Cannot create receive link from a closed"
- + " session.", sessionHandler.getConnectionId(), sessionName, entityPath, linkName),
- sessionHandler.getErrorContext())));
+ LoggingEventBuilder logBuilder = logger.atError()
+ .addKeyValue(SESSION_NAME_KEY, sessionName)
+ .addKeyValue(ENTITY_PATH_KEY, entityPath)
+ .addKeyValue(LINK_NAME_KEY, linkName);
+
+ return monoError(logBuilder, new AmqpException(true, "Cannot create receive link from a closed session.", sessionHandler.getErrorContext()));
}
final LinkSubscription existingLink = openReceiveLinks.get(linkName);
if (existingLink != null) {
- logger.info("linkName[{}] entityPath[{}] Returning existing receive link.", linkName, entityPath);
+ logger.atInfo()
+ .addKeyValue(LINK_NAME_KEY, linkName)
+ .addKeyValue(ENTITY_PATH_KEY, entityPath)
+ .log("Returning existing receive link.");
return Mono.just(existingLink.getLink());
}
@@ -360,15 +375,19 @@ protected Mono createConsumer(String linkName, String entityPat
final LinkSubscription computed = openReceiveLinks.compute(linkName,
(linkNameKey, existing) -> {
if (existing != null) {
- logger.info("linkName[{}]: Another receive link exists. Disposing of new one.",
- linkName);
+ logger.atInfo()
+ .addKeyValue(LINK_NAME_KEY, linkName)
+ .log("Another receive link exists. Disposing of new one.");
tokenManager.close();
return existing;
}
- logger.info("connectionId[{}] sessionId[{}] linkName[{}] Creating a new receiver link.",
- sessionHandler.getConnectionId(), sessionName, linkName);
+ logger.atInfo()
+ .addKeyValue(SESSION_NAME_KEY, sessionName)
+ .addKeyValue(LINK_NAME_KEY, linkName)
+ .log("Creating a new receiver link.");
+
return getSubscription(linkNameKey, entityPath, sourceFilters, receiverProperties,
receiverDesiredCapabilities, senderSettleMode, receiverSettleMode, tokenManager);
});
@@ -428,16 +447,18 @@ private Mono createProducer(String linkName, String entityPath,
Map linkProperties, boolean requiresAuthorization) {
if (isDisposed()) {
- return Mono.error(logger.logExceptionAsError(new AmqpException(true,
- String.format(
- "connectionId[%s] sessionName[%s] entityPath[%s] linkName[%s] Cannot create send link from a closed"
- + " session.", sessionHandler.getConnectionId(), sessionName, entityPath, linkName),
- sessionHandler.getErrorContext())));
+ LoggingEventBuilder logBuilder = logger.atError()
+ .addKeyValue(SESSION_NAME_KEY, sessionName)
+ .addKeyValue(ENTITY_PATH_KEY, entityPath)
+ .addKeyValue(LINK_NAME_KEY, linkName);
+ return monoError(logBuilder, new AmqpException(true, "Cannot create send link from a closed session.", sessionHandler.getErrorContext()));
}
final LinkSubscription existing = openSendLinks.get(linkName);
if (existing != null) {
- logger.verbose("linkName[{}]: Returning existing send link.", linkName);
+ logger.atVerbose()
+ .addKeyValue(LINK_NAME_KEY, linkName)
+ .log("Returning existing send link.");
return Mono.just(existing.getLink());
}
@@ -459,8 +480,9 @@ private Mono createProducer(String linkName, String entityPath,
final LinkSubscription computed = openSendLinks.compute(linkName,
(linkNameKey, existingLink) -> {
if (existingLink != null) {
- logger.info("linkName[{}]: Another send link exists. Disposing of new one.",
- linkName);
+ logger.atInfo()
+ .addKeyValue(LINK_NAME_KEY, linkName)
+ .log("Another send link exists. Disposing of new one.");
if (tokenManager != null) {
tokenManager.close();
@@ -468,8 +490,11 @@ private Mono createProducer(String linkName, String entityPath,
return existingLink;
}
- logger.info("connectionId[{}] sessionId[{}] linkName[{}] Creating a new send link.",
- sessionHandler.getConnectionId(), sessionName, linkName);
+ logger.atInfo()
+ .addKeyValue(LINK_NAME_KEY, linkName)
+ .addKeyValue(SESSION_NAME_KEY, sessionName)
+ .log("Creating a new send link.");
+
return getSubscription(linkName, entityPath, target, linkProperties, options,
tokenManager);
});
@@ -517,7 +542,10 @@ private LinkSubscription getSubscription(String linkName, String e
}
}, () -> {
if (!isDisposed.get()) {
- logger.info("linkName[{}]: Complete. Removing and disposing send link.", linkName);
+ logger.atInfo()
+ .addKeyValue(LINK_NAME_KEY, linkName)
+ .log("Complete. Removing and disposing send link.");
+
removeLink(openSendLinks, linkName);
}
});
@@ -577,8 +605,10 @@ private LinkSubscription getSubscription(String linkName, Strin
}
}, () -> {
if (!isDisposed.get()) {
- logger.info("linkName[{}] entityPath[{}]: Complete. Removing receive link.",
- linkName, entityPath);
+ logger.atInfo()
+ .addKeyValue(LINK_NAME_KEY, linkName)
+ .addKeyValue(ENTITY_PATH_KEY, entityPath)
+ .log("Complete. Removing receive link.");
removeLink(openReceiveLinks, linkName);
}
@@ -595,10 +625,10 @@ private LinkSubscription getSubscription(String linkName, Strin
*
* @return A Mono that completes when the shutdown signal is emitted. If it does, returns an error.
*/
- private Mono onClosedError(String message) {
+ private Mono onClosedError(String message, String linkName, String entityPath) {
return Mono.firstWithSignal(isClosedMono.asMono(), shutdownSignals.next())
.then(Mono.error(new AmqpException(false,
- String.format("connectionId[%s] Connection closed. %s", sessionHandler.getConnectionId(), message),
+ String.format("connectionId[%s] entityPath[%s] linkName[%s] Connection closed. %s", sessionHandler.getConnectionId(), entityPath, linkName, message),
sessionHandler.getErrorContext())));
}
@@ -614,16 +644,18 @@ private Mono onActiveEndpoint() {
}
private void handleClose() {
- logger.verbose(
- "connectionId[{}] sessionName[{}] Disposing of active send and receive links due to session close.",
- sessionHandler.getConnectionId(), sessionName);
+ logger.atVerbose()
+ .addKeyValue(SESSION_NAME_KEY, sessionName)
+ .log("Disposing of active send and receive links due to session close.");
closeAsync().subscribe();
}
private void handleError(Throwable error) {
- logger.verbose("connectionId[{}] sessionName[{}] Disposing of active links due to error.",
- sessionHandler.getConnectionId(), sessionName, error);
+ logger.atVerbose()
+ .addKeyValue(SESSION_NAME_KEY, sessionName)
+ .log("Disposing of active links due to error.");
+
final ErrorCondition condition;
if (error instanceof AmqpException) {
final AmqpException exception = ((AmqpException) error);
@@ -679,14 +711,17 @@ private void disposeWork(ErrorCondition errorCondition, boolean disposeLinks) {
// We want to complete the session so that the parent connection isn't waiting.
Mono closeLinksMono = Mono.when(closingLinks).timeout(retryOptions.getTryTimeout())
.onErrorResume(error -> {
- logger.warning("connectionId[{}] sessionName[{}] Timed out waiting for all links to close.",
- sessionHandler.getConnectionId(), sessionName, error);
+ logger.atWarning()
+ .addKeyValue(SESSION_NAME_KEY, sessionName)
+ .log("Timed out waiting for all links to close.", error);
return Mono.empty();
})
.then(Mono.fromRunnable(() -> {
isClosedMono.emitEmpty((signalType, result) -> {
- logger.warning("connectionId[{}] signal[{}] result[{}] Unable to emit shutdown signal.",
- sessionHandler.getConnectionId(), signalType, result);
+ addSignalTypeAndResult(logger.atWarning(), signalType, result)
+ .addKeyValue(SESSION_NAME_KEY, sessionName)
+ .log("Unable to emit shutdown signal.");
+
return false;
});
diff --git a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/RequestResponseChannel.java b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/RequestResponseChannel.java
index be296b85d981..f49f12062efc 100644
--- a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/RequestResponseChannel.java
+++ b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/RequestResponseChannel.java
@@ -47,6 +47,9 @@
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
+import static com.azure.core.amqp.implementation.ClientConstants.CONNECTION_ID_KEY;
+import static com.azure.core.amqp.implementation.ClientConstants.LINK_NAME_KEY;
+import static com.azure.core.amqp.implementation.AmqpLoggingUtils.addSignalTypeAndResult;
import static com.azure.core.util.FluxUtil.monoError;
import static java.nio.charset.StandardCharsets.UTF_8;
@@ -56,7 +59,7 @@
* link and {@link Receiver} link.
*/
public class RequestResponseChannel implements AsyncCloseable {
- private final ClientLogger logger = new ClientLogger(RequestResponseChannel.class);
+ private final ClientLogger logger;
private final Sender sendLink;
private final Receiver receiveLink;
@@ -89,8 +92,6 @@ public class RequestResponseChannel implements AsyncCloseable {
// those subscriptions should be disposed when the request-response-channel terminates.
private final Disposable.Composite subscriptions;
- private final String connectionId;
- private final String linkName;
private final AmqpRetryOptions retryOptions;
private final String replyTo;
private final String activeEndpointTimeoutMessage;
@@ -122,8 +123,7 @@ protected RequestResponseChannel(AmqpConnection amqpConnection, String connectio
AmqpRetryOptions retryOptions, ReactorHandlerProvider handlerProvider, ReactorProvider provider,
MessageSerializer messageSerializer, SenderSettleMode senderSettleMode,
ReceiverSettleMode receiverSettleMode) {
- this.connectionId = connectionId;
- this.linkName = linkName;
+ this.logger = new ClientLogger(RequestResponseChannel.class, Map.of(CONNECTION_ID_KEY, connectionId, LINK_NAME_KEY, linkName));
this.retryOptions = retryOptions;
this.provider = provider;
this.senderSettleMode = senderSettleMode;
@@ -169,8 +169,9 @@ protected RequestResponseChannel(AmqpConnection amqpConnection, String connectio
receiveLinkHandler.getDeliveredMessages()
.map(this::decodeDelivery)
.subscribe(message -> {
- logger.verbose("connectionId[{}], linkName[{}] messageId[{}]: Settling message.", connectionId,
- linkName, message.getCorrelationId());
+ logger.atVerbose()
+ .addKeyValue("messageId", message.getCorrelationId())
+ .log("Settling message.");
settleMessage(message);
}),
@@ -198,7 +199,7 @@ protected RequestResponseChannel(AmqpConnection amqpConnection, String connectio
//TODO (conniey): Do we need this if we already close the request response nodes when the
// connection.closeWork is executed? It would be preferred to get rid of this circular dependency.
amqpConnection.getShutdownSignals().next().flatMap(signal -> {
- logger.verbose("connectionId[{}] linkName[{}]: Shutdown signal received.", connectionId, linkName);
+ logger.verbose("Shutdown signal received.");
return closeAsync();
}).subscribe()
);
@@ -213,8 +214,7 @@ protected RequestResponseChannel(AmqpConnection amqpConnection, String connectio
this.receiveLink.open();
});
} catch (IOException | RejectedExecutionException e) {
- throw logger.logExceptionAsError(new RuntimeException(String.format(
- "connectionId[%s] linkName[%s]: Unable to open send and receive link.", connectionId, linkName), e));
+ throw logger.atError().log(new RuntimeException("Unable to open send and receive link.", e));
}
}
@@ -233,9 +233,8 @@ public Mono closeAsync() {
.timeout(retryOptions.getTryTimeout())
.onErrorResume(TimeoutException.class, error -> {
return Mono.fromRunnable(() -> {
- logger.info("connectionId[{}] linkName[{}] Timed out waiting for RequestResponseChannel to complete"
- + " closing. Manually closing.",
- connectionId, linkName);
+ logger.atInfo()
+ .log("Timed out waiting for RequestResponseChannel to complete closing. Manually closing.");
onTerminalState("SendLinkHandler");
onTerminalState("ReceiveLinkHandler");
@@ -244,25 +243,24 @@ public Mono closeAsync() {
.subscribeOn(Schedulers.boundedElastic());
if (isDisposed.getAndSet(true)) {
- logger.verbose("connectionId[{}] linkName[{}] Channel already closed.", connectionId, linkName);
+ logger.verbose("Channel already closed.");
return closeOperationWithTimeout;
}
- logger.verbose("connectionId[{}] linkName[{}] Closing request/response channel.", connectionId, linkName);
+ logger.verbose("Closing request/response channel.");
return Mono.fromRunnable(() -> {
try {
// Schedule API calls on proton-j entities on the ReactorThread associated with the connection.
provider.getReactorDispatcher().invoke(() -> {
- logger.verbose("connectionId[{}] linkName[{}] Closing send link and receive link.",
- connectionId, linkName);
+ logger.verbose("Closing send link and receive link.");
sendLink.close();
receiveLink.close();
});
} catch (IOException | RejectedExecutionException e) {
- logger.info("connectionId[{}] linkName[{}] Unable to schedule close work. Closing manually.",
- connectionId, linkName);
+ logger.info("Unable to schedule close work. Closing manually.");
+
sendLink.close();
receiveLink.close();
}
@@ -294,18 +292,17 @@ public Mono sendWithAck(final Message message) {
*/
public Mono sendWithAck(final Message message, DeliveryState deliveryState) {
if (isDisposed()) {
- return monoError(logger, new IllegalStateException(
- "Cannot send a message when request response channel is disposed."));
+ return monoError(logger.atError(), new IllegalStateException("Cannot send a message when request response channel is disposed."));
}
if (message == null) {
- return monoError(logger, new NullPointerException("message cannot be null"));
+ return monoError(logger.atError(), new NullPointerException("message cannot be null"));
}
if (message.getMessageId() != null) {
- return monoError(logger, new IllegalArgumentException("message.getMessageId() should be null"));
+ return monoError(logger.atError(), new IllegalArgumentException("message.getMessageId() should be null"));
}
if (message.getReplyTo() != null) {
- return monoError(logger, new IllegalArgumentException("message.getReplyTo() should be null"));
+ return monoError(logger.atError(), new IllegalArgumentException("message.getReplyTo() should be null"));
}
final UnsignedLong messageId = UnsignedLong.valueOf(requestId.incrementAndGet());
@@ -319,8 +316,9 @@ public Mono sendWithAck(final Message message, DeliveryState deliverySt
return RetryUtil.withRetry(onActiveEndpoints, retryOptions, activeEndpointTimeoutMessage)
.then(Mono.create(sink -> {
try {
- logger.verbose("connectionId[{}], linkName[{}] messageId[{}]: Scheduling on dispatcher. ",
- connectionId, linkName, messageId);
+ logger.atVerbose()
+ .addKeyValue("messageId", message.getCorrelationId())
+ .log("Scheduling on dispatcher.");
unconfirmedSends.putIfAbsent(messageId, sink);
// Schedule API calls on proton-j entities on the ReactorThread associated with the connection.
@@ -329,8 +327,9 @@ public Mono sendWithAck(final Message message, DeliveryState deliverySt
.replace("-", "").getBytes(UTF_8));
if (deliveryState != null) {
- logger.verbose("connectionId[{}], linkName[{}]: Setting delivery state as [{}].",
- connectionId, linkName, deliveryState);
+ logger.atVerbose()
+ .addKeyValue("state", deliveryState)
+ .log("Setting delivery state.");
delivery.setMessageFormat(DeliveryImpl.DEFAULT_MESSAGE_FORMAT);
delivery.disposition(deliveryState);
}
@@ -381,9 +380,9 @@ private void settleMessage(Message message) {
final MonoSink sink = unconfirmedSends.remove(correlationId);
if (sink == null) {
- logger.warning(
- "connectionId[{}] linkName[{}] messageId[{}] Received delivery without pending message.",
- connectionId, linkName, id);
+ logger.atWarning()
+ .addKeyValue("messageId", id)
+ .log("Received delivery without pending message.");
return;
}
@@ -395,12 +394,13 @@ private void handleError(Throwable error, String message) {
return;
}
- logger.error("connectionId[{}] linkName[{}] {} Disposing unconfirmed sends.", connectionId, linkName, message,
- error);
+ logger.atError()
+ .log("{} Disposing unconfirmed sends.", message, error);
endpointStates.emitError(error, (signalType, emitResult) -> {
- logger.warning("connectionId[{}] linkName[{}] signal[{}] result[{}] Could not emit error to sink.",
- connectionId, linkName, signalType, emitResult);
+ addSignalTypeAndResult(logger.atWarning(), signalType, emitResult)
+ .log("Could not emit error to sink.");
+
return false;
});
@@ -411,13 +411,15 @@ private void handleError(Throwable error, String message) {
private void onTerminalState(String handlerName) {
if (pendingLinkTerminations.get() <= 0) {
- logger.verbose("connectionId[{}] linkName[{}] Already disposed send/receive links.");
+ logger.atVerbose()
+ .log("Already disposed send/receive links.");
+
return;
}
final int remaining = pendingLinkTerminations.decrementAndGet();
- logger.verbose("connectionId[{}] linkName[{}] {} disposed. Remaining: {}",
- connectionId, linkName, handlerName, remaining);
+ logger.atVerbose()
+ .log("{} disposed. Remaining: {}", handlerName, remaining);
if (remaining == 0) {
subscriptions.dispose();
@@ -435,9 +437,8 @@ private void onTerminalState(String handlerName) {
}
private boolean onEmitSinkFailure(SignalType signalType, Sinks.EmitResult emitResult, String message) {
- logger.verbose("connectionId[{}] linkName[{}] signal[{}] result[{}] {}",
- connectionId, linkName, signalType, emitResult, message);
-
+ addSignalTypeAndResult(logger.atVerbose(), signalType, emitResult)
+ .log(message);
return false;
}
@@ -450,8 +451,10 @@ private synchronized void updateEndpointState(AmqpEndpointState sendLinkState, A
this.receiveLinkState = receiveLinkState;
}
- logger.verbose("connectionId[{}] linkName[{}] sendState[{}] receiveState[{}] Updating endpoint states.",
- connectionId, linkName, this.sendLinkState, this.receiveLinkState);
+ logger.atVerbose()
+ .addKeyValue("sendState", this.sendLinkState)
+ .addKeyValue("receiveState", this.receiveLinkState)
+ .log("Updating endpoint states.");
if (this.sendLinkState == this.receiveLinkState) {
this.endpointStates.emitNext(this.sendLinkState, Sinks.EmitFailureHandler.FAIL_FAST);
@@ -460,8 +463,8 @@ private synchronized void updateEndpointState(AmqpEndpointState sendLinkState, A
// Terminate the unconfirmed MonoSinks by notifying the given error.
private void terminateUnconfirmedSends(Throwable error) {
- logger.verbose("connectionId[{}] linkName[{}] terminating {} unconfirmed sends (reason: {}).",
- connectionId, linkName, unconfirmedSends.size(), error.getMessage());
+ logger.atVerbose()
+ .log("Terminating {} unconfirmed sends (reason: {}).", unconfirmedSends.size(), error.getMessage());
Map.Entry> next;
int count = 0;
while ((next = unconfirmedSends.pollFirstEntry()) != null) {
@@ -469,8 +472,9 @@ private void terminateUnconfirmedSends(Throwable error) {
next.getValue().error(error);
count++;
}
+
// The below log can also help debug if the external code that error() calls into never return.
- logger.verbose("connectionId[{}] linkName[{}] completed the termination of {} unconfirmed sends (reason: {}).",
- connectionId, linkName, count, error.getMessage());
+ logger.atVerbose()
+ .log("completed the termination of {} unconfirmed sends (reason: {}).", count, error.getMessage());
}
}
diff --git a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/ConnectionHandler.java b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/ConnectionHandler.java
index 3e529e475a7d..daa074bac0e1 100644
--- a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/ConnectionHandler.java
+++ b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/ConnectionHandler.java
@@ -29,6 +29,10 @@
import java.util.Map;
import java.util.Objects;
+import static com.azure.core.amqp.implementation.AmqpLoggingUtils.addErrorCondition;
+import static com.azure.core.amqp.implementation.ClientConstants.FULLY_QUALIFIED_NAMESPACE_KEY;
+import static com.azure.core.amqp.implementation.ClientConstants.HOSTNAME_KEY;
+
/**
* Creates an AMQP connection using sockets.
*/
@@ -57,8 +61,7 @@ public class ConnectionHandler extends Handler {
public ConnectionHandler(final String connectionId, final ConnectionOptions connectionOptions,
SslPeerDetails peerDetails) {
super(connectionId,
- Objects.requireNonNull(connectionOptions, "'connectionOptions' cannot be null.").getHostname(),
- new ClientLogger(ConnectionHandler.class));
+ Objects.requireNonNull(connectionOptions, "'connectionOptions' cannot be null.").getHostname(), ConnectionHandler.class.getName());
add(new Handshaker());
this.connectionOptions = connectionOptions;
@@ -131,8 +134,7 @@ protected void addTransportLayers(Event event, TransportInternal transport) {
try {
defaultSslContext = SSLContext.getDefault();
} catch (NoSuchAlgorithmException e) {
- throw logger.logExceptionAsError(new RuntimeException(
- "Default SSL algorithm not found in JRE. Please check your JRE setup.", e));
+ throw logger.atError().log(new RuntimeException("Default SSL algorithm not found in JRE. Please check your JRE setup.", e));
}
}
@@ -150,10 +152,10 @@ protected void addTransportLayers(Event event, TransportInternal transport) {
sslDomain.setSslContext(defaultSslContext);
sslDomain.setPeerAuthentication(SslDomain.VerifyMode.VERIFY_PEER);
} else if (verifyMode == SslDomain.VerifyMode.ANONYMOUS_PEER) {
- logger.warning("connectionId[{}] '{}' is not secure.", getConnectionId(), verifyMode);
+ logger.warning("'{}' is not secure.", verifyMode);
sslDomain.setPeerAuthentication(SslDomain.VerifyMode.ANONYMOUS_PEER);
} else {
- throw logger.logExceptionAsError(new UnsupportedOperationException(
+ throw logger.atError().log(new UnsupportedOperationException(
"verifyMode is not supported: " + verifyMode));
}
@@ -162,12 +164,14 @@ protected void addTransportLayers(Event event, TransportInternal transport) {
@Override
public void onConnectionInit(Event event) {
- logger.info("onConnectionInit connectionId[{}] hostname[{}] amqpHostname[{}]",
- getConnectionId(), getHostname(), connectionOptions.getFullyQualifiedNamespace());
+ logger.atInfo()
+ .addKeyValue(HOSTNAME_KEY, getHostname())
+ .addKeyValue(FULLY_QUALIFIED_NAMESPACE_KEY, connectionOptions.getFullyQualifiedNamespace())
+ .log("onConnectionInit");
final Connection connection = event.getConnection();
if (connection == null) {
- logger.warning("connectionId[{}] Underlying connection is null. Should not be possible.");
+ logger.warning("Underlying connection is null. Should not be possible.");
close();
return;
}
@@ -188,8 +192,10 @@ public void onConnectionInit(Event event) {
public void onConnectionBound(Event event) {
final Transport transport = event.getTransport();
- logger.info("onConnectionBound connectionId[{}] hostname[{}] peerDetails[{}:{}]", getConnectionId(),
- getHostname(), peerDetails.getHostname(), peerDetails.getPort());
+ logger.atInfo()
+ .addKeyValue(HOSTNAME_KEY, getHostname())
+ .addKeyValue("peerDetails", () -> peerDetails.getHostname() + ":" + peerDetails.getPort())
+ .log("onConnectionBound");
this.addTransportLayers(event, (TransportInternal) transport);
@@ -202,8 +208,11 @@ public void onConnectionBound(Event event) {
@Override
public void onConnectionUnbound(Event event) {
final Connection connection = event.getConnection();
- logger.info("onConnectionUnbound hostname[{}], connectionId[{}], state[{}], remoteState[{}]",
- connection.getHostname(), getConnectionId(), connection.getLocalState(), connection.getRemoteState());
+ logger.atInfo()
+ .addKeyValue(HOSTNAME_KEY, connection.getHostname())
+ .addKeyValue("localState", connection.getLocalState())
+ .addKeyValue("remoteState", connection.getRemoteState())
+ .log("onConnectionUnbound");
// if failure happened while establishing transport - nothing to free up.
if (connection.getRemoteState() != EndpointState.UNINITIALIZED) {
@@ -219,10 +228,9 @@ public void onTransportError(Event event) {
final Transport transport = event.getTransport();
final ErrorCondition condition = transport.getCondition();
- logger.warning("onTransportError hostname[{}], connectionId[{}], error[{}]",
- connection != null ? connection.getHostname() : ClientConstants.NOT_APPLICABLE,
- getConnectionId(),
- condition != null ? condition.getDescription() : ClientConstants.NOT_APPLICABLE);
+ addErrorCondition(logger.atWarning(), condition)
+ .addKeyValue(HOSTNAME_KEY, connection.getHostname())
+ .log("onTransportError");
if (connection != null) {
notifyErrorContext(connection, condition);
@@ -238,10 +246,9 @@ public void onTransportClosed(Event event) {
final Transport transport = event.getTransport();
final ErrorCondition condition = transport.getCondition();
- logger.info("onTransportClosed hostname[{}], connectionId[{}], error[{}]",
- connection != null ? connection.getHostname() : ClientConstants.NOT_APPLICABLE,
- getConnectionId(),
- condition != null ? condition.getDescription() : ClientConstants.NOT_APPLICABLE);
+ addErrorCondition(logger.atInfo(), condition)
+ .addKeyValue(HOSTNAME_KEY, connection.getHostname())
+ .log("onTransportClosed");
if (connection != null) {
notifyErrorContext(connection, condition);
@@ -260,8 +267,10 @@ public void onConnectionLocalOpen(Event event) {
public void onConnectionRemoteOpen(Event event) {
final Connection connection = event.getConnection();
- logger.info("onConnectionRemoteOpen hostname[{}], connectionId[{}], remoteContainer[{}]",
- connection.getHostname(), getConnectionId(), connection.getRemoteContainer());
+ logger.atInfo()
+ .addKeyValue(HOSTNAME_KEY, connection.getHostname())
+ .addKeyValue("remoteContainer", connection.getRemoteContainer())
+ .log("onConnectionRemoteOpen");
onNext(connection.getRemoteState());
}
@@ -317,8 +326,7 @@ private void notifyErrorContext(Connection connection, ErrorCondition condition)
}
if (condition == null) {
- throw logger.logExceptionAsError(new IllegalStateException(String.format(
- "connectionId[%s]: notifyErrorContext does not have an ErrorCondition.", getConnectionId())));
+ throw logger.atError().log(new IllegalStateException("notifyErrorContext does not have an ErrorCondition."));
}
// if the remote-peer abruptly closes the connection without issuing close frame issue one
@@ -329,11 +337,8 @@ private void notifyErrorContext(Connection connection, ErrorCondition condition)
}
private void logErrorCondition(String eventName, Connection connection, ErrorCondition error) {
- logger.info("{} connectionId[{}] hostname[{}] errorCondition[{}] errorDescription[{}]",
- eventName,
- getConnectionId(),
- connection.getHostname(),
- error != null ? error.getCondition() : ClientConstants.NOT_APPLICABLE,
- error != null ? error.getDescription() : ClientConstants.NOT_APPLICABLE);
+ addErrorCondition(logger.atInfo(), error)
+ .addKeyValue(HOSTNAME_KEY, connection.getHostname())
+ .log(eventName);
}
}
diff --git a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/CustomIOHandler.java b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/CustomIOHandler.java
index 1258d7698783..4b102e3954b7 100644
--- a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/CustomIOHandler.java
+++ b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/CustomIOHandler.java
@@ -9,14 +9,17 @@
import org.apache.qpid.proton.engine.Transport;
import org.apache.qpid.proton.reactor.impl.IOHandler;
+import java.util.Map;
+
+import static com.azure.core.amqp.implementation.ClientConstants.CONNECTION_ID_KEY;
+import static com.azure.core.amqp.implementation.ClientConstants.HOSTNAME_KEY;
import static com.azure.core.amqp.implementation.ClientConstants.NOT_APPLICABLE;
public class CustomIOHandler extends IOHandler {
- private final ClientLogger logger = new ClientLogger(CustomIOHandler.class);
- private final String connectionId;
+ private final ClientLogger logger;
public CustomIOHandler(final String connectionId) {
- this.connectionId = connectionId;
+ this.logger = new ClientLogger(CustomIOHandler.class, Map.of(CONNECTION_ID_KEY, connectionId));
}
@Override
@@ -24,8 +27,9 @@ public void onTransportClosed(Event event) {
final Transport transport = event.getTransport();
final Connection connection = event.getConnection();
- logger.info("onTransportClosed connectionId[{}], hostname[{}]",
- connectionId, (connection != null ? connection.getHostname() : NOT_APPLICABLE));
+ logger.atInfo()
+ .addKeyValue(HOSTNAME_KEY, connection != null ? connection.getHostname() : NOT_APPLICABLE)
+ .log("onTransportClosed");
if (transport != null && connection != null && connection.getTransport() != null) {
transport.unbind();
@@ -40,7 +44,7 @@ public void onUnhandled(Event event) {
try {
super.onUnhandled(event);
} catch (NullPointerException e) {
- logger.error("Exception occurred when handling event in super.", e);
+ logger.atError().log("Exception occurred when handling event in super.", e);
}
}
}
diff --git a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/Handler.java b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/Handler.java
index 4079b7a0892e..1282f0c2d9cd 100644
--- a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/Handler.java
+++ b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/Handler.java
@@ -10,9 +10,13 @@
import reactor.core.publisher.Sinks;
import java.io.Closeable;
+import java.util.Map;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicBoolean;
+import static com.azure.core.amqp.implementation.AmqpLoggingUtils.addSignalTypeAndResult;
+import static com.azure.core.amqp.implementation.ClientConstants.CONNECTION_ID_KEY;
+
/**
* Base class for all proton-j handlers.
*/
@@ -32,14 +36,15 @@ public abstract class Handler extends BaseHandler implements Closeable {
* @param hostname Hostname of the connection. This could be the DNS hostname or the IP address of the
* connection. Usually of the form {@literal ".service.windows.net"} but can change if the
* messages are brokered through an intermediary.
- * @param logger Logger to use for messages.
+ * @param loggerName loggerName to use.
*
* @throws NullPointerException if {@code connectionId}, {@code hostname}, or {@code logger} is null.
*/
- Handler(final String connectionId, final String hostname, ClientLogger logger) {
+ Handler(final String connectionId, final String hostname, final String loggerName) {
this.connectionId = Objects.requireNonNull(connectionId, "'connectionId' cannot be null.");
this.hostname = Objects.requireNonNull(hostname, "'hostname' cannot be null.");
- this.logger = Objects.requireNonNull(logger, "'logger' cannot be null.");
+ this.logger = new ClientLogger(Objects.requireNonNull(loggerName, "'loggerName' cannot be null."),
+ Map.of(CONNECTION_ID_KEY, connectionId));
}
/**
@@ -85,8 +90,8 @@ void onNext(EndpointState state) {
}
endpointStates.emitNext(state, (signalType, emitResult) -> {
- logger.verbose("connectionId[{}] signal[{}] result[{}] could not emit endpoint state.", connectionId,
- signalType, emitResult);
+ addSignalTypeAndResult(logger.atVerbose(), signalType, emitResult)
+ .log("could not emit endpoint state.");
return false;
});
@@ -103,8 +108,8 @@ void onError(Throwable error) {
}
endpointStates.emitError(error, (signalType, emitResult) -> {
- logger.warning("connectionId[{}] signal[{}] result[{}] Could not emit error.", connectionId,
- signalType, emitResult, error);
+ addSignalTypeAndResult(logger.atWarning(), signalType, emitResult)
+ .log("could not emit error.", error);
return false;
});
@@ -123,14 +128,15 @@ public void close() {
// This is fine in the case that someone called onNext(EndpointState.CLOSED) and then called handler.close().
// We want to ensure that the next endpoint subscriber does not believe the handler is alive still.
endpointStates.emitNext(EndpointState.CLOSED, (signalType, emitResult) -> {
- logger.info("connectionId[{}] signal[{}] result[{}] Could not emit closed endpoint state.", connectionId,
- signalType, emitResult);
+ addSignalTypeAndResult(logger.atInfo(), signalType, emitResult)
+ .log("Could not emit closed endpoint state.");
return false;
});
endpointStates.emitComplete((signalType, emitResult) -> {
- logger.verbose("connectionId[{}] result[{}] Could not emit complete.", connectionId, emitResult);
+ addSignalTypeAndResult(logger.atVerbose(), signalType, emitResult)
+ .log("Could not emit complete.");
return false;
});
diff --git a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/LinkHandler.java b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/LinkHandler.java
index 9727d822580f..9c584aff7ea8 100644
--- a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/LinkHandler.java
+++ b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/LinkHandler.java
@@ -15,6 +15,8 @@
import java.util.Objects;
import static com.azure.core.amqp.implementation.AmqpErrorCode.TRACKING_ID_PROPERTY;
+import static com.azure.core.amqp.implementation.ClientConstants.LINK_NAME_KEY;
+import static com.azure.core.amqp.implementation.AmqpLoggingUtils.addErrorCondition;
import static com.azure.core.amqp.implementation.ClientConstants.NOT_APPLICABLE;
/**
@@ -34,13 +36,13 @@ abstract class LinkHandler extends Handler {
* connection. Usually of the form {@literal ".service.windows.net"} but can change if the
* messages are brokered through an intermediary.
* @param entityPath The address within the message broker for this link.
- * @param logger Logger to use for messages.
+ * @param loggerName Logger name to use for messages.
*
* @throws NullPointerException if {@code connectionId}, {@code hostname}, {@code entityPath}, or {@code logger} is
* null.
*/
- LinkHandler(String connectionId, String hostname, String entityPath, ClientLogger logger) {
- super(connectionId, hostname, logger);
+ LinkHandler(String connectionId, String hostname, String entityPath, String loggerName) {
+ super(connectionId, hostname, loggerName);
this.entityPath = Objects.requireNonNull(entityPath, "'entityPath' cannot be null.");
}
@@ -49,11 +51,9 @@ public void onLinkLocalClose(Event event) {
final Link link = event.getLink();
final ErrorCondition condition = link.getCondition();
- logger.verbose("onLinkLocalClose connectionId[{}], linkName[{}], errorCondition[{}], errorDescription[{}]",
- getConnectionId(),
- link.getName(),
- condition != null ? condition.getCondition() : NOT_APPLICABLE,
- condition != null ? condition.getDescription() : NOT_APPLICABLE);
+ addErrorCondition(logger.atVerbose(), condition)
+ .addKeyValue(LINK_NAME_KEY, link.getName())
+ .log("onLinkLocalClose");
}
@Override
@@ -71,7 +71,9 @@ public void onLinkFinal(Event event) {
final String linkName = event != null && event.getLink() != null
? event.getLink().getName()
: NOT_APPLICABLE;
- logger.info("onLinkFinal connectionId[{}], linkName[{}]", getConnectionId(), linkName);
+ logger.atInfo()
+ .addKeyValue(LINK_NAME_KEY, linkName)
+ .log("onLinkFinal");
// Be explicit about wanting to call Handler.close(). When we receive onLinkFinal, the service and proton-j are
// releasing this link. So we want to complete the endpoint states.
@@ -93,14 +95,14 @@ private void handleRemoteLinkClosed(final String eventName, final Event event) {
final Link link = event.getLink();
final ErrorCondition condition = link.getRemoteCondition();
- logger.info("{} connectionId[{}] linkName[{}], errorCondition[{}] errorDescription[{}]",
- eventName, getConnectionId(), link.getName(),
- condition != null ? condition.getCondition() : NOT_APPLICABLE,
- condition != null ? condition.getDescription() : NOT_APPLICABLE);
+ addErrorCondition(logger.atInfo(), condition)
+ .addKeyValue(LINK_NAME_KEY, link.getName())
+ .log(eventName);
if (link.getLocalState() != EndpointState.CLOSED) {
- logger.info("connectionId[{}] linkName[{}] state[{}] Local link state is not closed.", getConnectionId(),
- link.getName(), link.getLocalState());
+ logger.atInfo()
+ .addKeyValue(LINK_NAME_KEY, link.getName())
+ .addKeyValue("state", link.getLocalState());
link.setCondition(condition);
link.close();
diff --git a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/ReactorHandler.java b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/ReactorHandler.java
index 5d8c9d9de74a..35d7774a3385 100644
--- a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/ReactorHandler.java
+++ b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/ReactorHandler.java
@@ -8,8 +8,11 @@
import org.apache.qpid.proton.engine.Event;
import org.apache.qpid.proton.reactor.Reactor;
+import java.util.Map;
import java.util.Objects;
+import static com.azure.core.amqp.implementation.ClientConstants.CONNECTION_ID_KEY;
+
/**
* Handler that sets the timeout period for waiting for Selectables.
*/
@@ -20,17 +23,16 @@ public class ReactorHandler extends BaseHandler {
*/
private static final int REACTOR_IO_POLL_TIMEOUT = 20;
- private final ClientLogger logger = new ClientLogger(ReactorHandler.class);
- private final String connectionId;
+ private final ClientLogger logger;
public ReactorHandler(final String connectionId) {
Objects.requireNonNull(connectionId);
- this.connectionId = connectionId;
+ this.logger = new ClientLogger(ReactorHandler.class, Map.of(CONNECTION_ID_KEY, connectionId));
}
@Override
public void onReactorInit(Event e) {
- logger.info("connectionId[{}] reactor.onReactorInit", connectionId);
+ logger.info("reactor.onReactorInit");
final Reactor reactor = e.getReactor();
reactor.setTimeout(REACTOR_IO_POLL_TIMEOUT);
@@ -38,6 +40,6 @@ public void onReactorInit(Event e) {
@Override
public void onReactorFinal(Event e) {
- logger.info("connectionId[{}] reactor.onReactorFinal. event: {}", connectionId, e);
+ logger.info("reactor.onReactorFinal. event: {}", e);
}
}
diff --git a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/ReceiveLinkHandler.java b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/ReceiveLinkHandler.java
index d9e83ed9d3d6..ac3b4b8582df 100644
--- a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/ReceiveLinkHandler.java
+++ b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/ReceiveLinkHandler.java
@@ -3,7 +3,7 @@
package com.azure.core.amqp.implementation.handler;
-import com.azure.core.util.logging.ClientLogger;
+import com.azure.core.util.logging.LoggingEventBuilder;
import org.apache.qpid.proton.amqp.Symbol;
import org.apache.qpid.proton.amqp.messaging.Modified;
import org.apache.qpid.proton.amqp.transport.ErrorCondition;
@@ -24,6 +24,11 @@
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;
+import static com.azure.core.amqp.implementation.AmqpLoggingUtils.addErrorCondition;
+import static com.azure.core.amqp.implementation.ClientConstants.ENTITY_PATH_KEY;
+import static com.azure.core.amqp.implementation.ClientConstants.LINK_NAME_KEY;
+
+
/**
* Handler that receives events from its corresponding {@link Receiver}. Handlers must be associated to a
* {@link Receiver} to receive its events.
@@ -45,9 +50,9 @@ public class ReceiveLinkHandler extends LinkHandler {
private final String entityPath;
public ReceiveLinkHandler(String connectionId, String hostname, String linkName, String entityPath) {
- super(connectionId, hostname, entityPath, new ClientLogger(ReceiveLinkHandler.class));
+ super(connectionId, hostname, entityPath, ReceiveLinkHandler.class.getName());
this.linkName = Objects.requireNonNull(linkName, "'linkName' cannot be null.");
- this.entityPath = entityPath;
+ this.entityPath = Objects.requireNonNull(entityPath, "'entityPath' cannot be null.");
}
public String getLinkName() {
@@ -78,8 +83,11 @@ public void close() {
public void onLinkLocalOpen(Event event) {
final Link link = event.getLink();
if (link instanceof Receiver) {
- logger.verbose("onLinkLocalOpen connectionId[{}], entityPath[{}], linkName[{}], localSource[{}]",
- getConnectionId(), entityPath, link.getName(), link.getSource());
+ logger.atVerbose()
+ .addKeyValue(ENTITY_PATH_KEY, entityPath)
+ .addKeyValue(LINK_NAME_KEY, link.getName())
+ .addKeyValue("localSource", link.getSource())
+ .log("onLinkLocalOpen");
}
}
@@ -90,17 +98,22 @@ public void onLinkRemoteOpen(Event event) {
return;
}
+ LoggingEventBuilder logBuilder = logger.atInfo()
+ .addKeyValue(ENTITY_PATH_KEY, entityPath)
+ .addKeyValue(LINK_NAME_KEY, link.getName());
+
if (link.getRemoteSource() != null) {
- logger.info("onLinkRemoteOpen connectionId[{}], entityPath[{}], linkName[{}], remoteSource[{}]",
- getConnectionId(), entityPath, link.getName(), link.getRemoteSource());
+ logBuilder.addKeyValue("remoteSource", link.getRemoteSource());
if (!isRemoteActive.getAndSet(true)) {
onNext(EndpointState.ACTIVE);
}
} else {
- logger.info("onLinkRemoteOpen connectionId[{}], entityPath[{}], linkName[{}], action[waitingForError]",
- getConnectionId(), entityPath, link.getName());
+ logBuilder
+ .addKeyValue("action", "waitingForError");
}
+
+ logBuilder.log("onLinkRemoteOpen");
}
@Override
@@ -123,14 +136,18 @@ public void onDelivery(Event event) {
// before we fix proton-j - this work around ensures that we ignore the duplicate Delivery event
if (wasSettled) {
if (link != null) {
- logger.info("onDelivery connectionId[{}], entityPath[{}], linkName[{}], updatedLinkCredit[{}],"
- + " remoteCredit[{}], remoteCondition[{}], delivery.isSettled[{}] Was already settled.",
- getConnectionId(), entityPath, link.getName(), link.getCredit(), link.getRemoteCredit(),
- link.getRemoteCondition(), delivery.isSettled());
+ addErrorCondition(logger.atInfo(), link.getRemoteCondition())
+ .addKeyValue(ENTITY_PATH_KEY, entityPath)
+ .addKeyValue(LINK_NAME_KEY, linkName)
+ .addKeyValue("updatedLinkCredit", link.getCredit())
+ .addKeyValue("remoteCredit",link.getRemoteCredit())
+ .addKeyValue("delivery.isSettled", delivery.isSettled())
+ .log("Was already settled.");
} else {
- logger.warning("connectionId[{}], entityPath[{}] delivery.isSettled[{}] Settled delivery with no "
- + " link.",
- getConnectionId(), entityPath, delivery.isSettled());
+ logger.atWarning()
+ .addKeyValue(ENTITY_PATH_KEY, entityPath)
+ .addKeyValue("delivery.isSettled", delivery.isSettled())
+ .log("Settled delivery with no delivery");
}
} else {
if (link.getLocalState() == EndpointState.CLOSED) {
@@ -144,9 +161,12 @@ public void onDelivery(Event event) {
} else {
queuedDeliveries.add(delivery);
deliveries.emitNext(delivery, (signalType, emitResult) -> {
- logger.warning("connectionId[{}], entityPath[{}], linkName[{}], emitResult[{}] "
- + "Could not emit delivery. {}",
- getConnectionId(), entityPath, linkName, emitResult, delivery);
+ logger.atWarning()
+ .addKeyValue(ENTITY_PATH_KEY, entityPath)
+ .addKeyValue(LINK_NAME_KEY, linkName)
+ .addKeyValue("emitResult", emitResult)
+ .log("Could not emit delivery. {}", delivery);
+
if (emitResult == Sinks.EmitResult.FAIL_OVERFLOW
&& link.getLocalState() != EndpointState.CLOSED) {
link.setCondition(new ErrorCondition(Symbol.getSymbol("delivery-buffer-overflow"),
@@ -164,11 +184,14 @@ public void onDelivery(Event event) {
if (link != null) {
final ErrorCondition condition = link.getRemoteCondition();
- logger.verbose("onDelivery connectionId[{}], linkName[{}], updatedLinkCredit[{}],"
- + "remoteCredit[{}], remoteCondition[{}], delivery.isPartial[{}], delivery.isSettled[{}]",
- getConnectionId(), link.getName(), link.getCredit(), link.getRemoteCredit(),
- condition != null && condition.getCondition() != null ? condition : "N/A",
- delivery.isPartial(), wasSettled);
+ addErrorCondition(logger.atVerbose(), condition)
+ .addKeyValue(ENTITY_PATH_KEY, entityPath)
+ .addKeyValue(LINK_NAME_KEY, linkName)
+ .addKeyValue("updatedLinkCredit", link.getCredit())
+ .addKeyValue("remoteCredit", link.getRemoteCredit())
+ .addKeyValue("delivery.isPartial", delivery.isPartial())
+ .addKeyValue("delivery.isSettled", wasSettled)
+ .log("onDelivery.");
}
}
@@ -179,8 +202,10 @@ public void onLinkLocalClose(Event event) {
// Someone called receiver.close() to set the local link state to close. Since the link was never remotely
// active, we complete getEndpointStates() ourselves.
if (!isRemoteActive.get()) {
- logger.info("connectionId[{}] linkName[{}] entityPath[{}] Receiver link was never active. Closing endpoint "
- + "states.", getConnectionId(), getLinkName(), entityPath);
+ logger.atInfo()
+ .addKeyValue(ENTITY_PATH_KEY, entityPath)
+ .addKeyValue(LINK_NAME_KEY, linkName)
+ .log("Receiver link was never active. Closing endpoint states");
super.close();
}
@@ -209,8 +234,10 @@ public void onLinkFinal(Event event) {
*/
private void clearAndCompleteDeliveries(String errorMessage) {
deliveries.emitComplete((signalType, emitResult) -> {
- logger.verbose("connectionId[{}], entityPath[{}], linkName[{}] {}", getConnectionId(), entityPath,
- linkName, errorMessage);
+ logger.atVerbose()
+ .addKeyValue(ENTITY_PATH_KEY, entityPath)
+ .addKeyValue(LINK_NAME_KEY, linkName)
+ .log(errorMessage);
return false;
});
diff --git a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/SendLinkHandler.java b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/SendLinkHandler.java
index cd11ef50e163..af73ef5f951d 100644
--- a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/SendLinkHandler.java
+++ b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/SendLinkHandler.java
@@ -3,7 +3,7 @@
package com.azure.core.amqp.implementation.handler;
-import com.azure.core.util.logging.ClientLogger;
+import com.azure.core.util.logging.LoggingEventBuilder;
import org.apache.qpid.proton.engine.BaseHandler;
import org.apache.qpid.proton.engine.Delivery;
import org.apache.qpid.proton.engine.EndpointState;
@@ -19,6 +19,11 @@
import java.util.Objects;
import java.util.concurrent.atomic.AtomicBoolean;
+import static com.azure.core.amqp.implementation.AmqpLoggingUtils.addSignalTypeAndResult;
+import static com.azure.core.amqp.implementation.ClientConstants.EMIT_RESULT_KEY;
+import static com.azure.core.amqp.implementation.ClientConstants.ENTITY_PATH_KEY;
+import static com.azure.core.amqp.implementation.ClientConstants.LINK_NAME_KEY;
+
/**
* Handler that receives events from its corresponding {@link Sender}. Handlers must be associated to a {@link Sender}
* to receive its events.
@@ -39,7 +44,7 @@ public class SendLinkHandler extends LinkHandler {
private final Sinks.Many deliveryProcessor = Sinks.many().multicast().onBackpressureBuffer();
public SendLinkHandler(String connectionId, String hostname, String linkName, String entityPath) {
- super(connectionId, hostname, entityPath, new ClientLogger(SendLinkHandler.class));
+ super(connectionId, hostname, entityPath, SendLinkHandler.class.getName());
this.linkName = Objects.requireNonNull(linkName, "'linkName' cannot be null.");
this.entityPath = entityPath;
}
@@ -69,8 +74,9 @@ public void close() {
creditProcessor.emitComplete(Sinks.EmitFailureHandler.FAIL_FAST);
deliveryProcessor.emitComplete((signalType, emitResult) -> {
- logger.verbose("connectionId[{}] linkName[{}] result[{}] Unable to emit complete on deliverySink.",
- getConnectionId(), linkName, emitResult);
+ addSignalTypeAndResult(logger.atVerbose(), signalType, emitResult)
+ .addKeyValue(LINK_NAME_KEY, linkName)
+ .log("Unable to emit complete on deliverySink.");
return false;
});
@@ -81,8 +87,11 @@ public void close() {
public void onLinkLocalOpen(Event event) {
final Link link = event.getLink();
if (link instanceof Sender) {
- logger.verbose("onLinkLocalOpen connectionId[{}], entityPath[{}], linkName[{}], localTarget[{}]",
- getConnectionId(), entityPath, link.getName(), link.getTarget());
+ logger.atVerbose()
+ .addKeyValue(LINK_NAME_KEY, link.getName())
+ .addKeyValue(ENTITY_PATH_KEY, entityPath)
+ .addKeyValue("localTarget", link.getTarget())
+ .log("onLinkLocalOpen");
}
}
@@ -93,18 +102,22 @@ public void onLinkRemoteOpen(Event event) {
return;
}
+ LoggingEventBuilder logBuilder = logger.atInfo()
+ .addKeyValue(LINK_NAME_KEY, link.getName())
+ .addKeyValue(ENTITY_PATH_KEY, entityPath);
+
if (link.getRemoteTarget() != null) {
- logger.info("onLinkRemoteOpen connectionId[{}], entityPath[{}], linkName[{}], remoteTarget[{}]",
- getConnectionId(), entityPath, link.getName(), link.getRemoteTarget());
+ // TODO escape
+ logBuilder.addKeyValue("remoteTarget", link.getRemoteTarget());
if (!isRemoteActive.getAndSet(true)) {
onNext(EndpointState.ACTIVE);
}
} else {
- logger.info("onLinkRemoteOpen connectionId[{}], entityPath[{}], linkName[{}], remoteTarget[null],"
- + " remoteSource[null], action[waitingForError]",
- getConnectionId(), entityPath, link.getName());
+ logBuilder.addKeyValue("remoteTarget", (String)null)
+ .addKeyValue("action", "waitingForError");
}
+ logBuilder.log("onLinkRemoteOpen");
}
@Override
@@ -116,13 +129,19 @@ public void onLinkFlow(Event event) {
final Sender sender = event.getSender();
final int credits = sender.getRemoteCredit();
creditProcessor.emitNext(credits, (signalType, emitResult) -> {
- logger.verbose("connectionId[{}] linkName[{}] result[{}] Unable to emit credits [{}].",
- getConnectionId(), linkName, emitResult, credits);
+ logger.atVerbose()
+ .addKeyValue(LINK_NAME_KEY, linkName)
+ .addKeyValue(EMIT_RESULT_KEY, emitResult)
+ .addKeyValue("credits", credits)
+ .log("Unable to emit credits.");
return false;
});
- logger.verbose("onLinkFlow connectionId[{}] linkName[{}] unsettled[{}] credit[{}]",
- getConnectionId(), sender.getName(), sender.getUnsettled(), sender.getCredit());
+ logger.atVerbose()
+ .addKeyValue(LINK_NAME_KEY, linkName)
+ .addKeyValue("unsettled", sender.getUnsettled())
+ .addKeyValue("credits", credits)
+ .log("onLinkFlow.");
}
@Override
@@ -132,8 +151,10 @@ public void onLinkLocalClose(Event event) {
// Someone called sender.close() to set the local link state to close. Since the link was never remotely
// active, we complete getEndpointStates() ourselves.
if (!isRemoteActive.get()) {
- logger.info("connectionId[{}] linkName[{}] entityPath[{}] Sender link was never active. Closing endpoint "
- + "states.", getConnectionId(), getLinkName(), entityPath);
+ logger.atInfo()
+ .addKeyValue(LINK_NAME_KEY, getLinkName())
+ .addKeyValue(ENTITY_PATH_KEY, entityPath)
+ .log("Sender link was never active. Closing endpoint states.");
super.close();
}
@@ -147,14 +168,21 @@ public void onDelivery(Event event) {
final Sender sender = (Sender) delivery.getLink();
final String deliveryTag = new String(delivery.getTag(), StandardCharsets.UTF_8);
- logger.verbose("onDelivery connectionId[{}] linkName[{}] unsettled[{}] credit[{}],"
- + " deliveryState[{}] delivery.isBuffered[{}] delivery.id[{}]",
- getConnectionId(), sender.getName(), sender.getUnsettled(), sender.getRemoteCredit(),
- delivery.getRemoteState(), delivery.isBuffered(), deliveryTag);
+ logger.atVerbose()
+ .addKeyValue(LINK_NAME_KEY, getLinkName())
+ .addKeyValue("unsettled", sender.getUnsettled())
+ .addKeyValue("credit", sender.getRemoteCredit())
+ .addKeyValue("deliveryState", delivery.getRemoteState())
+ .addKeyValue("delivery.isBuffered", delivery.isBuffered())
+ .addKeyValue("delivery.id", deliveryTag)
+ .log("onDelivery");
deliveryProcessor.emitNext(delivery, (signalType, emitResult) -> {
- logger.warning("connectionId[{}] linkName[{}] result[{}] Unable to emit delivery [{}].",
- getConnectionId(), linkName, emitResult, deliveryTag);
+ logger.atWarning()
+ .addKeyValue(LINK_NAME_KEY, getLinkName())
+ .addKeyValue(EMIT_RESULT_KEY, emitResult)
+ .addKeyValue("delivery.id", deliveryTag)
+ .log("Unable to emit delivery.");
return emitResult == Sinks.EmitResult.FAIL_OVERFLOW;
});
diff --git a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/SessionHandler.java b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/SessionHandler.java
index f8a633d98d7d..aa6d92ad6898 100644
--- a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/SessionHandler.java
+++ b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/SessionHandler.java
@@ -6,10 +6,9 @@
import com.azure.core.amqp.exception.AmqpErrorContext;
import com.azure.core.amqp.exception.AmqpException;
import com.azure.core.amqp.exception.SessionErrorContext;
-import com.azure.core.amqp.implementation.ClientConstants;
import com.azure.core.amqp.implementation.ExceptionUtil;
import com.azure.core.amqp.implementation.ReactorDispatcher;
-import com.azure.core.util.logging.ClientLogger;
+import com.azure.core.util.logging.LoggingEventBuilder;
import org.apache.qpid.proton.amqp.transport.ErrorCondition;
import org.apache.qpid.proton.engine.EndpointState;
import org.apache.qpid.proton.engine.Event;
@@ -20,46 +19,48 @@
import java.util.Locale;
import java.util.concurrent.RejectedExecutionException;
+import static com.azure.core.amqp.implementation.AmqpLoggingUtils.addErrorCondition;
+import static com.azure.core.amqp.implementation.ClientConstants.SESSION_NAME_KEY;
+
public class SessionHandler extends Handler {
- private final String entityName;
+ private final String sessionName;
private final Duration openTimeout;
private final ReactorDispatcher reactorDispatcher;
- public SessionHandler(String connectionId, String hostname, String entityName, ReactorDispatcher reactorDispatcher,
+ public SessionHandler(String connectionId, String hostname, String sessionName, ReactorDispatcher reactorDispatcher,
Duration openTimeout) {
- super(connectionId, hostname, new ClientLogger(SessionHandler.class));
- this.entityName = entityName;
+ super(connectionId, hostname, SessionHandler.class.getName());
+ this.sessionName = sessionName;
this.openTimeout = openTimeout;
this.reactorDispatcher = reactorDispatcher;
}
public AmqpErrorContext getErrorContext() {
- return new SessionErrorContext(getHostname(), entityName);
+ return new SessionErrorContext(getHostname(), sessionName);
}
@Override
public void onSessionLocalOpen(Event e) {
- logger.verbose("onSessionLocalOpen connectionId[{}], entityName[{}], condition[{}]",
- getConnectionId(), this.entityName,
- e.getSession().getCondition() == null
- ? ClientConstants.NOT_APPLICABLE
- : e.getSession().getCondition().toString());
+ addErrorCondition(logger.atVerbose(), e.getSession().getCondition())
+ .addKeyValue(SESSION_NAME_KEY, sessionName)
+ .log("onSessionLocalOpen");
final Session session = e.getSession();
try {
reactorDispatcher.invoke(this::onSessionTimeout, this.openTimeout);
} catch (IOException | RejectedExecutionException ioException) {
- logger.info("onSessionLocalOpen connectionId[{}], entityName[{}], reactorDispatcherError[{}]",
- getConnectionId(), this.entityName,
- ioException.getMessage());
+ logger.atInfo()
+ .addKeyValue(SESSION_NAME_KEY, sessionName)
+ .addKeyValue("reactorDispatcherError", ioException.getMessage())
+ .log("onSessionLocalOpen");
session.close();
final String message =
String.format(Locale.US, "onSessionLocalOpen connectionId[%s], entityName[%s], underlying IO of"
+ " reactorDispatcher faulted with error: %s",
- getConnectionId(), this.entityName, ioException.getMessage());
+ getConnectionId(), sessionName, ioException.getMessage());
final Throwable exception = new AmqpException(false, message, ioException, getErrorContext());
onError(exception);
@@ -69,18 +70,20 @@ public void onSessionLocalOpen(Event e) {
@Override
public void onSessionRemoteOpen(Event e) {
final Session session = e.getSession();
+ LoggingEventBuilder logBuilder;
if (session.getLocalState() == EndpointState.UNINITIALIZED) {
- logger.warning("onSessionRemoteOpen connectionId[{}], entityName[{}], sessionIncCapacity[{}],"
- + " sessionOutgoingWindow[{}] endpoint was uninitialised.",
- getConnectionId(), entityName, session.getIncomingCapacity(), session.getOutgoingWindow());
-
+ logBuilder = logger.atWarning();
session.open();
} else {
- logger.info("onSessionRemoteOpen connectionId[{}], entityName[{}], sessionIncCapacity[{}],"
- + " sessionOutgoingWindow[{}]",
- getConnectionId(), entityName, session.getIncomingCapacity(), session.getOutgoingWindow());
+ logBuilder = logger.atInfo();
}
+
+ logBuilder.addKeyValue(SESSION_NAME_KEY, sessionName)
+ .addKeyValue("sessionIncCapacity", session.getIncomingCapacity())
+ .addKeyValue("sessionOutgoingWindow", session.getOutgoingWindow())
+ .log("onSessionRemoteOpen");
+
onNext(EndpointState.ACTIVE);
}
@@ -90,30 +93,25 @@ public void onSessionLocalClose(Event e) {
? e.getSession().getCondition()
: null;
- logger.verbose("onSessionLocalClose connectionId[{}], entityName[{}], condition[{}]",
- entityName, getConnectionId(),
- condition == null ? ClientConstants.NOT_APPLICABLE : condition.toString());
+ addErrorCondition(logger.atVerbose(), condition)
+ .addKeyValue(SESSION_NAME_KEY, sessionName)
+ .log("onSessionLocalClose");
}
@Override
public void onSessionRemoteClose(Event e) {
final Session session = e.getSession();
- logger.info("onSessionRemoteClose connectionId[{}], entityName[{}], condition[{}]",
- entityName,
- getConnectionId(),
- session == null || session.getRemoteCondition() == null
- ? ClientConstants.NOT_APPLICABLE
- : session.getRemoteCondition().toString());
+ addErrorCondition(logger.atInfo(), session.getCondition())
+ .addKeyValue(SESSION_NAME_KEY, sessionName)
+ .log("onSessionRemoteClose");
ErrorCondition condition = session != null ? session.getRemoteCondition() : null;
if (session != null && session.getLocalState() != EndpointState.CLOSED) {
- logger.info("onSessionRemoteClose closing a local session for connectionId[{}], entityName[{}], "
- + "condition[{}], description[{}]",
- getConnectionId(), entityName,
- condition != null ? condition.getCondition() : ClientConstants.NOT_APPLICABLE,
- condition != null ? condition.getDescription() : ClientConstants.NOT_APPLICABLE);
+ addErrorCondition(logger.atInfo(), condition)
+ .addKeyValue(SESSION_NAME_KEY, sessionName)
+ .log("onSessionRemoteClose closing a local session.");
session.setCondition(session.getRemoteCondition());
session.close();
@@ -127,7 +125,7 @@ public void onSessionRemoteClose(Event e) {
final Exception exception = ExceptionUtil.toException(condition.getCondition().toString(),
String.format(Locale.US, "onSessionRemoteClose connectionId[%s], entityName[%s] condition[%s]",
- id, entityName, condition), context);
+ id, sessionName, condition), context);
onError(exception);
}
@@ -138,11 +136,9 @@ public void onSessionFinal(Event e) {
final Session session = e.getSession();
final ErrorCondition condition = session != null ? session.getCondition() : null;
- logger.info("onSessionFinal connectionId[{}], entityName[{}], condition[{}], description[{}]",
- getConnectionId(), entityName,
- condition != null ? condition.getCondition() : ClientConstants.NOT_APPLICABLE,
- condition != null ? condition.getDescription() : ClientConstants.NOT_APPLICABLE);
-
+ addErrorCondition(logger.atInfo(), condition)
+ .addKeyValue(SESSION_NAME_KEY, sessionName)
+ .log("onSessionFinal.");
close();
}
diff --git a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/WebSocketsConnectionHandler.java b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/WebSocketsConnectionHandler.java
index 192e222aa00f..37d4255c9572 100644
--- a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/WebSocketsConnectionHandler.java
+++ b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/WebSocketsConnectionHandler.java
@@ -10,6 +10,11 @@
import org.apache.qpid.proton.engine.SslPeerDetails;
import org.apache.qpid.proton.engine.impl.TransportInternal;
+import java.util.Map;
+
+import static com.azure.core.amqp.implementation.ClientConstants.CONNECTION_ID_KEY;
+import static com.azure.core.amqp.implementation.ClientConstants.HOSTNAME_KEY;
+
/**
* Creates an AMQP connection using web sockets (port 443).
*/
@@ -22,7 +27,7 @@ public class WebSocketsConnectionHandler extends ConnectionHandler {
private static final String SOCKET_PATH = "/$servicebus/websocket";
private static final String PROTOCOL = "AMQPWSB10";
- private final ClientLogger logger = new ClientLogger(WebSocketsConnectionHandler.class);
+ private final ClientLogger logger;
/**
* Creates a handler that handles proton-j's connection events using web sockets.
@@ -33,6 +38,7 @@ public class WebSocketsConnectionHandler extends ConnectionHandler {
public WebSocketsConnectionHandler(String connectionId, ConnectionOptions connectionOptions,
SslPeerDetails peerDetails) {
super(connectionId, connectionOptions, peerDetails);
+ logger = new ClientLogger(WebSocketsConnectionHandler.class, Map.of(CONNECTION_ID_KEY, connectionId));
}
/**
@@ -44,7 +50,6 @@ public WebSocketsConnectionHandler(String connectionId, ConnectionOptions connec
@Override
protected void addTransportLayers(final Event event, final TransportInternal transport) {
final String hostName = event.getConnection().getHostname();
-
logger.info("Adding web socket layer");
final WebSocketImpl webSocket = new WebSocketImpl();
webSocket.configure(
@@ -58,8 +63,9 @@ protected void addTransportLayers(final Event event, final TransportInternal tra
transport.addTransportLayer(webSocket);
- logger.verbose("connectionId[{}] Adding web sockets transport layer for hostname[{}]",
- getConnectionId(), hostName);
+ logger.atVerbose()
+ .addKeyValue(HOSTNAME_KEY, hostName)
+ .log("Adding web sockets transport layer.");
super.addTransportLayers(event, transport);
}
diff --git a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/WebSocketsProxyConnectionHandler.java b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/WebSocketsProxyConnectionHandler.java
index a2ace78afa76..fadb892ca552 100644
--- a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/WebSocketsProxyConnectionHandler.java
+++ b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/WebSocketsProxyConnectionHandler.java
@@ -27,16 +27,21 @@
import java.net.URI;
import java.util.List;
import java.util.Locale;
+import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
+import static com.azure.core.amqp.implementation.ClientConstants.CONNECTION_ID_KEY;
+import static com.azure.core.amqp.implementation.AmqpLoggingUtils.addErrorCondition;
+import static com.azure.core.amqp.implementation.ClientConstants.HOSTNAME_KEY;
+
/**
* Creates an AMQP connection using web sockets and connects through a proxy.
*/
public class WebSocketsProxyConnectionHandler extends WebSocketsConnectionHandler {
private static final String HTTPS_URI_FORMAT = "https://%s:%s";
- private final ClientLogger logger = new ClientLogger(WebSocketsProxyConnectionHandler.class);
+ private final ClientLogger logger;
private final InetSocketAddress connectionHostname;
private final ProxyOptions proxyOptions;
private final String fullyQualifiedNamespace;
@@ -60,14 +65,14 @@ public WebSocketsProxyConnectionHandler(String connectionId, ConnectionOptions c
this.proxyOptions = Objects.requireNonNull(proxyOptions, "'proxyConfiguration' cannot be null.");
this.fullyQualifiedNamespace = connectionOptions.getFullyQualifiedNamespace();
this.amqpBrokerHostname = connectionOptions.getFullyQualifiedNamespace() + ":" + connectionOptions.getPort();
-
+ this.logger = new ClientLogger(WebSocketsProxyConnectionHandler.class, Map.of(CONNECTION_ID_KEY, connectionId));
if (proxyOptions.isProxyAddressConfigured()) {
this.connectionHostname = (InetSocketAddress) proxyOptions.getProxyAddress().address();
} else {
final URI serviceUri = createURI(connectionOptions.getHostname(), connectionOptions.getPort());
final ProxySelector proxySelector = ProxySelector.getDefault();
if (proxySelector == null) {
- throw logger.logExceptionAsError(new IllegalStateException("ProxySelector should not be null."));
+ throw logger.atError().log(new IllegalStateException("ProxySelector should not be null."));
}
final List proxies = proxySelector.select(serviceUri);
@@ -75,7 +80,7 @@ public WebSocketsProxyConnectionHandler(String connectionId, ConnectionOptions c
final String formatted = String.format("No proxy address found for: '%s'. Available: %s.",
serviceUri, proxies.stream().map(Proxy::toString).collect(Collectors.joining(", ")));
- throw logger.logExceptionAsError(new IllegalStateException(formatted));
+ throw logger.atError().log(new IllegalStateException(formatted));
}
final Proxy proxy = proxies.get(0);
@@ -131,16 +136,15 @@ public void onTransportError(Event event) {
final Transport transport = event.getTransport();
final Connection connection = event.getConnection();
if (connection == null || transport == null) {
- logger.verbose("connectionId[{}] There is no connection or transport associated with error. Event: {}",
- event);
+ logger.verbose("There is no connection or transport associated with error. Event: {}", event);
return;
}
final ErrorCondition errorCondition = transport.getCondition();
if (errorCondition == null || !(errorCondition.getCondition().equals(ConnectionError.FRAMING_ERROR)
|| errorCondition.getCondition().equals(AmqpErrorCode.PROTON_IO_ERROR))) {
- logger.verbose("connectionId[{}] There is no error condition and these are not framing errors. Error: {}",
- errorCondition);
+ addErrorCondition(logger.atVerbose(), errorCondition)
+ .log("There is no error condition and these are not framing errors.");
return;
}
@@ -148,14 +152,14 @@ public void onTransportError(Event event) {
// If the proxy is not configured, or we are not connected to a host yet.
if (proxyOptions == null || CoreUtils.isNullOrEmpty(hostname)) {
- logger.verbose("connectionId[{}] Proxy is not configured and there is no host connected. Error: {}",
- errorCondition);
+ addErrorCondition(logger.atVerbose(), errorCondition)
+ .log("Proxy is not configured and there is no host connected.");
return;
}
final String[] hostNameParts = hostname.split(":");
if (hostNameParts.length != 2) {
- logger.warning("connectionId[{}] Invalid hostname: {}", getConnectionId(), hostname);
+ logger.warning("Invalid hostname: {}", hostname);
return;
}
@@ -163,7 +167,7 @@ public void onTransportError(Event event) {
try {
port = Integer.parseInt(hostNameParts[1]);
} catch (NumberFormatException ignore) {
- logger.warning("connectionId[{}] Invalid port number: {}", getConnectionId(), hostNameParts[1]);
+ logger.warning("Invalid port number: {}", hostNameParts[1]);
return;
}
@@ -174,8 +178,7 @@ public void onTransportError(Event event) {
final URI url = createURI(fullyQualifiedNamespace, port);
final InetSocketAddress address = new InetSocketAddress(hostNameParts[0], port);
- logger.error("connectionId[{}] Failed to connect to url: '{}', proxy host: '{}'",
- getConnectionId(), url, address.getHostString(), ioException);
+ logger.atError().log("Failed to connect to url: '{}', proxy host: '{}'", url, address.getHostString(), ioException);
final ProxySelector proxySelector = ProxySelector.getDefault();
if (proxySelector != null) {
@@ -200,7 +203,9 @@ protected void addTransportLayers(final Event event, final TransportInternal tra
transport.addTransportLayer(proxy);
- logger.info("connectionId[{}] addProxyHandshake: hostname[{}]", getConnectionId(), amqpBrokerHostname);
+ logger.atInfo()
+ .addKeyValue(HOSTNAME_KEY, amqpBrokerHostname)
+ .log("addProxyHandshake");
}
private com.microsoft.azure.proton.transport.proxy.ProxyConfiguration getProtonConfiguration() {
@@ -227,8 +232,7 @@ private com.microsoft.azure.proton.transport.proxy.ProxyAuthenticationType getPr
case NONE:
return com.microsoft.azure.proton.transport.proxy.ProxyAuthenticationType.NONE;
default:
- throw logger.logExceptionAsError(new IllegalArgumentException(String.format(
- "connectionId[%s]: This authentication type is unknown: %s", getConnectionId(), type.name())));
+ throw logger.atError().log(new IllegalArgumentException(String.format("This authentication type is unknown: %s", type.name())));
}
}
diff --git a/sdk/core/azure-core-amqp/src/test/java/com/azure/core/amqp/implementation/AmqpChannelProcessorTest.java b/sdk/core/azure-core-amqp/src/test/java/com/azure/core/amqp/implementation/AmqpChannelProcessorTest.java
index 8c53f8a25d0b..815420f16cdf 100644
--- a/sdk/core/azure-core-amqp/src/test/java/com/azure/core/amqp/implementation/AmqpChannelProcessorTest.java
+++ b/sdk/core/azure-core-amqp/src/test/java/com/azure/core/amqp/implementation/AmqpChannelProcessorTest.java
@@ -58,8 +58,7 @@ void setup() {
mocksCloseable = MockitoAnnotations.openMocks(this);
channelProcessor = new AmqpChannelProcessor<>("connection-test", "test-path",
- TestObject::getStates, retryPolicy,
- new ClientLogger(AmqpChannelProcessor.class.getName() + ""));
+ TestObject::getStates, retryPolicy, "TestLogger");
}
@AfterEach
diff --git a/sdk/core/azure-core-amqp/src/test/java/com/azure/core/amqp/implementation/ManagementChannelTest.java b/sdk/core/azure-core-amqp/src/test/java/com/azure/core/amqp/implementation/ManagementChannelTest.java
index ef442a7b45d8..3626f5558b7f 100644
--- a/sdk/core/azure-core-amqp/src/test/java/com/azure/core/amqp/implementation/ManagementChannelTest.java
+++ b/sdk/core/azure-core-amqp/src/test/java/com/azure/core/amqp/implementation/ManagementChannelTest.java
@@ -95,8 +95,7 @@ public void setup(TestInfo testInfo) {
final AmqpChannelProcessor requestResponseMono =
Mono.defer(() -> Mono.just(requestResponseChannel)).subscribeWith(new AmqpChannelProcessor<>(
- "foo", "bar", RequestResponseChannel::getEndpointStates,
- retryPolicy, logger));
+ "foo", "bar", RequestResponseChannel::getEndpointStates, retryPolicy, "TestLogger"));
when(tokenManager.authorize()).thenReturn(Mono.just(1000L));
when(tokenManager.getAuthorizationResults()).thenReturn(tokenProviderResults.flux());
diff --git a/sdk/core/azure-core-amqp/src/test/java/com/azure/core/amqp/implementation/ReactorSenderTest.java b/sdk/core/azure-core-amqp/src/test/java/com/azure/core/amqp/implementation/ReactorSenderTest.java
index c46cc3059a8f..b60bbb6474f5 100644
--- a/sdk/core/azure-core-amqp/src/test/java/com/azure/core/amqp/implementation/ReactorSenderTest.java
+++ b/sdk/core/azure-core-amqp/src/test/java/com/azure/core/amqp/implementation/ReactorSenderTest.java
@@ -128,6 +128,7 @@ public void setup() throws IOException {
when(handler.getLinkCredits()).thenReturn(Flux.just(100));
when(handler.getEndpointStates()).thenReturn(endpointStatePublisher.flux());
+ when(handler.getConnectionId()).thenReturn("connectionId");
endpointStatePublisher.next(EndpointState.ACTIVE);
when(tokenManager.getAuthorizationResults()).thenReturn(authorizationResults.flux());
diff --git a/sdk/core/azure-core-amqp/src/test/java/com/azure/core/amqp/implementation/handler/HandlerTest.java b/sdk/core/azure-core-amqp/src/test/java/com/azure/core/amqp/implementation/handler/HandlerTest.java
index 15235a1a2e51..b23b9ad76069 100644
--- a/sdk/core/azure-core-amqp/src/test/java/com/azure/core/amqp/implementation/handler/HandlerTest.java
+++ b/sdk/core/azure-core-amqp/src/test/java/com/azure/core/amqp/implementation/handler/HandlerTest.java
@@ -39,13 +39,12 @@ public void teardown() {
@Test
public void constructor() {
// Arrange
- final ClientLogger logger = new ClientLogger(TestHandler.class);
final String connectionId = "id";
final String hostname = "hostname";
// Act
- assertThrows(NullPointerException.class, () -> new TestHandler(null, hostname, logger));
- assertThrows(NullPointerException.class, () -> new TestHandler(connectionId, null, logger));
+ assertThrows(NullPointerException.class, () -> new TestHandler(null, hostname, TestHandler.class.getName()));
+ assertThrows(NullPointerException.class, () -> new TestHandler(connectionId, null, TestHandler.class.getName()));
assertThrows(NullPointerException.class, () -> new TestHandler(connectionId, hostname, null));
}
@@ -158,11 +157,11 @@ private static class TestHandler extends Handler {
static final String HOSTNAME = "test-hostname";
TestHandler() {
- super(CONNECTION_ID, HOSTNAME, new ClientLogger(TestHandler.class));
+ super(CONNECTION_ID, HOSTNAME, TestHandler.class.getName());
}
- TestHandler(String connectionId, String hostname, ClientLogger logger) {
- super(connectionId, hostname, logger);
+ TestHandler(String connectionId, String hostname, String loggerName) {
+ super(connectionId, hostname, loggerName);
}
}
}
diff --git a/sdk/core/azure-core-amqp/src/test/java/com/azure/core/amqp/implementation/handler/LinkHandlerTest.java b/sdk/core/azure-core-amqp/src/test/java/com/azure/core/amqp/implementation/handler/LinkHandlerTest.java
index 18b2e8081aa3..a34cca0521cf 100644
--- a/sdk/core/azure-core-amqp/src/test/java/com/azure/core/amqp/implementation/handler/LinkHandlerTest.java
+++ b/sdk/core/azure-core-amqp/src/test/java/com/azure/core/amqp/implementation/handler/LinkHandlerTest.java
@@ -59,11 +59,11 @@ public class LinkHandlerTest {
@Mock
private Session session;
- private final ClientLogger logger = new ClientLogger(LinkHandlerTest.class);
+ private final String loggerName = LinkHandlerTest.class.getName();
private final AmqpErrorCondition linkStolen = LINK_STOLEN;
private final Symbol symbol = Symbol.getSymbol(linkStolen.getErrorCondition());
private final String description = "test-description";
- private final LinkHandler handler = new MockLinkHandler(CONNECTION_ID, HOSTNAME, ENTITY_PATH, logger);
+ private final LinkHandler handler = new MockLinkHandler(CONNECTION_ID, HOSTNAME, ENTITY_PATH, loggerName);
private AutoCloseable mocksCloseable;
@BeforeEach
@@ -333,11 +333,11 @@ public void onLinkFinal() {
public void constructor() {
// Act
assertThrows(NullPointerException.class,
- () -> new MockLinkHandler(null, HOSTNAME, ENTITY_PATH, logger));
+ () -> new MockLinkHandler(null, HOSTNAME, ENTITY_PATH, loggerName));
assertThrows(NullPointerException.class,
- () -> new MockLinkHandler(CONNECTION_ID, null, ENTITY_PATH, logger));
+ () -> new MockLinkHandler(CONNECTION_ID, null, ENTITY_PATH, loggerName));
assertThrows(NullPointerException.class,
- () -> new MockLinkHandler(CONNECTION_ID, HOSTNAME, null, logger));
+ () -> new MockLinkHandler(CONNECTION_ID, HOSTNAME, null, loggerName));
assertThrows(NullPointerException.class,
() -> new MockLinkHandler(CONNECTION_ID, HOSTNAME, ENTITY_PATH, null));
}
@@ -409,8 +409,8 @@ public void errorContextNoReferenceId(Map properties) {
}
private static final class MockLinkHandler extends LinkHandler {
- MockLinkHandler(String connectionId, String hostname, String entityPath, ClientLogger logger) {
- super(connectionId, hostname, entityPath, logger);
+ MockLinkHandler(String connectionId, String hostname, String entityPath, String loggerName) {
+ super(connectionId, hostname, entityPath, loggerName);
}
}
}
diff --git a/sdk/core/azure-core/src/main/java/com/azure/core/util/FluxUtil.java b/sdk/core/azure-core/src/main/java/com/azure/core/util/FluxUtil.java
index b4d7c586fada..f3f64860df45 100644
--- a/sdk/core/azure-core/src/main/java/com/azure/core/util/FluxUtil.java
+++ b/sdk/core/azure-core/src/main/java/com/azure/core/util/FluxUtil.java
@@ -11,6 +11,7 @@
import com.azure.core.implementation.RetriableDownloadFlux;
import com.azure.core.implementation.TypeUtil;
import com.azure.core.util.logging.ClientLogger;
+import com.azure.core.util.logging.LoggingEventBuilder;
import org.reactivestreams.Subscriber;
import org.reactivestreams.Subscription;
import reactor.core.CoreSubscriber;
@@ -313,6 +314,18 @@ public static Mono monoError(ClientLogger logger, RuntimeException ex) {
return Mono.error(logger.logExceptionAsError(Exceptions.propagate(ex)));
}
+ /**
+ * Propagates a {@link RuntimeException} through the error channel of {@link Mono}.
+ *
+ * @param logBuilder The {@link LoggingEventBuilder} with context to log the exception.
+ * @param ex The {@link RuntimeException}.
+ * @param The return type.
+ * @return A {@link Mono} that terminates with error wrapping the {@link RuntimeException}.
+ */
+ public static Mono monoError(LoggingEventBuilder logBuilder, RuntimeException ex) {
+ return Mono.error(logBuilder.log(Exceptions.propagate(ex)));
+ }
+
/**
* Propagates a {@link RuntimeException} through the error channel of {@link Flux}.
*
From 2f86731082639376fc04cf2afd863f4594b47eb8 Mon Sep 17 00:00:00 2001
From: Liudmila Molkova
Date: Tue, 30 Nov 2021 13:57:29 -0800
Subject: [PATCH 02/17] clean up
---
.../java/com/azure/core/amqp/AmqpShutdownSignal.java | 12 ++----------
.../amqp/implementation/AmqpExceptionHandler.java | 5 +++--
.../core/amqp/implementation/AmqpLoggingUtils.java | 9 +++++++++
.../core/amqp/implementation/ReactorConnection.java | 7 ++++---
4 files changed, 18 insertions(+), 15 deletions(-)
diff --git a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/AmqpShutdownSignal.java b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/AmqpShutdownSignal.java
index e9e3c9665b2a..cca9f7d4c895 100644
--- a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/AmqpShutdownSignal.java
+++ b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/AmqpShutdownSignal.java
@@ -48,21 +48,13 @@ public boolean isInitiatedByClient() {
return isInitiatedByClient;
}
- public LoggingEventBuilder addContext(LoggingEventBuilder logBuilder) {
- return logBuilder
- .addKeyValue("isTransient", isTransient)
- .addKeyValue("isInitiatedByClient", isInitiatedByClient)
- .addKeyValue("shutdownMessage", message);
- }
-
/**
* Returns String representing this {@code AmqpShutdownSignal} signal.
*
- * To write logs, please use {@link AmqpShutdownSignal#addContext} instead.
+ * To write logs, please use {@link com.azure.core.amqp.implementation.AmqpLoggingUtils#addShutdownSignal(LoggingEventBuilder, AmqpShutdownSignal)}.
*/
@Override
public String toString() {
- return String.format(Locale.US, "%s, isTransient[%s], initiatedByClient[%s]", message, isTransient,
- isInitiatedByClient);
+ return message;
}
}
diff --git a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/AmqpExceptionHandler.java b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/AmqpExceptionHandler.java
index fa02f50883bd..9e88e86eaaa8 100644
--- a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/AmqpExceptionHandler.java
+++ b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/AmqpExceptionHandler.java
@@ -7,6 +7,8 @@
import com.azure.core.util.logging.ClientLogger;
import com.azure.core.util.logging.ClientLogger;
+import static com.azure.core.amqp.implementation.AmqpLoggingUtils.addShutdownSignal;
+
/**
* Handles exceptions generated by AMQP connections, sessions, and/or links.
*/
@@ -34,7 +36,6 @@ void onConnectionError(Throwable exception) {
* @param shutdownSignal The shutdown signal that was received.
*/
void onConnectionShutdown(AmqpShutdownSignal shutdownSignal) {
- shutdownSignal
- .addContext(logger.atInfo()).log("Shutdown received");
+ addShutdownSignal(logger.atInfo(), shutdownSignal).log("Shutdown received");
}
}
diff --git a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/AmqpLoggingUtils.java b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/AmqpLoggingUtils.java
index d00d778047b7..a34faa72a2c7 100644
--- a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/AmqpLoggingUtils.java
+++ b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/AmqpLoggingUtils.java
@@ -1,5 +1,6 @@
package com.azure.core.amqp.implementation;
+import com.azure.core.amqp.AmqpShutdownSignal;
import com.azure.core.util.logging.LoggingEventBuilder;
import org.apache.qpid.proton.amqp.transport.ErrorCondition;
import reactor.core.publisher.SignalType;
@@ -29,5 +30,13 @@ public static LoggingEventBuilder addErrorCondition(LoggingEventBuilder logBuild
.addKeyValue(ERROR_CONDITION_KEY, errorCondition.getCondition())
.addKeyValue(ERROR_DESCRIPTION_KEY, errorCondition.getDescription());
}
+
+ public static LoggingEventBuilder addShutdownSignal(LoggingEventBuilder logBuilder, AmqpShutdownSignal shutdownSignal) {
+ return logBuilder
+ .addKeyValue("isTransient", shutdownSignal.isTransient())
+ .addKeyValue("isInitiatedByClient", shutdownSignal.isInitiatedByClient())
+ // will call toString() if logging is enabled
+ .addKeyValue("shutdownMessage", shutdownSignal);
+ }
}
diff --git a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ReactorConnection.java b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ReactorConnection.java
index 851eb1bbdd4d..9d27d166874d 100644
--- a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ReactorConnection.java
+++ b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ReactorConnection.java
@@ -41,6 +41,7 @@
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.atomic.AtomicBoolean;
+import static com.azure.core.amqp.implementation.AmqpLoggingUtils.addShutdownSignal;
import static com.azure.core.amqp.implementation.AmqpLoggingUtils.addSignalTypeAndResult;
import static com.azure.core.amqp.implementation.ClientConstants.CONNECTION_ID_KEY;
import static com.azure.core.amqp.implementation.ClientConstants.EMIT_RESULT_KEY;
@@ -423,12 +424,12 @@ public Mono closeAsync() {
}
Mono closeAsync(AmqpShutdownSignal shutdownSignal) {
- shutdownSignal.addContext(logger.atInfo()).log("Disposing of ReactorConnection.");
+ addShutdownSignal(logger.atInfo(), shutdownSignal).log("Disposing of ReactorConnection.");
final Sinks.EmitResult result = shutdownSignalSink.tryEmitValue(shutdownSignal);
if (result.isFailure()) {
// It's possible that another one was already emitted, so it's all good.
- shutdownSignal.addContext(logger.atInfo())
+ addShutdownSignal(logger.atInfo(), shutdownSignal)
.addKeyValue(EMIT_RESULT_KEY, result)
.log("Unable to emit shutdown signal.");
}
@@ -618,7 +619,7 @@ public void onConnectionError(Throwable exception) {
@Override
void onConnectionShutdown(AmqpShutdownSignal shutdownSignal) {
- shutdownSignal.addContext(logger.atInfo())
+ addShutdownSignal(logger.atInfo(), shutdownSignal)
.addKeyValue(FULLY_QUALIFIED_NAMESPACE_KEY, getFullyQualifiedNamespace())
.log("onConnectionShutdown. Shutting down.");
From adeb0d07446534390a1b142d72c72202d07599db Mon Sep 17 00:00:00 2001
From: Liudmila Molkova
Date: Tue, 30 Nov 2021 14:08:46 -0800
Subject: [PATCH 03/17] clean up
---
.../amqp/implementation/ActiveClientTokenManager.java | 3 +--
.../azure/core/amqp/implementation/ReactorReceiver.java | 2 +-
.../core/amqp/implementation/RequestResponseChannel.java | 8 ++++----
3 files changed, 6 insertions(+), 7 deletions(-)
diff --git a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ActiveClientTokenManager.java b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ActiveClientTokenManager.java
index e9e3dce79ee8..bdadf85d4485 100644
--- a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ActiveClientTokenManager.java
+++ b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ActiveClientTokenManager.java
@@ -26,7 +26,7 @@
* Manages the re-authorization of the client to the token audience against the CBS node.
*/
public class ActiveClientTokenManager implements TokenManager {
- private final ClientLogger logger;
+ private final ClientLogger logger = new ClientLogger(ActiveClientTokenManager.class);
private final AtomicBoolean hasScheduled = new AtomicBoolean();
private final AtomicBoolean hasDisposed = new AtomicBoolean();
private final Mono cbsNode;
@@ -42,7 +42,6 @@ public ActiveClientTokenManager(Mono cbsNode, String to
this.cbsNode = cbsNode;
this.tokenAudience = tokenAudience;
this.scopes = scopes;
- this.logger = new ClientLogger(ActiveClientTokenManager.class);
}
/**
diff --git a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ReactorReceiver.java b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ReactorReceiver.java
index b34abf0d85d8..536135097655 100644
--- a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ReactorReceiver.java
+++ b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ReactorReceiver.java
@@ -191,7 +191,7 @@ public Flux receive() {
@Override
public Mono addCredits(int credits) {
if (isDisposed()) {
- return monoError(logger.atError(), Exceptions.propagate(new IllegalStateException("Cannot add credits to closed link: " + getLinkName())));
+ return monoError(logger, Exceptions.propagate(new IllegalStateException("Cannot add credits to closed link: " + getLinkName())));
}
return Mono.create(sink -> {
diff --git a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/RequestResponseChannel.java b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/RequestResponseChannel.java
index f49f12062efc..beb1cd4e4daf 100644
--- a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/RequestResponseChannel.java
+++ b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/RequestResponseChannel.java
@@ -292,17 +292,17 @@ public Mono sendWithAck(final Message message) {
*/
public Mono sendWithAck(final Message message, DeliveryState deliveryState) {
if (isDisposed()) {
- return monoError(logger.atError(), new IllegalStateException("Cannot send a message when request response channel is disposed."));
+ return monoError(logger, new IllegalStateException("Cannot send a message when request response channel is disposed."));
}
if (message == null) {
- return monoError(logger.atError(), new NullPointerException("message cannot be null"));
+ return monoError(logger, new NullPointerException("message cannot be null"));
}
if (message.getMessageId() != null) {
- return monoError(logger.atError(), new IllegalArgumentException("message.getMessageId() should be null"));
+ return monoError(logger, new IllegalArgumentException("message.getMessageId() should be null"));
}
if (message.getReplyTo() != null) {
- return monoError(logger.atError(), new IllegalArgumentException("message.getReplyTo() should be null"));
+ return monoError(logger, new IllegalArgumentException("message.getReplyTo() should be null"));
}
final UnsignedLong messageId = UnsignedLong.valueOf(requestId.incrementAndGet());
From e689306fe2168740162a46ed405fbb2c2c64473d Mon Sep 17 00:00:00 2001
From: Liudmila Molkova
Date: Wed, 1 Dec 2021 15:42:01 -0800
Subject: [PATCH 04/17] clean up
---
.../checks/ThrowFromClientLoggerCheck.java | 36 +++++++++++++--
.../ThrowFromClientLoggerCheckTest.java | 4 +-
.../DirectThrowExceptionTestData.java | 17 +++++++
.../azure/core/amqp/AmqpShutdownSignal.java | 2 -
.../ActiveClientTokenManager.java | 37 ++++++++--------
.../implementation/AmqpChannelProcessor.java | 10 +++--
.../implementation/AmqpExceptionHandler.java | 1 -
.../amqp/implementation/AmqpLoggingUtils.java | 44 +++++++++++++++++++
.../amqp/implementation/ClientConstants.java | 20 ++++-----
.../implementation/ManagementChannel.java | 9 ++--
.../implementation/ReactorConnection.java | 9 ++--
.../implementation/ReactorDispatcher.java | 6 +--
.../amqp/implementation/ReactorExecutor.java | 6 +--
.../amqp/implementation/ReactorReceiver.java | 25 ++++++-----
.../amqp/implementation/ReactorSender.java | 11 +++--
.../amqp/implementation/ReactorSession.java | 4 +-
.../RequestResponseChannel.java | 8 +++-
.../handler/ConnectionHandler.java | 5 +--
.../handler/CustomIOHandler.java | 6 +--
.../amqp/implementation/handler/Handler.java | 6 +--
.../implementation/handler/LinkHandler.java | 1 -
.../handler/ReactorHandler.java | 5 +--
.../handler/ReceiveLinkHandler.java | 2 +-
.../handler/SendLinkHandler.java | 4 +-
.../handler/SessionHandler.java | 5 +--
.../handler/WebSocketsConnectionHandler.java | 7 +--
.../WebSocketsProxyConnectionHandler.java | 5 +--
.../AmqpChannelProcessorTest.java | 1 -
.../implementation/handler/HandlerTest.java | 1 -
.../handler/LinkHandlerTest.java | 1 -
30 files changed, 191 insertions(+), 107 deletions(-)
diff --git a/eng/code-quality-reports/src/main/java/com/azure/tools/checkstyle/checks/ThrowFromClientLoggerCheck.java b/eng/code-quality-reports/src/main/java/com/azure/tools/checkstyle/checks/ThrowFromClientLoggerCheck.java
index 1a9729f10848..08caf8094ddc 100644
--- a/eng/code-quality-reports/src/main/java/com/azure/tools/checkstyle/checks/ThrowFromClientLoggerCheck.java
+++ b/eng/code-quality-reports/src/main/java/com/azure/tools/checkstyle/checks/ThrowFromClientLoggerCheck.java
@@ -7,6 +7,7 @@
import com.puppycrawl.tools.checkstyle.api.DetailAST;
import com.puppycrawl.tools.checkstyle.api.FullIdent;
import com.puppycrawl.tools.checkstyle.api.TokenTypes;
+
import java.util.ArrayDeque;
import java.util.Collections;
import java.util.Queue;
@@ -25,12 +26,15 @@
public class ThrowFromClientLoggerCheck extends AbstractCheck {
private static final String LOGGER_LOG_EXCEPTION_AS_ERROR = "logger.logExceptionAsError";
private static final String LOGGER_LOG_THROWABLE_AS_ERROR = "logger.logThrowableAsError";
+ private static final String LOGGING_BUILDER_LOG_THROWABLE_AS_ERROR = "logger.atError().log";
private static final String LOGGER_LOG_EXCEPTION_AS_WARNING = "logger.logExceptionAsWarning";
- private static final String LOGGER_LOG_THROWABLE_AS_WARNING = "logger.logThrowableAsWarning";
+ private static final String LOGGER_LOG_THROWABLE_AS_WARNING = "logger.logThrowableAsWarning";
+ private static final String LOGGING_BUILDER_LOG_THROWABLE_AS_WARNING = "logger.atWarning().log";
+
static final String THROW_LOGGER_EXCEPTION_MESSAGE = String.format("Directly throwing an exception is disallowed. "
- + "Must throw through \"ClientLogger\" API, either of \"%s\", \"%s\", \"%s\", or \"%s\" where \"logger\" is "
+ + "Must throw through \"ClientLogger\" API, either of \"%s\", \"%s\", \"%s\", \"%s\", \"%s\", or \"%s\" where \"logger\" is "
+ "type of ClientLogger from Azure Core package.", LOGGER_LOG_EXCEPTION_AS_ERROR,
- LOGGER_LOG_THROWABLE_AS_ERROR, LOGGER_LOG_EXCEPTION_AS_WARNING, LOGGER_LOG_THROWABLE_AS_WARNING);
+ LOGGER_LOG_THROWABLE_AS_ERROR, LOGGING_BUILDER_LOG_THROWABLE_AS_ERROR, LOGGER_LOG_EXCEPTION_AS_WARNING, LOGGER_LOG_THROWABLE_AS_WARNING, LOGGING_BUILDER_LOG_THROWABLE_AS_WARNING);
// A LIFO queue stores the static status of class, skip this ThrowFromClientLoggerCheck if the class is static
private final Queue classStaticDeque = Collections.asLifoQueue(new ArrayDeque<>());
@@ -94,9 +98,11 @@ public void visitToken(DetailAST token) {
case TokenTypes.LITERAL_THROW:
// Skip check if the throw exception from static class, constructor or static method
if (classStaticDeque.isEmpty() || classStaticDeque.peek() || isInConstructor
- || methodStaticDeque.isEmpty() || methodStaticDeque.peek()) {
+ || methodStaticDeque.isEmpty() || methodStaticDeque.peek()
+ || findLogMethodIdentifier(token)) {
return;
}
+
DetailAST methodCallToken =
token.findFirstToken(TokenTypes.EXPR).findFirstToken(TokenTypes.METHOD_CALL);
if (methodCallToken == null) {
@@ -118,4 +124,26 @@ public void visitToken(DetailAST token) {
break;
}
}
+
+ /**
+ *
+ **/
+ private static boolean findLogMethodIdentifier(DetailAST root) {
+ for (DetailAST ast = root.getFirstChild(); ast != null; ast = ast.getNextSibling()) {
+ if (ast.getType() == TokenTypes.METHOD_CALL) {
+ DetailAST dot = ast.findFirstToken(TokenTypes.DOT);
+ if (dot != null) {
+ DetailAST ident = dot.findFirstToken(TokenTypes.IDENT);
+ if ("log".equals(ident.getText())) {
+ return true;
+ }
+ }
+ }
+ if (findLogMethodIdentifier(ast)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
}
diff --git a/eng/code-quality-reports/src/test/java/com/azure/tools/checkstyle/checks/ThrowFromClientLoggerCheckTest.java b/eng/code-quality-reports/src/test/java/com/azure/tools/checkstyle/checks/ThrowFromClientLoggerCheckTest.java
index fba2d2215799..d2cb7f377a36 100644
--- a/eng/code-quality-reports/src/test/java/com/azure/tools/checkstyle/checks/ThrowFromClientLoggerCheckTest.java
+++ b/eng/code-quality-reports/src/test/java/com/azure/tools/checkstyle/checks/ThrowFromClientLoggerCheckTest.java
@@ -9,6 +9,7 @@
import org.junit.Before;
import org.junit.Test;
+
import static com.azure.tools.checkstyle.checks.ThrowFromClientLoggerCheck.THROW_LOGGER_EXCEPTION_MESSAGE;
public class ThrowFromClientLoggerCheckTest extends AbstractModuleTestSupport {
@@ -32,7 +33,8 @@ protected String getPackageLocation() {
@Test
public void directThrowExceptionTestData() throws Exception {
String[] expected = {
- expectedErrorMessage(12, 9)
+ expectedErrorMessage(12, 9),
+ expectedErrorMessage(60, 9)
};
verify(checker, getPath("DirectThrowExceptionTestData.java"), expected);
}
diff --git a/eng/code-quality-reports/src/test/resources/com/azure/tools/checkstyle/checks/ThrowFromClientLoggerCheck/DirectThrowExceptionTestData.java b/eng/code-quality-reports/src/test/resources/com/azure/tools/checkstyle/checks/ThrowFromClientLoggerCheck/DirectThrowExceptionTestData.java
index 7b00762ac3a8..7fb461af0880 100644
--- a/eng/code-quality-reports/src/test/resources/com/azure/tools/checkstyle/checks/ThrowFromClientLoggerCheck/DirectThrowExceptionTestData.java
+++ b/eng/code-quality-reports/src/test/resources/com/azure/tools/checkstyle/checks/ThrowFromClientLoggerCheck/DirectThrowExceptionTestData.java
@@ -42,4 +42,21 @@ public void validLogExceptionAsWarning() {
public void validLogThrowableAsWarning() {
throw logger.logThrowableAsWarning(new RuntimeException("Error message."));
}
+
+ public void validThrowExceptionWithBuilder() {
+ throw logger.atError().log(Exceptions.propagate(new IllegalStateException("Error Messages")));
+ }
+
+ public void validThrowExceptionWithBuilderAndContext() {
+ throw logger.atError().addKeyValuePair("foo", "bar").log(new RuntimeException("Error message."));
+ }
+
+ public void validThrowExceptionWithBuilderAndContextAdvanced() {
+ LoggingEventBuilder builder = logger.atError();
+ throw builder.addKeyValuePair("foo", "bar").log(new RuntimeException("Error message."));
+ }
+
+ public void invalidLoggingBuilderNoLogCall() {
+ throw logger.atError();
+ }
}
diff --git a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/AmqpShutdownSignal.java b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/AmqpShutdownSignal.java
index cca9f7d4c895..24e3a9a72db4 100644
--- a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/AmqpShutdownSignal.java
+++ b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/AmqpShutdownSignal.java
@@ -5,8 +5,6 @@
import com.azure.core.util.logging.LoggingEventBuilder;
-import java.util.Locale;
-
/**
* Represents a signal that caused the AMQP connection to shutdown.
*/
diff --git a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ActiveClientTokenManager.java b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ActiveClientTokenManager.java
index bdadf85d4485..fb39f6e7fd20 100644
--- a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ActiveClientTokenManager.java
+++ b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ActiveClientTokenManager.java
@@ -19,7 +19,6 @@
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
-import static com.azure.core.amqp.implementation.AmqpLoggingUtils.addErrorCondition;
import static com.azure.core.amqp.implementation.AmqpLoggingUtils.addSignalTypeAndResult;
/**
@@ -176,29 +175,29 @@ private Disposable scheduleRefreshTokenTask(Duration initialRefresh) {
return false;
});
}, error -> {
- logger.atError()
- .addKeyValue("scopes", scopes)
- .addKeyValue("audience", tokenAudience)
- .log("Error occurred while refreshing token that is not retriable. Not scheduling"
+ logger.atError()
+ .addKeyValue("scopes", scopes)
+ .addKeyValue("audience", tokenAudience)
+ .log("Error occurred while refreshing token that is not retriable. Not scheduling"
+ " refresh task. Use ActiveClientTokenManager.authorize() to schedule task again.", error);
- // This hasn't been disposed yet.
- if (!hasDisposed.getAndSet(true)) {
- hasScheduled.set(false);
- durationSource.emitComplete((signalType, emitResult) -> {
- addSignalTypeAndResult(logger.atVerbose(), signalType, emitResult)
- .log("Could not close durationSource.");
+ // This hasn't been disposed yet.
+ if (!hasDisposed.getAndSet(true)) {
+ hasScheduled.set(false);
+ durationSource.emitComplete((signalType, emitResult) -> {
+ addSignalTypeAndResult(logger.atVerbose(), signalType, emitResult)
+ .log("Could not close durationSource.");
- return false;
- });
+ return false;
+ });
- authorizationResults.emitError(error, (signalType, emitResult) -> {
- addSignalTypeAndResult(logger.atVerbose(), signalType, emitResult)
+ authorizationResults.emitError(error, (signalType, emitResult) -> {
+ addSignalTypeAndResult(logger.atVerbose(), signalType, emitResult)
.log("Could not emit authorization error.", error);
- return false;
- });
- }
- });
+ return false;
+ });
+ }
+ });
}
}
diff --git a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/AmqpChannelProcessor.java b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/AmqpChannelProcessor.java
index 0f95feaec32a..2a6640992646 100644
--- a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/AmqpChannelProcessor.java
+++ b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/AmqpChannelProcessor.java
@@ -9,7 +9,6 @@
import com.azure.core.amqp.exception.AmqpException;
import com.azure.core.util.AsyncCloseable;
import com.azure.core.util.logging.ClientLogger;
-import com.azure.core.util.logging.ClientLogger;
import org.reactivestreams.Processor;
import org.reactivestreams.Subscription;
import reactor.core.CoreSubscriber;
@@ -19,6 +18,7 @@
import reactor.core.publisher.Operators;
import java.time.Duration;
+import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentLinkedDeque;
@@ -60,9 +60,11 @@ public AmqpChannelProcessor(String fullyQualifiedNamespace, String entityPath,
this.endpointStatesFunction = Objects.requireNonNull(endpointStatesFunction,
"'endpointStates' cannot be null.");
this.retryPolicy = Objects.requireNonNull(retryPolicy, "'retryPolicy' cannot be null.");
- this.logger = new ClientLogger(loggerName, Map.of(
- FULLY_QUALIFIED_NAMESPACE_KEY, Objects.requireNonNull(fullyQualifiedNamespace, "'fullyQualifiedNamespace' cannot be null."),
- ENTITY_PATH_KEY, Objects.requireNonNull(entityPath, "'entityPath' cannot be null.")));
+
+ Map loggingContext = new HashMap<>();
+ loggingContext.put(FULLY_QUALIFIED_NAMESPACE_KEY, Objects.requireNonNull(fullyQualifiedNamespace, "'fullyQualifiedNamespace' cannot be null."));
+ loggingContext.put(ENTITY_PATH_KEY, Objects.requireNonNull(entityPath, "'entityPath' cannot be null."));
+ this.logger = new ClientLogger(loggerName, loggingContext);
this.errorContext = new AmqpErrorContext(fullyQualifiedNamespace);
}
diff --git a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/AmqpExceptionHandler.java b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/AmqpExceptionHandler.java
index 9e88e86eaaa8..a8c61303cb1f 100644
--- a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/AmqpExceptionHandler.java
+++ b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/AmqpExceptionHandler.java
@@ -5,7 +5,6 @@
import com.azure.core.amqp.AmqpShutdownSignal;
import com.azure.core.util.logging.ClientLogger;
-import com.azure.core.util.logging.ClientLogger;
import static com.azure.core.amqp.implementation.AmqpLoggingUtils.addShutdownSignal;
diff --git a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/AmqpLoggingUtils.java b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/AmqpLoggingUtils.java
index a34faa72a2c7..030ac2568deb 100644
--- a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/AmqpLoggingUtils.java
+++ b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/AmqpLoggingUtils.java
@@ -1,3 +1,6 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
package com.azure.core.amqp.implementation;
import com.azure.core.amqp.AmqpShutdownSignal;
@@ -6,19 +9,51 @@
import reactor.core.publisher.SignalType;
import reactor.core.publisher.Sinks;
+import java.util.HashMap;
+import java.util.Map;
+
+import static com.azure.core.amqp.implementation.ClientConstants.CONNECTION_ID_KEY;
import static com.azure.core.amqp.implementation.ClientConstants.EMIT_RESULT_KEY;
import static com.azure.core.amqp.implementation.ClientConstants.ERROR_CONDITION_KEY;
import static com.azure.core.amqp.implementation.ClientConstants.ERROR_DESCRIPTION_KEY;
import static com.azure.core.amqp.implementation.ClientConstants.NOT_APPLICABLE;
import static com.azure.core.amqp.implementation.ClientConstants.SIGNAL_TYPE_KEY;
+/**
+ * Utils for contextual logging.
+ */
public class AmqpLoggingUtils {
+
+ /**
+ * Creates logging context with connectionId.
+ */
+ public static Map createContextWithConnectionId(String connectionId) {
+ Map globalLoggingContext = new HashMap<>();
+ globalLoggingContext.put(CONNECTION_ID_KEY, connectionId);
+
+ return globalLoggingContext;
+ }
+
+ /**
+ * Adds {@link SignalType} under {@code signalType} key and {@link reactor.core.publisher.Sinks.EmitResult}
+ * under {@code emitResult} key to the {@link LoggingEventBuilder}
+
+ * @return updated {@link LoggingEventBuilder} for chaining.
+ */
public static LoggingEventBuilder addSignalTypeAndResult(LoggingEventBuilder logBuilder, SignalType signalType, Sinks.EmitResult result) {
return logBuilder
.addKeyValue(SIGNAL_TYPE_KEY, signalType)
.addKeyValue(EMIT_RESULT_KEY, result);
}
+ /**
+ * Adds {@link ErrorCondition} to the {@link LoggingEventBuilder}. Writes the {@code getCondition()} under {@code errorCondition} key
+ * and {@code getDescription()} under {@code errorDescription} keys.
+ *
+ * If errorCondition is {@code null} writes {@code n/a}.
+
+ * @return updated {@link LoggingEventBuilder} for chaining.
+ */
public static LoggingEventBuilder addErrorCondition(LoggingEventBuilder logBuilder, ErrorCondition errorCondition) {
if (errorCondition == null) {
return logBuilder
@@ -31,6 +66,15 @@ public static LoggingEventBuilder addErrorCondition(LoggingEventBuilder logBuild
.addKeyValue(ERROR_DESCRIPTION_KEY, errorCondition.getDescription());
}
+ /**
+ * Adds {@link AmqpShutdownSignal} to the {@link LoggingEventBuilder}. Writes
+ *
+ * - {@code isTransient()} under {@code isTransient}
+ * - {@code isInitiatedByClient()} under {@code isInitiatedByClient}
+ * - {@code toString()} under {@code shutdownMessage}
+ *
+ * @return updated {@link LoggingEventBuilder} for chaining.
+ */
public static LoggingEventBuilder addShutdownSignal(LoggingEventBuilder logBuilder, AmqpShutdownSignal shutdownSignal) {
return logBuilder
.addKeyValue("isTransient", shutdownSignal.isTransient())
diff --git a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ClientConstants.java b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ClientConstants.java
index 04210a669653..6dad9c4b002f 100644
--- a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ClientConstants.java
+++ b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ClientConstants.java
@@ -13,16 +13,16 @@ public final class ClientConstants {
public static final Duration SERVER_BUSY_WAIT_TIME = Duration.ofSeconds(4);
// Logging context keys
- public final static String CONNECTION_ID_KEY = "connectionId";
- public final static String LINK_NAME_KEY = "linkName";
- public final static String ENTITY_PATH_KEY = "entityPath";
- public final static String SESSION_NAME_KEY = "sessionName";
- public final static String FULLY_QUALIFIED_NAMESPACE_KEY = "namespace";
- public final static String ERROR_CONDITION_KEY = "errorCondition";
- public final static String ERROR_DESCRIPTION_KEY = "errorDescription";
- public final static String EMIT_RESULT_KEY = "emitResult";
- public final static String SIGNAL_TYPE_KEY = "signalType";
- public final static String HOSTNAME_KEY = "hostName";
+ public static final String CONNECTION_ID_KEY = "connectionId";
+ public static final String LINK_NAME_KEY = "linkName";
+ public static final String ENTITY_PATH_KEY = "entityPath";
+ public static final String SESSION_NAME_KEY = "sessionName";
+ public static final String FULLY_QUALIFIED_NAMESPACE_KEY = "namespace";
+ public static final String ERROR_CONDITION_KEY = "errorCondition";
+ public static final String ERROR_DESCRIPTION_KEY = "errorDescription";
+ public static final String EMIT_RESULT_KEY = "emitResult";
+ public static final String SIGNAL_TYPE_KEY = "signalType";
+ public static final String HOSTNAME_KEY = "hostName";
/**
* The default maximum allowable size, in bytes, for a batch to be sent.
diff --git a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ManagementChannel.java b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ManagementChannel.java
index 853a99384519..f2c15f34cdb1 100644
--- a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ManagementChannel.java
+++ b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ManagementChannel.java
@@ -12,13 +12,12 @@
import com.azure.core.amqp.models.AmqpAnnotatedMessage;
import com.azure.core.amqp.models.DeliveryOutcome;
import com.azure.core.util.logging.ClientLogger;
-import com.azure.core.util.logging.ClientLogger;
import org.apache.qpid.proton.amqp.transport.DeliveryState;
import org.apache.qpid.proton.message.Message;
-import org.slf4j.LoggerFactory;
import reactor.core.publisher.Mono;
import reactor.core.publisher.SynchronousSink;
+import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
@@ -42,7 +41,11 @@ public ManagementChannel(AmqpChannelProcessor createChan
this.fullyQualifiedNamespace = Objects.requireNonNull(fullyQualifiedNamespace,
"'fullyQualifiedNamespace' cannot be null.");
this.entityPath = Objects.requireNonNull(entityPath, "'entityPath' cannot be null.");
- this.logger = new ClientLogger(ManagementChannel.class, Map.of(ENTITY_PATH_KEY, entityPath));
+
+ Map globalLoggingContext = new HashMap<>();
+ globalLoggingContext.put(ENTITY_PATH_KEY, entityPath);
+ this.logger = new ClientLogger(ManagementChannel.class, globalLoggingContext);
+
this.tokenManager = Objects.requireNonNull(tokenManager, "'tokenManager' cannot be null.");
}
diff --git a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ReactorConnection.java b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ReactorConnection.java
index 9d27d166874d..f1a537155cbe 100644
--- a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ReactorConnection.java
+++ b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ReactorConnection.java
@@ -15,7 +15,6 @@
import com.azure.core.amqp.implementation.handler.ConnectionHandler;
import com.azure.core.amqp.implementation.handler.SessionHandler;
import com.azure.core.util.logging.ClientLogger;
-import com.azure.core.util.logging.LoggingEventBuilder;
import org.apache.qpid.proton.amqp.transport.ReceiverSettleMode;
import org.apache.qpid.proton.amqp.transport.SenderSettleMode;
import org.apache.qpid.proton.engine.BaseHandler;
@@ -43,12 +42,12 @@
import static com.azure.core.amqp.implementation.AmqpLoggingUtils.addShutdownSignal;
import static com.azure.core.amqp.implementation.AmqpLoggingUtils.addSignalTypeAndResult;
-import static com.azure.core.amqp.implementation.ClientConstants.CONNECTION_ID_KEY;
+import static com.azure.core.amqp.implementation.AmqpLoggingUtils.createContextWithConnectionId;
import static com.azure.core.amqp.implementation.ClientConstants.EMIT_RESULT_KEY;
import static com.azure.core.amqp.implementation.ClientConstants.ENTITY_PATH_KEY;
+import static com.azure.core.amqp.implementation.ClientConstants.FULLY_QUALIFIED_NAMESPACE_KEY;
import static com.azure.core.amqp.implementation.ClientConstants.HOSTNAME_KEY;
import static com.azure.core.amqp.implementation.ClientConstants.LINK_NAME_KEY;
-import static com.azure.core.amqp.implementation.ClientConstants.FULLY_QUALIFIED_NAMESPACE_KEY;
import static com.azure.core.amqp.implementation.ClientConstants.SESSION_NAME_KEY;
import static com.azure.core.amqp.implementation.ClientConstants.SIGNAL_TYPE_KEY;
import static com.azure.core.util.FluxUtil.monoError;
@@ -114,7 +113,7 @@ public ReactorConnection(String connectionId, ConnectionOptions connectionOption
this.connectionOptions = connectionOptions;
this.reactorProvider = reactorProvider;
this.connectionId = connectionId;
- this.logger = new ClientLogger(ReactorConnection.class, Map.of(CONNECTION_ID_KEY, connectionId));
+ this.logger = new ClientLogger(ReactorConnection.class, createContextWithConnectionId(connectionId));
this.handlerProvider = handlerProvider;
this.tokenManagerProvider = Objects.requireNonNull(tokenManagerProvider,
"'tokenManagerProvider' cannot be null.");
@@ -484,7 +483,7 @@ Mono closeAsync(AmqpShutdownSignal shutdownSignal) {
private synchronized void closeConnectionWork() {
if (connection == null) {
isClosedMono.emitEmpty((signalType, emitResult) -> {
- addSignalTypeAndResult(logger.atInfo(), signalType, emitResult)
+ addSignalTypeAndResult(logger.atInfo(), signalType, emitResult)
.log("Unable to complete closeMono.");
return false;
diff --git a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ReactorDispatcher.java b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ReactorDispatcher.java
index ac4ce4baefb3..5bfee1bfc13d 100644
--- a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ReactorDispatcher.java
+++ b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ReactorDispatcher.java
@@ -6,7 +6,6 @@
import com.azure.core.amqp.AmqpShutdownSignal;
import com.azure.core.amqp.implementation.handler.DispatchHandler;
import com.azure.core.util.logging.ClientLogger;
-import com.azure.core.util.logging.ClientLogger;
import org.apache.qpid.proton.Proton;
import org.apache.qpid.proton.reactor.Reactor;
import org.apache.qpid.proton.reactor.Selectable;
@@ -19,13 +18,12 @@
import java.nio.channels.ClosedChannelException;
import java.nio.channels.Pipe;
import java.time.Duration;
-import java.util.Map;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
-import static com.azure.core.amqp.implementation.ClientConstants.CONNECTION_ID_KEY;
+import static com.azure.core.amqp.implementation.AmqpLoggingUtils.createContextWithConnectionId;
/**
* The following utility class is used to generate an event to hook into {@link Reactor}'s event delegation pattern. It
@@ -69,7 +67,7 @@ public ReactorDispatcher(final String connectionId, final Reactor reactor, final
this.workQueue = new ConcurrentLinkedQueue<>();
this.onClose = new CloseHandler();
this.workScheduler = new WorkScheduler();
- this.logger = new ClientLogger(ReactorDispatcher.class , Map.of(CONNECTION_ID_KEY, connectionId));
+ this.logger = new ClientLogger(ReactorDispatcher.class, createContextWithConnectionId(connectionId));
// The Proton-J reactor goes quiescent when there is no work to do, and it only wakes up when a Selectable (by
// default, the network connection) signals that data is available.
//
diff --git a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ReactorExecutor.java b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ReactorExecutor.java
index 8aee5ae47dbc..98e168be3724 100644
--- a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ReactorExecutor.java
+++ b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ReactorExecutor.java
@@ -18,14 +18,13 @@
import java.nio.channels.UnresolvedAddressException;
import java.time.Duration;
import java.util.Locale;
-import java.util.Map;
import java.util.Objects;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import static com.azure.core.amqp.implementation.AmqpLoggingUtils.addSignalTypeAndResult;
-import static com.azure.core.amqp.implementation.ClientConstants.CONNECTION_ID_KEY;
+import static com.azure.core.amqp.implementation.AmqpLoggingUtils.createContextWithConnectionId;
/**
* Schedules the proton-j reactor to continuously run work.
@@ -50,7 +49,8 @@ class ReactorExecutor implements AsyncCloseable {
this.timeout = Objects.requireNonNull(timeout, "'timeout' cannot be null.");
this.exceptionHandler = Objects.requireNonNull(exceptionHandler, "'exceptionHandler' cannot be null.");
this.hostname = Objects.requireNonNull(hostname, "'hostname' cannot be null.");
- this.logger = new ClientLogger(ReactorExecutor.class, Map.of(CONNECTION_ID_KEY, Objects.requireNonNull(connectionId, "'connectionId' cannot be null.")));
+ Objects.requireNonNull(connectionId, "'connectionId' cannot be null.");
+ this.logger = new ClientLogger(ReactorExecutor.class, createContextWithConnectionId(connectionId));
}
/**
diff --git a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ReactorReceiver.java b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ReactorReceiver.java
index 536135097655..e4d6c45272b4 100644
--- a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ReactorReceiver.java
+++ b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ReactorReceiver.java
@@ -6,12 +6,10 @@
import com.azure.core.amqp.AmqpConnection;
import com.azure.core.amqp.AmqpEndpointState;
import com.azure.core.amqp.AmqpRetryOptions;
-import com.azure.core.amqp.AmqpShutdownSignal;
import com.azure.core.amqp.exception.AmqpErrorCondition;
import com.azure.core.amqp.implementation.handler.ReceiveLinkHandler;
import com.azure.core.util.AsyncCloseable;
import com.azure.core.util.logging.ClientLogger;
-import com.azure.core.util.logging.ClientLogger;
import com.azure.core.util.logging.LoggingEventBuilder;
import org.apache.qpid.proton.Proton;
import org.apache.qpid.proton.amqp.Symbol;
@@ -37,13 +35,12 @@
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Supplier;
+import static com.azure.core.amqp.implementation.AmqpLoggingUtils.addErrorCondition;
import static com.azure.core.amqp.implementation.AmqpLoggingUtils.addSignalTypeAndResult;
+import static com.azure.core.amqp.implementation.AmqpLoggingUtils.createContextWithConnectionId;
import static com.azure.core.amqp.implementation.ClientConstants.CONNECTION_ID_KEY;
import static com.azure.core.amqp.implementation.ClientConstants.ENTITY_PATH_KEY;
import static com.azure.core.amqp.implementation.ClientConstants.LINK_NAME_KEY;
-import static com.azure.core.amqp.implementation.AmqpLoggingUtils.addErrorCondition;
-import static com.azure.core.amqp.implementation.AmqpLoggingUtils.addErrorCondition;
-import static com.azure.core.amqp.implementation.ClientConstants.NOT_APPLICABLE;
import static com.azure.core.util.FluxUtil.monoError;
/**
@@ -73,7 +70,11 @@ protected ReactorReceiver(AmqpConnection amqpConnection, String entityPath, Rece
this.handler = handler;
this.tokenManager = tokenManager;
this.dispatcher = dispatcher;
- this.logger = new ClientLogger(ReactorReceiver.class, Map.of(CONNECTION_ID_KEY, handler.getConnectionId(), LINK_NAME_KEY, this.handler.getLinkName()));
+
+ Map loggingContext = createContextWithConnectionId(handler.getConnectionId());
+ loggingContext.put(LINK_NAME_KEY, this.handler.getLinkName());
+ this.logger = new ClientLogger(ReactorReceiver.class, loggingContext);
+
// Delivered messages are not published on another scheduler because we want the settlement method that happens
// in decodeDelivery to take place and since proton-j is not thread safe, it could end up with hundreds of
// backed up deliveries waiting to be settled. (Which, consequently, ends up in a FAIL_OVERFLOW error from
@@ -160,12 +161,12 @@ protected ReactorReceiver(AmqpConnection amqpConnection, String entityPath, Rece
}).subscribe(response ->
logger.atVerbose()
.addKeyValue("response", response)
- .log("Token refreshed.")
- , error -> {
- }, () -> {
- logger.atVerbose()
- .addKeyValue(ENTITY_PATH_KEY, entityPath)
- .log("Authorization completed.");
+ .log("Token refreshed."),
+ error -> { },
+ () -> {
+ logger.atVerbose()
+ .addKeyValue(ENTITY_PATH_KEY, entityPath)
+ .log("Authorization completed.");
closeAsync("Authorization completed. Disposing.", null).subscribe();
}),
diff --git a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ReactorSender.java b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ReactorSender.java
index 8048c1e0ab2f..398c023237c7 100644
--- a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ReactorSender.java
+++ b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ReactorSender.java
@@ -58,7 +58,7 @@
import static com.azure.core.amqp.exception.AmqpErrorCondition.NOT_ALLOWED;
import static com.azure.core.amqp.implementation.AmqpLoggingUtils.addErrorCondition;
-import static com.azure.core.amqp.implementation.ClientConstants.CONNECTION_ID_KEY;
+import static com.azure.core.amqp.implementation.AmqpLoggingUtils.createContextWithConnectionId;
import static com.azure.core.amqp.implementation.ClientConstants.ENTITY_PATH_KEY;
import static com.azure.core.amqp.implementation.ClientConstants.LINK_NAME_KEY;
import static com.azure.core.amqp.implementation.ClientConstants.MAX_AMQP_HEADER_SIZE_BYTES;
@@ -131,7 +131,12 @@ class ReactorSender implements AmqpSendLink, AsyncCloseable, AutoCloseable {
String connectionId = handler.getConnectionId() == null ? NOT_APPLICABLE : handler.getConnectionId();
String linkName = getLinkName() == null ? NOT_APPLICABLE : getLinkName();
- this.logger = new ClientLogger(ReactorSender.class, Map.of(CONNECTION_ID_KEY, connectionId, ENTITY_PATH_KEY, entityPath, LINK_NAME_KEY, linkName));
+
+ Map loggingContext = createContextWithConnectionId(connectionId);
+ loggingContext.put(LINK_NAME_KEY, linkName);
+ loggingContext.put(ENTITY_PATH_KEY, entityPath);
+ this.logger = new ClientLogger(ReactorSender.class, loggingContext);
+
this.activeTimeoutMessage = String.format(
"ReactorSender connectionId[%s] linkName[%s]: Waiting for send and receive handler to be ACTIVE",
handler.getConnectionId(), handler.getLinkName());
@@ -338,7 +343,7 @@ public Mono getLinkSize() {
if (remoteMaxMessageSize != null) {
linkSize = remoteMaxMessageSize.intValue();
} else {
- logger.warning("Could not get the getRemoteMaxMessageSize. Returning current link size: {}",linkSize);
+ logger.warning("Could not get the getRemoteMaxMessageSize. Returning current link size: {}", linkSize);
}
return linkSize;
diff --git a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ReactorSession.java b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ReactorSession.java
index 5e71fef941a6..a5e7e10df09a 100644
--- a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ReactorSession.java
+++ b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ReactorSession.java
@@ -52,7 +52,7 @@
import java.util.function.Consumer;
import static com.azure.core.amqp.implementation.AmqpLoggingUtils.addSignalTypeAndResult;
-import static com.azure.core.amqp.implementation.ClientConstants.CONNECTION_ID_KEY;
+import static com.azure.core.amqp.implementation.AmqpLoggingUtils.createContextWithConnectionId;
import static com.azure.core.amqp.implementation.ClientConstants.ENTITY_PATH_KEY;
import static com.azure.core.amqp.implementation.ClientConstants.LINK_NAME_KEY;
import static com.azure.core.amqp.implementation.AmqpLoggingUtils.addErrorCondition;
@@ -128,7 +128,7 @@ public ReactorSession(AmqpConnection amqpConnection, Session session, SessionHan
"ReactorSession connectionId[%s], session[%s]: Retries exhausted waiting for ACTIVE endpoint state.",
sessionHandler.getConnectionId(), sessionName);
- this.logger = new ClientLogger(ReactorSession.class, Map.of(CONNECTION_ID_KEY, this.sessionHandler.getConnectionId()));
+ this.logger = new ClientLogger(ReactorSession.class, createContextWithConnectionId(this.sessionHandler.getConnectionId()));
this.endpointStates = sessionHandler.getEndpointStates()
.map(state -> {
diff --git a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/RequestResponseChannel.java b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/RequestResponseChannel.java
index beb1cd4e4daf..fba17564fde9 100644
--- a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/RequestResponseChannel.java
+++ b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/RequestResponseChannel.java
@@ -47,7 +47,7 @@
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
-import static com.azure.core.amqp.implementation.ClientConstants.CONNECTION_ID_KEY;
+import static com.azure.core.amqp.implementation.AmqpLoggingUtils.createContextWithConnectionId;
import static com.azure.core.amqp.implementation.ClientConstants.LINK_NAME_KEY;
import static com.azure.core.amqp.implementation.AmqpLoggingUtils.addSignalTypeAndResult;
import static com.azure.core.util.FluxUtil.monoError;
@@ -123,7 +123,11 @@ protected RequestResponseChannel(AmqpConnection amqpConnection, String connectio
AmqpRetryOptions retryOptions, ReactorHandlerProvider handlerProvider, ReactorProvider provider,
MessageSerializer messageSerializer, SenderSettleMode senderSettleMode,
ReceiverSettleMode receiverSettleMode) {
- this.logger = new ClientLogger(RequestResponseChannel.class, Map.of(CONNECTION_ID_KEY, connectionId, LINK_NAME_KEY, linkName));
+
+ Map loggingContext = createContextWithConnectionId(connectionId);
+ loggingContext.put(LINK_NAME_KEY, linkName);
+ this.logger = new ClientLogger(RequestResponseChannel.class, loggingContext);
+
this.retryOptions = retryOptions;
this.provider = provider;
this.senderSettleMode = senderSettleMode;
diff --git a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/ConnectionHandler.java b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/ConnectionHandler.java
index daa074bac0e1..b99ce0492867 100644
--- a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/ConnectionHandler.java
+++ b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/ConnectionHandler.java
@@ -10,7 +10,6 @@
import com.azure.core.util.ClientOptions;
import com.azure.core.util.CoreUtils;
import com.azure.core.util.UserAgentUtil;
-import com.azure.core.util.logging.ClientLogger;
import org.apache.qpid.proton.Proton;
import org.apache.qpid.proton.amqp.Symbol;
import org.apache.qpid.proton.amqp.transport.ErrorCondition;
@@ -229,7 +228,7 @@ public void onTransportError(Event event) {
final ErrorCondition condition = transport.getCondition();
addErrorCondition(logger.atWarning(), condition)
- .addKeyValue(HOSTNAME_KEY, connection.getHostname())
+ .addKeyValue(HOSTNAME_KEY, connection != null ? connection.getHostname() : ClientConstants.NOT_APPLICABLE)
.log("onTransportError");
if (connection != null) {
@@ -247,7 +246,7 @@ public void onTransportClosed(Event event) {
final ErrorCondition condition = transport.getCondition();
addErrorCondition(logger.atInfo(), condition)
- .addKeyValue(HOSTNAME_KEY, connection.getHostname())
+ .addKeyValue(HOSTNAME_KEY, connection != null ? connection.getHostname() : ClientConstants.NOT_APPLICABLE)
.log("onTransportClosed");
if (connection != null) {
diff --git a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/CustomIOHandler.java b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/CustomIOHandler.java
index 4b102e3954b7..f39bb9e70cb0 100644
--- a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/CustomIOHandler.java
+++ b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/CustomIOHandler.java
@@ -9,9 +9,7 @@
import org.apache.qpid.proton.engine.Transport;
import org.apache.qpid.proton.reactor.impl.IOHandler;
-import java.util.Map;
-
-import static com.azure.core.amqp.implementation.ClientConstants.CONNECTION_ID_KEY;
+import static com.azure.core.amqp.implementation.AmqpLoggingUtils.createContextWithConnectionId;
import static com.azure.core.amqp.implementation.ClientConstants.HOSTNAME_KEY;
import static com.azure.core.amqp.implementation.ClientConstants.NOT_APPLICABLE;
@@ -19,7 +17,7 @@ public class CustomIOHandler extends IOHandler {
private final ClientLogger logger;
public CustomIOHandler(final String connectionId) {
- this.logger = new ClientLogger(CustomIOHandler.class, Map.of(CONNECTION_ID_KEY, connectionId));
+ this.logger = new ClientLogger(CustomIOHandler.class, createContextWithConnectionId(connectionId));
}
@Override
diff --git a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/Handler.java b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/Handler.java
index 1282f0c2d9cd..0e308e9e1122 100644
--- a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/Handler.java
+++ b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/Handler.java
@@ -10,12 +10,11 @@
import reactor.core.publisher.Sinks;
import java.io.Closeable;
-import java.util.Map;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicBoolean;
import static com.azure.core.amqp.implementation.AmqpLoggingUtils.addSignalTypeAndResult;
-import static com.azure.core.amqp.implementation.ClientConstants.CONNECTION_ID_KEY;
+import static com.azure.core.amqp.implementation.AmqpLoggingUtils.createContextWithConnectionId;
/**
* Base class for all proton-j handlers.
@@ -43,8 +42,7 @@ public abstract class Handler extends BaseHandler implements Closeable {
Handler(final String connectionId, final String hostname, final String loggerName) {
this.connectionId = Objects.requireNonNull(connectionId, "'connectionId' cannot be null.");
this.hostname = Objects.requireNonNull(hostname, "'hostname' cannot be null.");
- this.logger = new ClientLogger(Objects.requireNonNull(loggerName, "'loggerName' cannot be null."),
- Map.of(CONNECTION_ID_KEY, connectionId));
+ this.logger = new ClientLogger(Objects.requireNonNull(loggerName, "'loggerName' cannot be null."), createContextWithConnectionId(connectionId));
}
/**
diff --git a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/LinkHandler.java b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/LinkHandler.java
index 9c584aff7ea8..7ee02b2d973b 100644
--- a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/LinkHandler.java
+++ b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/LinkHandler.java
@@ -6,7 +6,6 @@
import com.azure.core.amqp.exception.AmqpErrorContext;
import com.azure.core.amqp.exception.LinkErrorContext;
import com.azure.core.amqp.implementation.ExceptionUtil;
-import com.azure.core.util.logging.ClientLogger;
import org.apache.qpid.proton.amqp.transport.ErrorCondition;
import org.apache.qpid.proton.engine.EndpointState;
import org.apache.qpid.proton.engine.Event;
diff --git a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/ReactorHandler.java b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/ReactorHandler.java
index 35d7774a3385..0ad459c6431e 100644
--- a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/ReactorHandler.java
+++ b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/ReactorHandler.java
@@ -8,10 +8,9 @@
import org.apache.qpid.proton.engine.Event;
import org.apache.qpid.proton.reactor.Reactor;
-import java.util.Map;
import java.util.Objects;
-import static com.azure.core.amqp.implementation.ClientConstants.CONNECTION_ID_KEY;
+import static com.azure.core.amqp.implementation.AmqpLoggingUtils.createContextWithConnectionId;
/**
* Handler that sets the timeout period for waiting for Selectables.
@@ -27,7 +26,7 @@ public class ReactorHandler extends BaseHandler {
public ReactorHandler(final String connectionId) {
Objects.requireNonNull(connectionId);
- this.logger = new ClientLogger(ReactorHandler.class, Map.of(CONNECTION_ID_KEY, connectionId));
+ this.logger = new ClientLogger(ReactorHandler.class, createContextWithConnectionId(connectionId));
}
@Override
diff --git a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/ReceiveLinkHandler.java b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/ReceiveLinkHandler.java
index ac3b4b8582df..08146c596425 100644
--- a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/ReceiveLinkHandler.java
+++ b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/ReceiveLinkHandler.java
@@ -140,7 +140,7 @@ public void onDelivery(Event event) {
.addKeyValue(ENTITY_PATH_KEY, entityPath)
.addKeyValue(LINK_NAME_KEY, linkName)
.addKeyValue("updatedLinkCredit", link.getCredit())
- .addKeyValue("remoteCredit",link.getRemoteCredit())
+ .addKeyValue("remoteCredit", link.getRemoteCredit())
.addKeyValue("delivery.isSettled", delivery.isSettled())
.log("Was already settled.");
} else {
diff --git a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/SendLinkHandler.java b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/SendLinkHandler.java
index af73ef5f951d..0ee4cafd4a17 100644
--- a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/SendLinkHandler.java
+++ b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/SendLinkHandler.java
@@ -23,6 +23,7 @@
import static com.azure.core.amqp.implementation.ClientConstants.EMIT_RESULT_KEY;
import static com.azure.core.amqp.implementation.ClientConstants.ENTITY_PATH_KEY;
import static com.azure.core.amqp.implementation.ClientConstants.LINK_NAME_KEY;
+import static com.azure.core.amqp.implementation.ClientConstants.NOT_APPLICABLE;
/**
* Handler that receives events from its corresponding {@link Sender}. Handlers must be associated to a {@link Sender}
@@ -107,14 +108,13 @@ public void onLinkRemoteOpen(Event event) {
.addKeyValue(ENTITY_PATH_KEY, entityPath);
if (link.getRemoteTarget() != null) {
- // TODO escape
logBuilder.addKeyValue("remoteTarget", link.getRemoteTarget());
if (!isRemoteActive.getAndSet(true)) {
onNext(EndpointState.ACTIVE);
}
} else {
- logBuilder.addKeyValue("remoteTarget", (String)null)
+ logBuilder.addKeyValue("remoteTarget", NOT_APPLICABLE)
.addKeyValue("action", "waitingForError");
}
logBuilder.log("onLinkRemoteOpen");
diff --git a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/SessionHandler.java b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/SessionHandler.java
index aa6d92ad6898..b6ba8e3c429a 100644
--- a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/SessionHandler.java
+++ b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/SessionHandler.java
@@ -101,13 +101,12 @@ public void onSessionLocalClose(Event e) {
@Override
public void onSessionRemoteClose(Event e) {
final Session session = e.getSession();
+ final ErrorCondition condition = session != null ? session.getRemoteCondition() : null;
- addErrorCondition(logger.atInfo(), session.getCondition())
+ addErrorCondition(logger.atInfo(), condition)
.addKeyValue(SESSION_NAME_KEY, sessionName)
.log("onSessionRemoteClose");
- ErrorCondition condition = session != null ? session.getRemoteCondition() : null;
-
if (session != null && session.getLocalState() != EndpointState.CLOSED) {
addErrorCondition(logger.atInfo(), condition)
.addKeyValue(SESSION_NAME_KEY, sessionName)
diff --git a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/WebSocketsConnectionHandler.java b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/WebSocketsConnectionHandler.java
index 37d4255c9572..9e4d59541a32 100644
--- a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/WebSocketsConnectionHandler.java
+++ b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/WebSocketsConnectionHandler.java
@@ -9,10 +9,7 @@
import org.apache.qpid.proton.engine.Event;
import org.apache.qpid.proton.engine.SslPeerDetails;
import org.apache.qpid.proton.engine.impl.TransportInternal;
-
-import java.util.Map;
-
-import static com.azure.core.amqp.implementation.ClientConstants.CONNECTION_ID_KEY;
+import static com.azure.core.amqp.implementation.AmqpLoggingUtils.createContextWithConnectionId;
import static com.azure.core.amqp.implementation.ClientConstants.HOSTNAME_KEY;
/**
@@ -38,7 +35,7 @@ public class WebSocketsConnectionHandler extends ConnectionHandler {
public WebSocketsConnectionHandler(String connectionId, ConnectionOptions connectionOptions,
SslPeerDetails peerDetails) {
super(connectionId, connectionOptions, peerDetails);
- logger = new ClientLogger(WebSocketsConnectionHandler.class, Map.of(CONNECTION_ID_KEY, connectionId));
+ logger = new ClientLogger(WebSocketsConnectionHandler.class, createContextWithConnectionId(connectionId));
}
/**
diff --git a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/WebSocketsProxyConnectionHandler.java b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/WebSocketsProxyConnectionHandler.java
index fadb892ca552..3c919d8ccffc 100644
--- a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/WebSocketsProxyConnectionHandler.java
+++ b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/WebSocketsProxyConnectionHandler.java
@@ -27,11 +27,10 @@
import java.net.URI;
import java.util.List;
import java.util.Locale;
-import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
-import static com.azure.core.amqp.implementation.ClientConstants.CONNECTION_ID_KEY;
+import static com.azure.core.amqp.implementation.AmqpLoggingUtils.createContextWithConnectionId;
import static com.azure.core.amqp.implementation.AmqpLoggingUtils.addErrorCondition;
import static com.azure.core.amqp.implementation.ClientConstants.HOSTNAME_KEY;
@@ -65,7 +64,7 @@ public WebSocketsProxyConnectionHandler(String connectionId, ConnectionOptions c
this.proxyOptions = Objects.requireNonNull(proxyOptions, "'proxyConfiguration' cannot be null.");
this.fullyQualifiedNamespace = connectionOptions.getFullyQualifiedNamespace();
this.amqpBrokerHostname = connectionOptions.getFullyQualifiedNamespace() + ":" + connectionOptions.getPort();
- this.logger = new ClientLogger(WebSocketsProxyConnectionHandler.class, Map.of(CONNECTION_ID_KEY, connectionId));
+ this.logger = new ClientLogger(WebSocketsProxyConnectionHandler.class, createContextWithConnectionId(connectionId));
if (proxyOptions.isProxyAddressConfigured()) {
this.connectionHostname = (InetSocketAddress) proxyOptions.getProxyAddress().address();
} else {
diff --git a/sdk/core/azure-core-amqp/src/test/java/com/azure/core/amqp/implementation/AmqpChannelProcessorTest.java b/sdk/core/azure-core-amqp/src/test/java/com/azure/core/amqp/implementation/AmqpChannelProcessorTest.java
index 815420f16cdf..53c3b1b4ed69 100644
--- a/sdk/core/azure-core-amqp/src/test/java/com/azure/core/amqp/implementation/AmqpChannelProcessorTest.java
+++ b/sdk/core/azure-core-amqp/src/test/java/com/azure/core/amqp/implementation/AmqpChannelProcessorTest.java
@@ -8,7 +8,6 @@
import com.azure.core.amqp.exception.AmqpErrorCondition;
import com.azure.core.amqp.exception.AmqpErrorContext;
import com.azure.core.amqp.exception.AmqpException;
-import com.azure.core.util.logging.ClientLogger;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
diff --git a/sdk/core/azure-core-amqp/src/test/java/com/azure/core/amqp/implementation/handler/HandlerTest.java b/sdk/core/azure-core-amqp/src/test/java/com/azure/core/amqp/implementation/handler/HandlerTest.java
index b23b9ad76069..546e2c2326b8 100644
--- a/sdk/core/azure-core-amqp/src/test/java/com/azure/core/amqp/implementation/handler/HandlerTest.java
+++ b/sdk/core/azure-core-amqp/src/test/java/com/azure/core/amqp/implementation/handler/HandlerTest.java
@@ -5,7 +5,6 @@
import com.azure.core.amqp.exception.AmqpErrorContext;
import com.azure.core.amqp.exception.AmqpException;
-import com.azure.core.util.logging.ClientLogger;
import org.apache.qpid.proton.engine.EndpointState;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
diff --git a/sdk/core/azure-core-amqp/src/test/java/com/azure/core/amqp/implementation/handler/LinkHandlerTest.java b/sdk/core/azure-core-amqp/src/test/java/com/azure/core/amqp/implementation/handler/LinkHandlerTest.java
index a34cca0521cf..6d8cf3470164 100644
--- a/sdk/core/azure-core-amqp/src/test/java/com/azure/core/amqp/implementation/handler/LinkHandlerTest.java
+++ b/sdk/core/azure-core-amqp/src/test/java/com/azure/core/amqp/implementation/handler/LinkHandlerTest.java
@@ -7,7 +7,6 @@
import com.azure.core.amqp.exception.AmqpErrorContext;
import com.azure.core.amqp.exception.AmqpException;
import com.azure.core.amqp.exception.LinkErrorContext;
-import com.azure.core.util.logging.ClientLogger;
import org.apache.qpid.proton.amqp.Symbol;
import org.apache.qpid.proton.amqp.transport.ErrorCondition;
import org.apache.qpid.proton.engine.EndpointState;
From dece26bcbdb02b7350c81efebb2dfebb10057252 Mon Sep 17 00:00:00 2001
From: Liudmila Molkova
Date: Wed, 1 Dec 2021 16:42:10 -0800
Subject: [PATCH 05/17] mroe cleanup
---
.../azure/core/amqp/AmqpShutdownSignal.java | 2 +-
.../ActiveClientTokenManager.java | 2 +-
.../implementation/AmqpChannelProcessor.java | 2 +-
.../AzureTokenManagerProvider.java | 2 +-
.../implementation/ReactorConnection.java | 7 +++--
.../implementation/ReactorDispatcher.java | 19 ++++++-------
.../amqp/implementation/ReactorReceiver.java | 27 +++----------------
.../amqp/implementation/ReactorSender.java | 5 ++--
.../amqp/implementation/ReactorSession.java | 4 +--
.../RequestResponseChannel.java | 8 +++---
.../handler/ConnectionHandler.java | 8 +++---
.../handler/CustomIOHandler.java | 2 +-
.../implementation/handler/LinkHandler.java | 3 ++-
.../handler/ReceiveLinkHandler.java | 7 ++---
.../WebSocketsProxyConnectionHandler.java | 6 ++---
15 files changed, 41 insertions(+), 63 deletions(-)
diff --git a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/AmqpShutdownSignal.java b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/AmqpShutdownSignal.java
index 24e3a9a72db4..88bd392265fd 100644
--- a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/AmqpShutdownSignal.java
+++ b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/AmqpShutdownSignal.java
@@ -47,7 +47,7 @@ public boolean isInitiatedByClient() {
}
/**
- * Returns String representing this {@code AmqpShutdownSignal} signal.
+ * Returns String representing the message of this {@code AmqpShutdownSignal} signal.
*
* To write logs, please use {@link com.azure.core.amqp.implementation.AmqpLoggingUtils#addShutdownSignal(LoggingEventBuilder, AmqpShutdownSignal)}.
*/
diff --git a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ActiveClientTokenManager.java b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ActiveClientTokenManager.java
index fb39f6e7fd20..2a91370a2488 100644
--- a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ActiveClientTokenManager.java
+++ b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ActiveClientTokenManager.java
@@ -148,7 +148,7 @@ private Disposable scheduleRefreshTokenTask(Duration initialRefresh) {
durationSource.emitNext(lastRefresh, (signalType, emitResult) -> {
addSignalTypeAndResult(logger.atVerbose(), signalType, emitResult)
.addKeyValue("lastRefresh", lastRefresh)
- .log("Could not emit.");
+ .log("Could not emit lastRefresh.");
return false;
});
diff --git a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/AmqpChannelProcessor.java b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/AmqpChannelProcessor.java
index 2a6640992646..ee8340730601 100644
--- a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/AmqpChannelProcessor.java
+++ b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/AmqpChannelProcessor.java
@@ -231,7 +231,7 @@ public void subscribe(CoreSubscriber super T> actual) {
actual.onSubscribe(Operators.emptySubscription());
actual.onError(lastError);
} else {
- Operators.error(actual, logger.atError().log(new IllegalStateException("Cannot subscribe. Processor is already terminated.")));
+ Operators.error(actual, logger.logExceptionAsError(new IllegalStateException("Cannot subscribe. Processor is already terminated.")));
}
return;
diff --git a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/AzureTokenManagerProvider.java b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/AzureTokenManagerProvider.java
index fe4488f92fc1..9a015af447f8 100644
--- a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/AzureTokenManagerProvider.java
+++ b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/AzureTokenManagerProvider.java
@@ -66,7 +66,7 @@ public String getScopesFromResource(String resource) {
} else if (CbsAuthorizationType.SHARED_ACCESS_SIGNATURE.equals(authorizationType)) {
return String.format(Locale.US, TOKEN_AUDIENCE_FORMAT, fullyQualifiedNamespace, resource);
} else {
- throw logger.atError().log(new IllegalArgumentException(String.format(Locale.US,
+ throw logger.logExceptionAsError(new IllegalArgumentException(String.format(Locale.US,
"'%s' is not supported authorization type for token audience.", authorizationType)));
}
}
diff --git a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ReactorConnection.java b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ReactorConnection.java
index f1a537155cbe..bf0ee0f18d03 100644
--- a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ReactorConnection.java
+++ b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ReactorConnection.java
@@ -137,8 +137,7 @@ public ReactorConnection(String connectionId, ConnectionOptions connectionOption
})
.doOnError(error -> {
if (isDisposed.getAndSet(true)) {
- logger.atVerbose()
- .log("Connection was already disposed: Error occurred while connection was starting.", error);
+ logger.verbose("Connection was already disposed: Error occurred while connection was starting.", error);
} else {
closeAsync(new AmqpShutdownSignal(false, false, String.format(
"Error occurred while connection was starting. Error: %s", error))).subscribe();
@@ -207,7 +206,7 @@ public Mono getManagementNode(String entityPath) {
return tokenManager.authorize().thenReturn(managementNodes.compute(entityPath, (key, current) -> {
if (current != null) {
- logger.atInfo().addKeyValue(ENTITY_PATH_KEY, entityPath).log("A management node exists already, returning it.");
+ logger.info("A management node exists already, returning it.");
// Close the token manager we had created during this because it is unneeded now.
tokenManager.close();
@@ -302,7 +301,7 @@ public Mono createSession(String sessionName) {
logger.atVerbose()
.addKeyValue(SESSION_NAME_KEY, sessionName)
- .log("connectionId[{}] sessionName[{}]: Complete. Removing and disposing session.");
+ .log("Complete. Removing and disposing session.");
removeSession(key);
});
diff --git a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ReactorDispatcher.java b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ReactorDispatcher.java
index 5bfee1bfc13d..77bdd2338f47 100644
--- a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ReactorDispatcher.java
+++ b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ReactorDispatcher.java
@@ -127,7 +127,7 @@ private void throwIfSchedulerError() {
final RejectedExecutionException rejectedException = this.reactor.attachments()
.get(RejectedExecutionException.class, RejectedExecutionException.class);
if (rejectedException != null) {
- throw logger.atWarning().log(new RejectedExecutionException(
+ throw logger.logExceptionAsWarning(new RejectedExecutionException(
"Underlying Reactor was already disposed. Should not continue dispatching work to this. "
+ rejectedException.getMessage(), rejectedException));
}
@@ -135,7 +135,7 @@ private void throwIfSchedulerError() {
// throw when the pipe is in closed state - in which case,
// signalling the new event-dispatch will fail
if (!this.ioSignal.sink().isOpen()) {
- throw logger.atWarning().log(new RejectedExecutionException(
+ throw logger.logExceptionAsWarning(new RejectedExecutionException(
"ReactorDispatcher instance is closed. Should not continue dispatching work to this reactor."));
}
}
@@ -148,8 +148,7 @@ private void signalWorkQueue() throws IOException {
}
} catch (ClosedChannelException ignorePipeClosedDuringReactorShutdown) {
if (!isClosed.get()) {
- logger.atWarning()
- .log("signalWorkQueue failed before reactor closed.", ignorePipeClosedDuringReactorShutdown);
+ logger.warning("signalWorkQueue failed before reactor closed.", ignorePipeClosedDuringReactorShutdown);
shutdownSignal.emitError(new RuntimeException(String.format(
"connectionId[%s] IO Sink was interrupted before reactor closed.", connectionId),
ignorePipeClosedDuringReactorShutdown), Sinks.EmitFailureHandler.FAIL_FAST);
@@ -180,19 +179,17 @@ public void run(Selectable selectable) {
}
} catch (ClosedChannelException ignorePipeClosedDuringReactorShutdown) {
if (!isClosed.get()) {
- logger.atWarning()
- .log("WorkScheduler.run() failed before reactor was closed.", ignorePipeClosedDuringReactorShutdown);
+ logger.warning("WorkScheduler.run() failed before reactor was closed.", ignorePipeClosedDuringReactorShutdown);
shutdownSignal.emitError(new RuntimeException(String.format(
"connectionId[%s] IO Source was interrupted before reactor closed.", connectionId),
ignorePipeClosedDuringReactorShutdown), Sinks.EmitFailureHandler.FAIL_FAST);
} else {
- logger.atVerbose()
- .log("WorkScheduler.run() failed with an error. Can be ignored.", ignorePipeClosedDuringReactorShutdown);
+ logger.verbose("WorkScheduler.run() failed with an error. Can be ignored.", ignorePipeClosedDuringReactorShutdown);
}
break;
} catch (IOException ioException) {
- shutdownSignal.emitError(logger.atError().log(new RuntimeException(
+ shutdownSignal.emitError(logger.logExceptionAsError(new RuntimeException(
"WorkScheduler.run() failed with an error.", ioException)), Sinks.EmitFailureHandler.FAIL_FAST);
break;
}
@@ -232,7 +229,7 @@ public void run(Selectable selectable) {
ioSignal.sink().close();
}
} catch (IOException ioException) {
- logger.atError().log("CloseHandler.sink().close() failed with an error.", ioException);
+ logger.error("CloseHandler.sink().close() failed with an error.", ioException);
}
workScheduler.run(null);
@@ -242,7 +239,7 @@ public void run(Selectable selectable) {
ioSignal.source().close();
}
} catch (IOException ioException) {
- logger.atError().log("CloseHandler.source().close() failed with an error.", ioException);
+ logger.error("CloseHandler.source().close() failed with an error.", ioException);
}
}
}
diff --git a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ReactorReceiver.java b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ReactorReceiver.java
index e4d6c45272b4..130cf68df478 100644
--- a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ReactorReceiver.java
+++ b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ReactorReceiver.java
@@ -10,7 +10,6 @@
import com.azure.core.amqp.implementation.handler.ReceiveLinkHandler;
import com.azure.core.util.AsyncCloseable;
import com.azure.core.util.logging.ClientLogger;
-import com.azure.core.util.logging.LoggingEventBuilder;
import org.apache.qpid.proton.Proton;
import org.apache.qpid.proton.amqp.Symbol;
import org.apache.qpid.proton.amqp.transport.ErrorCondition;
@@ -20,7 +19,6 @@
import org.apache.qpid.proton.message.Message;
import reactor.core.Disposable;
import reactor.core.Disposables;
-import reactor.core.Exceptions;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.core.publisher.Sinks;
@@ -38,7 +36,6 @@
import static com.azure.core.amqp.implementation.AmqpLoggingUtils.addErrorCondition;
import static com.azure.core.amqp.implementation.AmqpLoggingUtils.addSignalTypeAndResult;
import static com.azure.core.amqp.implementation.AmqpLoggingUtils.createContextWithConnectionId;
-import static com.azure.core.amqp.implementation.ClientConstants.CONNECTION_ID_KEY;
import static com.azure.core.amqp.implementation.ClientConstants.ENTITY_PATH_KEY;
import static com.azure.core.amqp.implementation.ClientConstants.LINK_NAME_KEY;
import static com.azure.core.util.FluxUtil.monoError;
@@ -172,8 +169,7 @@ protected ReactorReceiver(AmqpConnection amqpConnection, String entityPath, Rece
}),
amqpConnection.getShutdownSignals().flatMap(signal -> {
- logger.atVerbose()
- .log("Shutdown signal received.");
+ logger.verbose("Shutdown signal received.");
return closeAsync("Connection shutdown.", null);
}).subscribe());
//@formatter:on
@@ -192,7 +188,7 @@ public Flux receive() {
@Override
public Mono addCredits(int credits) {
if (isDisposed()) {
- return monoError(logger, Exceptions.propagate(new IllegalStateException("Cannot add credits to closed link: " + getLinkName())));
+ return monoError(logger, new IllegalStateException("Cannot add credits to closed link: " + getLinkName()));
}
return Mono.create(sink -> {
@@ -299,15 +295,13 @@ Mono closeAsync(String message, ErrorCondition errorCondition) {
try {
dispatcher.invoke(closeReceiver);
} catch (IOException e) {
- logger.atWarning()
- .log("IO sink was closed when scheduling work. Manually invoking and completing close.", e);
+ logger.warning("IO sink was closed when scheduling work. Manually invoking and completing close.", e);
closeReceiver.run();
completeClose();
} catch (RejectedExecutionException e) {
// Not logging error here again because we have to log the exception when we throw it.
- logger.atInfo()
- .log("RejectedExecutionException when scheduling on ReactorDispatcher. Manually invoking and completing close.");
+ logger.info("RejectedExecutionException when scheduling on ReactorDispatcher. Manually invoking and completing close.");
closeReceiver.run();
completeClose();
@@ -322,7 +316,6 @@ private void completeClose() {
isClosedMono.emitEmpty((signalType, result) -> {
addSignalTypeAndResult(logger.atWarning(), signalType, result)
- .addKeyValue(ENTITY_PATH_KEY, entityPath)
.log("Unable to emit shutdown signal.");
return false;
});
@@ -337,18 +330,6 @@ private void completeClose() {
receiver.free();
}
- public LoggingEventBuilder addContext(LoggingEventBuilder logBuilder) {
- return logBuilder
- .addKeyValue(CONNECTION_ID_KEY, receiver.getName())
- .addKeyValue(ENTITY_PATH_KEY, entityPath)
- .addKeyValue(LINK_NAME_KEY, getLinkName());
- }
-
- /**
- * Returns String representing this {@code ReactorReceiver} signal.
- *
- * To write logs, please use {@link ReactorReceiver#addContext} instead.
- */
@Override
public String toString() {
return String.format("connectionId: [%s] entity path: [%s] linkName: [%s]", receiver.getName(), entityPath,
diff --git a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ReactorSender.java b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ReactorSender.java
index 398c023237c7..90a16e855a95 100644
--- a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ReactorSender.java
+++ b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ReactorSender.java
@@ -58,6 +58,7 @@
import static com.azure.core.amqp.exception.AmqpErrorCondition.NOT_ALLOWED;
import static com.azure.core.amqp.implementation.AmqpLoggingUtils.addErrorCondition;
+import static com.azure.core.amqp.implementation.AmqpLoggingUtils.addSignalTypeAndResult;
import static com.azure.core.amqp.implementation.AmqpLoggingUtils.createContextWithConnectionId;
import static com.azure.core.amqp.implementation.ClientConstants.ENTITY_PATH_KEY;
import static com.azure.core.amqp.implementation.ClientConstants.LINK_NAME_KEY;
@@ -569,7 +570,7 @@ private void processDeliveredMessage(Delivery delivery) {
if (workItem == null) {
logger.atVerbose()
.addKeyValue(DELIVERY_TAG_KEY, deliveryTag)
- .log("Mismatch (or send timed out.");
+ .log("Mismatch (or send timed out).");
return;
} else if (workItem.isDeliveryStateProvided()) {
@@ -655,7 +656,7 @@ private void cleanupFailedSend(final RetriableWorkItem workItem, final Exception
private void completeClose() {
isClosedMono.emitEmpty((signalType, result) -> {
- logger.warning("Unable to emit shutdown signal.");
+ addSignalTypeAndResult(logger.atWarning(), signalType, result).log("Unable to emit shutdown signal.");
return false;
});
diff --git a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ReactorSession.java b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ReactorSession.java
index a5e7e10df09a..ca8dcf47d4fd 100644
--- a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ReactorSession.java
+++ b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ReactorSession.java
@@ -266,13 +266,13 @@ Mono closeAsync(String message, ErrorCondition errorCondition, boolean dis
addErrorCondition(logger.atVerbose(), errorCondition)
.addKeyValue(SESSION_NAME_KEY, sessionName)
- .log("Disposing session. {}", message != null ? message : "");
+ .log("Setting error condition and disposing session. {}", message);
return Mono.fromRunnable(() -> {
try {
provider.getReactorDispatcher().invoke(() -> disposeWork(errorCondition, disposeLinks));
} catch (IOException e) {
- addErrorCondition(logger.atInfo(), errorCondition)
+ logger.atInfo()
.addKeyValue(SESSION_NAME_KEY, sessionName)
.log("Error while scheduling work. Manually disposing.", e);
diff --git a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/RequestResponseChannel.java b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/RequestResponseChannel.java
index fba17564fde9..7743937df527 100644
--- a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/RequestResponseChannel.java
+++ b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/RequestResponseChannel.java
@@ -218,7 +218,7 @@ protected RequestResponseChannel(AmqpConnection amqpConnection, String connectio
this.receiveLink.open();
});
} catch (IOException | RejectedExecutionException e) {
- throw logger.atError().log(new RuntimeException("Unable to open send and receive link.", e));
+ throw logger.logExceptionAsError(new RuntimeException("Unable to open send and receive link.", e));
}
}
@@ -422,8 +422,7 @@ private void onTerminalState(String handlerName) {
}
final int remaining = pendingLinkTerminations.decrementAndGet();
- logger.atVerbose()
- .log("{} disposed. Remaining: {}", handlerName, remaining);
+ logger.verbose("{} disposed. Remaining: {}", handlerName, remaining);
if (remaining == 0) {
subscriptions.dispose();
@@ -467,8 +466,7 @@ private synchronized void updateEndpointState(AmqpEndpointState sendLinkState, A
// Terminate the unconfirmed MonoSinks by notifying the given error.
private void terminateUnconfirmedSends(Throwable error) {
- logger.atVerbose()
- .log("Terminating {} unconfirmed sends (reason: {}).", unconfirmedSends.size(), error.getMessage());
+ logger.verbose("Terminating {} unconfirmed sends (reason: {}).", unconfirmedSends.size(), error.getMessage());
Map.Entry> next;
int count = 0;
while ((next = unconfirmedSends.pollFirstEntry()) != null) {
diff --git a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/ConnectionHandler.java b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/ConnectionHandler.java
index b99ce0492867..e3855805430f 100644
--- a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/ConnectionHandler.java
+++ b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/ConnectionHandler.java
@@ -133,7 +133,7 @@ protected void addTransportLayers(Event event, TransportInternal transport) {
try {
defaultSslContext = SSLContext.getDefault();
} catch (NoSuchAlgorithmException e) {
- throw logger.atError().log(new RuntimeException("Default SSL algorithm not found in JRE. Please check your JRE setup.", e));
+ throw logger.logExceptionAsError(new RuntimeException("Default SSL algorithm not found in JRE. Please check your JRE setup.", e));
}
}
@@ -154,7 +154,7 @@ protected void addTransportLayers(Event event, TransportInternal transport) {
logger.warning("'{}' is not secure.", verifyMode);
sslDomain.setPeerAuthentication(SslDomain.VerifyMode.ANONYMOUS_PEER);
} else {
- throw logger.atError().log(new UnsupportedOperationException(
+ throw logger.logExceptionAsError(new UnsupportedOperationException(
"verifyMode is not supported: " + verifyMode));
}
@@ -209,7 +209,7 @@ public void onConnectionUnbound(Event event) {
final Connection connection = event.getConnection();
logger.atInfo()
.addKeyValue(HOSTNAME_KEY, connection.getHostname())
- .addKeyValue("localState", connection.getLocalState())
+ .addKeyValue("state", connection.getLocalState())
.addKeyValue("remoteState", connection.getRemoteState())
.log("onConnectionUnbound");
@@ -325,7 +325,7 @@ private void notifyErrorContext(Connection connection, ErrorCondition condition)
}
if (condition == null) {
- throw logger.atError().log(new IllegalStateException("notifyErrorContext does not have an ErrorCondition."));
+ throw logger.logExceptionAsError(new IllegalStateException("notifyErrorContext does not have an ErrorCondition."));
}
// if the remote-peer abruptly closes the connection without issuing close frame issue one
diff --git a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/CustomIOHandler.java b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/CustomIOHandler.java
index f39bb9e70cb0..a83c8bb6c2fb 100644
--- a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/CustomIOHandler.java
+++ b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/CustomIOHandler.java
@@ -42,7 +42,7 @@ public void onUnhandled(Event event) {
try {
super.onUnhandled(event);
} catch (NullPointerException e) {
- logger.atError().log("Exception occurred when handling event in super.", e);
+ logger.error("Exception occurred when handling event in super.", e);
}
}
}
diff --git a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/LinkHandler.java b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/LinkHandler.java
index 7ee02b2d973b..9bc36927b9f2 100644
--- a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/LinkHandler.java
+++ b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/LinkHandler.java
@@ -101,7 +101,8 @@ private void handleRemoteLinkClosed(final String eventName, final Event event) {
if (link.getLocalState() != EndpointState.CLOSED) {
logger.atInfo()
.addKeyValue(LINK_NAME_KEY, link.getName())
- .addKeyValue("state", link.getLocalState());
+ .addKeyValue("state", link.getLocalState())
+ .log("Local link state is not closed.");
link.setCondition(condition);
link.close();
diff --git a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/ReceiveLinkHandler.java b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/ReceiveLinkHandler.java
index 08146c596425..308a0d7db020 100644
--- a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/ReceiveLinkHandler.java
+++ b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/ReceiveLinkHandler.java
@@ -25,6 +25,7 @@
import java.util.concurrent.atomic.AtomicBoolean;
import static com.azure.core.amqp.implementation.AmqpLoggingUtils.addErrorCondition;
+import static com.azure.core.amqp.implementation.ClientConstants.EMIT_RESULT_KEY;
import static com.azure.core.amqp.implementation.ClientConstants.ENTITY_PATH_KEY;
import static com.azure.core.amqp.implementation.ClientConstants.LINK_NAME_KEY;
@@ -142,12 +143,12 @@ public void onDelivery(Event event) {
.addKeyValue("updatedLinkCredit", link.getCredit())
.addKeyValue("remoteCredit", link.getRemoteCredit())
.addKeyValue("delivery.isSettled", delivery.isSettled())
- .log("Was already settled.");
+ .log("onDelivery. Was already settled.");
} else {
logger.atWarning()
.addKeyValue(ENTITY_PATH_KEY, entityPath)
.addKeyValue("delivery.isSettled", delivery.isSettled())
- .log("Settled delivery with no delivery");
+ .log("Settled delivery with no link.");
}
} else {
if (link.getLocalState() == EndpointState.CLOSED) {
@@ -164,7 +165,7 @@ public void onDelivery(Event event) {
logger.atWarning()
.addKeyValue(ENTITY_PATH_KEY, entityPath)
.addKeyValue(LINK_NAME_KEY, linkName)
- .addKeyValue("emitResult", emitResult)
+ .addKeyValue(EMIT_RESULT_KEY, emitResult)
.log("Could not emit delivery. {}", delivery);
if (emitResult == Sinks.EmitResult.FAIL_OVERFLOW
diff --git a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/WebSocketsProxyConnectionHandler.java b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/WebSocketsProxyConnectionHandler.java
index 3c919d8ccffc..38ecbdd66f87 100644
--- a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/WebSocketsProxyConnectionHandler.java
+++ b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/WebSocketsProxyConnectionHandler.java
@@ -71,7 +71,7 @@ public WebSocketsProxyConnectionHandler(String connectionId, ConnectionOptions c
final URI serviceUri = createURI(connectionOptions.getHostname(), connectionOptions.getPort());
final ProxySelector proxySelector = ProxySelector.getDefault();
if (proxySelector == null) {
- throw logger.atError().log(new IllegalStateException("ProxySelector should not be null."));
+ throw logger.logExceptionAsError(new IllegalStateException("ProxySelector should not be null."));
}
final List proxies = proxySelector.select(serviceUri);
@@ -79,7 +79,7 @@ public WebSocketsProxyConnectionHandler(String connectionId, ConnectionOptions c
final String formatted = String.format("No proxy address found for: '%s'. Available: %s.",
serviceUri, proxies.stream().map(Proxy::toString).collect(Collectors.joining(", ")));
- throw logger.atError().log(new IllegalStateException(formatted));
+ throw logger.logExceptionAsError(new IllegalStateException(formatted));
}
final Proxy proxy = proxies.get(0);
@@ -231,7 +231,7 @@ private com.microsoft.azure.proton.transport.proxy.ProxyAuthenticationType getPr
case NONE:
return com.microsoft.azure.proton.transport.proxy.ProxyAuthenticationType.NONE;
default:
- throw logger.atError().log(new IllegalArgumentException(String.format("This authentication type is unknown: %s", type.name())));
+ throw logger.logExceptionAsError(new IllegalArgumentException(String.format("This authentication type is unknown: %s", type.name())));
}
}
From d631a91e5214bae770adb6a3e67e03fc8b1d4184 Mon Sep 17 00:00:00 2001
From: Liudmila Molkova
Date: Fri, 3 Dec 2021 11:44:07 -0800
Subject: [PATCH 06/17] create logger in handler implementations
---
.../amqp/implementation/AmqpLoggingUtils.java | 2 +
.../handler/ConnectionHandler.java | 5 +-
.../amqp/implementation/handler/Handler.java | 7 ++-
.../implementation/handler/LinkHandler.java | 7 +--
.../handler/ReceiveLinkHandler.java | 4 +-
.../handler/SendLinkHandler.java | 4 +-
.../handler/SessionHandler.java | 4 +-
.../implementation/handler/HandlerTest.java | 12 +++--
.../handler/LinkHandlerTest.java | 15 +++---
.../azure-core-tracing-opentelemetry/pom.xml | 2 +
.../OpenTelemetryHttpPolicy.java | 10 ++--
.../OpenTelemetrySpanSuppressionHelper.java | 52 ++++---------------
12 files changed, 52 insertions(+), 72 deletions(-)
diff --git a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/AmqpLoggingUtils.java b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/AmqpLoggingUtils.java
index 030ac2568deb..44bebb6072fc 100644
--- a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/AmqpLoggingUtils.java
+++ b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/AmqpLoggingUtils.java
@@ -11,6 +11,7 @@
import java.util.HashMap;
import java.util.Map;
+import java.util.Objects;
import static com.azure.core.amqp.implementation.ClientConstants.CONNECTION_ID_KEY;
import static com.azure.core.amqp.implementation.ClientConstants.EMIT_RESULT_KEY;
@@ -28,6 +29,7 @@ public class AmqpLoggingUtils {
* Creates logging context with connectionId.
*/
public static Map createContextWithConnectionId(String connectionId) {
+ Objects.requireNonNull(connectionId, "'connectionId' cannot be null.");
Map globalLoggingContext = new HashMap<>();
globalLoggingContext.put(CONNECTION_ID_KEY, connectionId);
diff --git a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/ConnectionHandler.java b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/ConnectionHandler.java
index e3855805430f..c3d96ed58dad 100644
--- a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/ConnectionHandler.java
+++ b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/ConnectionHandler.java
@@ -10,6 +10,7 @@
import com.azure.core.util.ClientOptions;
import com.azure.core.util.CoreUtils;
import com.azure.core.util.UserAgentUtil;
+import com.azure.core.util.logging.ClientLogger;
import org.apache.qpid.proton.Proton;
import org.apache.qpid.proton.amqp.Symbol;
import org.apache.qpid.proton.amqp.transport.ErrorCondition;
@@ -29,6 +30,7 @@
import java.util.Objects;
import static com.azure.core.amqp.implementation.AmqpLoggingUtils.addErrorCondition;
+import static com.azure.core.amqp.implementation.AmqpLoggingUtils.createContextWithConnectionId;
import static com.azure.core.amqp.implementation.ClientConstants.FULLY_QUALIFIED_NAMESPACE_KEY;
import static com.azure.core.amqp.implementation.ClientConstants.HOSTNAME_KEY;
@@ -60,7 +62,8 @@ public class ConnectionHandler extends Handler {
public ConnectionHandler(final String connectionId, final ConnectionOptions connectionOptions,
SslPeerDetails peerDetails) {
super(connectionId,
- Objects.requireNonNull(connectionOptions, "'connectionOptions' cannot be null.").getHostname(), ConnectionHandler.class.getName());
+ Objects.requireNonNull(connectionOptions, "'connectionOptions' cannot be null.").getHostname(),
+ new ClientLogger(ConnectionHandler.class, createContextWithConnectionId(connectionId)));
add(new Handshaker());
this.connectionOptions = connectionOptions;
diff --git a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/Handler.java b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/Handler.java
index 0e308e9e1122..95d389965fbb 100644
--- a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/Handler.java
+++ b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/Handler.java
@@ -14,7 +14,6 @@
import java.util.concurrent.atomic.AtomicBoolean;
import static com.azure.core.amqp.implementation.AmqpLoggingUtils.addSignalTypeAndResult;
-import static com.azure.core.amqp.implementation.AmqpLoggingUtils.createContextWithConnectionId;
/**
* Base class for all proton-j handlers.
@@ -35,14 +34,14 @@ public abstract class Handler extends BaseHandler implements Closeable {
* @param hostname Hostname of the connection. This could be the DNS hostname or the IP address of the
* connection. Usually of the form {@literal ".service.windows.net"} but can change if the
* messages are brokered through an intermediary.
- * @param loggerName loggerName to use.
+ * @param logger Logger to use for messages.
*
* @throws NullPointerException if {@code connectionId}, {@code hostname}, or {@code logger} is null.
*/
- Handler(final String connectionId, final String hostname, final String loggerName) {
+ Handler(final String connectionId, final String hostname, final ClientLogger logger) {
this.connectionId = Objects.requireNonNull(connectionId, "'connectionId' cannot be null.");
this.hostname = Objects.requireNonNull(hostname, "'hostname' cannot be null.");
- this.logger = new ClientLogger(Objects.requireNonNull(loggerName, "'loggerName' cannot be null."), createContextWithConnectionId(connectionId));
+ this.logger = Objects.requireNonNull(logger, "'logger' cannot be null.");
}
/**
diff --git a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/LinkHandler.java b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/LinkHandler.java
index 9bc36927b9f2..df5842bad7d6 100644
--- a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/LinkHandler.java
+++ b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/LinkHandler.java
@@ -6,6 +6,7 @@
import com.azure.core.amqp.exception.AmqpErrorContext;
import com.azure.core.amqp.exception.LinkErrorContext;
import com.azure.core.amqp.implementation.ExceptionUtil;
+import com.azure.core.util.logging.ClientLogger;
import org.apache.qpid.proton.amqp.transport.ErrorCondition;
import org.apache.qpid.proton.engine.EndpointState;
import org.apache.qpid.proton.engine.Event;
@@ -35,13 +36,13 @@ abstract class LinkHandler extends Handler {
* connection. Usually of the form {@literal ".service.windows.net"} but can change if the
* messages are brokered through an intermediary.
* @param entityPath The address within the message broker for this link.
- * @param loggerName Logger name to use for messages.
+ * @param logger Logger to use for messages.
*
* @throws NullPointerException if {@code connectionId}, {@code hostname}, {@code entityPath}, or {@code logger} is
* null.
*/
- LinkHandler(String connectionId, String hostname, String entityPath, String loggerName) {
- super(connectionId, hostname, loggerName);
+ LinkHandler(String connectionId, String hostname, String entityPath, ClientLogger logger) {
+ super(connectionId, hostname, logger);
this.entityPath = Objects.requireNonNull(entityPath, "'entityPath' cannot be null.");
}
diff --git a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/ReceiveLinkHandler.java b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/ReceiveLinkHandler.java
index 308a0d7db020..e0af148f3bd4 100644
--- a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/ReceiveLinkHandler.java
+++ b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/ReceiveLinkHandler.java
@@ -3,6 +3,7 @@
package com.azure.core.amqp.implementation.handler;
+import com.azure.core.util.logging.ClientLogger;
import com.azure.core.util.logging.LoggingEventBuilder;
import org.apache.qpid.proton.amqp.Symbol;
import org.apache.qpid.proton.amqp.messaging.Modified;
@@ -25,6 +26,7 @@
import java.util.concurrent.atomic.AtomicBoolean;
import static com.azure.core.amqp.implementation.AmqpLoggingUtils.addErrorCondition;
+import static com.azure.core.amqp.implementation.AmqpLoggingUtils.createContextWithConnectionId;
import static com.azure.core.amqp.implementation.ClientConstants.EMIT_RESULT_KEY;
import static com.azure.core.amqp.implementation.ClientConstants.ENTITY_PATH_KEY;
import static com.azure.core.amqp.implementation.ClientConstants.LINK_NAME_KEY;
@@ -51,7 +53,7 @@ public class ReceiveLinkHandler extends LinkHandler {
private final String entityPath;
public ReceiveLinkHandler(String connectionId, String hostname, String linkName, String entityPath) {
- super(connectionId, hostname, entityPath, ReceiveLinkHandler.class.getName());
+ super(connectionId, hostname, entityPath, new ClientLogger(ReceiveLinkHandler.class, createContextWithConnectionId(connectionId)));
this.linkName = Objects.requireNonNull(linkName, "'linkName' cannot be null.");
this.entityPath = Objects.requireNonNull(entityPath, "'entityPath' cannot be null.");
}
diff --git a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/SendLinkHandler.java b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/SendLinkHandler.java
index 0ee4cafd4a17..81b2a24c25cd 100644
--- a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/SendLinkHandler.java
+++ b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/SendLinkHandler.java
@@ -3,6 +3,7 @@
package com.azure.core.amqp.implementation.handler;
+import com.azure.core.util.logging.ClientLogger;
import com.azure.core.util.logging.LoggingEventBuilder;
import org.apache.qpid.proton.engine.BaseHandler;
import org.apache.qpid.proton.engine.Delivery;
@@ -20,6 +21,7 @@
import java.util.concurrent.atomic.AtomicBoolean;
import static com.azure.core.amqp.implementation.AmqpLoggingUtils.addSignalTypeAndResult;
+import static com.azure.core.amqp.implementation.AmqpLoggingUtils.createContextWithConnectionId;
import static com.azure.core.amqp.implementation.ClientConstants.EMIT_RESULT_KEY;
import static com.azure.core.amqp.implementation.ClientConstants.ENTITY_PATH_KEY;
import static com.azure.core.amqp.implementation.ClientConstants.LINK_NAME_KEY;
@@ -45,7 +47,7 @@ public class SendLinkHandler extends LinkHandler {
private final Sinks.Many deliveryProcessor = Sinks.many().multicast().onBackpressureBuffer();
public SendLinkHandler(String connectionId, String hostname, String linkName, String entityPath) {
- super(connectionId, hostname, entityPath, SendLinkHandler.class.getName());
+ super(connectionId, hostname, entityPath, new ClientLogger(SendLinkHandler.class, createContextWithConnectionId(connectionId)));
this.linkName = Objects.requireNonNull(linkName, "'linkName' cannot be null.");
this.entityPath = entityPath;
}
diff --git a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/SessionHandler.java b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/SessionHandler.java
index b6ba8e3c429a..7cad0c3b2991 100644
--- a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/SessionHandler.java
+++ b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/SessionHandler.java
@@ -8,6 +8,7 @@
import com.azure.core.amqp.exception.SessionErrorContext;
import com.azure.core.amqp.implementation.ExceptionUtil;
import com.azure.core.amqp.implementation.ReactorDispatcher;
+import com.azure.core.util.logging.ClientLogger;
import com.azure.core.util.logging.LoggingEventBuilder;
import org.apache.qpid.proton.amqp.transport.ErrorCondition;
import org.apache.qpid.proton.engine.EndpointState;
@@ -20,6 +21,7 @@
import java.util.concurrent.RejectedExecutionException;
import static com.azure.core.amqp.implementation.AmqpLoggingUtils.addErrorCondition;
+import static com.azure.core.amqp.implementation.AmqpLoggingUtils.createContextWithConnectionId;
import static com.azure.core.amqp.implementation.ClientConstants.SESSION_NAME_KEY;
public class SessionHandler extends Handler {
@@ -29,7 +31,7 @@ public class SessionHandler extends Handler {
public SessionHandler(String connectionId, String hostname, String sessionName, ReactorDispatcher reactorDispatcher,
Duration openTimeout) {
- super(connectionId, hostname, SessionHandler.class.getName());
+ super(connectionId, hostname, new ClientLogger(SessionHandler.class, createContextWithConnectionId(connectionId)));
this.sessionName = sessionName;
this.openTimeout = openTimeout;
this.reactorDispatcher = reactorDispatcher;
diff --git a/sdk/core/azure-core-amqp/src/test/java/com/azure/core/amqp/implementation/handler/HandlerTest.java b/sdk/core/azure-core-amqp/src/test/java/com/azure/core/amqp/implementation/handler/HandlerTest.java
index 546e2c2326b8..0ee6b6c9fb59 100644
--- a/sdk/core/azure-core-amqp/src/test/java/com/azure/core/amqp/implementation/handler/HandlerTest.java
+++ b/sdk/core/azure-core-amqp/src/test/java/com/azure/core/amqp/implementation/handler/HandlerTest.java
@@ -5,6 +5,7 @@
import com.azure.core.amqp.exception.AmqpErrorContext;
import com.azure.core.amqp.exception.AmqpException;
+import com.azure.core.util.logging.ClientLogger;
import org.apache.qpid.proton.engine.EndpointState;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
@@ -12,6 +13,7 @@
import org.mockito.Mockito;
import reactor.test.StepVerifier;
+import static com.azure.core.amqp.implementation.AmqpLoggingUtils.createContextWithConnectionId;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
@@ -42,8 +44,8 @@ public void constructor() {
final String hostname = "hostname";
// Act
- assertThrows(NullPointerException.class, () -> new TestHandler(null, hostname, TestHandler.class.getName()));
- assertThrows(NullPointerException.class, () -> new TestHandler(connectionId, null, TestHandler.class.getName()));
+ assertThrows(NullPointerException.class, () -> new TestHandler(null, hostname, new ClientLogger(TestHandler.class)));
+ assertThrows(NullPointerException.class, () -> new TestHandler(connectionId, null, new ClientLogger(TestHandler.class)));
assertThrows(NullPointerException.class, () -> new TestHandler(connectionId, hostname, null));
}
@@ -156,11 +158,11 @@ private static class TestHandler extends Handler {
static final String HOSTNAME = "test-hostname";
TestHandler() {
- super(CONNECTION_ID, HOSTNAME, TestHandler.class.getName());
+ super(CONNECTION_ID, HOSTNAME, new ClientLogger(TestHandler.class, createContextWithConnectionId(CONNECTION_ID)));
}
- TestHandler(String connectionId, String hostname, String loggerName) {
- super(connectionId, hostname, loggerName);
+ TestHandler(String connectionId, String hostname, ClientLogger logger) {
+ super(connectionId, hostname, logger);
}
}
}
diff --git a/sdk/core/azure-core-amqp/src/test/java/com/azure/core/amqp/implementation/handler/LinkHandlerTest.java b/sdk/core/azure-core-amqp/src/test/java/com/azure/core/amqp/implementation/handler/LinkHandlerTest.java
index 6d8cf3470164..7649fe7bc1ab 100644
--- a/sdk/core/azure-core-amqp/src/test/java/com/azure/core/amqp/implementation/handler/LinkHandlerTest.java
+++ b/sdk/core/azure-core-amqp/src/test/java/com/azure/core/amqp/implementation/handler/LinkHandlerTest.java
@@ -7,6 +7,7 @@
import com.azure.core.amqp.exception.AmqpErrorContext;
import com.azure.core.amqp.exception.AmqpException;
import com.azure.core.amqp.exception.LinkErrorContext;
+import com.azure.core.util.logging.ClientLogger;
import org.apache.qpid.proton.amqp.Symbol;
import org.apache.qpid.proton.amqp.transport.ErrorCondition;
import org.apache.qpid.proton.engine.EndpointState;
@@ -58,11 +59,11 @@ public class LinkHandlerTest {
@Mock
private Session session;
- private final String loggerName = LinkHandlerTest.class.getName();
private final AmqpErrorCondition linkStolen = LINK_STOLEN;
private final Symbol symbol = Symbol.getSymbol(linkStolen.getErrorCondition());
private final String description = "test-description";
- private final LinkHandler handler = new MockLinkHandler(CONNECTION_ID, HOSTNAME, ENTITY_PATH, loggerName);
+ private final ClientLogger logger = new ClientLogger(LinkHandlerTest.class);
+ private final LinkHandler handler = new MockLinkHandler(CONNECTION_ID, HOSTNAME, ENTITY_PATH, logger);
private AutoCloseable mocksCloseable;
@BeforeEach
@@ -332,11 +333,11 @@ public void onLinkFinal() {
public void constructor() {
// Act
assertThrows(NullPointerException.class,
- () -> new MockLinkHandler(null, HOSTNAME, ENTITY_PATH, loggerName));
+ () -> new MockLinkHandler(null, HOSTNAME, ENTITY_PATH, logger));
assertThrows(NullPointerException.class,
- () -> new MockLinkHandler(CONNECTION_ID, null, ENTITY_PATH, loggerName));
+ () -> new MockLinkHandler(CONNECTION_ID, null, ENTITY_PATH, logger));
assertThrows(NullPointerException.class,
- () -> new MockLinkHandler(CONNECTION_ID, HOSTNAME, null, loggerName));
+ () -> new MockLinkHandler(CONNECTION_ID, HOSTNAME, null, logger));
assertThrows(NullPointerException.class,
() -> new MockLinkHandler(CONNECTION_ID, HOSTNAME, ENTITY_PATH, null));
}
@@ -408,8 +409,8 @@ public void errorContextNoReferenceId(Map properties) {
}
private static final class MockLinkHandler extends LinkHandler {
- MockLinkHandler(String connectionId, String hostname, String entityPath, String loggerName) {
- super(connectionId, hostname, entityPath, loggerName);
+ MockLinkHandler(String connectionId, String hostname, String entityPath, ClientLogger logger) {
+ super(connectionId, hostname, entityPath, logger);
}
}
}
diff --git a/sdk/core/azure-core-tracing-opentelemetry/pom.xml b/sdk/core/azure-core-tracing-opentelemetry/pom.xml
index 642fe28930c4..aac8a1033288 100644
--- a/sdk/core/azure-core-tracing-opentelemetry/pom.xml
+++ b/sdk/core/azure-core-tracing-opentelemetry/pom.xml
@@ -46,6 +46,7 @@
opentelemetry-api
1.0.0
+
com.azure
azure-core
@@ -149,6 +150,7 @@
io.opentelemetry:opentelemetry-sdk:[1.0.0]
io.opentelemetry:opentelemetry-exporter-logging:[1.0.0]
io.opentelemetry:opentelemetry-exporter-jaeger:[1.0.0]
+ io.opentelemetry.instrumentation:opentelemetry-instrumentation-api:[1.9.0-alpha]
diff --git a/sdk/core/azure-core-tracing-opentelemetry/src/main/java/com/azure/core/tracing/opentelemetry/OpenTelemetryHttpPolicy.java b/sdk/core/azure-core-tracing-opentelemetry/src/main/java/com/azure/core/tracing/opentelemetry/OpenTelemetryHttpPolicy.java
index 65bcf0b74b2c..fc5399914ce0 100644
--- a/sdk/core/azure-core-tracing-opentelemetry/src/main/java/com/azure/core/tracing/opentelemetry/OpenTelemetryHttpPolicy.java
+++ b/sdk/core/azure-core-tracing-opentelemetry/src/main/java/com/azure/core/tracing/opentelemetry/OpenTelemetryHttpPolicy.java
@@ -20,6 +20,7 @@
import io.opentelemetry.api.trace.Tracer;
import io.opentelemetry.api.trace.propagation.W3CTraceContextPropagator;
import io.opentelemetry.context.Context;
+import io.opentelemetry.context.Scope;
import io.opentelemetry.context.propagation.TextMapPropagator;
import io.opentelemetry.context.propagation.TextMapSetter;
import reactor.core.CoreSubscriber;
@@ -226,6 +227,7 @@ private static io.opentelemetry.context.Context getTraceContextOrCurrent(HttpPip
*
* OpenTelemetry reactor auto-instrumentation will take care of the cold path.
*/
+ @SuppressWarnings("try")
static final class ScalarPropagatingMono extends Mono
-
com.azure
azure-core
@@ -150,7 +149,6 @@
io.opentelemetry:opentelemetry-sdk:[1.0.0]
io.opentelemetry:opentelemetry-exporter-logging:[1.0.0]
io.opentelemetry:opentelemetry-exporter-jaeger:[1.0.0]
- io.opentelemetry.instrumentation:opentelemetry-instrumentation-api:[1.9.0-alpha]
diff --git a/sdk/core/azure-core-tracing-opentelemetry/src/main/java/com/azure/core/tracing/opentelemetry/OpenTelemetryHttpPolicy.java b/sdk/core/azure-core-tracing-opentelemetry/src/main/java/com/azure/core/tracing/opentelemetry/OpenTelemetryHttpPolicy.java
index fc5399914ce0..65bcf0b74b2c 100644
--- a/sdk/core/azure-core-tracing-opentelemetry/src/main/java/com/azure/core/tracing/opentelemetry/OpenTelemetryHttpPolicy.java
+++ b/sdk/core/azure-core-tracing-opentelemetry/src/main/java/com/azure/core/tracing/opentelemetry/OpenTelemetryHttpPolicy.java
@@ -20,7 +20,6 @@
import io.opentelemetry.api.trace.Tracer;
import io.opentelemetry.api.trace.propagation.W3CTraceContextPropagator;
import io.opentelemetry.context.Context;
-import io.opentelemetry.context.Scope;
import io.opentelemetry.context.propagation.TextMapPropagator;
import io.opentelemetry.context.propagation.TextMapSetter;
import reactor.core.CoreSubscriber;
@@ -227,7 +226,6 @@ private static io.opentelemetry.context.Context getTraceContextOrCurrent(HttpPip
*
* OpenTelemetry reactor auto-instrumentation will take care of the cold path.
*/
- @SuppressWarnings("try")
static final class ScalarPropagatingMono extends Mono {
public static final Mono INSTANCE = new ScalarPropagatingMono();
@@ -240,8 +238,12 @@ private ScalarPropagatingMono() {
public void subscribe(CoreSubscriber super Object> actual) {
Context traceContext = actual.currentContext().getOrDefault(REACTOR_PARENT_TRACE_CONTEXT_KEY, null);
if (traceContext != null) {
- try (Scope s = OpenTelemetrySpanSuppressionHelper.registerClientSpan(traceContext).makeCurrent()) {
- actual.onSubscribe(Operators.scalarSubscription(actual, value));
+ Object agentContext = OpenTelemetrySpanSuppressionHelper.registerClientSpan(traceContext);
+ AutoCloseable closeable = OpenTelemetrySpanSuppressionHelper.makeCurrent(agentContext, traceContext);
+ actual.onSubscribe(Operators.scalarSubscription(actual, value));
+ try {
+ closeable.close();
+ } catch (Throwable ignored) {
}
} else {
actual.onSubscribe(Operators.scalarSubscription(actual, value));
diff --git a/sdk/core/azure-core-tracing-opentelemetry/src/main/java/com/azure/core/tracing/opentelemetry/implementation/OpenTelemetrySpanSuppressionHelper.java b/sdk/core/azure-core-tracing-opentelemetry/src/main/java/com/azure/core/tracing/opentelemetry/implementation/OpenTelemetrySpanSuppressionHelper.java
index 888b0822744f..170004e76472 100644
--- a/sdk/core/azure-core-tracing-opentelemetry/src/main/java/com/azure/core/tracing/opentelemetry/implementation/OpenTelemetrySpanSuppressionHelper.java
+++ b/sdk/core/azure-core-tracing-opentelemetry/src/main/java/com/azure/core/tracing/opentelemetry/implementation/OpenTelemetrySpanSuppressionHelper.java
@@ -19,19 +19,31 @@
public class OpenTelemetrySpanSuppressionHelper {
private static boolean agentDiscovered;
private static final ClientLogger LOGGER = new ClientLogger(OpenTelemetrySpanSuppressionHelper.class);
-
+ private static Method getAgentContextMethod;
private static Method setSpanKeyMethod;
private static Object clientSpanKey;
+ private static Method getAgentSpanMethod;
+ private static Method agentContextMakeCurrentMethod;
static {
agentDiscovered = true;
try {
- Class> spanKeyClass = Class.forName("io.opentelemetry.instrumentation.api.instrumenter.SpanKey");
+ Class> agentContextStorageClass = Class.forName("io.opentelemetry.javaagent.instrumentation.opentelemetryapi.context.AgentContextStorage");
+ Class> agentContextClass = Class.forName("io.opentelemetry.javaagent.shaded.io.opentelemetry.context.Context");
+ Class> spanKeyClass = Class.forName("io.opentelemetry.javaagent.shaded.instrumentation.api.instrumenter.SpanKey");
+ Class> bridgingClass = Class.forName("io.opentelemetry.javaagent.instrumentation.opentelemetryapi.trace.Bridging");
+ Class> agentSpanClass = Class.forName("io.opentelemetry.javaagent.shaded.io.opentelemetry.api.trace.Span");
+ getAgentContextMethod = agentContextStorageClass.getDeclaredMethod("getAgentContext", io.opentelemetry.context.Context.class);
+ getAgentSpanMethod = bridgingClass.getDeclaredMethod("toAgentOrNull", io.opentelemetry.api.trace.Span.class);
clientSpanKey = spanKeyClass.getDeclaredField("ALL_CLIENTS").get(null);
- setSpanKeyMethod = spanKeyClass.getDeclaredMethod("storeInContext", Context.class, Span.class);
+ setSpanKeyMethod = spanKeyClass.getDeclaredMethod("storeInContext", agentContextClass, agentSpanClass);
+ agentContextMakeCurrentMethod = agentContextClass.getMethod("makeCurrent");
- if (setSpanKeyMethod.getReturnType() != Context.class) {
+ if (getAgentContextMethod.getReturnType() != agentContextClass
+ || getAgentSpanMethod.getReturnType() != agentSpanClass
+ || setSpanKeyMethod.getReturnType() != agentContextClass
+ || !AutoCloseable.class.isAssignableFrom(agentContextMakeCurrentMethod.getReturnType())) {
agentDiscovered = false;
}
@@ -46,20 +58,42 @@ public class OpenTelemetrySpanSuppressionHelper {
* @param traceContext OpenTelemetry context with client span
* @return Agent context or null when agent is not running or doesn't behave as expected.
*/
- public static Context registerClientSpan(Context traceContext) {
+ public static Object registerClientSpan(Context traceContext) {
Objects.requireNonNull(traceContext, "'traceContext' cannot be null");
if (agentDiscovered) {
try {
- return (Context) setSpanKeyMethod.invoke(
+ return setSpanKeyMethod.invoke(
clientSpanKey,
- traceContext,
- Span.fromContext(traceContext));
+ getAgentContextMethod.invoke(null, traceContext),
+ getAgentSpanMethod.invoke(null, Span.fromContext(traceContext)));
} catch (Throwable t) {
// should not happen, If it does, we'll log it once.
LOGGER.warning("Failed to register client span on OpenTelemetry agent");
agentDiscovered = false;
}
}
- return traceContext;
+ return null;
+ }
+
+ /**
+ * Makes passed agent context current. Falls back to passed trace context when agent is not running
+ * or doesn't behave as expected.
+ * @param agentContext agent context instance obtained from {@link OpenTelemetrySpanSuppressionHelper#registerClientSpan}
+ * @param traceContext Regular OpenTelemetry context to fallback to.
+ * @return scope to be closed in the same thread as it was started.
+ */
+ public static AutoCloseable makeCurrent(Object agentContext, Context traceContext) {
+ Objects.requireNonNull(traceContext, "'traceContext' cannot be null");
+ if (agentDiscovered && agentContext != null) {
+ try {
+ return (AutoCloseable) agentContextMakeCurrentMethod.invoke(agentContext);
+ } catch (Throwable t) {
+ // should not happen, If it does, we'll log it once.
+ LOGGER.warning("Failed to make OpenTelemetry agent context current");
+ agentDiscovered = false;
+ }
+ }
+
+ return traceContext.makeCurrent();
}
}
From fcd55fe55cff22ea67e16a577c74e190d3b01f23 Mon Sep 17 00:00:00 2001
From: Liudmila Molkova
Date: Fri, 3 Dec 2021 16:35:44 -0800
Subject: [PATCH 08/17] more fixes
---
.../amqp/implementation/AmqpChannelProcessor.java | 14 +++++---------
.../amqp/implementation/ReactorConnection.java | 5 ++++-
.../implementation/AmqpChannelProcessorTest.java | 4 +++-
.../amqp/implementation/ManagementChannelTest.java | 2 +-
4 files changed, 13 insertions(+), 12 deletions(-)
diff --git a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/AmqpChannelProcessor.java b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/AmqpChannelProcessor.java
index ee8340730601..a39297f5b99d 100644
--- a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/AmqpChannelProcessor.java
+++ b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/AmqpChannelProcessor.java
@@ -18,8 +18,6 @@
import reactor.core.publisher.Operators;
import java.time.Duration;
-import java.util.HashMap;
-import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentLinkedDeque;
import java.util.concurrent.RejectedExecutionException;
@@ -28,9 +26,6 @@
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
import java.util.function.Function;
-import static com.azure.core.amqp.implementation.ClientConstants.ENTITY_PATH_KEY;
-import static com.azure.core.amqp.implementation.ClientConstants.FULLY_QUALIFIED_NAMESPACE_KEY;
-
public class AmqpChannelProcessor extends Mono implements Processor, CoreSubscriber, Disposable {
@SuppressWarnings("rawtypes")
private static final AtomicReferenceFieldUpdater UPSTREAM =
@@ -56,15 +51,16 @@ public class AmqpChannelProcessor extends Mono implements Processor,
private volatile Disposable retrySubscription;
public AmqpChannelProcessor(String fullyQualifiedNamespace, String entityPath,
- Function> endpointStatesFunction, AmqpRetryPolicy retryPolicy, String loggerName) {
+ Function> endpointStatesFunction, AmqpRetryPolicy retryPolicy, ClientLogger logger) {
this.endpointStatesFunction = Objects.requireNonNull(endpointStatesFunction,
"'endpointStates' cannot be null.");
this.retryPolicy = Objects.requireNonNull(retryPolicy, "'retryPolicy' cannot be null.");
- Map loggingContext = new HashMap<>();
+ /*Map loggingContext = new HashMap<>();
loggingContext.put(FULLY_QUALIFIED_NAMESPACE_KEY, Objects.requireNonNull(fullyQualifiedNamespace, "'fullyQualifiedNamespace' cannot be null."));
- loggingContext.put(ENTITY_PATH_KEY, Objects.requireNonNull(entityPath, "'entityPath' cannot be null."));
- this.logger = new ClientLogger(loggerName, loggingContext);
+ loggingContext.put(ENTITY_PATH_KEY, Objects.requireNonNull(entityPath, "'entityPath' cannot be null."));*/
+ this.logger = Objects.requireNonNull(logger, "'retryPolicy' cannot be null.");
+
this.errorContext = new AmqpErrorContext(fullyQualifiedNamespace);
}
diff --git a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ReactorConnection.java b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ReactorConnection.java
index bf0ee0f18d03..9166fa41b59c 100644
--- a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ReactorConnection.java
+++ b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ReactorConnection.java
@@ -406,9 +406,12 @@ protected AmqpChannelProcessor createRequestResponseChan
})
.repeat();
+ Map loggingContext = createContextWithConnectionId(connectionId);
+ loggingContext.put(ENTITY_PATH_KEY, Objects.requireNonNull(entityPath, "'entityPath' cannot be null."));
+
return createChannel
.subscribeWith(new AmqpChannelProcessor<>(connectionId, entityPath,
- channel -> channel.getEndpointStates(), retryPolicy, RequestResponseChannel.class.getName()));
+ channel -> channel.getEndpointStates(), retryPolicy, new ClientLogger(RequestResponseChannel.class, loggingContext)));
}
@Override
diff --git a/sdk/core/azure-core-amqp/src/test/java/com/azure/core/amqp/implementation/AmqpChannelProcessorTest.java b/sdk/core/azure-core-amqp/src/test/java/com/azure/core/amqp/implementation/AmqpChannelProcessorTest.java
index 53c3b1b4ed69..bc151714c88b 100644
--- a/sdk/core/azure-core-amqp/src/test/java/com/azure/core/amqp/implementation/AmqpChannelProcessorTest.java
+++ b/sdk/core/azure-core-amqp/src/test/java/com/azure/core/amqp/implementation/AmqpChannelProcessorTest.java
@@ -8,6 +8,8 @@
import com.azure.core.amqp.exception.AmqpErrorCondition;
import com.azure.core.amqp.exception.AmqpErrorContext;
import com.azure.core.amqp.exception.AmqpException;
+import com.azure.core.amqp.implementation.handler.LinkHandlerTest;
+import com.azure.core.util.logging.ClientLogger;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
@@ -57,7 +59,7 @@ void setup() {
mocksCloseable = MockitoAnnotations.openMocks(this);
channelProcessor = new AmqpChannelProcessor<>("connection-test", "test-path",
- TestObject::getStates, retryPolicy, "TestLogger");
+ TestObject::getStates, retryPolicy, new ClientLogger(LinkHandlerTest.class));
}
@AfterEach
diff --git a/sdk/core/azure-core-amqp/src/test/java/com/azure/core/amqp/implementation/ManagementChannelTest.java b/sdk/core/azure-core-amqp/src/test/java/com/azure/core/amqp/implementation/ManagementChannelTest.java
index 3626f5558b7f..314a33eef0ad 100644
--- a/sdk/core/azure-core-amqp/src/test/java/com/azure/core/amqp/implementation/ManagementChannelTest.java
+++ b/sdk/core/azure-core-amqp/src/test/java/com/azure/core/amqp/implementation/ManagementChannelTest.java
@@ -95,7 +95,7 @@ public void setup(TestInfo testInfo) {
final AmqpChannelProcessor requestResponseMono =
Mono.defer(() -> Mono.just(requestResponseChannel)).subscribeWith(new AmqpChannelProcessor<>(
- "foo", "bar", RequestResponseChannel::getEndpointStates, retryPolicy, "TestLogger"));
+ "foo", "bar", RequestResponseChannel::getEndpointStates, retryPolicy, new ClientLogger(ManagementChannelTest.class)));
when(tokenManager.authorize()).thenReturn(Mono.just(1000L));
when(tokenManager.getAuthorizationResults()).thenReturn(tokenProviderResults.flux());
From 8602b4ce132f7d198bd1118401d761038b667cf2 Mon Sep 17 00:00:00 2001
From: Liudmila Molkova
Date: Mon, 13 Dec 2021 21:36:01 -0800
Subject: [PATCH 09/17] review
---
.../ActiveClientTokenManager.java | 7 +++--
.../implementation/AmqpChannelProcessor.java | 27 ++++++++++++-------
.../amqp/implementation/AmqpLoggingUtils.java | 8 ++++--
.../amqp/implementation/ClientConstants.java | 1 +
.../implementation/ReactorConnection.java | 10 ++++---
.../amqp/implementation/ReactorExecutor.java | 1 -
.../amqp/implementation/ReactorSender.java | 9 +++++--
.../RequestResponseChannel.java | 3 +--
.../ServiceBusReactorReceiverTest.java | 2 ++
9 files changed, 46 insertions(+), 22 deletions(-)
diff --git a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ActiveClientTokenManager.java b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ActiveClientTokenManager.java
index 2a91370a2488..c3e97a14ea3f 100644
--- a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ActiveClientTokenManager.java
+++ b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ActiveClientTokenManager.java
@@ -20,6 +20,7 @@
import java.util.concurrent.atomic.AtomicReference;
import static com.azure.core.amqp.implementation.AmqpLoggingUtils.addSignalTypeAndResult;
+import static com.azure.core.amqp.implementation.ClientConstants.INTERVAL_KEY;
/**
* Manages the re-authorization of the client to the token audience against the CBS node.
@@ -143,7 +144,8 @@ private Disposable scheduleRefreshTokenTask(Duration initialRefresh) {
logger.atError()
.addKeyValue("scopes", scopes)
- .log("Error is transient. Rescheduling authorization task at interval {} ms", lastRefresh.toMillis(), amqpException);
+ .addKeyValue(INTERVAL_KEY, interval)
+ .log("Error is transient. Rescheduling authorization task.", amqpException);
durationSource.emitNext(lastRefresh, (signalType, emitResult) -> {
addSignalTypeAndResult(logger.atVerbose(), signalType, emitResult)
@@ -156,7 +158,8 @@ private Disposable scheduleRefreshTokenTask(Duration initialRefresh) {
.subscribe(interval -> {
logger.atVerbose()
.addKeyValue("scopes", scopes)
- .log("Authorization successful. Refreshing token in {} ms.", interval);
+ .addKeyValue(INTERVAL_KEY, interval)
+ .log("Authorization successful. Refreshing token.");
authorizationResults.emitNext(AmqpResponseCode.ACCEPTED, (signalType, emitResult) -> {
addSignalTypeAndResult(logger.atVerbose(), signalType, emitResult)
diff --git a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/AmqpChannelProcessor.java b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/AmqpChannelProcessor.java
index a39297f5b99d..c009b3651bd0 100644
--- a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/AmqpChannelProcessor.java
+++ b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/AmqpChannelProcessor.java
@@ -26,12 +26,16 @@
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
import java.util.function.Function;
+import static com.azure.core.amqp.implementation.ClientConstants.INTERVAL_KEY;
+
public class AmqpChannelProcessor extends Mono implements Processor, CoreSubscriber, Disposable {
@SuppressWarnings("rawtypes")
private static final AtomicReferenceFieldUpdater UPSTREAM =
AtomicReferenceFieldUpdater.newUpdater(AmqpChannelProcessor.class, Subscription.class,
"upstream");
+ private static final String RETRY_NUMBER_KEY = "retry";
+
private final ClientLogger logger;
private final AtomicBoolean isDisposed = new AtomicBoolean();
private final AtomicBoolean isRequested = new AtomicBoolean();
@@ -55,11 +59,7 @@ public AmqpChannelProcessor(String fullyQualifiedNamespace, String entityPath,
this.endpointStatesFunction = Objects.requireNonNull(endpointStatesFunction,
"'endpointStates' cannot be null.");
this.retryPolicy = Objects.requireNonNull(retryPolicy, "'retryPolicy' cannot be null.");
-
- /*Map loggingContext = new HashMap<>();
- loggingContext.put(FULLY_QUALIFIED_NAMESPACE_KEY, Objects.requireNonNull(fullyQualifiedNamespace, "'fullyQualifiedNamespace' cannot be null."));
- loggingContext.put(ENTITY_PATH_KEY, Objects.requireNonNull(entityPath, "'entityPath' cannot be null."));*/
- this.logger = Objects.requireNonNull(logger, "'retryPolicy' cannot be null.");
+ this.logger = Objects.requireNonNull(logger, "'logger' cannot be null.");
this.errorContext = new AmqpErrorContext(fullyQualifiedNamespace);
}
@@ -178,20 +178,29 @@ public void onError(Throwable throwable) {
return;
}
- logger.info("Retry #{}. Transient error occurred. Retrying after {} ms.", attempts, retryInterval.toMillis(), throwable);
+ logger.atInfo()
+ .addKeyValue(RETRY_NUMBER_KEY, attempts)
+ .addKeyValue(INTERVAL_KEY, retryInterval.toMillis())
+ .log("Transient error occurred. Retrying.", throwable);
retrySubscription = Mono.delay(retryInterval).subscribe(i -> {
if (isDisposed()) {
- logger.info("Retry #{}. Not requesting from upstream. Processor is disposed.", attempts);
+ logger.atInfo()
+ .addKeyValue(RETRY_NUMBER_KEY, attempts)
+ .log("Not requesting from upstream. Processor is disposed.");
} else {
- logger.info("Retry #{}. Requesting from upstream.", attempts);
+ logger.atInfo()
+ .addKeyValue(RETRY_NUMBER_KEY, attempts)
+ .log("Requesting from upstream.");
requestUpstream();
isRetryPending.set(false);
}
});
} else {
- logger.warning("Retry #{}. Retry attempts exhausted or exception was not retriable.", attempts, throwable);
+ logger.atWarning()
+ .addKeyValue(RETRY_NUMBER_KEY, attempts)
+ .log("Retry attempts exhausted or exception was not retriable.", throwable);
lastError = throwable;
isDisposed.set(true);
diff --git a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/AmqpLoggingUtils.java b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/AmqpLoggingUtils.java
index 44bebb6072fc..beb185b18ad9 100644
--- a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/AmqpLoggingUtils.java
+++ b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/AmqpLoggingUtils.java
@@ -23,14 +23,18 @@
/**
* Utils for contextual logging.
*/
-public class AmqpLoggingUtils {
+public final class AmqpLoggingUtils {
+
+ private AmqpLoggingUtils() {
+ }
/**
* Creates logging context with connectionId.
*/
public static Map createContextWithConnectionId(String connectionId) {
Objects.requireNonNull(connectionId, "'connectionId' cannot be null.");
- Map globalLoggingContext = new HashMap<>();
+ // caller should be able to add more context, please keep the map mutable.
+ Map globalLoggingContext = new HashMap<>(1);
globalLoggingContext.put(CONNECTION_ID_KEY, connectionId);
return globalLoggingContext;
diff --git a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ClientConstants.java b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ClientConstants.java
index 6dad9c4b002f..d9024b734a78 100644
--- a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ClientConstants.java
+++ b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ClientConstants.java
@@ -23,6 +23,7 @@ public final class ClientConstants {
public static final String EMIT_RESULT_KEY = "emitResult";
public static final String SIGNAL_TYPE_KEY = "signalType";
public static final String HOSTNAME_KEY = "hostName";
+ public static final String INTERVAL_KEY = "interval_ms";
/**
* The default maximum allowable size, in bytes, for a batch to be sent.
diff --git a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ReactorConnection.java b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ReactorConnection.java
index 9166fa41b59c..c5902a03b22c 100644
--- a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ReactorConnection.java
+++ b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ReactorConnection.java
@@ -139,8 +139,8 @@ public ReactorConnection(String connectionId, ConnectionOptions connectionOption
if (isDisposed.getAndSet(true)) {
logger.verbose("Connection was already disposed: Error occurred while connection was starting.", error);
} else {
- closeAsync(new AmqpShutdownSignal(false, false, String.format(
- "Error occurred while connection was starting. Error: %s", error))).subscribe();
+ closeAsync(new AmqpShutdownSignal(false, false,
+ "Error occurred while connection was starting. Error: " + error)).subscribe();
}
});
@@ -393,6 +393,8 @@ protected Mono getReactorConnection() {
protected AmqpChannelProcessor createRequestResponseChannel(String sessionName,
String linkName, String entityPath) {
+ Objects.requireNonNull(entityPath, "'entityPath' cannot be null.");
+
final Flux createChannel = createSession(sessionName)
.cast(ReactorSession.class)
.map(reactorSession -> new RequestResponseChannel(this, getId(), getFullyQualifiedNamespace(), linkName,
@@ -407,7 +409,7 @@ protected AmqpChannelProcessor createRequestResponseChan
.repeat();
Map loggingContext = createContextWithConnectionId(connectionId);
- loggingContext.put(ENTITY_PATH_KEY, Objects.requireNonNull(entityPath, "'entityPath' cannot be null."));
+ loggingContext.put(ENTITY_PATH_KEY, entityPath);
return createChannel
.subscribeWith(new AmqpChannelProcessor<>(connectionId, entityPath,
@@ -453,7 +455,7 @@ Mono closeAsync(AmqpShutdownSignal shutdownSignal) {
try {
dispatcher.invoke(() -> closeConnectionWork());
} catch (IOException e) {
- logger.warning("IOException while scheduling closeConnection work. Manually disposing", e);
+ logger.warning("IOException while scheduling closeConnection work. Manually disposing.", e);
closeConnectionWork();
} catch (RejectedExecutionException e) {
diff --git a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ReactorExecutor.java b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ReactorExecutor.java
index 98e168be3724..e5ffa0b3664f 100644
--- a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ReactorExecutor.java
+++ b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ReactorExecutor.java
@@ -49,7 +49,6 @@ class ReactorExecutor implements AsyncCloseable {
this.timeout = Objects.requireNonNull(timeout, "'timeout' cannot be null.");
this.exceptionHandler = Objects.requireNonNull(exceptionHandler, "'exceptionHandler' cannot be null.");
this.hostname = Objects.requireNonNull(hostname, "'hostname' cannot be null.");
- Objects.requireNonNull(connectionId, "'connectionId' cannot be null.");
this.logger = new ClientLogger(ReactorExecutor.class, createContextWithConnectionId(connectionId));
}
diff --git a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ReactorSender.java b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ReactorSender.java
index 90a16e855a95..a4baaeb1cfab 100644
--- a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ReactorSender.java
+++ b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ReactorSender.java
@@ -72,6 +72,7 @@
*/
class ReactorSender implements AmqpSendLink, AsyncCloseable, AutoCloseable {
private static final String DELIVERY_TAG_KEY = "deliveryTag";
+ private static final String PENDING_SENDS_SIZE_KEY = "pending_sends_size";
private final String entityPath;
private final Sender sender;
private final SendLinkHandler handler;
@@ -677,7 +678,9 @@ private void handleError(Throwable error) {
if (isDisposed.getAndSet(true)) {
logger.verbose("This was already disposed. Dropping error.");
} else {
- logger.verbose("Disposing of '{}' pending sends with error.", pendingSendsMap.size());
+ logger.atVerbose()
+ .addKeyValue(PENDING_SENDS_SIZE_KEY, () -> String.valueOf(pendingSendsMap.size()))
+ .log("Disposing pending sends with error.");
}
pendingSendsMap.forEach((key, value) -> value.error(error));
@@ -697,7 +700,9 @@ private void handleClose() {
if (isDisposed.getAndSet(true)) {
logger.verbose("This was already disposed.");
} else {
- logger.verbose("Disposing of '{}' pending sends.", pendingSendsMap.size());
+ logger.atVerbose()
+ .addKeyValue(PENDING_SENDS_SIZE_KEY, () -> String.valueOf(pendingSendsMap.size()))
+ .log("Disposing pending sends.");
}
pendingSendsMap.forEach((key, value) -> value.error(new AmqpException(true, message, context)));
diff --git a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/RequestResponseChannel.java b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/RequestResponseChannel.java
index 7743937df527..cc9f8209823e 100644
--- a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/RequestResponseChannel.java
+++ b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/RequestResponseChannel.java
@@ -237,8 +237,7 @@ public Mono closeAsync() {
.timeout(retryOptions.getTryTimeout())
.onErrorResume(TimeoutException.class, error -> {
return Mono.fromRunnable(() -> {
- logger.atInfo()
- .log("Timed out waiting for RequestResponseChannel to complete closing. Manually closing.");
+ logger.info("Timed out waiting for RequestResponseChannel to complete closing. Manually closing.");
onTerminalState("SendLinkHandler");
onTerminalState("ReceiveLinkHandler");
diff --git a/sdk/servicebus/azure-messaging-servicebus/src/test/java/com/azure/messaging/servicebus/implementation/ServiceBusReactorReceiverTest.java b/sdk/servicebus/azure-messaging-servicebus/src/test/java/com/azure/messaging/servicebus/implementation/ServiceBusReactorReceiverTest.java
index 7ed02bbabdb4..75331257543f 100644
--- a/sdk/servicebus/azure-messaging-servicebus/src/test/java/com/azure/messaging/servicebus/implementation/ServiceBusReactorReceiverTest.java
+++ b/sdk/servicebus/azure-messaging-servicebus/src/test/java/com/azure/messaging/servicebus/implementation/ServiceBusReactorReceiverTest.java
@@ -51,6 +51,7 @@
class ServiceBusReactorReceiverTest {
private static final String ENTITY_PATH = "queue-name";
private static final String LINK_NAME = "a-link-name";
+ private static final String CONNECTION_ID = "a-connection-id";
private final ClientLogger logger = new ClientLogger(ServiceBusReactorReceiver.class);
private final EmitterProcessor endpointStates = EmitterProcessor.create();
@@ -110,6 +111,7 @@ void setup(TestInfo testInfo) throws IOException {
when(receiveLinkHandler.getEndpointStates()).thenReturn(endpointStates);
when(tokenManager.getAuthorizationResults()).thenReturn(Flux.create(sink -> sink.next(AmqpResponseCode.OK)));
+ when(receiveLinkHandler.getConnectionId()).thenReturn(CONNECTION_ID);
when(connection.getShutdownSignals()).thenReturn(Flux.never());
From 06ed3d7e57f57df9f5012d399310f6764bb93946 Mon Sep 17 00:00:00 2001
From: Liudmila Molkova
Date: Mon, 13 Dec 2021 21:52:14 -0800
Subject: [PATCH 10/17] up
---
.../com/azure/core/amqp/implementation/AmqpLoggingUtils.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/AmqpLoggingUtils.java b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/AmqpLoggingUtils.java
index beb185b18ad9..871504866ec7 100644
--- a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/AmqpLoggingUtils.java
+++ b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/AmqpLoggingUtils.java
@@ -85,7 +85,7 @@ public static LoggingEventBuilder addShutdownSignal(LoggingEventBuilder logBuild
return logBuilder
.addKeyValue("isTransient", shutdownSignal.isTransient())
.addKeyValue("isInitiatedByClient", shutdownSignal.isInitiatedByClient())
- // will call toString() if logging is enabled
+ // will call toString() when performing logging (if enabled)
.addKeyValue("shutdownMessage", shutdownSignal);
}
}
From c16b8a6b188ae03f450e96a1c717089d267aaaca Mon Sep 17 00:00:00 2001
From: Liudmila Molkova
Date: Tue, 14 Dec 2021 10:47:42 -0800
Subject: [PATCH 11/17] AmqpChannelProcessor add constructor overload that
creates logger and deprecate old one
---
.../implementation/AmqpChannelProcessor.java | 21 +++++++++++++++++++
.../implementation/ReactorConnection.java | 4 ++--
.../AmqpChannelProcessorTest.java | 6 ++----
.../implementation/ManagementChannelTest.java | 2 +-
4 files changed, 26 insertions(+), 7 deletions(-)
diff --git a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/AmqpChannelProcessor.java b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/AmqpChannelProcessor.java
index c009b3651bd0..65dcff548b11 100644
--- a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/AmqpChannelProcessor.java
+++ b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/AmqpChannelProcessor.java
@@ -18,6 +18,7 @@
import reactor.core.publisher.Operators;
import java.time.Duration;
+import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentLinkedDeque;
import java.util.concurrent.RejectedExecutionException;
@@ -26,6 +27,8 @@
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
import java.util.function.Function;
+import static com.azure.core.amqp.implementation.AmqpLoggingUtils.createContextWithConnectionId;
+import static com.azure.core.amqp.implementation.ClientConstants.ENTITY_PATH_KEY;
import static com.azure.core.amqp.implementation.ClientConstants.INTERVAL_KEY;
public class AmqpChannelProcessor extends Mono implements Processor, CoreSubscriber, Disposable {
@@ -54,6 +57,10 @@ public class AmqpChannelProcessor extends Mono implements Processor,
private volatile Disposable connectionSubscription;
private volatile Disposable retrySubscription;
+ /**
+ * @deprecated Use constructor overload that does not take {@link ClientLogger}
+ */
+ @Deprecated
public AmqpChannelProcessor(String fullyQualifiedNamespace, String entityPath,
Function> endpointStatesFunction, AmqpRetryPolicy retryPolicy, ClientLogger logger) {
this.endpointStatesFunction = Objects.requireNonNull(endpointStatesFunction,
@@ -64,6 +71,20 @@ public AmqpChannelProcessor(String fullyQualifiedNamespace, String entityPath,
this.errorContext = new AmqpErrorContext(fullyQualifiedNamespace);
}
+
+ public AmqpChannelProcessor(String fullyQualifiedNamespace, String entityPath, String connectionId,
+ Function> endpointStatesFunction, AmqpRetryPolicy retryPolicy) {
+ this.endpointStatesFunction = Objects.requireNonNull(endpointStatesFunction,
+ "'endpointStates' cannot be null.");
+ this.retryPolicy = Objects.requireNonNull(retryPolicy, "'retryPolicy' cannot be null.");
+
+ Map loggingContext = createContextWithConnectionId(connectionId);
+ loggingContext.put(ENTITY_PATH_KEY, Objects.requireNonNull(entityPath, "'entityPath' cannot be null."));
+ this.logger = new ClientLogger(AmqpChannelProcessor.class, loggingContext);
+
+ this.errorContext = new AmqpErrorContext(fullyQualifiedNamespace);
+ }
+
@Override
public void onSubscribe(Subscription subscription) {
if (Operators.setOnce(UPSTREAM, this, subscription)) {
diff --git a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ReactorConnection.java b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ReactorConnection.java
index c5902a03b22c..25bf8f5e9309 100644
--- a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ReactorConnection.java
+++ b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ReactorConnection.java
@@ -412,8 +412,8 @@ protected AmqpChannelProcessor createRequestResponseChan
loggingContext.put(ENTITY_PATH_KEY, entityPath);
return createChannel
- .subscribeWith(new AmqpChannelProcessor<>(connectionId, entityPath,
- channel -> channel.getEndpointStates(), retryPolicy, new ClientLogger(RequestResponseChannel.class, loggingContext)));
+ .subscribeWith(new AmqpChannelProcessor<>(getFullyQualifiedNamespace(), entityPath, connectionId,
+ channel -> channel.getEndpointStates(), retryPolicy));
}
@Override
diff --git a/sdk/core/azure-core-amqp/src/test/java/com/azure/core/amqp/implementation/AmqpChannelProcessorTest.java b/sdk/core/azure-core-amqp/src/test/java/com/azure/core/amqp/implementation/AmqpChannelProcessorTest.java
index bc151714c88b..bc42248afd7b 100644
--- a/sdk/core/azure-core-amqp/src/test/java/com/azure/core/amqp/implementation/AmqpChannelProcessorTest.java
+++ b/sdk/core/azure-core-amqp/src/test/java/com/azure/core/amqp/implementation/AmqpChannelProcessorTest.java
@@ -8,8 +8,6 @@
import com.azure.core.amqp.exception.AmqpErrorCondition;
import com.azure.core.amqp.exception.AmqpErrorContext;
import com.azure.core.amqp.exception.AmqpException;
-import com.azure.core.amqp.implementation.handler.LinkHandlerTest;
-import com.azure.core.util.logging.ClientLogger;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
@@ -58,8 +56,8 @@ class AmqpChannelProcessorTest {
void setup() {
mocksCloseable = MockitoAnnotations.openMocks(this);
- channelProcessor = new AmqpChannelProcessor<>("connection-test", "test-path",
- TestObject::getStates, retryPolicy, new ClientLogger(LinkHandlerTest.class));
+ channelProcessor = new AmqpChannelProcessor<>("namespace-test", "test-path", "connection-test",
+ TestObject::getStates, retryPolicy);
}
@AfterEach
diff --git a/sdk/core/azure-core-amqp/src/test/java/com/azure/core/amqp/implementation/ManagementChannelTest.java b/sdk/core/azure-core-amqp/src/test/java/com/azure/core/amqp/implementation/ManagementChannelTest.java
index 314a33eef0ad..7f873f719ef6 100644
--- a/sdk/core/azure-core-amqp/src/test/java/com/azure/core/amqp/implementation/ManagementChannelTest.java
+++ b/sdk/core/azure-core-amqp/src/test/java/com/azure/core/amqp/implementation/ManagementChannelTest.java
@@ -95,7 +95,7 @@ public void setup(TestInfo testInfo) {
final AmqpChannelProcessor requestResponseMono =
Mono.defer(() -> Mono.just(requestResponseChannel)).subscribeWith(new AmqpChannelProcessor<>(
- "foo", "bar", RequestResponseChannel::getEndpointStates, retryPolicy, new ClientLogger(ManagementChannelTest.class)));
+ "foo", "bar", "baz", RequestResponseChannel::getEndpointStates, retryPolicy));
when(tokenManager.authorize()).thenReturn(Mono.just(1000L));
when(tokenManager.getAuthorizationResults()).thenReturn(tokenProviderResults.flux());
From 0efd69e2f2efeb83cf9bfbf2da671eb0c4717d28 Mon Sep 17 00:00:00 2001
From: Liudmila Molkova
Date: Tue, 14 Dec 2021 11:27:42 -0800
Subject: [PATCH 12/17] remove clientlogger from Handler ctor
---
.../handler/ConnectionHandler.java | 5 +----
.../amqp/implementation/handler/Handler.java | 8 ++++----
.../amqp/implementation/handler/LinkHandler.java | 8 +++-----
.../handler/ReceiveLinkHandler.java | 4 +---
.../implementation/handler/SendLinkHandler.java | 4 +---
.../implementation/handler/SessionHandler.java | 4 +---
.../handler/WebSocketsConnectionHandler.java | 5 +----
.../WebSocketsProxyConnectionHandler.java | 4 ----
.../amqp/implementation/handler/HandlerTest.java | 13 +++++--------
.../implementation/handler/LinkHandlerTest.java | 16 +++++-----------
10 files changed, 22 insertions(+), 49 deletions(-)
diff --git a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/ConnectionHandler.java b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/ConnectionHandler.java
index c3d96ed58dad..f42ed44e6a4c 100644
--- a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/ConnectionHandler.java
+++ b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/ConnectionHandler.java
@@ -10,7 +10,6 @@
import com.azure.core.util.ClientOptions;
import com.azure.core.util.CoreUtils;
import com.azure.core.util.UserAgentUtil;
-import com.azure.core.util.logging.ClientLogger;
import org.apache.qpid.proton.Proton;
import org.apache.qpid.proton.amqp.Symbol;
import org.apache.qpid.proton.amqp.transport.ErrorCondition;
@@ -30,7 +29,6 @@
import java.util.Objects;
import static com.azure.core.amqp.implementation.AmqpLoggingUtils.addErrorCondition;
-import static com.azure.core.amqp.implementation.AmqpLoggingUtils.createContextWithConnectionId;
import static com.azure.core.amqp.implementation.ClientConstants.FULLY_QUALIFIED_NAMESPACE_KEY;
import static com.azure.core.amqp.implementation.ClientConstants.HOSTNAME_KEY;
@@ -62,8 +60,7 @@ public class ConnectionHandler extends Handler {
public ConnectionHandler(final String connectionId, final ConnectionOptions connectionOptions,
SslPeerDetails peerDetails) {
super(connectionId,
- Objects.requireNonNull(connectionOptions, "'connectionOptions' cannot be null.").getHostname(),
- new ClientLogger(ConnectionHandler.class, createContextWithConnectionId(connectionId)));
+ Objects.requireNonNull(connectionOptions, "'connectionOptions' cannot be null.").getHostname());
add(new Handshaker());
this.connectionOptions = connectionOptions;
diff --git a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/Handler.java b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/Handler.java
index 95d389965fbb..2c8504721d24 100644
--- a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/Handler.java
+++ b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/Handler.java
@@ -14,6 +14,7 @@
import java.util.concurrent.atomic.AtomicBoolean;
import static com.azure.core.amqp.implementation.AmqpLoggingUtils.addSignalTypeAndResult;
+import static com.azure.core.amqp.implementation.AmqpLoggingUtils.createContextWithConnectionId;
/**
* Base class for all proton-j handlers.
@@ -34,14 +35,13 @@ public abstract class Handler extends BaseHandler implements Closeable {
* @param hostname Hostname of the connection. This could be the DNS hostname or the IP address of the
* connection. Usually of the form {@literal ".service.windows.net"} but can change if the
* messages are brokered through an intermediary.
- * @param logger Logger to use for messages.
*
- * @throws NullPointerException if {@code connectionId}, {@code hostname}, or {@code logger} is null.
+ * @throws NullPointerException if {@code connectionId} or {@code hostname} is null.
*/
- Handler(final String connectionId, final String hostname, final ClientLogger logger) {
+ Handler(final String connectionId, final String hostname) {
this.connectionId = Objects.requireNonNull(connectionId, "'connectionId' cannot be null.");
this.hostname = Objects.requireNonNull(hostname, "'hostname' cannot be null.");
- this.logger = Objects.requireNonNull(logger, "'logger' cannot be null.");
+ this.logger = new ClientLogger(getClass(), createContextWithConnectionId(connectionId));
}
/**
diff --git a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/LinkHandler.java b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/LinkHandler.java
index df5842bad7d6..b961f5c9bdc4 100644
--- a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/LinkHandler.java
+++ b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/LinkHandler.java
@@ -6,7 +6,6 @@
import com.azure.core.amqp.exception.AmqpErrorContext;
import com.azure.core.amqp.exception.LinkErrorContext;
import com.azure.core.amqp.implementation.ExceptionUtil;
-import com.azure.core.util.logging.ClientLogger;
import org.apache.qpid.proton.amqp.transport.ErrorCondition;
import org.apache.qpid.proton.engine.EndpointState;
import org.apache.qpid.proton.engine.Event;
@@ -15,8 +14,8 @@
import java.util.Objects;
import static com.azure.core.amqp.implementation.AmqpErrorCode.TRACKING_ID_PROPERTY;
-import static com.azure.core.amqp.implementation.ClientConstants.LINK_NAME_KEY;
import static com.azure.core.amqp.implementation.AmqpLoggingUtils.addErrorCondition;
+import static com.azure.core.amqp.implementation.ClientConstants.LINK_NAME_KEY;
import static com.azure.core.amqp.implementation.ClientConstants.NOT_APPLICABLE;
/**
@@ -36,13 +35,12 @@ abstract class LinkHandler extends Handler {
* connection. Usually of the form {@literal ".service.windows.net"} but can change if the
* messages are brokered through an intermediary.
* @param entityPath The address within the message broker for this link.
- * @param logger Logger to use for messages.
*
* @throws NullPointerException if {@code connectionId}, {@code hostname}, {@code entityPath}, or {@code logger} is
* null.
*/
- LinkHandler(String connectionId, String hostname, String entityPath, ClientLogger logger) {
- super(connectionId, hostname, logger);
+ LinkHandler(String connectionId, String hostname, String entityPath) {
+ super(connectionId, hostname);
this.entityPath = Objects.requireNonNull(entityPath, "'entityPath' cannot be null.");
}
diff --git a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/ReceiveLinkHandler.java b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/ReceiveLinkHandler.java
index e0af148f3bd4..a75b2ef2bdf2 100644
--- a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/ReceiveLinkHandler.java
+++ b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/ReceiveLinkHandler.java
@@ -3,7 +3,6 @@
package com.azure.core.amqp.implementation.handler;
-import com.azure.core.util.logging.ClientLogger;
import com.azure.core.util.logging.LoggingEventBuilder;
import org.apache.qpid.proton.amqp.Symbol;
import org.apache.qpid.proton.amqp.messaging.Modified;
@@ -26,7 +25,6 @@
import java.util.concurrent.atomic.AtomicBoolean;
import static com.azure.core.amqp.implementation.AmqpLoggingUtils.addErrorCondition;
-import static com.azure.core.amqp.implementation.AmqpLoggingUtils.createContextWithConnectionId;
import static com.azure.core.amqp.implementation.ClientConstants.EMIT_RESULT_KEY;
import static com.azure.core.amqp.implementation.ClientConstants.ENTITY_PATH_KEY;
import static com.azure.core.amqp.implementation.ClientConstants.LINK_NAME_KEY;
@@ -53,7 +51,7 @@ public class ReceiveLinkHandler extends LinkHandler {
private final String entityPath;
public ReceiveLinkHandler(String connectionId, String hostname, String linkName, String entityPath) {
- super(connectionId, hostname, entityPath, new ClientLogger(ReceiveLinkHandler.class, createContextWithConnectionId(connectionId)));
+ super(connectionId, hostname, entityPath);
this.linkName = Objects.requireNonNull(linkName, "'linkName' cannot be null.");
this.entityPath = Objects.requireNonNull(entityPath, "'entityPath' cannot be null.");
}
diff --git a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/SendLinkHandler.java b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/SendLinkHandler.java
index 81b2a24c25cd..c24c1ed9d186 100644
--- a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/SendLinkHandler.java
+++ b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/SendLinkHandler.java
@@ -3,7 +3,6 @@
package com.azure.core.amqp.implementation.handler;
-import com.azure.core.util.logging.ClientLogger;
import com.azure.core.util.logging.LoggingEventBuilder;
import org.apache.qpid.proton.engine.BaseHandler;
import org.apache.qpid.proton.engine.Delivery;
@@ -21,7 +20,6 @@
import java.util.concurrent.atomic.AtomicBoolean;
import static com.azure.core.amqp.implementation.AmqpLoggingUtils.addSignalTypeAndResult;
-import static com.azure.core.amqp.implementation.AmqpLoggingUtils.createContextWithConnectionId;
import static com.azure.core.amqp.implementation.ClientConstants.EMIT_RESULT_KEY;
import static com.azure.core.amqp.implementation.ClientConstants.ENTITY_PATH_KEY;
import static com.azure.core.amqp.implementation.ClientConstants.LINK_NAME_KEY;
@@ -47,7 +45,7 @@ public class SendLinkHandler extends LinkHandler {
private final Sinks.Many deliveryProcessor = Sinks.many().multicast().onBackpressureBuffer();
public SendLinkHandler(String connectionId, String hostname, String linkName, String entityPath) {
- super(connectionId, hostname, entityPath, new ClientLogger(SendLinkHandler.class, createContextWithConnectionId(connectionId)));
+ super(connectionId, hostname, entityPath);
this.linkName = Objects.requireNonNull(linkName, "'linkName' cannot be null.");
this.entityPath = entityPath;
}
diff --git a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/SessionHandler.java b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/SessionHandler.java
index 7cad0c3b2991..cb0dc1fc788c 100644
--- a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/SessionHandler.java
+++ b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/SessionHandler.java
@@ -8,7 +8,6 @@
import com.azure.core.amqp.exception.SessionErrorContext;
import com.azure.core.amqp.implementation.ExceptionUtil;
import com.azure.core.amqp.implementation.ReactorDispatcher;
-import com.azure.core.util.logging.ClientLogger;
import com.azure.core.util.logging.LoggingEventBuilder;
import org.apache.qpid.proton.amqp.transport.ErrorCondition;
import org.apache.qpid.proton.engine.EndpointState;
@@ -21,7 +20,6 @@
import java.util.concurrent.RejectedExecutionException;
import static com.azure.core.amqp.implementation.AmqpLoggingUtils.addErrorCondition;
-import static com.azure.core.amqp.implementation.AmqpLoggingUtils.createContextWithConnectionId;
import static com.azure.core.amqp.implementation.ClientConstants.SESSION_NAME_KEY;
public class SessionHandler extends Handler {
@@ -31,7 +29,7 @@ public class SessionHandler extends Handler {
public SessionHandler(String connectionId, String hostname, String sessionName, ReactorDispatcher reactorDispatcher,
Duration openTimeout) {
- super(connectionId, hostname, new ClientLogger(SessionHandler.class, createContextWithConnectionId(connectionId)));
+ super(connectionId, hostname);
this.sessionName = sessionName;
this.openTimeout = openTimeout;
this.reactorDispatcher = reactorDispatcher;
diff --git a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/WebSocketsConnectionHandler.java b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/WebSocketsConnectionHandler.java
index 9e4d59541a32..1620cbb75a4b 100644
--- a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/WebSocketsConnectionHandler.java
+++ b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/WebSocketsConnectionHandler.java
@@ -4,12 +4,11 @@
package com.azure.core.amqp.implementation.handler;
import com.azure.core.amqp.implementation.ConnectionOptions;
-import com.azure.core.util.logging.ClientLogger;
import com.microsoft.azure.proton.transport.ws.impl.WebSocketImpl;
import org.apache.qpid.proton.engine.Event;
import org.apache.qpid.proton.engine.SslPeerDetails;
import org.apache.qpid.proton.engine.impl.TransportInternal;
-import static com.azure.core.amqp.implementation.AmqpLoggingUtils.createContextWithConnectionId;
+
import static com.azure.core.amqp.implementation.ClientConstants.HOSTNAME_KEY;
/**
@@ -24,7 +23,6 @@ public class WebSocketsConnectionHandler extends ConnectionHandler {
private static final String SOCKET_PATH = "/$servicebus/websocket";
private static final String PROTOCOL = "AMQPWSB10";
- private final ClientLogger logger;
/**
* Creates a handler that handles proton-j's connection events using web sockets.
@@ -35,7 +33,6 @@ public class WebSocketsConnectionHandler extends ConnectionHandler {
public WebSocketsConnectionHandler(String connectionId, ConnectionOptions connectionOptions,
SslPeerDetails peerDetails) {
super(connectionId, connectionOptions, peerDetails);
- logger = new ClientLogger(WebSocketsConnectionHandler.class, createContextWithConnectionId(connectionId));
}
/**
diff --git a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/WebSocketsProxyConnectionHandler.java b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/WebSocketsProxyConnectionHandler.java
index 38ecbdd66f87..263ce20793f6 100644
--- a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/WebSocketsProxyConnectionHandler.java
+++ b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/handler/WebSocketsProxyConnectionHandler.java
@@ -8,7 +8,6 @@
import com.azure.core.amqp.implementation.AmqpErrorCode;
import com.azure.core.amqp.implementation.ConnectionOptions;
import com.azure.core.util.CoreUtils;
-import com.azure.core.util.logging.ClientLogger;
import com.microsoft.azure.proton.transport.proxy.ProxyHandler;
import com.microsoft.azure.proton.transport.proxy.impl.ProxyHandlerImpl;
import com.microsoft.azure.proton.transport.proxy.impl.ProxyImpl;
@@ -30,7 +29,6 @@
import java.util.Objects;
import java.util.stream.Collectors;
-import static com.azure.core.amqp.implementation.AmqpLoggingUtils.createContextWithConnectionId;
import static com.azure.core.amqp.implementation.AmqpLoggingUtils.addErrorCondition;
import static com.azure.core.amqp.implementation.ClientConstants.HOSTNAME_KEY;
@@ -40,7 +38,6 @@
public class WebSocketsProxyConnectionHandler extends WebSocketsConnectionHandler {
private static final String HTTPS_URI_FORMAT = "https://%s:%s";
- private final ClientLogger logger;
private final InetSocketAddress connectionHostname;
private final ProxyOptions proxyOptions;
private final String fullyQualifiedNamespace;
@@ -64,7 +61,6 @@ public WebSocketsProxyConnectionHandler(String connectionId, ConnectionOptions c
this.proxyOptions = Objects.requireNonNull(proxyOptions, "'proxyConfiguration' cannot be null.");
this.fullyQualifiedNamespace = connectionOptions.getFullyQualifiedNamespace();
this.amqpBrokerHostname = connectionOptions.getFullyQualifiedNamespace() + ":" + connectionOptions.getPort();
- this.logger = new ClientLogger(WebSocketsProxyConnectionHandler.class, createContextWithConnectionId(connectionId));
if (proxyOptions.isProxyAddressConfigured()) {
this.connectionHostname = (InetSocketAddress) proxyOptions.getProxyAddress().address();
} else {
diff --git a/sdk/core/azure-core-amqp/src/test/java/com/azure/core/amqp/implementation/handler/HandlerTest.java b/sdk/core/azure-core-amqp/src/test/java/com/azure/core/amqp/implementation/handler/HandlerTest.java
index 0ee6b6c9fb59..56a2e35115fc 100644
--- a/sdk/core/azure-core-amqp/src/test/java/com/azure/core/amqp/implementation/handler/HandlerTest.java
+++ b/sdk/core/azure-core-amqp/src/test/java/com/azure/core/amqp/implementation/handler/HandlerTest.java
@@ -5,7 +5,6 @@
import com.azure.core.amqp.exception.AmqpErrorContext;
import com.azure.core.amqp.exception.AmqpException;
-import com.azure.core.util.logging.ClientLogger;
import org.apache.qpid.proton.engine.EndpointState;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
@@ -13,7 +12,6 @@
import org.mockito.Mockito;
import reactor.test.StepVerifier;
-import static com.azure.core.amqp.implementation.AmqpLoggingUtils.createContextWithConnectionId;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
@@ -44,9 +42,8 @@ public void constructor() {
final String hostname = "hostname";
// Act
- assertThrows(NullPointerException.class, () -> new TestHandler(null, hostname, new ClientLogger(TestHandler.class)));
- assertThrows(NullPointerException.class, () -> new TestHandler(connectionId, null, new ClientLogger(TestHandler.class)));
- assertThrows(NullPointerException.class, () -> new TestHandler(connectionId, hostname, null));
+ assertThrows(NullPointerException.class, () -> new TestHandler(null, hostname));
+ assertThrows(NullPointerException.class, () -> new TestHandler(connectionId, null));
}
@Test
@@ -158,11 +155,11 @@ private static class TestHandler extends Handler {
static final String HOSTNAME = "test-hostname";
TestHandler() {
- super(CONNECTION_ID, HOSTNAME, new ClientLogger(TestHandler.class, createContextWithConnectionId(CONNECTION_ID)));
+ super(CONNECTION_ID, HOSTNAME);
}
- TestHandler(String connectionId, String hostname, ClientLogger logger) {
- super(connectionId, hostname, logger);
+ TestHandler(String connectionId, String hostname) {
+ super(connectionId, hostname);
}
}
}
diff --git a/sdk/core/azure-core-amqp/src/test/java/com/azure/core/amqp/implementation/handler/LinkHandlerTest.java b/sdk/core/azure-core-amqp/src/test/java/com/azure/core/amqp/implementation/handler/LinkHandlerTest.java
index 7649fe7bc1ab..9719cbcbb68c 100644
--- a/sdk/core/azure-core-amqp/src/test/java/com/azure/core/amqp/implementation/handler/LinkHandlerTest.java
+++ b/sdk/core/azure-core-amqp/src/test/java/com/azure/core/amqp/implementation/handler/LinkHandlerTest.java
@@ -7,7 +7,6 @@
import com.azure.core.amqp.exception.AmqpErrorContext;
import com.azure.core.amqp.exception.AmqpException;
import com.azure.core.amqp.exception.LinkErrorContext;
-import com.azure.core.util.logging.ClientLogger;
import org.apache.qpid.proton.amqp.Symbol;
import org.apache.qpid.proton.amqp.transport.ErrorCondition;
import org.apache.qpid.proton.engine.EndpointState;
@@ -62,8 +61,7 @@ public class LinkHandlerTest {
private final AmqpErrorCondition linkStolen = LINK_STOLEN;
private final Symbol symbol = Symbol.getSymbol(linkStolen.getErrorCondition());
private final String description = "test-description";
- private final ClientLogger logger = new ClientLogger(LinkHandlerTest.class);
- private final LinkHandler handler = new MockLinkHandler(CONNECTION_ID, HOSTNAME, ENTITY_PATH, logger);
+ private final LinkHandler handler = new MockLinkHandler(CONNECTION_ID, HOSTNAME, ENTITY_PATH);
private AutoCloseable mocksCloseable;
@BeforeEach
@@ -333,13 +331,9 @@ public void onLinkFinal() {
public void constructor() {
// Act
assertThrows(NullPointerException.class,
- () -> new MockLinkHandler(null, HOSTNAME, ENTITY_PATH, logger));
+ () -> new MockLinkHandler(null, HOSTNAME, ENTITY_PATH));
assertThrows(NullPointerException.class,
- () -> new MockLinkHandler(CONNECTION_ID, null, ENTITY_PATH, logger));
- assertThrows(NullPointerException.class,
- () -> new MockLinkHandler(CONNECTION_ID, HOSTNAME, null, logger));
- assertThrows(NullPointerException.class,
- () -> new MockLinkHandler(CONNECTION_ID, HOSTNAME, ENTITY_PATH, null));
+ () -> new MockLinkHandler(CONNECTION_ID, null, ENTITY_PATH));
}
/**
@@ -409,8 +403,8 @@ public void errorContextNoReferenceId(Map properties) {
}
private static final class MockLinkHandler extends LinkHandler {
- MockLinkHandler(String connectionId, String hostname, String entityPath, ClientLogger logger) {
- super(connectionId, hostname, entityPath, logger);
+ MockLinkHandler(String connectionId, String hostname, String entityPath) {
+ super(connectionId, hostname, entityPath);
}
}
}
From 90fe335a369eddd99ca9f47a51f0172dee47538b Mon Sep 17 00:00:00 2001
From: Liudmila Molkova
Date: Mon, 3 Jan 2022 16:25:53 -0800
Subject: [PATCH 13/17] Fix AmqpChannelProcessor to take loggingContext
---
.../checkstyle/checks/ThrowFromClientLoggerCheck.java | 7 ++++---
.../amqp/implementation/AmqpChannelProcessor.java | 11 ++---------
.../core/amqp/implementation/ReactorConnection.java | 3 +--
.../amqp/implementation/AmqpChannelProcessorTest.java | 5 ++---
.../amqp/implementation/ManagementChannelTest.java | 2 +-
5 files changed, 10 insertions(+), 18 deletions(-)
diff --git a/eng/code-quality-reports/src/main/java/com/azure/tools/checkstyle/checks/ThrowFromClientLoggerCheck.java b/eng/code-quality-reports/src/main/java/com/azure/tools/checkstyle/checks/ThrowFromClientLoggerCheck.java
index 08caf8094ddc..1b98639f6418 100644
--- a/eng/code-quality-reports/src/main/java/com/azure/tools/checkstyle/checks/ThrowFromClientLoggerCheck.java
+++ b/eng/code-quality-reports/src/main/java/com/azure/tools/checkstyle/checks/ThrowFromClientLoggerCheck.java
@@ -125,9 +125,10 @@ public void visitToken(DetailAST token) {
}
}
- /**
- *
- **/
+ /*
+ * Checks if the expression includes call to log(), which verifies logging builder call
+ * e.g. logger.atError().log(ex)
+ */
private static boolean findLogMethodIdentifier(DetailAST root) {
for (DetailAST ast = root.getFirstChild(); ast != null; ast = ast.getNextSibling()) {
if (ast.getType() == TokenTypes.METHOD_CALL) {
diff --git a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/AmqpChannelProcessor.java b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/AmqpChannelProcessor.java
index 65dcff548b11..3a61e9f458ee 100644
--- a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/AmqpChannelProcessor.java
+++ b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/AmqpChannelProcessor.java
@@ -27,8 +27,6 @@
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
import java.util.function.Function;
-import static com.azure.core.amqp.implementation.AmqpLoggingUtils.createContextWithConnectionId;
-import static com.azure.core.amqp.implementation.ClientConstants.ENTITY_PATH_KEY;
import static com.azure.core.amqp.implementation.ClientConstants.INTERVAL_KEY;
public class AmqpChannelProcessor extends Mono implements Processor, CoreSubscriber, Disposable {
@@ -71,16 +69,11 @@ public AmqpChannelProcessor(String fullyQualifiedNamespace, String entityPath,
this.errorContext = new AmqpErrorContext(fullyQualifiedNamespace);
}
-
- public AmqpChannelProcessor(String fullyQualifiedNamespace, String entityPath, String connectionId,
- Function> endpointStatesFunction, AmqpRetryPolicy retryPolicy) {
+ public AmqpChannelProcessor(String fullyQualifiedNamespace, Function> endpointStatesFunction, AmqpRetryPolicy retryPolicy, Map loggingContext) {
this.endpointStatesFunction = Objects.requireNonNull(endpointStatesFunction,
"'endpointStates' cannot be null.");
this.retryPolicy = Objects.requireNonNull(retryPolicy, "'retryPolicy' cannot be null.");
-
- Map loggingContext = createContextWithConnectionId(connectionId);
- loggingContext.put(ENTITY_PATH_KEY, Objects.requireNonNull(entityPath, "'entityPath' cannot be null."));
- this.logger = new ClientLogger(AmqpChannelProcessor.class, loggingContext);
+ this.logger = new ClientLogger(AmqpChannelProcessor.class, Objects.requireNonNull(loggingContext, "'loggingContext' cannot be null."));
this.errorContext = new AmqpErrorContext(fullyQualifiedNamespace);
}
diff --git a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ReactorConnection.java b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ReactorConnection.java
index 25bf8f5e9309..324279cb91bf 100644
--- a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ReactorConnection.java
+++ b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ReactorConnection.java
@@ -412,8 +412,7 @@ protected AmqpChannelProcessor createRequestResponseChan
loggingContext.put(ENTITY_PATH_KEY, entityPath);
return createChannel
- .subscribeWith(new AmqpChannelProcessor<>(getFullyQualifiedNamespace(), entityPath, connectionId,
- channel -> channel.getEndpointStates(), retryPolicy));
+ .subscribeWith(new AmqpChannelProcessor<>(getFullyQualifiedNamespace(), channel -> channel.getEndpointStates(), retryPolicy, loggingContext));
}
@Override
diff --git a/sdk/core/azure-core-amqp/src/test/java/com/azure/core/amqp/implementation/AmqpChannelProcessorTest.java b/sdk/core/azure-core-amqp/src/test/java/com/azure/core/amqp/implementation/AmqpChannelProcessorTest.java
index bc42248afd7b..03f2682836e1 100644
--- a/sdk/core/azure-core-amqp/src/test/java/com/azure/core/amqp/implementation/AmqpChannelProcessorTest.java
+++ b/sdk/core/azure-core-amqp/src/test/java/com/azure/core/amqp/implementation/AmqpChannelProcessorTest.java
@@ -25,6 +25,7 @@
import reactor.test.publisher.TestPublisher;
import java.time.Duration;
+import java.util.HashMap;
import java.util.Objects;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.atomic.AtomicInteger;
@@ -55,9 +56,7 @@ class AmqpChannelProcessorTest {
@BeforeEach
void setup() {
mocksCloseable = MockitoAnnotations.openMocks(this);
-
- channelProcessor = new AmqpChannelProcessor<>("namespace-test", "test-path", "connection-test",
- TestObject::getStates, retryPolicy);
+ channelProcessor = new AmqpChannelProcessor<>("namespace-test", TestObject::getStates, retryPolicy, new HashMap<>());
}
@AfterEach
diff --git a/sdk/core/azure-core-amqp/src/test/java/com/azure/core/amqp/implementation/ManagementChannelTest.java b/sdk/core/azure-core-amqp/src/test/java/com/azure/core/amqp/implementation/ManagementChannelTest.java
index 7f873f719ef6..8b492e059393 100644
--- a/sdk/core/azure-core-amqp/src/test/java/com/azure/core/amqp/implementation/ManagementChannelTest.java
+++ b/sdk/core/azure-core-amqp/src/test/java/com/azure/core/amqp/implementation/ManagementChannelTest.java
@@ -95,7 +95,7 @@ public void setup(TestInfo testInfo) {
final AmqpChannelProcessor requestResponseMono =
Mono.defer(() -> Mono.just(requestResponseChannel)).subscribeWith(new AmqpChannelProcessor<>(
- "foo", "bar", "baz", RequestResponseChannel::getEndpointStates, retryPolicy));
+ "foo", RequestResponseChannel::getEndpointStates, retryPolicy, new HashMap<>()));
when(tokenManager.authorize()).thenReturn(Mono.just(1000L));
when(tokenManager.getAuthorizationResults()).thenReturn(tokenProviderResults.flux());
From b418cb0dfcac9091d27421f156adc4567365c7e5 Mon Sep 17 00:00:00 2001
From: Liudmila Molkova
Date: Mon, 3 Jan 2022 19:45:22 -0800
Subject: [PATCH 14/17] up
---
.../com/azure/core/amqp/implementation/AmqpChannelProcessor.java | 1 -
1 file changed, 1 deletion(-)
diff --git a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/AmqpChannelProcessor.java b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/AmqpChannelProcessor.java
index 3a61e9f458ee..704d10c2ee06 100644
--- a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/AmqpChannelProcessor.java
+++ b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/AmqpChannelProcessor.java
@@ -74,7 +74,6 @@ public AmqpChannelProcessor(String fullyQualifiedNamespace, Function
Date: Mon, 10 Jan 2022 14:00:15 -0800
Subject: [PATCH 15/17] review comments
---
.../ActiveClientTokenManager.java | 2 +-
.../implementation/AmqpChannelProcessor.java | 2 +-
.../azure/core/util/ConfigurationTests.java | 166 ------------------
3 files changed, 2 insertions(+), 168 deletions(-)
delete mode 100644 sdk/core/azure-core/src/test/java/com/azure/core/util/ConfigurationTests.java
diff --git a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ActiveClientTokenManager.java b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ActiveClientTokenManager.java
index c3e97a14ea3f..10bbf7cac11c 100644
--- a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ActiveClientTokenManager.java
+++ b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ActiveClientTokenManager.java
@@ -122,7 +122,7 @@ public void close() {
private Disposable scheduleRefreshTokenTask(Duration initialRefresh) {
// EmitterProcessor can queue up an initial refresh interval before any subscribers are received.
durationSource.emitNext(initialRefresh, (signalType, emitResult) -> {
- addSignalTypeAndResult(logger.atVerbose(), signalType, emitResult).log(" Could not emit initial refresh interval.");
+ addSignalTypeAndResult(logger.atVerbose(), signalType, emitResult).log("Could not emit initial refresh interval.");
return false;
});
diff --git a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/AmqpChannelProcessor.java b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/AmqpChannelProcessor.java
index 704d10c2ee06..7c6e464548e5 100644
--- a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/AmqpChannelProcessor.java
+++ b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/AmqpChannelProcessor.java
@@ -73,7 +73,7 @@ public AmqpChannelProcessor(String fullyQualifiedNamespace, Function getOrDefaultSupplier() {
- return Stream.of(
- Arguments.of(String.valueOf((byte) 42), (byte) 12, (byte) 42),
- Arguments.of(String.valueOf((short) 42), (short) 12, (short) 42),
- Arguments.of(String.valueOf(42), 12, 42),
- Arguments.of(String.valueOf(42L), 12L, 42L),
- Arguments.of(String.valueOf(42F), 12F, 42F),
- Arguments.of(String.valueOf(42D), 12D, 42D),
- Arguments.of(String.valueOf(true), false, true),
- Arguments.of("42", "12", "42")
- );
- }
-
- @Test
- public void getOrDefaultReturnsDefault() {
- assertEquals("42", new Configuration().get("empty", "42"));
- }
-}
From b16914193c051b2f483acb7071d0a39bf815168e Mon Sep 17 00:00:00 2001
From: Liudmila Molkova
Date: Mon, 10 Jan 2022 14:01:09 -0800
Subject: [PATCH 16/17] oops
---
.../azure/core/util/ConfigurationTests.java | 166 ++++++++++++++++++
1 file changed, 166 insertions(+)
create mode 100644 sdk/core/azure-core/src/test/java/com/azure/core/util/ConfigurationTests.java
diff --git a/sdk/core/azure-core/src/test/java/com/azure/core/util/ConfigurationTests.java b/sdk/core/azure-core/src/test/java/com/azure/core/util/ConfigurationTests.java
new file mode 100644
index 000000000000..bff1c787b6ed
--- /dev/null
+++ b/sdk/core/azure-core/src/test/java/com/azure/core/util/ConfigurationTests.java
@@ -0,0 +1,166 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package com.azure.core.util;
+
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+import java.util.stream.Stream;
+
+import static com.azure.core.util.Configuration.PROPERTY_AZURE_TRACING_DISABLED;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+/**
+ * Tests the configuration API.
+ */
+public class ConfigurationTests {
+ private static final String MY_CONFIGURATION = "myConfigurationABC123";
+ private static final String EXPECTED_VALUE = "aConfigurationValueAbc123";
+ private static final String UNEXPECTED_VALUE = "notMyConfigurationValueDef456";
+ private static final String DEFAULT_VALUE = "theDefaultValueGhi789";
+
+ /**
+ * Verifies that a runtime parameter is able to be retrieved.
+ */
+ @Test
+ public void runtimeConfigurationFound() {
+ Configuration configuration = spy(Configuration.class);
+ when(configuration.loadFromProperties(MY_CONFIGURATION)).thenReturn(EXPECTED_VALUE);
+ when(configuration.loadFromEnvironment(MY_CONFIGURATION)).thenReturn(null);
+
+ assertEquals(EXPECTED_VALUE, configuration.get(MY_CONFIGURATION));
+ }
+
+ /**
+ * Verifies that an environment variable is able to be retrieved.
+ */
+ @Test
+ public void environmentConfigurationFound() {
+ Configuration configuration = spy(Configuration.class);
+ when(configuration.loadFromProperties(MY_CONFIGURATION)).thenReturn(null);
+ when(configuration.loadFromEnvironment(MY_CONFIGURATION)).thenReturn(EXPECTED_VALUE);
+
+ assertEquals(EXPECTED_VALUE, configuration.get(MY_CONFIGURATION));
+ }
+
+ /**
+ * Verifies that null is returned when a configuration isn't found.
+ */
+ @Test
+ public void configurationNotFound() {
+ Configuration configuration = new Configuration();
+ assertNull(configuration.get(MY_CONFIGURATION));
+ }
+
+ /**
+ * Verifies that runtime parameters are preferred over environment variables.
+ */
+ @Test
+ public void runtimeConfigurationPreferredOverEnvironmentConfiguration() {
+ Configuration configuration = spy(Configuration.class);
+ when(configuration.loadFromProperties(MY_CONFIGURATION)).thenReturn(EXPECTED_VALUE);
+ when(configuration.loadFromEnvironment(MY_CONFIGURATION)).thenReturn(UNEXPECTED_VALUE);
+
+ assertEquals(EXPECTED_VALUE, configuration.get(MY_CONFIGURATION));
+ }
+
+ /**
+ * Verifies that a found configuration value is preferred over the default value.
+ */
+ @Test
+ public void foundConfigurationPreferredOverDefault() {
+ Configuration configuration = spy(Configuration.class);
+ when(configuration.loadFromEnvironment(MY_CONFIGURATION)).thenReturn(EXPECTED_VALUE);
+
+ assertEquals(EXPECTED_VALUE, configuration.get(MY_CONFIGURATION, DEFAULT_VALUE));
+ }
+
+ /**
+ * Verifies that when a configuration value isn't found the default will be returned.
+ */
+ @Test
+ public void fallbackToDefaultConfiguration() {
+ Configuration configuration = new Configuration();
+
+ assertEquals(DEFAULT_VALUE, configuration.get(MY_CONFIGURATION, DEFAULT_VALUE));
+ }
+
+ /**
+ * Verifies that a found configuration value is able to be mapped.
+ */
+ @Test
+ public void foundConfigurationIsConverted() {
+ Configuration configuration = spy(Configuration.class);
+ when(configuration.loadFromProperties(MY_CONFIGURATION)).thenReturn(EXPECTED_VALUE);
+
+ assertEquals(EXPECTED_VALUE.toUpperCase(), configuration.get(MY_CONFIGURATION, String::toUpperCase));
+ }
+
+ /**
+ * Verifies that when a configuration isn't found the converter returns null.
+ */
+ @Test
+ public void notFoundConfigurationIsConvertedToNull() {
+ assertNull(new Configuration().get(MY_CONFIGURATION, String::toUpperCase));
+ }
+
+ @Test
+ public void cloneConfiguration() {
+ Configuration configuration = new Configuration()
+ .put("variable1", "value1")
+ .put("variable2", "value2");
+
+ Configuration configurationClone = configuration.clone();
+
+ // Verify that the clone has the expected values.
+ assertEquals(configuration.get("variable1"), configurationClone.get("variable1"));
+ assertEquals(configuration.get("variable2"), configurationClone.get("variable2"));
+
+ // The clone should be a separate instance, verify its modifications won't affect the original copy.
+ configurationClone.remove("variable2");
+ assertTrue(configuration.contains("variable2"));
+ }
+
+ @Test
+ public void loadValueTwice() {
+ Configuration configuration = new Configuration();
+ String tracingDisabled = configuration.get(PROPERTY_AZURE_TRACING_DISABLED);
+ String tracingDisabled2 = configuration.get(PROPERTY_AZURE_TRACING_DISABLED);
+
+ assertEquals(tracingDisabled, tracingDisabled2);
+ }
+
+ @ParameterizedTest
+ @MethodSource("getOrDefaultSupplier")
+ public void getOrDefault(String configurationValue, Object defaultValue, Object expectedValue) {
+ Configuration configuration = new Configuration()
+ .put("getOrDefault", configurationValue);
+
+ assertEquals(expectedValue, configuration.get("getOrDefault", defaultValue));
+ }
+
+ private static Stream getOrDefaultSupplier() {
+ return Stream.of(
+ Arguments.of(String.valueOf((byte) 42), (byte) 12, (byte) 42),
+ Arguments.of(String.valueOf((short) 42), (short) 12, (short) 42),
+ Arguments.of(String.valueOf(42), 12, 42),
+ Arguments.of(String.valueOf(42L), 12L, 42L),
+ Arguments.of(String.valueOf(42F), 12F, 42F),
+ Arguments.of(String.valueOf(42D), 12D, 42D),
+ Arguments.of(String.valueOf(true), false, true),
+ Arguments.of("42", "12", "42")
+ );
+ }
+
+ @Test
+ public void getOrDefaultReturnsDefault() {
+ assertEquals("42", new Configuration().get("empty", "42"));
+ }
+}
From cdcdde57cc70987795d1dd01978195d6398e91bf Mon Sep 17 00:00:00 2001
From: Liudmila Molkova
Date: Mon, 10 Jan 2022 16:54:38 -0800
Subject: [PATCH 17/17] don't use FluxUtil.monoError(builder) yet to simplify
dependency management
---
.../amqp/implementation/ReactorConnection.java | 9 +++++++--
.../amqp/implementation/ReactorSession.java | 17 +++++++++++++----
2 files changed, 20 insertions(+), 6 deletions(-)
diff --git a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ReactorConnection.java b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ReactorConnection.java
index 324279cb91bf..88bdbb3724e3 100644
--- a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ReactorConnection.java
+++ b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ReactorConnection.java
@@ -24,6 +24,7 @@
import org.apache.qpid.proton.reactor.Reactor;
import reactor.core.Disposable;
import reactor.core.Disposables;
+import reactor.core.Exceptions;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.core.publisher.Sinks;
@@ -50,7 +51,6 @@
import static com.azure.core.amqp.implementation.ClientConstants.LINK_NAME_KEY;
import static com.azure.core.amqp.implementation.ClientConstants.SESSION_NAME_KEY;
import static com.azure.core.amqp.implementation.ClientConstants.SIGNAL_TYPE_KEY;
-import static com.azure.core.util.FluxUtil.monoError;
/**
* An AMQP connection backed by proton-j.
@@ -192,7 +192,12 @@ public Flux getShutdownSignals() {
public Mono getManagementNode(String entityPath) {
return Mono.defer(() -> {
if (isDisposed()) {
- return monoError(logger.atError().addKeyValue(ENTITY_PATH_KEY, entityPath), new IllegalStateException("Connection is disposed. Cannot get management instance."));
+ // TODO(limolkova) this can be simplified with FluxUtil.monoError(LoggingEventBuilder), not using it for now
+ // to allow using azure-core-amqp with stable azure-core 1.24.0 to simplify dependency management
+ // we should switch to it once monoError(LoggingEventBuilder) ships in stable azure-core
+ return Mono.error(logger.atError()
+ .addKeyValue(ENTITY_PATH_KEY, entityPath)
+ .log(Exceptions.propagate(new IllegalStateException("Connection is disposed. Cannot get management instance."))));
}
final AmqpManagementNode existing = managementNodes.get(entityPath);
diff --git a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ReactorSession.java b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ReactorSession.java
index ca8dcf47d4fd..79609df90635 100644
--- a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ReactorSession.java
+++ b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/ReactorSession.java
@@ -33,6 +33,7 @@
import org.apache.qpid.proton.engine.Session;
import reactor.core.Disposable;
import reactor.core.Disposables;
+import reactor.core.Exceptions;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.core.publisher.MonoSink;
@@ -51,14 +52,13 @@
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Consumer;
+import static com.azure.core.amqp.implementation.AmqpLoggingUtils.addErrorCondition;
import static com.azure.core.amqp.implementation.AmqpLoggingUtils.addSignalTypeAndResult;
import static com.azure.core.amqp.implementation.AmqpLoggingUtils.createContextWithConnectionId;
import static com.azure.core.amqp.implementation.ClientConstants.ENTITY_PATH_KEY;
import static com.azure.core.amqp.implementation.ClientConstants.LINK_NAME_KEY;
-import static com.azure.core.amqp.implementation.AmqpLoggingUtils.addErrorCondition;
import static com.azure.core.amqp.implementation.ClientConstants.NOT_APPLICABLE;
import static com.azure.core.amqp.implementation.ClientConstants.SESSION_NAME_KEY;
-import static com.azure.core.util.FluxUtil.monoError;
/**
* Represents an AMQP session using proton-j reactor.
@@ -353,7 +353,11 @@ protected Mono createConsumer(String linkName, String entityPat
.addKeyValue(ENTITY_PATH_KEY, entityPath)
.addKeyValue(LINK_NAME_KEY, linkName);
- return monoError(logBuilder, new AmqpException(true, "Cannot create receive link from a closed session.", sessionHandler.getErrorContext()));
+ // TODO(limolkova) this can be simplified with FluxUtil.monoError(LoggingEventBuilder), not using it for now
+ // to allow using azure-core-amqp with stable azure-core 1.24.0 to simplify dependency management
+ // we should switch to it once monoError(LoggingEventBuilder) ships in stable azure-core
+ return Mono.error(logBuilder
+ .log(Exceptions.propagate(new AmqpException(true, "Cannot create receive link from a closed session.", sessionHandler.getErrorContext()))));
}
final LinkSubscription existingLink = openReceiveLinks.get(linkName);
@@ -451,7 +455,12 @@ private Mono createProducer(String linkName, String entityPath,
.addKeyValue(SESSION_NAME_KEY, sessionName)
.addKeyValue(ENTITY_PATH_KEY, entityPath)
.addKeyValue(LINK_NAME_KEY, linkName);
- return monoError(logBuilder, new AmqpException(true, "Cannot create send link from a closed session.", sessionHandler.getErrorContext()));
+
+ // TODO(limolkova) this can be simplified with FluxUtil.monoError(LoggingEventBuilder), not using it for now
+ // to allow using azure-core-amqp with stable azure-core 1.24.0 to simplify dependency management
+ // we should switch to it once monoError(LoggingEventBuilder) ships in stable azure-core
+ return Mono.error(logBuilder
+ .log(Exceptions.propagate(new AmqpException(true, "Cannot create send link from a closed session.", sessionHandler.getErrorContext()))));
}
final LinkSubscription existing = openSendLinks.get(linkName);