Skip to content

Commit 85933e6

Browse files
committed
Remove stacktrace from connection acquisition attempts in LoadBalancer (neo4j#944)
This is to reduce the noise in the logs on connection acquisition errors. Complete failures are reported separately.
1 parent b590e33 commit 85933e6

File tree

4 files changed

+36
-17
lines changed

4 files changed

+36
-17
lines changed

driver/src/main/java/org/neo4j/driver/internal/cluster/RediscoveryImpl.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,9 @@ public class RediscoveryImpl implements Rediscovery
5757
{
5858
private static final String NO_ROUTERS_AVAILABLE = "Could not perform discovery for database '%s'. No routing server available.";
5959
private static final String RECOVERABLE_ROUTING_ERROR = "Failed to update routing table with server '%s'.";
60+
private static final String RECOVERABLE_DISCOVERY_ERROR_WITH_SERVER = "Received a recoverable discovery error with server '%s', " +
61+
"will continue discovery with other routing servers if available. " +
62+
"Complete failure is reported separately from this entry.";
6063

6164
private final BoltServerAddress initialRouter;
6265
private final RoutingSettings settings;
@@ -258,8 +261,9 @@ private ClusterComposition handleRoutingProcedureError( Throwable error, Routing
258261
// Retriable error happened during discovery.
259262
DiscoveryException discoveryError = new DiscoveryException( format( RECOVERABLE_ROUTING_ERROR, routerAddress ), error );
260263
Futures.combineErrors( baseError, discoveryError ); // we record each failure here
261-
logger.warn( format( "Received a recoverable discovery error with server '%s', will continue discovery with other routing servers if available.",
262-
routerAddress ), discoveryError );
264+
String warningMessage = format( RECOVERABLE_DISCOVERY_ERROR_WITH_SERVER, routerAddress );
265+
logger.warn( warningMessage );
266+
logger.debug( warningMessage, discoveryError );
263267
routingTable.forget( routerAddress );
264268
return null;
265269
}

driver/src/main/java/org/neo4j/driver/internal/cluster/loadbalancing/LoadBalancer.java

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
import io.netty.util.concurrent.EventExecutorGroup;
2222

23+
import java.util.ArrayList;
2324
import java.util.List;
2425
import java.util.concurrent.CompletableFuture;
2526
import java.util.concurrent.CompletionStage;
@@ -60,6 +61,11 @@
6061
public class LoadBalancer implements ConnectionProvider
6162
{
6263
private static final String LOAD_BALANCER_LOG_NAME = "LoadBalancer";
64+
private static final String CONNECTION_ACQUISITION_COMPLETION_FAILURE_MESSAGE = "Connection acquisition failed for all available addresses.";
65+
private static final String CONNECTION_ACQUISITION_COMPLETION_EXCEPTION_MESSAGE =
66+
"Failed to obtain connection towards %s server. Known routing table is: %s";
67+
private static final String CONNECTION_ACQUISITION_ATTEMPT_FAILURE_MESSAGE =
68+
"Failed to obtain a connection towards address %s, will try other addresses if available. Complete failure is reported separately from this entry.";
6369
private final ConnectionPool connectionPool;
6470
private final RoutingTableRegistry routingTables;
6571
private final LoadBalancingStrategy loadBalancingStrategy;
@@ -177,19 +183,23 @@ private CompletionStage<Connection> acquire( AccessMode mode, RoutingTable routi
177183
{
178184
AddressSet addresses = addressSet( mode, routingTable );
179185
CompletableFuture<Connection> result = new CompletableFuture<>();
180-
acquire( mode, routingTable, addresses, result );
186+
List<Throwable> attemptExceptions = new ArrayList<>();
187+
acquire( mode, routingTable, addresses, result, attemptExceptions );
181188
return result;
182189
}
183190

184-
private void acquire( AccessMode mode, RoutingTable routingTable, AddressSet addresses, CompletableFuture<Connection> result )
191+
private void acquire( AccessMode mode, RoutingTable routingTable, AddressSet addresses, CompletableFuture<Connection> result,
192+
List<Throwable> attemptErrors )
185193
{
186194
BoltServerAddress address = selectAddress( mode, addresses );
187195

188196
if ( address == null )
189197
{
190-
result.completeExceptionally( new SessionExpiredException(
191-
"Failed to obtain connection towards " + mode + " server. " +
192-
"Known routing table is: " + routingTable ) );
198+
SessionExpiredException completionError =
199+
new SessionExpiredException( format( CONNECTION_ACQUISITION_COMPLETION_EXCEPTION_MESSAGE, mode, routingTable ) );
200+
attemptErrors.forEach( completionError::addSuppressed );
201+
log.error( CONNECTION_ACQUISITION_COMPLETION_FAILURE_MESSAGE, completionError );
202+
result.completeExceptionally( completionError );
193203
return;
194204
}
195205

@@ -200,10 +210,12 @@ private void acquire( AccessMode mode, RoutingTable routingTable, AddressSet add
200210
{
201211
if ( error instanceof ServiceUnavailableException )
202212
{
203-
SessionExpiredException errorToLog = new SessionExpiredException( format( "Server at %s is no longer available", address ), error );
204-
log.warn( "Failed to obtain a connection towards address " + address, errorToLog );
213+
String attemptMessage = format( CONNECTION_ACQUISITION_ATTEMPT_FAILURE_MESSAGE, address );
214+
log.warn( attemptMessage );
215+
log.debug( attemptMessage, error );
216+
attemptErrors.add( error );
205217
routingTable.forget( address );
206-
eventExecutorGroup.next().execute( () -> acquire( mode, routingTable, addresses, result ) );
218+
eventExecutorGroup.next().execute( () -> acquire( mode, routingTable, addresses, result, attemptErrors ) );
207219
}
208220
else
209221
{

driver/src/test/java/org/neo4j/driver/integration/RoutingDriverBoltKitTest.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@
3636
import java.util.concurrent.TimeUnit;
3737
import java.util.concurrent.atomic.AtomicBoolean;
3838
import java.util.concurrent.atomic.AtomicInteger;
39-
import java.util.function.Function;
4039

4140
import org.neo4j.driver.AccessMode;
4241
import org.neo4j.driver.AuthToken;
@@ -827,7 +826,7 @@ void shouldRetryWriteTransactionUntilSuccessWithWhenLeaderIsRemoved() throws Exc
827826
assertEquals( 0, writer.exitStatus() );
828827
}
829828
verify( logger, times( 3 ) ).warn( startsWith( "Transaction failed and will be retried in" ), any( SessionExpiredException.class ) );
830-
verify( logger ).warn( startsWith( "Failed to obtain a connection towards address 127.0.0.1:9004" ), any( SessionExpiredException.class ) );
829+
verify( logger ).warn( startsWith( "Failed to obtain a connection towards address 127.0.0.1:9004" ) );
831830
}
832831

833832
@Test
@@ -861,7 +860,7 @@ void shouldRetryWriteTransactionUntilSuccessWithWhenLeaderIsRemovedV3() throws E
861860
}
862861
verify( logger, times( 1 ) ).warn( startsWith( "Transaction failed and will be retried in" ), any( TransientException.class ) );
863862
verify( logger, times( 2 ) ).warn( startsWith( "Transaction failed and will be retried in" ), any( SessionExpiredException.class ) );
864-
verify( logger ).warn( startsWith( "Failed to obtain a connection towards address 127.0.0.1:9004" ), any( SessionExpiredException.class ) );
863+
verify( logger ).warn( startsWith( "Failed to obtain a connection towards address 127.0.0.1:9004" ) );
865864
}
866865

867866
@Test

driver/src/test/java/org/neo4j/driver/internal/cluster/RediscoveryTest.java

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,6 @@
5252
import static org.junit.jupiter.api.Assertions.assertNotNull;
5353
import static org.junit.jupiter.api.Assertions.assertThrows;
5454
import static org.mockito.ArgumentMatchers.any;
55-
import static org.mockito.ArgumentMatchers.anyString;
5655
import static org.mockito.Mockito.mock;
5756
import static org.mockito.Mockito.never;
5857
import static org.mockito.Mockito.startsWith;
@@ -182,9 +181,14 @@ void shouldFailImmediatelyWhenClusterCompositionProviderReturnsFailure()
182181
ClusterComposition composition = await( rediscovery.lookupClusterComposition( table, pool, empty() ) );
183182
assertEquals( validComposition, composition );
184183

185-
ArgumentCaptor<DiscoveryException> argument = ArgumentCaptor.forClass( DiscoveryException.class );
186-
verify( logger ).warn( anyString(), argument.capture() );
187-
assertThat( argument.getValue().getCause(), equalTo( protocolError ) );
184+
ArgumentCaptor<String> warningMessageCaptor = ArgumentCaptor.forClass( String.class );
185+
ArgumentCaptor<String> debugMessageCaptor = ArgumentCaptor.forClass( String.class );
186+
ArgumentCaptor<DiscoveryException> debugThrowableCaptor = ArgumentCaptor.forClass( DiscoveryException.class );
187+
verify( logger ).warn( warningMessageCaptor.capture() );
188+
verify( logger ).debug( debugMessageCaptor.capture(), debugThrowableCaptor.capture() );
189+
assertNotNull( warningMessageCaptor.getValue() );
190+
assertEquals( warningMessageCaptor.getValue(), debugMessageCaptor.getValue() );
191+
assertThat( debugThrowableCaptor.getValue().getCause(), equalTo( protocolError ) );
188192
}
189193

190194
@Test

0 commit comments

Comments
 (0)