From c58f606d90241618290bf8cbeeab687bdaf26d6b Mon Sep 17 00:00:00 2001 From: Zhen Date: Thu, 1 Feb 2018 17:27:06 +0100 Subject: [PATCH 1/6] Draft of driver metrics Added Basics of Driver metrics and Connection pool metrics. The driver metrics are enabled with system property `driver.metrics.enabled=true` TODO: Histgram and ConnectionMetrics --- .../neo4j/driver/internal/DriverFactory.java | 26 ++- .../neo4j/driver/internal/InternalDriver.java | 12 ++ .../async/pool/ConnectionPoolImpl.java | 66 ++++++-- .../internal/async/pool/NettyChannelPool.java | 15 +- ...lTracker.java => NettyChannelTracker.java} | 77 ++++++++- .../LeastConnectedLoadBalancingStrategy.java | 2 +- .../metrics/ConnectionPoolListener.java | 35 ++++ .../metrics/DriverMetricsHandler.java | 39 +++++ .../InternalAbstractDriverMetrics.java | 93 ++++++++++ .../InternalConnectionPoolMetrics.java | 159 ++++++++++++++++++ .../metrics/InternalDriverMetrics.java | 128 ++++++++++++++ .../internal/metrics/ListenerEvent.java | 26 +++ .../metrics/SimpleTimerListenerEvent.java | 37 ++++ .../metrics/spi/ConnectionMetrics.java | 23 +++ .../metrics/spi/ConnectionPoolMetrics.java | 34 ++++ .../internal/metrics/spi/DriverMetrics.java | 35 ++++ .../internal/metrics/spi/Histogram.java | 31 ++++ .../driver/internal/spi/ConnectionPool.java | 6 +- .../driver/internal/DriverFactoryTest.java | 36 +++- .../async/pool/ActiveChannelTrackerTest.java | 113 ------------- .../async/pool/ConnectionPoolImplTest.java | 39 ++--- .../async/pool/NettyChannelPoolTest.java | 16 +- .../async/pool/NettyChannelTrackerTest.java | 141 ++++++++++++++++ ...astConnectedLoadBalancingStrategyTest.java | 20 +-- .../loadbalancing/LoadBalancerTest.java | 6 +- .../util/ChannelTrackingDriverFactory.java | 9 +- .../util/FailingConnectionDriverFactory.java | 22 ++- .../v1/integration/ConnectionHandlingIT.java | 7 +- .../v1/stress/AbstractStressTestBase.java | 10 +- 29 files changed, 1059 insertions(+), 204 deletions(-) rename driver/src/main/java/org/neo4j/driver/internal/async/pool/{ActiveChannelTracker.java => NettyChannelTracker.java} (50%) create mode 100644 driver/src/main/java/org/neo4j/driver/internal/metrics/ConnectionPoolListener.java create mode 100644 driver/src/main/java/org/neo4j/driver/internal/metrics/DriverMetricsHandler.java create mode 100644 driver/src/main/java/org/neo4j/driver/internal/metrics/InternalAbstractDriverMetrics.java create mode 100644 driver/src/main/java/org/neo4j/driver/internal/metrics/InternalConnectionPoolMetrics.java create mode 100644 driver/src/main/java/org/neo4j/driver/internal/metrics/InternalDriverMetrics.java create mode 100644 driver/src/main/java/org/neo4j/driver/internal/metrics/ListenerEvent.java create mode 100644 driver/src/main/java/org/neo4j/driver/internal/metrics/SimpleTimerListenerEvent.java create mode 100644 driver/src/main/java/org/neo4j/driver/internal/metrics/spi/ConnectionMetrics.java create mode 100644 driver/src/main/java/org/neo4j/driver/internal/metrics/spi/ConnectionPoolMetrics.java create mode 100644 driver/src/main/java/org/neo4j/driver/internal/metrics/spi/DriverMetrics.java create mode 100644 driver/src/main/java/org/neo4j/driver/internal/metrics/spi/Histogram.java delete mode 100644 driver/src/test/java/org/neo4j/driver/internal/async/pool/ActiveChannelTrackerTest.java create mode 100644 driver/src/test/java/org/neo4j/driver/internal/async/pool/NettyChannelTrackerTest.java diff --git a/driver/src/main/java/org/neo4j/driver/internal/DriverFactory.java b/driver/src/main/java/org/neo4j/driver/internal/DriverFactory.java index 9de1eca0b1..d2b54e8eda 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/DriverFactory.java +++ b/driver/src/main/java/org/neo4j/driver/internal/DriverFactory.java @@ -38,6 +38,9 @@ import org.neo4j.driver.internal.cluster.loadbalancing.LoadBalancingStrategy; import org.neo4j.driver.internal.cluster.loadbalancing.RoundRobinLoadBalancingStrategy; import org.neo4j.driver.internal.logging.NettyLogging; +import org.neo4j.driver.internal.metrics.DriverMetricsHandler; +import org.neo4j.driver.internal.metrics.InternalAbstractDriverMetrics; +import org.neo4j.driver.internal.metrics.InternalDriverMetrics; import org.neo4j.driver.internal.retry.ExponentialBackoffRetryLogic; import org.neo4j.driver.internal.retry.RetryLogic; import org.neo4j.driver.internal.retry.RetrySettings; @@ -56,6 +59,8 @@ import org.neo4j.driver.v1.exceptions.ServiceUnavailableException; import static java.lang.String.format; +import static org.neo4j.driver.internal.metrics.InternalAbstractDriverMetrics.DEV_NULL_METRICS; +import static org.neo4j.driver.internal.metrics.spi.DriverMetrics.isDriverMetricsEnabled; import static org.neo4j.driver.internal.security.SecurityPlan.insecure; public class DriverFactory @@ -77,18 +82,19 @@ public final Driver newInstance( URI uri, AuthToken authToken, RoutingSettings r EventExecutorGroup eventExecutorGroup = bootstrap.config().group(); RetryLogic retryLogic = createRetryLogic( retrySettings, eventExecutorGroup, config.logging() ); - ConnectionPool connectionPool = createConnectionPool( authToken, securityPlan, bootstrap, config ); + InternalAbstractDriverMetrics metrics = createDriverMetrics( config ); + ConnectionPool connectionPool = createConnectionPool( authToken, securityPlan, bootstrap, metrics, config ); InternalDriver driver = createDriver( uri, address, connectionPool, config, newRoutingSettings, eventExecutorGroup, securityPlan, retryLogic ); + driver.driverMetrics( metrics ); verifyConnectivity( driver, connectionPool, config ); return driver; } - protected ConnectionPool createConnectionPool( AuthToken authToken, SecurityPlan securityPlan, - Bootstrap bootstrap, Config config ) + protected ConnectionPool createConnectionPool( AuthToken authToken, SecurityPlan securityPlan, Bootstrap bootstrap, DriverMetricsHandler metrics, Config config ) { Clock clock = createClock(); ConnectionSettings settings = new ConnectionSettings( authToken, config.connectionTimeoutMillis() ); @@ -97,7 +103,19 @@ protected ConnectionPool createConnectionPool( AuthToken authToken, SecurityPlan config.connectionAcquisitionTimeoutMillis(), config.maxConnectionLifetimeMillis(), config.idleTimeBeforeConnectionTest() ); - return new ConnectionPoolImpl( connector, bootstrap, poolSettings, config.logging(), clock ); + return new ConnectionPoolImpl( connector, bootstrap, poolSettings, metrics, config.logging(), clock ); + } + + protected static InternalAbstractDriverMetrics createDriverMetrics( Config config ) + { + if( isDriverMetricsEnabled() ) + { + return new InternalDriverMetrics( config ); + } + else + { + return DEV_NULL_METRICS; + } } protected ChannelConnector createConnector( ConnectionSettings settings, SecurityPlan securityPlan, diff --git a/driver/src/main/java/org/neo4j/driver/internal/InternalDriver.java b/driver/src/main/java/org/neo4j/driver/internal/InternalDriver.java index 2528d493fd..a4b22aa892 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/InternalDriver.java +++ b/driver/src/main/java/org/neo4j/driver/internal/InternalDriver.java @@ -21,6 +21,7 @@ import java.util.concurrent.CompletionStage; import java.util.concurrent.atomic.AtomicBoolean; +import org.neo4j.driver.internal.metrics.spi.DriverMetrics; import org.neo4j.driver.internal.security.SecurityPlan; import org.neo4j.driver.internal.util.Futures; import org.neo4j.driver.v1.AccessMode; @@ -38,6 +39,7 @@ public class InternalDriver implements Driver private final Logger log; private AtomicBoolean closed = new AtomicBoolean( false ); + private DriverMetrics driverMetrics; InternalDriver( SecurityPlan securityPlan, SessionFactory sessionFactory, Logging logging ) { @@ -144,6 +146,16 @@ private void assertOpen() } } + public DriverMetrics driverMetrics() + { + return this.driverMetrics; + } + + void driverMetrics( DriverMetrics driverMetrics ) + { + this.driverMetrics = driverMetrics; + } + private static RuntimeException driverCloseException() { return new IllegalStateException( "This driver instance has already been closed" ); diff --git a/driver/src/main/java/org/neo4j/driver/internal/async/pool/ConnectionPoolImpl.java b/driver/src/main/java/org/neo4j/driver/internal/async/pool/ConnectionPoolImpl.java index 264e6286bd..8b49376388 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/async/pool/ConnectionPoolImpl.java +++ b/driver/src/main/java/org/neo4j/driver/internal/async/pool/ConnectionPoolImpl.java @@ -36,6 +36,9 @@ import org.neo4j.driver.internal.BoltServerAddress; import org.neo4j.driver.internal.async.ChannelConnector; import org.neo4j.driver.internal.async.NettyConnection; +import org.neo4j.driver.internal.metrics.DriverMetricsHandler; +import org.neo4j.driver.internal.metrics.ListenerEvent; +import org.neo4j.driver.internal.metrics.SimpleTimerListenerEvent; import org.neo4j.driver.internal.spi.Connection; import org.neo4j.driver.internal.spi.ConnectionPool; import org.neo4j.driver.internal.util.Clock; @@ -48,29 +51,31 @@ public class ConnectionPoolImpl implements ConnectionPool { private final ChannelConnector connector; private final Bootstrap bootstrap; - private final ActiveChannelTracker activeChannelTracker; + private final NettyChannelTracker nettyChannelTracker; private final NettyChannelHealthChecker channelHealthChecker; private final PoolSettings settings; private final Clock clock; private final Logger log; + private DriverMetricsHandler driverMetrics; private final ConcurrentMap pools = new ConcurrentHashMap<>(); private final AtomicBoolean closed = new AtomicBoolean(); public ConnectionPoolImpl( ChannelConnector connector, Bootstrap bootstrap, PoolSettings settings, - Logging logging, Clock clock ) + DriverMetricsHandler metricsHandler, Logging logging, Clock clock ) { - this( connector, bootstrap, new ActiveChannelTracker( logging ), settings, logging, clock ); + this( connector, bootstrap, new NettyChannelTracker( metricsHandler, logging ), settings, metricsHandler, logging, clock ); } - ConnectionPoolImpl( ChannelConnector connector, Bootstrap bootstrap, ActiveChannelTracker activeChannelTracker, - PoolSettings settings, Logging logging, Clock clock ) + ConnectionPoolImpl( ChannelConnector connector, Bootstrap bootstrap, NettyChannelTracker nettyChannelTracker, + PoolSettings settings, DriverMetricsHandler driverMetrics, Logging logging, Clock clock ) { this.connector = connector; this.bootstrap = bootstrap; - this.activeChannelTracker = activeChannelTracker; + this.nettyChannelTracker = nettyChannelTracker; this.channelHealthChecker = new NettyChannelHealthChecker( settings, clock, logging ); this.settings = settings; + this.driverMetrics = driverMetrics; this.clock = clock; this.log = logging.getLog( ConnectionPool.class.getSimpleName() ); } @@ -80,15 +85,26 @@ public CompletionStage acquire( BoltServerAddress address ) { log.trace( "Acquiring a connection from pool towards %s", address ); + // TODO no need to init if no driver metrics + ListenerEvent acquireEvent = new SimpleTimerListenerEvent(); + assertNotClosed(); ChannelPool pool = getOrCreatePool( address ); + driverMetrics.beforeAcquiring( address, acquireEvent ); Future connectionFuture = pool.acquire(); return Futures.asCompletionStage( connectionFuture ).handle( ( channel, error ) -> { - processAcquisitionError( error ); - assertNotClosed( address, channel, pool ); - return new NettyConnection( channel, pool, clock ); + try + { + processAcquisitionError( error ); + assertNotClosed( address, channel, pool ); + return new NettyConnection( channel, pool, clock ); + } + finally + { + driverMetrics.afterAcquired( address, acquireEvent ); + } } ); } @@ -99,7 +115,7 @@ public void retainAll( Set addressesToRetain ) { if ( !addressesToRetain.contains( address ) ) { - int activeChannels = activeChannelTracker.activeChannelCount( address ); + int activeChannels = nettyChannelTracker.inUseChannelCount( address ); if ( activeChannels == 0 ) { // address is not present in updated routing table and has no active connections @@ -118,9 +134,15 @@ public void retainAll( Set addressesToRetain ) } @Override - public int activeConnections( BoltServerAddress address ) + public int inUseConnections( BoltServerAddress address ) + { + return nettyChannelTracker.inUseChannelCount( address ); + } + + @Override + public int idleConnections( BoltServerAddress address ) { - return activeChannelTracker.activeChannelCount( address ); + return nettyChannelTracker.idleChannelCount( address ); } @Override @@ -150,6 +172,12 @@ public CompletionStage close() .thenApply( ignore -> null ); } + @Override + public boolean isOpen() + { + return !closed.get(); + } + private ChannelPool getOrCreatePool( BoltServerAddress address ) { ChannelPool pool = pools.get( address ); @@ -163,13 +191,19 @@ private ChannelPool getOrCreatePool( BoltServerAddress address ) pool.close(); return getOrCreatePool( address ); } + else + { + // We added a new pool as a result we add a new metrics for the pool too + driverMetrics.addPoolMetrics( address, this ); + } } + return pool; } ChannelPool newPool( BoltServerAddress address ) { - return new NettyChannelPool( address, connector, bootstrap, activeChannelTracker, channelHealthChecker, + return new NettyChannelPool( address, connector, bootstrap, nettyChannelTracker, channelHealthChecker, settings.connectionAcquisitionTimeout(), settings.maxConnectionPoolSize() ); } @@ -217,4 +251,10 @@ private void assertNotClosed( BoltServerAddress address, Channel channel, Channe assertNotClosed(); } } + + @Override + public String toString() + { + return "ConnectionPoolImpl{" + "pools=" + pools + '}'; + } } diff --git a/driver/src/main/java/org/neo4j/driver/internal/async/pool/NettyChannelPool.java b/driver/src/main/java/org/neo4j/driver/internal/async/pool/NettyChannelPool.java index 893f189f7d..be25aacfcc 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/async/pool/NettyChannelPool.java +++ b/driver/src/main/java/org/neo4j/driver/internal/async/pool/NettyChannelPool.java @@ -19,9 +19,9 @@ package org.neo4j.driver.internal.async.pool; import io.netty.bootstrap.Bootstrap; +import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.pool.ChannelHealthChecker; -import io.netty.channel.pool.ChannelPoolHandler; import io.netty.channel.pool.FixedChannelPool; import org.neo4j.driver.internal.BoltServerAddress; @@ -42,9 +42,10 @@ public class NettyChannelPool extends FixedChannelPool private final BoltServerAddress address; private final ChannelConnector connector; + private final NettyChannelTracker handler; public NettyChannelPool( BoltServerAddress address, ChannelConnector connector, Bootstrap bootstrap, - ChannelPoolHandler handler, ChannelHealthChecker healthCheck, long acquireTimeoutMillis, + NettyChannelTracker handler, ChannelHealthChecker healthCheck, long acquireTimeoutMillis, int maxConnections ) { super( bootstrap, handler, healthCheck, AcquireTimeoutAction.FAIL, acquireTimeoutMillis, maxConnections, @@ -52,18 +53,26 @@ public NettyChannelPool( BoltServerAddress address, ChannelConnector connector, this.address = requireNonNull( address ); this.connector = requireNonNull( connector ); + this.handler = requireNonNull( handler ); } @Override protected ChannelFuture connectChannel( Bootstrap bootstrap ) { + handler.channelCreating( address ); ChannelFuture channelFuture = connector.connect( address, bootstrap ); channelFuture.addListener( future -> { if ( future.isSuccess() ) { // notify pool handler about a successful connection - handler().channelCreated( channelFuture.channel() ); + Channel channel = channelFuture.channel(); + handler.channelCreated( channel ); + channel.closeFuture().addListener( closeFuture -> handler.channelClosed( channel ) ); + } + else + { + handler.channelFailedToCreate( address ); } } ); return channelFuture; diff --git a/driver/src/main/java/org/neo4j/driver/internal/async/pool/ActiveChannelTracker.java b/driver/src/main/java/org/neo4j/driver/internal/async/pool/NettyChannelTracker.java similarity index 50% rename from driver/src/main/java/org/neo4j/driver/internal/async/pool/ActiveChannelTracker.java rename to driver/src/main/java/org/neo4j/driver/internal/async/pool/NettyChannelTracker.java index 728c96da8a..0cc4243f45 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/async/pool/ActiveChannelTracker.java +++ b/driver/src/main/java/org/neo4j/driver/internal/async/pool/NettyChannelTracker.java @@ -26,18 +26,22 @@ import java.util.concurrent.atomic.AtomicInteger; import org.neo4j.driver.internal.BoltServerAddress; +import org.neo4j.driver.internal.metrics.DriverMetricsHandler; import org.neo4j.driver.v1.Logger; import org.neo4j.driver.v1.Logging; import static org.neo4j.driver.internal.async.ChannelAttributes.serverAddress; -public class ActiveChannelTracker implements ChannelPoolHandler +public class NettyChannelTracker implements ChannelPoolHandler { - private final Map addressToActiveChannelCount = new ConcurrentHashMap<>(); + private final Map addressToInUseChannelCount = new ConcurrentHashMap<>(); + private final Map addressToIdleChannelCount = new ConcurrentHashMap<>(); private final Logger log; + private DriverMetricsHandler metricsHandler; - public ActiveChannelTracker( Logging logging ) + public NettyChannelTracker( DriverMetricsHandler metricsHandler, Logging logging ) { + this.metricsHandler = metricsHandler; this.log = logging.getLog( getClass().getSimpleName() ); } @@ -59,26 +63,81 @@ public void channelAcquired( Channel channel ) public void channelCreated( Channel channel ) { log.debug( "Channel %s created", channel ); - channelActive( channel ); + incrementInUse( channel ); + metricsHandler.afterCreatedSuccessfully( serverAddress( channel ) ); } - public int activeChannelCount( BoltServerAddress address ) + public void channelFailedToCreate( BoltServerAddress address ) { - AtomicInteger count = addressToActiveChannelCount.get( address ); + metricsHandler.afterFailedToCreate( address ); + } + + public void channelCreating( BoltServerAddress address ) + { + metricsHandler.beforeCreating( address ); + } + + public void channelClosed( Channel channel ) + { + decrementIdle( channel ); + metricsHandler.afterClosed( serverAddress( channel ) ); + } + + public int inUseChannelCount( BoltServerAddress address ) + { + AtomicInteger count = addressToInUseChannelCount.get( address ); + return count == null ? 0 : count.get(); + } + + public int idleChannelCount( BoltServerAddress address ) + { + AtomicInteger count = addressToIdleChannelCount.get( address ); return count == null ? 0 : count.get(); } private void channelActive( Channel channel ) + { + incrementInUse( channel ); + decrementIdle( channel ); + } + + private void channelInactive( Channel channel ) + { + decrementInUse( channel ); + incrementIdle( channel ); + } + + private void incrementInUse( Channel channel ) + { + increment( channel, addressToInUseChannelCount ); + } + + private void decrementInUse( Channel channel ) + { + decrement( channel, addressToInUseChannelCount ); + } + + private void incrementIdle( Channel channel ) + { + increment( channel, addressToIdleChannelCount ); + } + + private void decrementIdle( Channel channel ) + { + decrement( channel, addressToIdleChannelCount ); + } + + private void increment( Channel channel, Map countMap ) { BoltServerAddress address = serverAddress( channel ); - AtomicInteger count = addressToActiveChannelCount.computeIfAbsent( address, k -> new AtomicInteger() ); + AtomicInteger count = countMap.computeIfAbsent( address, k -> new AtomicInteger() ); count.incrementAndGet(); } - private void channelInactive( Channel channel ) + private void decrement( Channel channel, Map countMap ) { BoltServerAddress address = serverAddress( channel ); - AtomicInteger count = addressToActiveChannelCount.get( address ); + AtomicInteger count = countMap.get( address ); if ( count == null ) { throw new IllegalStateException( "No count exist for address '" + address + "'" ); diff --git a/driver/src/main/java/org/neo4j/driver/internal/cluster/loadbalancing/LeastConnectedLoadBalancingStrategy.java b/driver/src/main/java/org/neo4j/driver/internal/cluster/loadbalancing/LeastConnectedLoadBalancingStrategy.java index ff7df31fec..c85ff26254 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/cluster/loadbalancing/LeastConnectedLoadBalancingStrategy.java +++ b/driver/src/main/java/org/neo4j/driver/internal/cluster/loadbalancing/LeastConnectedLoadBalancingStrategy.java @@ -77,7 +77,7 @@ private BoltServerAddress select( BoltServerAddress[] addresses, RoundRobinArray do { BoltServerAddress address = addresses[index]; - int activeConnections = connectionPool.activeConnections( address ); + int activeConnections = connectionPool.inUseConnections( address ); if ( activeConnections < leastActiveConnections ) { diff --git a/driver/src/main/java/org/neo4j/driver/internal/metrics/ConnectionPoolListener.java b/driver/src/main/java/org/neo4j/driver/internal/metrics/ConnectionPoolListener.java new file mode 100644 index 0000000000..4ee7ad1def --- /dev/null +++ b/driver/src/main/java/org/neo4j/driver/internal/metrics/ConnectionPoolListener.java @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2002-2018 "Neo Technology," + * Network Engine for Objects in Lund AB [http://neotechnology.com] + * + * This file is part of Neo4j. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.neo4j.driver.internal.metrics; + +public interface ConnectionPoolListener +{ + void beforeCreating(); + + void afterCreatedSuccessfully(); + + void afterFailedToCreate(); + + void afterClosed(); + + void beforeAcquire( ListenerEvent listenerEvent ); + + void afterAcquire( ListenerEvent listenerEvent ); +} + diff --git a/driver/src/main/java/org/neo4j/driver/internal/metrics/DriverMetricsHandler.java b/driver/src/main/java/org/neo4j/driver/internal/metrics/DriverMetricsHandler.java new file mode 100644 index 0000000000..bb5e87cf02 --- /dev/null +++ b/driver/src/main/java/org/neo4j/driver/internal/metrics/DriverMetricsHandler.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2002-2018 "Neo Technology," + * Network Engine for Objects in Lund AB [http://neotechnology.com] + * + * This file is part of Neo4j. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.neo4j.driver.internal.metrics; + +import org.neo4j.driver.internal.BoltServerAddress; +import org.neo4j.driver.internal.spi.ConnectionPool; + +public interface DriverMetricsHandler +{ + void addPoolMetrics(BoltServerAddress serverAddress, ConnectionPool pool); + + void beforeCreating(BoltServerAddress serverAddress); + + void afterCreatedSuccessfully(BoltServerAddress serverAddress); + + void afterFailedToCreate(BoltServerAddress serverAddress); + + void afterClosed(BoltServerAddress serverAddress); + + void beforeAcquiring( BoltServerAddress serverAddress, ListenerEvent listenerEvent ); + + void afterAcquired( BoltServerAddress serverAddress, ListenerEvent listenerEvent ); +} diff --git a/driver/src/main/java/org/neo4j/driver/internal/metrics/InternalAbstractDriverMetrics.java b/driver/src/main/java/org/neo4j/driver/internal/metrics/InternalAbstractDriverMetrics.java new file mode 100644 index 0000000000..f3e246f89f --- /dev/null +++ b/driver/src/main/java/org/neo4j/driver/internal/metrics/InternalAbstractDriverMetrics.java @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2002-2018 "Neo Technology," + * Network Engine for Objects in Lund AB [http://neotechnology.com] + * + * This file is part of Neo4j. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.neo4j.driver.internal.metrics; + +import java.util.Map; + +import org.neo4j.driver.internal.BoltServerAddress; +import org.neo4j.driver.internal.metrics.spi.ConnectionMetrics; +import org.neo4j.driver.internal.metrics.spi.ConnectionPoolMetrics; +import org.neo4j.driver.internal.metrics.spi.DriverMetrics; +import org.neo4j.driver.internal.spi.ConnectionPool; + +public abstract class InternalAbstractDriverMetrics implements DriverMetrics, DriverMetricsHandler +{ + public static final InternalAbstractDriverMetrics DEV_NULL_METRICS = new InternalAbstractDriverMetrics() + { + @Override + public void addPoolMetrics( BoltServerAddress serverAddress, ConnectionPool pool ) + { + + } + + @Override + public void beforeCreating( BoltServerAddress serverAddress ) + { + + } + + @Override + public void afterCreatedSuccessfully( BoltServerAddress serverAddress ) + { + + } + + @Override + public void afterFailedToCreate( BoltServerAddress serverAddress ) + { + + } + + @Override + public void afterClosed( BoltServerAddress serverAddress ) + { + + } + + @Override + public void beforeAcquiring( BoltServerAddress serverAddress, ListenerEvent listenerEvent ) + { + + } + + @Override + public void afterAcquired( BoltServerAddress serverAddress, ListenerEvent listenerEvent ) + { + + } + + @Override + public Map connectionPoolMetrics() + { + return null; + } + + @Override + public Map connectionMetrics() + { + return null; + } + + @Override + public String toString() + { + return "Driver metrics not available while driver metrics is not enabled."; + } + }; +} diff --git a/driver/src/main/java/org/neo4j/driver/internal/metrics/InternalConnectionPoolMetrics.java b/driver/src/main/java/org/neo4j/driver/internal/metrics/InternalConnectionPoolMetrics.java new file mode 100644 index 0000000000..94f609c210 --- /dev/null +++ b/driver/src/main/java/org/neo4j/driver/internal/metrics/InternalConnectionPoolMetrics.java @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2002-2018 "Neo Technology," + * Network Engine for Objects in Lund AB [http://neotechnology.com] + * + * This file is part of Neo4j. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.neo4j.driver.internal.metrics; + +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicLong; + +import org.neo4j.driver.internal.BoltServerAddress; +import org.neo4j.driver.internal.metrics.spi.ConnectionPoolMetrics; +import org.neo4j.driver.internal.metrics.spi.Histogram; +import org.neo4j.driver.internal.spi.ConnectionPool; + +import static java.lang.String.format; +import static org.neo4j.driver.internal.metrics.InternalDriverMetrics.serverAddressToUniqueName; + +public class InternalConnectionPoolMetrics implements ConnectionPoolMetrics, ConnectionPoolListener +{ + private final BoltServerAddress address; + private final ConnectionPool pool; + + private AtomicLong created = new AtomicLong(); + private AtomicLong closed = new AtomicLong(); + private AtomicInteger toCreate = new AtomicInteger(); + private AtomicLong failedToCreate = new AtomicLong(); + + // TODO + private Histogram histogram; + + public InternalConnectionPoolMetrics(BoltServerAddress address, ConnectionPool pool, long connAcquisitionTimeoutMs) + { + this.address = address; + this.pool = pool; + this.histogram = null; + } + + @Override + public void beforeCreating() + { + toCreate.incrementAndGet(); + } + + @Override + public void afterCreatedSuccessfully() + { + created.incrementAndGet(); + toCreate.decrementAndGet(); + } + + @Override + public void afterFailedToCreate() + { + failedToCreate.incrementAndGet(); + toCreate.decrementAndGet(); + } + + @Override + public void afterClosed() + { + closed.incrementAndGet(); + } + + @Override + public void beforeAcquire( ListenerEvent listenerEvent ) + { + listenerEvent.start(); + } + + @Override + public void afterAcquire( ListenerEvent listenerEvent ) + { + long elapsed = listenerEvent.elapsed(); + // TODO register in histogram + } + + @Override + public String uniqueName() + { + return serverAddressToUniqueName( address ); + } + + @Override + public String poolStatus() + { + if ( pool.isOpen() ) + { + return "\"Open\""; + } + else + { + return "\"Closed\""; + } + } + + @Override + public int inUse() + { + return pool.inUseConnections( address ); + } + + @Override + public int idle() + { + return pool.idleConnections( address ); + } + + @Override + public int toCreate() + { + return toCreate.get(); + } + + @Override + public long created() + { + return created.get(); + } + + @Override + public long failedToCreate() + { + return failedToCreate.get(); + } + + @Override + public long closed() + { + return closed.get(); + } + + @Override + public Histogram acquisitionTimeHistogram() + { + return null; + } + + @Override + public String toString() + { + return format( "[created=%s, closed=%s, toCreate=%s, failedToCreate=%s inUse=%s, idle=%s, poolStatus=%s]", + created(), closed(), toCreate(), failedToCreate(), inUse(), idle(), poolStatus() ); + } +} diff --git a/driver/src/main/java/org/neo4j/driver/internal/metrics/InternalDriverMetrics.java b/driver/src/main/java/org/neo4j/driver/internal/metrics/InternalDriverMetrics.java new file mode 100644 index 0000000000..8aca091b0b --- /dev/null +++ b/driver/src/main/java/org/neo4j/driver/internal/metrics/InternalDriverMetrics.java @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2002-2018 "Neo Technology," + * Network Engine for Objects in Lund AB [http://neotechnology.com] + * + * This file is part of Neo4j. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.neo4j.driver.internal.metrics; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import org.neo4j.driver.internal.BoltServerAddress; +import org.neo4j.driver.internal.metrics.spi.ConnectionMetrics; +import org.neo4j.driver.internal.metrics.spi.ConnectionPoolMetrics; +import org.neo4j.driver.internal.spi.ConnectionPool; +import org.neo4j.driver.v1.Config; +import org.neo4j.driver.v1.exceptions.ClientException; + +import static java.lang.String.format; + +public class InternalDriverMetrics extends InternalAbstractDriverMetrics +{ + private final Map connectionPoolMetrics; + private final Map connectionMetrics; + private final Config config; + + public InternalDriverMetrics( Config config ) + { + this.config = config; + this.connectionPoolMetrics = new ConcurrentHashMap<>(); + this.connectionMetrics = new ConcurrentHashMap<>(); + } + + @Override + public void addPoolMetrics( BoltServerAddress serverAddress, ConnectionPool pool ) + { + this.connectionPoolMetrics.put( serverAddressToUniqueName( serverAddress ), + new InternalConnectionPoolMetrics( serverAddress, pool, config.connectionAcquisitionTimeoutMillis() ) ); + } + + @Override + public void beforeCreating( BoltServerAddress serverAddress ) + { + InternalConnectionPoolMetrics poolMetrics = getPoolMetrics( serverAddress ); + poolMetrics.beforeCreating(); + } + + @Override + public void afterCreatedSuccessfully( BoltServerAddress serverAddress ) + { + InternalConnectionPoolMetrics poolMetrics = getPoolMetrics( serverAddress ); + poolMetrics.afterCreatedSuccessfully(); + } + + @Override + public void afterFailedToCreate( BoltServerAddress serverAddress ) + { + InternalConnectionPoolMetrics poolMetrics = getPoolMetrics( serverAddress ); + poolMetrics.afterFailedToCreate(); + } + + @Override + public void afterClosed( BoltServerAddress serverAddress ) + { + InternalConnectionPoolMetrics poolMetrics = getPoolMetrics( serverAddress ); + poolMetrics.afterClosed(); + } + + @Override + public void beforeAcquiring( BoltServerAddress serverAddress, ListenerEvent listenerEvent ) + { + InternalConnectionPoolMetrics poolMetrics = getPoolMetrics( serverAddress ); + poolMetrics.beforeAcquire( listenerEvent ); + } + + @Override + public void afterAcquired( BoltServerAddress serverAddress, ListenerEvent listenerEvent ) + { + InternalConnectionPoolMetrics poolMetrics = getPoolMetrics( serverAddress ); + poolMetrics.afterAcquire( listenerEvent ); + } + + @Override + public Map connectionPoolMetrics() + { + return this.connectionPoolMetrics; + } + + @Override + public Map connectionMetrics() + { + return this.connectionMetrics; + } + + @Override + public String toString() + { + return format( "PoolMetrics=%s, ConnMetrics=%s", connectionPoolMetrics, connectionMetrics ); + } + + public static String serverAddressToUniqueName( BoltServerAddress serverAddress ) + { + return serverAddress.toString(); + } + + private InternalConnectionPoolMetrics getPoolMetrics( BoltServerAddress serverAddress ) + { + InternalConnectionPoolMetrics poolMetrics = + (InternalConnectionPoolMetrics) this.connectionPoolMetrics.get( serverAddressToUniqueName( serverAddress ) ); + if ( poolMetrics == null ) + { + throw new ClientException( format( "Failed to find pool metrics for server %s in pool %s", serverAddress, this.connectionPoolMetrics ) ); + } + return poolMetrics; + } +} diff --git a/driver/src/main/java/org/neo4j/driver/internal/metrics/ListenerEvent.java b/driver/src/main/java/org/neo4j/driver/internal/metrics/ListenerEvent.java new file mode 100644 index 0000000000..e939b40ff7 --- /dev/null +++ b/driver/src/main/java/org/neo4j/driver/internal/metrics/ListenerEvent.java @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2002-2018 "Neo Technology," + * Network Engine for Objects in Lund AB [http://neotechnology.com] + * + * This file is part of Neo4j. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.neo4j.driver.internal.metrics; + + +public interface ListenerEvent +{ + void start(); + long elapsed(); +} diff --git a/driver/src/main/java/org/neo4j/driver/internal/metrics/SimpleTimerListenerEvent.java b/driver/src/main/java/org/neo4j/driver/internal/metrics/SimpleTimerListenerEvent.java new file mode 100644 index 0000000000..045153c470 --- /dev/null +++ b/driver/src/main/java/org/neo4j/driver/internal/metrics/SimpleTimerListenerEvent.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2002-2018 "Neo Technology," + * Network Engine for Objects in Lund AB [http://neotechnology.com] + * + * This file is part of Neo4j. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.neo4j.driver.internal.metrics; + +public class SimpleTimerListenerEvent implements ListenerEvent +{ + private long startTimestamp; + + @Override + public void start() + { + startTimestamp = System.currentTimeMillis(); + } + + @Override + public long elapsed() + { + return System.currentTimeMillis() - startTimestamp; + } +} diff --git a/driver/src/main/java/org/neo4j/driver/internal/metrics/spi/ConnectionMetrics.java b/driver/src/main/java/org/neo4j/driver/internal/metrics/spi/ConnectionMetrics.java new file mode 100644 index 0000000000..f39289f79e --- /dev/null +++ b/driver/src/main/java/org/neo4j/driver/internal/metrics/spi/ConnectionMetrics.java @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2002-2018 "Neo Technology," + * Network Engine for Objects in Lund AB [http://neotechnology.com] + * + * This file is part of Neo4j. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.neo4j.driver.internal.metrics.spi; + +public interface ConnectionMetrics +{ +} diff --git a/driver/src/main/java/org/neo4j/driver/internal/metrics/spi/ConnectionPoolMetrics.java b/driver/src/main/java/org/neo4j/driver/internal/metrics/spi/ConnectionPoolMetrics.java new file mode 100644 index 0000000000..ac1e14ea74 --- /dev/null +++ b/driver/src/main/java/org/neo4j/driver/internal/metrics/spi/ConnectionPoolMetrics.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2002-2018 "Neo Technology," + * Network Engine for Objects in Lund AB [http://neotechnology.com] + * + * This file is part of Neo4j. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.neo4j.driver.internal.metrics.spi; + +public interface ConnectionPoolMetrics +{ + String uniqueName(); + String poolStatus(); + int inUse(); + int idle(); + int toCreate(); + + long created(); + long failedToCreate(); + long closed(); + + Histogram acquisitionTimeHistogram(); +} diff --git a/driver/src/main/java/org/neo4j/driver/internal/metrics/spi/DriverMetrics.java b/driver/src/main/java/org/neo4j/driver/internal/metrics/spi/DriverMetrics.java new file mode 100644 index 0000000000..5ed778053c --- /dev/null +++ b/driver/src/main/java/org/neo4j/driver/internal/metrics/spi/DriverMetrics.java @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2002-2018 "Neo Technology," + * Network Engine for Objects in Lund AB [http://neotechnology.com] + * + * This file is part of Neo4j. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.neo4j.driver.internal.metrics.spi; + +import java.util.Map; + +public interface DriverMetrics +{ + // TODO Once this interface because public, find a better way to enable metrics + String DRIVER_METRICS_ENABLED_KEY = "driver.metrics.enabled"; + + Map connectionPoolMetrics(); + Map connectionMetrics(); + + public static boolean isDriverMetricsEnabled() + { + return Boolean.valueOf( System.getProperty( DRIVER_METRICS_ENABLED_KEY, "false" ) ); + } +} diff --git a/driver/src/main/java/org/neo4j/driver/internal/metrics/spi/Histogram.java b/driver/src/main/java/org/neo4j/driver/internal/metrics/spi/Histogram.java new file mode 100644 index 0000000000..221d88bc24 --- /dev/null +++ b/driver/src/main/java/org/neo4j/driver/internal/metrics/spi/Histogram.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2002-2018 "Neo Technology," + * Network Engine for Objects in Lund AB [http://neotechnology.com] + * + * This file is part of Neo4j. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.neo4j.driver.internal.metrics.spi; + +public interface Histogram +{ + long max(); + double mean(); + double stdDeviation(); + + long totalCount(); + long valueAtPercentile(double percentile); + + void reset(); +} diff --git a/driver/src/main/java/org/neo4j/driver/internal/spi/ConnectionPool.java b/driver/src/main/java/org/neo4j/driver/internal/spi/ConnectionPool.java index ca3de53f41..73c7f6d86b 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/spi/ConnectionPool.java +++ b/driver/src/main/java/org/neo4j/driver/internal/spi/ConnectionPool.java @@ -29,7 +29,11 @@ public interface ConnectionPool void retainAll( Set addressesToRetain ); - int activeConnections( BoltServerAddress address ); + int inUseConnections( BoltServerAddress address ); + + int idleConnections( BoltServerAddress address ); CompletionStage close(); + + boolean isOpen(); } diff --git a/driver/src/test/java/org/neo4j/driver/internal/DriverFactoryTest.java b/driver/src/test/java/org/neo4j/driver/internal/DriverFactoryTest.java index 5235dc0618..e5dc4de0f5 100644 --- a/driver/src/test/java/org/neo4j/driver/internal/DriverFactoryTest.java +++ b/driver/src/test/java/org/neo4j/driver/internal/DriverFactoryTest.java @@ -33,6 +33,8 @@ import org.neo4j.driver.internal.async.BootstrapFactory; import org.neo4j.driver.internal.cluster.RoutingSettings; import org.neo4j.driver.internal.cluster.loadbalancing.LoadBalancer; +import org.neo4j.driver.internal.metrics.DriverMetricsHandler; +import org.neo4j.driver.internal.metrics.InternalDriverMetrics; import org.neo4j.driver.internal.retry.RetryLogic; import org.neo4j.driver.internal.retry.RetrySettings; import org.neo4j.driver.internal.security.SecurityPlan; @@ -47,6 +49,7 @@ import static java.util.concurrent.CompletableFuture.completedFuture; import static org.hamcrest.Matchers.instanceOf; +import static org.hamcrest.Matchers.is; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; @@ -56,6 +59,7 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import static org.neo4j.driver.internal.metrics.InternalAbstractDriverMetrics.DEV_NULL_METRICS; import static org.neo4j.driver.internal.util.Futures.completedWithNull; import static org.neo4j.driver.internal.util.Futures.failedFuture; import static org.neo4j.driver.v1.AccessMode.READ; @@ -175,6 +179,29 @@ public void shouldThrowWhenUnableToVerifyConnectivity() } } + @Test + public void shouldNotCreateDriverMetrics() throws Throwable + { + // Given + Config config = mock( Config.class ); + // When + DriverMetricsHandler handler = DriverFactory.createDriverMetrics( config ); + // Then + assertThat( handler, is( DEV_NULL_METRICS ) ); + } + + @Test + public void shouldCreateDriverMetricsIfMonitoringEnabled() throws Throwable + { + // Given + System.setProperty( "driver.metrics.enabled", "True" ); + Config config = mock( Config.class ); + // When + DriverMetricsHandler handler = DriverFactory.createDriverMetrics( config ); + // Then + assertThat( handler instanceof InternalDriverMetrics, is( true ) ); + } + private Driver createDriver( DriverFactory driverFactory ) { return createDriver( driverFactory, defaultConfig() ); @@ -220,8 +247,7 @@ protected InternalDriver createRoutingDriver( BoltServerAddress address, Connect } @Override - protected ConnectionPool createConnectionPool( AuthToken authToken, SecurityPlan securityPlan, - Bootstrap bootstrap, Config config ) + protected ConnectionPool createConnectionPool( AuthToken authToken, SecurityPlan securityPlan, Bootstrap bootstrap, DriverMetricsHandler metrics, Config config ) { return connectionPool; } @@ -256,8 +282,7 @@ protected SessionFactory createSessionFactory( ConnectionProvider connectionProv } @Override - protected ConnectionPool createConnectionPool( AuthToken authToken, SecurityPlan securityPlan, - Bootstrap bootstrap, Config config ) + protected ConnectionPool createConnectionPool( AuthToken authToken, SecurityPlan securityPlan, Bootstrap bootstrap, DriverMetricsHandler metrics, Config config ) { return connectionPoolMock(); } @@ -279,8 +304,7 @@ protected Bootstrap createBootstrap() } @Override - protected ConnectionPool createConnectionPool( AuthToken authToken, SecurityPlan securityPlan, - Bootstrap bootstrap, Config config ) + protected ConnectionPool createConnectionPool( AuthToken authToken, SecurityPlan securityPlan, Bootstrap bootstrap, DriverMetricsHandler metrics, Config config ) { return connectionPoolMock(); } diff --git a/driver/src/test/java/org/neo4j/driver/internal/async/pool/ActiveChannelTrackerTest.java b/driver/src/test/java/org/neo4j/driver/internal/async/pool/ActiveChannelTrackerTest.java deleted file mode 100644 index 9c2c747c95..0000000000 --- a/driver/src/test/java/org/neo4j/driver/internal/async/pool/ActiveChannelTrackerTest.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (c) 2002-2018 "Neo Technology," - * Network Engine for Objects in Lund AB [http://neotechnology.com] - * - * This file is part of Neo4j. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.async.pool; - -import io.netty.channel.Channel; -import io.netty.channel.embedded.EmbeddedChannel; -import org.junit.Test; - -import org.neo4j.driver.internal.BoltServerAddress; - -import static org.hamcrest.Matchers.instanceOf; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertThat; -import static org.junit.Assert.fail; -import static org.neo4j.driver.internal.async.ChannelAttributes.setServerAddress; -import static org.neo4j.driver.internal.logging.DevNullLogging.DEV_NULL_LOGGING; - -public class ActiveChannelTrackerTest -{ - private final BoltServerAddress address = BoltServerAddress.LOCAL_DEFAULT; - private final ActiveChannelTracker tracker = new ActiveChannelTracker( DEV_NULL_LOGGING ); - - @Test - public void shouldIncrementCountWhenChannelCreated() - { - Channel channel = newChannel(); - assertEquals( 0, tracker.activeChannelCount( address ) ); - - tracker.channelCreated( channel ); - assertEquals( 1, tracker.activeChannelCount( address ) ); - } - - @Test - public void shouldIncrementCountForAddress() - { - Channel channel1 = newChannel(); - Channel channel2 = newChannel(); - Channel channel3 = newChannel(); - - assertEquals( 0, tracker.activeChannelCount( address ) ); - tracker.channelAcquired( channel1 ); - assertEquals( 1, tracker.activeChannelCount( address ) ); - tracker.channelAcquired( channel2 ); - assertEquals( 2, tracker.activeChannelCount( address ) ); - tracker.channelAcquired( channel3 ); - assertEquals( 3, tracker.activeChannelCount( address ) ); - } - - @Test - public void shouldDecrementCountForAddress() - { - Channel channel1 = newChannel(); - Channel channel2 = newChannel(); - Channel channel3 = newChannel(); - - tracker.channelAcquired( channel1 ); - tracker.channelAcquired( channel2 ); - tracker.channelAcquired( channel3 ); - assertEquals( 3, tracker.activeChannelCount( address ) ); - - tracker.channelReleased( channel1 ); - assertEquals( 2, tracker.activeChannelCount( address ) ); - tracker.channelReleased( channel2 ); - assertEquals( 1, tracker.activeChannelCount( address ) ); - tracker.channelReleased( channel3 ); - assertEquals( 0, tracker.activeChannelCount( address ) ); - } - - @Test - public void shouldThrowWhenDecrementingForUnknownAddress() - { - Channel channel = newChannel(); - - try - { - tracker.channelReleased( channel ); - fail( "Exception expected" ); - } - catch ( Exception e ) - { - assertThat( e, instanceOf( IllegalStateException.class ) ); - } - } - - @Test - public void shouldReturnZeroActiveCountForUnknownAddress() - { - assertEquals( 0, tracker.activeChannelCount( address ) ); - } - - private Channel newChannel() - { - EmbeddedChannel channel = new EmbeddedChannel(); - setServerAddress( channel, address ); - return channel; - } -} diff --git a/driver/src/test/java/org/neo4j/driver/internal/async/pool/ConnectionPoolImplTest.java b/driver/src/test/java/org/neo4j/driver/internal/async/pool/ConnectionPoolImplTest.java index f6a4c496e5..bf218db6fe 100644 --- a/driver/src/test/java/org/neo4j/driver/internal/async/pool/ConnectionPoolImplTest.java +++ b/driver/src/test/java/org/neo4j/driver/internal/async/pool/ConnectionPoolImplTest.java @@ -59,6 +59,7 @@ import static org.mockito.Mockito.when; import static org.neo4j.driver.internal.BoltServerAddress.LOCAL_DEFAULT; import static org.neo4j.driver.internal.logging.DevNullLogging.DEV_NULL_LOGGING; +import static org.neo4j.driver.internal.metrics.InternalAbstractDriverMetrics.DEV_NULL_METRICS; import static org.neo4j.driver.v1.util.TestUtil.await; public class ConnectionPoolImplTest @@ -146,19 +147,19 @@ public void shouldNotCloseWhenClosed() @Test public void shouldDoNothingWhenRetainOnEmptyPool() { - ActiveChannelTracker activeChannelTracker = mock( ActiveChannelTracker.class ); - TestConnectionPool pool = new TestConnectionPool( activeChannelTracker ); + NettyChannelTracker nettyChannelTracker = mock( NettyChannelTracker.class ); + TestConnectionPool pool = new TestConnectionPool( nettyChannelTracker ); pool.retainAll( singleton( LOCAL_DEFAULT ) ); - verifyZeroInteractions( activeChannelTracker ); + verifyZeroInteractions( nettyChannelTracker ); } @Test public void shouldRetainSpecifiedAddresses() { - ActiveChannelTracker activeChannelTracker = mock( ActiveChannelTracker.class ); - TestConnectionPool pool = new TestConnectionPool( activeChannelTracker ); + NettyChannelTracker nettyChannelTracker = mock( NettyChannelTracker.class ); + TestConnectionPool pool = new TestConnectionPool( nettyChannelTracker ); pool.acquire( ADDRESS_1 ); pool.acquire( ADDRESS_2 ); @@ -174,16 +175,16 @@ public void shouldRetainSpecifiedAddresses() @Test public void shouldClosePoolsWhenRetaining() { - ActiveChannelTracker activeChannelTracker = mock( ActiveChannelTracker.class ); - TestConnectionPool pool = new TestConnectionPool( activeChannelTracker ); + NettyChannelTracker nettyChannelTracker = mock( NettyChannelTracker.class ); + TestConnectionPool pool = new TestConnectionPool( nettyChannelTracker ); pool.acquire( ADDRESS_1 ); pool.acquire( ADDRESS_2 ); pool.acquire( ADDRESS_3 ); - when( activeChannelTracker.activeChannelCount( ADDRESS_1 ) ).thenReturn( 2 ); - when( activeChannelTracker.activeChannelCount( ADDRESS_2 ) ).thenReturn( 0 ); - when( activeChannelTracker.activeChannelCount( ADDRESS_3 ) ).thenReturn( 3 ); + when( nettyChannelTracker.inUseChannelCount( ADDRESS_1 ) ).thenReturn( 2 ); + when( nettyChannelTracker.inUseChannelCount( ADDRESS_2 ) ).thenReturn( 0 ); + when( nettyChannelTracker.inUseChannelCount( ADDRESS_3 ) ).thenReturn( 3 ); pool.retainAll( new HashSet<>( asList( ADDRESS_1, ADDRESS_3 ) ) ); verify( pool.getPool( ADDRESS_1 ), never() ).close(); @@ -194,16 +195,16 @@ public void shouldClosePoolsWhenRetaining() @Test public void shouldNotClosePoolsWithActiveConnectionsWhenRetaining() { - ActiveChannelTracker activeChannelTracker = mock( ActiveChannelTracker.class ); - TestConnectionPool pool = new TestConnectionPool( activeChannelTracker ); + NettyChannelTracker nettyChannelTracker = mock( NettyChannelTracker.class ); + TestConnectionPool pool = new TestConnectionPool( nettyChannelTracker ); pool.acquire( ADDRESS_1 ); pool.acquire( ADDRESS_2 ); pool.acquire( ADDRESS_3 ); - when( activeChannelTracker.activeChannelCount( ADDRESS_1 ) ).thenReturn( 1 ); - when( activeChannelTracker.activeChannelCount( ADDRESS_2 ) ).thenReturn( 42 ); - when( activeChannelTracker.activeChannelCount( ADDRESS_3 ) ).thenReturn( 0 ); + when( nettyChannelTracker.inUseChannelCount( ADDRESS_1 ) ).thenReturn( 1 ); + when( nettyChannelTracker.inUseChannelCount( ADDRESS_2 ) ).thenReturn( 42 ); + when( nettyChannelTracker.inUseChannelCount( ADDRESS_3 ) ).thenReturn( 0 ); pool.retainAll( singleton( ADDRESS_2 ) ); verify( pool.getPool( ADDRESS_1 ), never() ).close(); @@ -219,7 +220,7 @@ private ConnectionPoolImpl newPool() throws Exception DEV_NULL_LOGGING, clock ); PoolSettings poolSettings = newSettings(); Bootstrap bootstrap = BootstrapFactory.newBootstrap( 1 ); - return new ConnectionPoolImpl( connector, bootstrap, poolSettings, DEV_NULL_LOGGING, clock ); + return new ConnectionPoolImpl( connector, bootstrap, poolSettings, DEV_NULL_METRICS, DEV_NULL_LOGGING, clock ); } private static PoolSettings newSettings() @@ -231,10 +232,10 @@ private static class TestConnectionPool extends ConnectionPoolImpl { final Map channelPoolsByAddress = new HashMap<>(); - TestConnectionPool( ActiveChannelTracker activeChannelTracker ) + TestConnectionPool( NettyChannelTracker nettyChannelTracker ) { - super( mock( ChannelConnector.class ), mock( Bootstrap.class ), activeChannelTracker, newSettings(), - DEV_NULL_LOGGING, new FakeClock() ); + super( mock( ChannelConnector.class ), mock( Bootstrap.class ), nettyChannelTracker, newSettings(), + DEV_NULL_METRICS, DEV_NULL_LOGGING, new FakeClock() ); } ChannelPool getPool( BoltServerAddress address ) diff --git a/driver/src/test/java/org/neo4j/driver/internal/async/pool/NettyChannelPoolTest.java b/driver/src/test/java/org/neo4j/driver/internal/async/pool/NettyChannelPoolTest.java index dd640e49d2..4d6eea30ae 100644 --- a/driver/src/test/java/org/neo4j/driver/internal/async/pool/NettyChannelPoolTest.java +++ b/driver/src/test/java/org/neo4j/driver/internal/async/pool/NettyChannelPoolTest.java @@ -21,7 +21,6 @@ import io.netty.bootstrap.Bootstrap; import io.netty.channel.Channel; import io.netty.channel.pool.ChannelHealthChecker; -import io.netty.channel.pool.ChannelPoolHandler; import io.netty.util.concurrent.Future; import org.junit.After; import org.junit.Before; @@ -58,6 +57,7 @@ import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.neo4j.driver.internal.logging.DevNullLogging.DEV_NULL_LOGGING; +import static org.neo4j.driver.internal.metrics.InternalAbstractDriverMetrics.DEV_NULL_METRICS; import static org.neo4j.driver.v1.Values.value; public class NettyChannelPoolTest @@ -66,14 +66,14 @@ public class NettyChannelPoolTest public final TestNeo4j neo4j = new TestNeo4j(); private Bootstrap bootstrap; - private ChannelPoolHandler poolHandler; + private NettyChannelTracker poolHandler; private NettyChannelPool pool; @Before public void setUp() { bootstrap = BootstrapFactory.newBootstrap( 1 ); - poolHandler = mock( ChannelPoolHandler.class ); + poolHandler = mock( NettyChannelTracker.class ); } @After @@ -183,24 +183,24 @@ public void shouldLimitNumberOfConcurrentConnections() throws Exception @Test public void shouldTrackActiveChannels() throws Exception { - ActiveChannelTracker activeChannelTracker = new ActiveChannelTracker( DEV_NULL_LOGGING ); + NettyChannelTracker tracker = new NettyChannelTracker( DEV_NULL_METRICS, DEV_NULL_LOGGING ); - poolHandler = activeChannelTracker; + poolHandler = tracker; pool = newPool( neo4j.authToken() ); Channel channel1 = acquire( pool ); Channel channel2 = acquire( pool ); Channel channel3 = acquire( pool ); - assertEquals( 3, activeChannelTracker.activeChannelCount( neo4j.address() ) ); + assertEquals( 3, tracker.inUseChannelCount( neo4j.address() ) ); release( channel1 ); release( channel2 ); release( channel3 ); - assertEquals( 0, activeChannelTracker.activeChannelCount( neo4j.address() ) ); + assertEquals( 0, tracker.inUseChannelCount( neo4j.address() ) ); assertNotNull( acquire( pool ) ); assertNotNull( acquire( pool ) ); - assertEquals( 2, activeChannelTracker.activeChannelCount( neo4j.address() ) ); + assertEquals( 2, tracker.inUseChannelCount( neo4j.address() ) ); } private NettyChannelPool newPool( AuthToken authToken ) diff --git a/driver/src/test/java/org/neo4j/driver/internal/async/pool/NettyChannelTrackerTest.java b/driver/src/test/java/org/neo4j/driver/internal/async/pool/NettyChannelTrackerTest.java new file mode 100644 index 0000000000..1ffd077e4d --- /dev/null +++ b/driver/src/test/java/org/neo4j/driver/internal/async/pool/NettyChannelTrackerTest.java @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2002-2018 "Neo Technology," + * Network Engine for Objects in Lund AB [http://neotechnology.com] + * + * This file is part of Neo4j. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.neo4j.driver.internal.async.pool; + +import io.netty.channel.Channel; +import io.netty.channel.embedded.EmbeddedChannel; +import org.junit.Test; + +import org.neo4j.driver.internal.BoltServerAddress; + +import static org.hamcrest.Matchers.instanceOf; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.fail; +import static org.neo4j.driver.internal.async.ChannelAttributes.setServerAddress; +import static org.neo4j.driver.internal.logging.DevNullLogging.DEV_NULL_LOGGING; +import static org.neo4j.driver.internal.metrics.InternalAbstractDriverMetrics.DEV_NULL_METRICS; + +public class NettyChannelTrackerTest +{ + private final BoltServerAddress address = BoltServerAddress.LOCAL_DEFAULT; + private final NettyChannelTracker tracker = new NettyChannelTracker( DEV_NULL_METRICS, DEV_NULL_LOGGING ); + + @Test + public void shouldIncrementInUseCountWhenChannelCreated() + { + Channel channel = newChannel(); + assertEquals( 0, tracker.inUseChannelCount( address ) ); + assertEquals( 0, tracker.idleChannelCount( address ) ); + + tracker.channelCreated( channel ); + assertEquals( 1, tracker.inUseChannelCount( address ) ); + assertEquals( 0, tracker.idleChannelCount( address ) ); + } + + @Test + public void shouldIncrementInUseCountWhenChannelAcquired() + { + Channel channel = newChannel(); + assertEquals( 0, tracker.inUseChannelCount( address ) ); + assertEquals( 0, tracker.idleChannelCount( address ) ); + + tracker.channelCreated( channel ); + assertEquals( 1, tracker.inUseChannelCount( address ) ); + assertEquals( 0, tracker.idleChannelCount( address ) ); + + tracker.channelReleased( channel ); + assertEquals( 0, tracker.inUseChannelCount( address ) ); + assertEquals( 1, tracker.idleChannelCount( address ) ); + + tracker.channelAcquired( channel ); + assertEquals( 1, tracker.inUseChannelCount( address ) ); + assertEquals( 0, tracker.idleChannelCount( address ) ); + } + + @Test + public void shouldIncrementInuseCountForAddress() + { + Channel channel1 = newChannel(); + Channel channel2 = newChannel(); + Channel channel3 = newChannel(); + + assertEquals( 0, tracker.inUseChannelCount( address ) ); + tracker.channelCreated( channel1 ); + assertEquals( 1, tracker.inUseChannelCount( address ) ); + tracker.channelCreated( channel2 ); + assertEquals( 2, tracker.inUseChannelCount( address ) ); + tracker.channelCreated( channel3 ); + assertEquals( 3, tracker.inUseChannelCount( address ) ); + assertEquals( 0, tracker.idleChannelCount( address ) ); + } + + @Test + public void shouldDecrementCountForAddress() + { + Channel channel1 = newChannel(); + Channel channel2 = newChannel(); + Channel channel3 = newChannel(); + + tracker.channelCreated( channel1 ); + tracker.channelCreated( channel2 ); + tracker.channelCreated( channel3 ); + assertEquals( 3, tracker.inUseChannelCount( address ) ); + assertEquals( 0, tracker.idleChannelCount( address ) ); + + tracker.channelReleased( channel1 ); + assertEquals( 2, tracker.inUseChannelCount( address ) ); + assertEquals( 1, tracker.idleChannelCount( address ) ); + tracker.channelReleased( channel2 ); + assertEquals( 1, tracker.inUseChannelCount( address ) ); + assertEquals( 2, tracker.idleChannelCount( address ) ); + tracker.channelReleased( channel3 ); + assertEquals( 0, tracker.inUseChannelCount( address ) ); + assertEquals( 3, tracker.idleChannelCount( address ) ); + } + + @Test + public void shouldThrowWhenDecrementingForUnknownAddress() + { + Channel channel = newChannel(); + + try + { + tracker.channelReleased( channel ); + fail( "Exception expected" ); + } + catch ( Exception e ) + { + assertThat( e, instanceOf( IllegalStateException.class ) ); + } + } + + @Test + public void shouldReturnZeroActiveCountForUnknownAddress() + { + assertEquals( 0, tracker.inUseChannelCount( address ) ); + } + + private Channel newChannel() + { + EmbeddedChannel channel = new EmbeddedChannel(); + setServerAddress( channel, address ); + return channel; + } +} diff --git a/driver/src/test/java/org/neo4j/driver/internal/cluster/loadbalancing/LeastConnectedLoadBalancingStrategyTest.java b/driver/src/test/java/org/neo4j/driver/internal/cluster/loadbalancing/LeastConnectedLoadBalancingStrategyTest.java index 6b1f39a8bb..aba9e7b478 100644 --- a/driver/src/test/java/org/neo4j/driver/internal/cluster/loadbalancing/LeastConnectedLoadBalancingStrategyTest.java +++ b/driver/src/test/java/org/neo4j/driver/internal/cluster/loadbalancing/LeastConnectedLoadBalancingStrategyTest.java @@ -85,7 +85,7 @@ public void shouldHandleSingleWriterWithoutActiveConnections() public void shouldHandleSingleReaderWithActiveConnections() { BoltServerAddress address = new BoltServerAddress( "reader", 9999 ); - when( connectionPool.activeConnections( address ) ).thenReturn( 42 ); + when( connectionPool.inUseConnections( address ) ).thenReturn( 42 ); assertEquals( address, strategy.selectReader( new BoltServerAddress[]{address} ) ); } @@ -94,7 +94,7 @@ public void shouldHandleSingleReaderWithActiveConnections() public void shouldHandleSingleWriterWithActiveConnections() { BoltServerAddress address = new BoltServerAddress( "writer", 9999 ); - when( connectionPool.activeConnections( address ) ).thenReturn( 24 ); + when( connectionPool.inUseConnections( address ) ).thenReturn( 24 ); assertEquals( address, strategy.selectWriter( new BoltServerAddress[]{address} ) ); } @@ -106,9 +106,9 @@ public void shouldHandleMultipleReadersWithActiveConnections() BoltServerAddress address2 = new BoltServerAddress( "reader", 2 ); BoltServerAddress address3 = new BoltServerAddress( "reader", 3 ); - when( connectionPool.activeConnections( address1 ) ).thenReturn( 3 ); - when( connectionPool.activeConnections( address2 ) ).thenReturn( 4 ); - when( connectionPool.activeConnections( address3 ) ).thenReturn( 1 ); + when( connectionPool.inUseConnections( address1 ) ).thenReturn( 3 ); + when( connectionPool.inUseConnections( address2 ) ).thenReturn( 4 ); + when( connectionPool.inUseConnections( address3 ) ).thenReturn( 1 ); assertEquals( address3, strategy.selectReader( new BoltServerAddress[]{address1, address2, address3} ) ); } @@ -121,10 +121,10 @@ public void shouldHandleMultipleWritersWithActiveConnections() BoltServerAddress address3 = new BoltServerAddress( "writer", 3 ); BoltServerAddress address4 = new BoltServerAddress( "writer", 4 ); - when( connectionPool.activeConnections( address1 ) ).thenReturn( 5 ); - when( connectionPool.activeConnections( address2 ) ).thenReturn( 6 ); - when( connectionPool.activeConnections( address3 ) ).thenReturn( 0 ); - when( connectionPool.activeConnections( address4 ) ).thenReturn( 1 ); + when( connectionPool.inUseConnections( address1 ) ).thenReturn( 5 ); + when( connectionPool.inUseConnections( address2 ) ).thenReturn( 6 ); + when( connectionPool.inUseConnections( address3 ) ).thenReturn( 0 ); + when( connectionPool.inUseConnections( address4 ) ).thenReturn( 1 ); assertEquals( address3, strategy.selectWriter( new BoltServerAddress[]{address1, address2, address3, address4} ) ); @@ -182,7 +182,7 @@ public void shouldTraceLogSelectedAddress() Logger logger = mock( Logger.class ); when( logging.getLog( anyString() ) ).thenReturn( logger ); - when( connectionPool.activeConnections( any( BoltServerAddress.class ) ) ).thenReturn( 42 ); + when( connectionPool.inUseConnections( any( BoltServerAddress.class ) ) ).thenReturn( 42 ); LoadBalancingStrategy strategy = new LeastConnectedLoadBalancingStrategy( connectionPool, logging ); diff --git a/driver/src/test/java/org/neo4j/driver/internal/cluster/loadbalancing/LoadBalancerTest.java b/driver/src/test/java/org/neo4j/driver/internal/cluster/loadbalancing/LoadBalancerTest.java index d1c85ff462..47fc02b1b6 100644 --- a/driver/src/test/java/org/neo4j/driver/internal/cluster/loadbalancing/LoadBalancerTest.java +++ b/driver/src/test/java/org/neo4j/driver/internal/cluster/loadbalancing/LoadBalancerTest.java @@ -171,9 +171,9 @@ public void shouldSelectLeastConnectedAddress() { ConnectionPool connectionPool = newConnectionPoolMock(); - when( connectionPool.activeConnections( A ) ).thenReturn( 0 ); - when( connectionPool.activeConnections( B ) ).thenReturn( 20 ); - when( connectionPool.activeConnections( C ) ).thenReturn( 0 ); + when( connectionPool.inUseConnections( A ) ).thenReturn( 0 ); + when( connectionPool.inUseConnections( B ) ).thenReturn( 20 ); + when( connectionPool.inUseConnections( C ) ).thenReturn( 0 ); RoutingTable routingTable = mock( RoutingTable.class ); AddressSet readerAddresses = mock( AddressSet.class ); diff --git a/driver/src/test/java/org/neo4j/driver/internal/util/ChannelTrackingDriverFactory.java b/driver/src/test/java/org/neo4j/driver/internal/util/ChannelTrackingDriverFactory.java index cacd88711b..a39036134e 100644 --- a/driver/src/test/java/org/neo4j/driver/internal/util/ChannelTrackingDriverFactory.java +++ b/driver/src/test/java/org/neo4j/driver/internal/util/ChannelTrackingDriverFactory.java @@ -29,6 +29,7 @@ import org.neo4j.driver.internal.ConnectionSettings; import org.neo4j.driver.internal.async.BootstrapFactory; import org.neo4j.driver.internal.async.ChannelConnector; +import org.neo4j.driver.internal.metrics.DriverMetricsHandler; import org.neo4j.driver.internal.security.SecurityPlan; import org.neo4j.driver.internal.spi.ConnectionPool; import org.neo4j.driver.v1.AuthToken; @@ -70,10 +71,10 @@ protected final ChannelConnector createConnector( ConnectionSettings settings, S } @Override - protected final ConnectionPool createConnectionPool( AuthToken authToken, SecurityPlan securityPlan, - Bootstrap bootstrap, Config config ) + protected final ConnectionPool createConnectionPool( AuthToken authToken, SecurityPlan securityPlan, Bootstrap bootstrap, DriverMetricsHandler metrics, + Config config ) { - pool = super.createConnectionPool( authToken, securityPlan, bootstrap, config ); + pool = super.createConnectionPool( authToken, securityPlan, bootstrap, metrics, config ); return pool; } @@ -102,6 +103,6 @@ public List pollChannels() public int activeChannels( BoltServerAddress address ) { - return pool == null ? 0 : pool.activeConnections( address ); + return pool == null ? 0 : pool.inUseConnections( address ); } } diff --git a/driver/src/test/java/org/neo4j/driver/internal/util/FailingConnectionDriverFactory.java b/driver/src/test/java/org/neo4j/driver/internal/util/FailingConnectionDriverFactory.java index cb7ec6cba2..90460969bd 100644 --- a/driver/src/test/java/org/neo4j/driver/internal/util/FailingConnectionDriverFactory.java +++ b/driver/src/test/java/org/neo4j/driver/internal/util/FailingConnectionDriverFactory.java @@ -27,6 +27,7 @@ import org.neo4j.driver.internal.BoltServerAddress; import org.neo4j.driver.internal.DriverFactory; +import org.neo4j.driver.internal.metrics.DriverMetricsHandler; import org.neo4j.driver.internal.security.SecurityPlan; import org.neo4j.driver.internal.spi.Connection; import org.neo4j.driver.internal.spi.ConnectionPool; @@ -40,10 +41,9 @@ public class FailingConnectionDriverFactory extends DriverFactory private final AtomicReference nextRunFailure = new AtomicReference<>(); @Override - protected ConnectionPool createConnectionPool( AuthToken authToken, SecurityPlan securityPlan, Bootstrap bootstrap, - Config config ) + protected ConnectionPool createConnectionPool( AuthToken authToken, SecurityPlan securityPlan, Bootstrap bootstrap, DriverMetricsHandler metrics, Config config ) { - ConnectionPool pool = super.createConnectionPool( authToken, securityPlan, bootstrap, config ); + ConnectionPool pool = super.createConnectionPool( authToken, securityPlan, bootstrap, metrics, config ); return new ConnectionPoolWithFailingConnections( pool, nextRunFailure ); } @@ -77,9 +77,15 @@ public void retainAll( Set addressesToRetain ) } @Override - public int activeConnections( BoltServerAddress address ) + public int inUseConnections( BoltServerAddress address ) { - return delegate.activeConnections( address ); + return delegate.inUseConnections( address ); + } + + @Override + public int idleConnections( BoltServerAddress address ) + { + return delegate.idleConnections( address ); } @Override @@ -87,6 +93,12 @@ public CompletionStage close() { return delegate.close(); } + + @Override + public boolean isOpen() + { + return delegate.isOpen(); + } } private static class FailingConnection implements Connection diff --git a/driver/src/test/java/org/neo4j/driver/v1/integration/ConnectionHandlingIT.java b/driver/src/test/java/org/neo4j/driver/v1/integration/ConnectionHandlingIT.java index 93ff0cc96d..af0e496fa6 100644 --- a/driver/src/test/java/org/neo4j/driver/v1/integration/ConnectionHandlingIT.java +++ b/driver/src/test/java/org/neo4j/driver/v1/integration/ConnectionHandlingIT.java @@ -36,6 +36,7 @@ import org.neo4j.driver.internal.async.pool.ConnectionPoolImpl; import org.neo4j.driver.internal.async.pool.PoolSettings; import org.neo4j.driver.internal.cluster.RoutingSettings; +import org.neo4j.driver.internal.metrics.DriverMetricsHandler; import org.neo4j.driver.internal.retry.RetrySettings; import org.neo4j.driver.internal.security.SecurityPlan; import org.neo4j.driver.internal.spi.Connection; @@ -64,6 +65,7 @@ import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; +import static org.neo4j.driver.internal.metrics.InternalAbstractDriverMetrics.DEV_NULL_METRICS; import static org.neo4j.driver.v1.Config.defaultConfig; import static org.neo4j.driver.v1.Values.parameters; import static org.neo4j.driver.v1.util.TestUtil.await; @@ -294,8 +296,7 @@ private static class DriverFactoryWithConnectionPool extends DriverFactory MemorizingConnectionPool connectionPool; @Override - protected ConnectionPool createConnectionPool( AuthToken authToken, SecurityPlan securityPlan, - Bootstrap bootstrap, Config config ) + protected ConnectionPool createConnectionPool( AuthToken authToken, SecurityPlan securityPlan, Bootstrap bootstrap, DriverMetricsHandler metrics, Config config ) { ConnectionSettings connectionSettings = new ConnectionSettings( authToken, 1000 ); PoolSettings poolSettings = new PoolSettings( config.maxConnectionPoolSize(), @@ -317,7 +318,7 @@ private static class MemorizingConnectionPool extends ConnectionPoolImpl MemorizingConnectionPool( ChannelConnector connector, Bootstrap bootstrap, PoolSettings settings, Logging logging, Clock clock ) { - super( connector, bootstrap, settings, logging, clock ); + super( connector, bootstrap, settings, DEV_NULL_METRICS, logging, clock ); } diff --git a/driver/src/test/java/org/neo4j/driver/v1/stress/AbstractStressTestBase.java b/driver/src/test/java/org/neo4j/driver/v1/stress/AbstractStressTestBase.java index cc2377c3aa..6661108f12 100644 --- a/driver/src/test/java/org/neo4j/driver/v1/stress/AbstractStressTestBase.java +++ b/driver/src/test/java/org/neo4j/driver/v1/stress/AbstractStressTestBase.java @@ -44,6 +44,7 @@ import java.util.function.Function; import java.util.logging.Level; +import org.neo4j.driver.internal.InternalDriver; import org.neo4j.driver.internal.logging.ConsoleLogging; import org.neo4j.driver.internal.logging.DevNullLogger; import org.neo4j.driver.internal.util.Futures; @@ -73,6 +74,7 @@ import static org.junit.Assert.assertNull; import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; +import static org.neo4j.driver.internal.metrics.spi.DriverMetrics.DRIVER_METRICS_ENABLED_KEY; public abstract class AbstractStressTestBase { @@ -87,11 +89,12 @@ public abstract class AbstractStressTestBase private LoggerNameTrackingLogging logging; private ExecutorService executor; - Driver driver; + InternalDriver driver; @Before public void setUp() { + System.setProperty( DRIVER_METRICS_ENABLED_KEY, "true" ); logging = new LoggerNameTrackingLogging(); Config config = Config.build() @@ -100,7 +103,8 @@ public void setUp() .withConnectionAcquisitionTimeout( 1, MINUTES ) .toConfig(); - driver = GraphDatabase.driver( databaseUri(), authToken(), config ); + driver = (InternalDriver) GraphDatabase.driver( databaseUri(), authToken(), config ); + System.setProperty( DRIVER_METRICS_ENABLED_KEY, "false" ); ThreadFactory threadFactory = new DaemonThreadFactory( getClass().getSimpleName() + "-worker-" ); executor = Executors.newCachedThreadPool( threadFactory ); @@ -109,10 +113,12 @@ public void setUp() @After public void tearDown() { + System.out.println( driver.driverMetrics() ); executor.shutdownNow(); if ( driver != null ) { driver.close(); + System.out.println( driver.driverMetrics() ); } } From 2c6aa9d834ecbf4fca3ec94478670c2628adcae3 Mon Sep 17 00:00:00 2001 From: Zhen Date: Wed, 14 Feb 2018 17:50:08 +0000 Subject: [PATCH 2/6] Added histogram support --- driver/pom.xml | 10 ++ .../internal/metrics/HistogramSanpshot.java | 75 +++++++++++ .../InternalConnectionPoolMetrics.java | 13 +- .../internal/metrics/InternalHistogram.java | 125 ++++++++++++++++++ pom.xml | 5 + 5 files changed, 221 insertions(+), 7 deletions(-) create mode 100644 driver/src/main/java/org/neo4j/driver/internal/metrics/HistogramSanpshot.java create mode 100644 driver/src/main/java/org/neo4j/driver/internal/metrics/InternalHistogram.java diff --git a/driver/pom.xml b/driver/pom.xml index 6dd4eed4ea..f155d59b74 100644 --- a/driver/pom.xml +++ b/driver/pom.xml @@ -71,6 +71,16 @@ com.fasterxml.jackson.core jackson-databind + + org.hdrhistogram + HdrHistogram + 2.1.2 + + + org.hdrhistogram + HdrHistogram + 2.1.2 + diff --git a/driver/src/main/java/org/neo4j/driver/internal/metrics/HistogramSanpshot.java b/driver/src/main/java/org/neo4j/driver/internal/metrics/HistogramSanpshot.java new file mode 100644 index 0000000000..7e3ef605ed --- /dev/null +++ b/driver/src/main/java/org/neo4j/driver/internal/metrics/HistogramSanpshot.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2002-2018 "Neo Technology," + * Network Engine for Objects in Lund AB [http://neotechnology.com] + * + * This file is part of Neo4j. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.neo4j.driver.internal.metrics; + +import org.neo4j.driver.internal.metrics.spi.Histogram; + +public class HistogramSanpshot implements Histogram +{ + private Histogram copy; + private Histogram origin; + + public HistogramSanpshot( Histogram copy, Histogram origin ) + { + this.copy = copy; + this.origin = origin; + } + + @Override + public long max() + { + return copy.max(); + } + + @Override + public double mean() + { + return copy.mean(); + } + + @Override + public double stdDeviation() + { + return copy.stdDeviation(); + } + + @Override + public long totalCount() + { + return copy.totalCount(); + } + + @Override + public long valueAtPercentile( double percentile ) + { + return copy.valueAtPercentile( percentile ); + } + + @Override + public void reset() + { + origin.reset(); + } + + @Override + public String toString() + { + return copy.toString(); + } +} diff --git a/driver/src/main/java/org/neo4j/driver/internal/metrics/InternalConnectionPoolMetrics.java b/driver/src/main/java/org/neo4j/driver/internal/metrics/InternalConnectionPoolMetrics.java index 94f609c210..bb440b412e 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/metrics/InternalConnectionPoolMetrics.java +++ b/driver/src/main/java/org/neo4j/driver/internal/metrics/InternalConnectionPoolMetrics.java @@ -40,14 +40,13 @@ public class InternalConnectionPoolMetrics implements ConnectionPoolMetrics, Con private AtomicInteger toCreate = new AtomicInteger(); private AtomicLong failedToCreate = new AtomicLong(); - // TODO - private Histogram histogram; + private InternalHistogram histogram; public InternalConnectionPoolMetrics(BoltServerAddress address, ConnectionPool pool, long connAcquisitionTimeoutMs) { this.address = address; this.pool = pool; - this.histogram = null; + this.histogram = new InternalHistogram( connAcquisitionTimeoutMs ); } @Override @@ -86,7 +85,7 @@ public void beforeAcquire( ListenerEvent listenerEvent ) public void afterAcquire( ListenerEvent listenerEvent ) { long elapsed = listenerEvent.elapsed(); - // TODO register in histogram + histogram.recordValue( elapsed ); } @Override @@ -147,13 +146,13 @@ public long closed() @Override public Histogram acquisitionTimeHistogram() { - return null; + return this.histogram.snapshot(); } @Override public String toString() { - return format( "[created=%s, closed=%s, toCreate=%s, failedToCreate=%s inUse=%s, idle=%s, poolStatus=%s]", - created(), closed(), toCreate(), failedToCreate(), inUse(), idle(), poolStatus() ); + return format( "[created=%s, closed=%s, toCreate=%s, failedToCreate=%s inUse=%s, idle=%s, poolStatus=%s, acquisitionTimeHistogram=%n%s]", + created(), closed(), toCreate(), failedToCreate(), inUse(), idle(), poolStatus(), acquisitionTimeHistogram() ); } } diff --git a/driver/src/main/java/org/neo4j/driver/internal/metrics/InternalHistogram.java b/driver/src/main/java/org/neo4j/driver/internal/metrics/InternalHistogram.java new file mode 100644 index 0000000000..a9e5c7c0d1 --- /dev/null +++ b/driver/src/main/java/org/neo4j/driver/internal/metrics/InternalHistogram.java @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2002-2018 "Neo Technology," + * Network Engine for Objects in Lund AB [http://neotechnology.com] + * + * This file is part of Neo4j. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.neo4j.driver.internal.metrics; + +import org.HdrHistogram.AbstractHistogram; +import org.HdrHistogram.ConcurrentHistogram; + +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; +import java.time.Duration; + +import org.neo4j.driver.internal.metrics.spi.Histogram; + +public class InternalHistogram implements Histogram +{ + private static final long DEFAULT_HIGHEST_TRACKABLE_MS = Duration.ofMinutes( 10 ).toMillis(); + + private final AbstractHistogram delegate; + + public InternalHistogram() + { + this( DEFAULT_HIGHEST_TRACKABLE_MS ); + } + + public InternalHistogram( long highestTrackableValue ) + { + this.delegate = createHdrHistogram( highestTrackableValue ); + } + + public InternalHistogram( AbstractHistogram histogram ) + { + this.delegate = histogram; + } + + public void recordValue( long value ) + { + long newValue = truncateValue( value, delegate ); + this.delegate.recordValue( newValue ); + } + + @Override + public long max() + { + return delegate.getMaxValue(); + } + + @Override + public double mean() + { + return delegate.getMean(); + } + + @Override + public double stdDeviation() + { + return delegate.getStdDeviation(); + } + + @Override + public long totalCount() + { + return delegate.getTotalCount(); + } + + @Override + public long valueAtPercentile( double percentile ) + { + return delegate.getValueAtPercentile( percentile ); + } + + @Override + public void reset() + { + delegate.reset(); + } + + public static ConcurrentHistogram createHdrHistogram( long highestTrackableValue ) + { + return new ConcurrentHistogram( highestTrackableValue, 3 ); + } + + private static long truncateValue( long value, AbstractHistogram histogram ) + { + if ( value > histogram.getHighestTrackableValue() ) + { + return histogram.getHighestTrackableValue(); + } + else + { + return value; + } + } + + public Histogram snapshot() + { + return new HistogramSanpshot( new InternalHistogram( this.delegate.copy() ), this ); + } + + @Override + public String toString() + { + ByteArrayOutputStream stream = new ByteArrayOutputStream(); + PrintStream writer = new PrintStream( stream ); + delegate.outputPercentileDistribution( writer, 1.0 ); + String content = new String( stream.toByteArray() ); + writer.close(); + return content; + } +} diff --git a/pom.xml b/pom.xml index ad103e574f..79106f645b 100644 --- a/pom.xml +++ b/pom.xml @@ -56,6 +56,11 @@ netty-handler 4.1.16.Final + + org.hdrhistogram + hdrHistogram + 2.1.10 + From 0b33ab4c953c0b5b8354a8c2195a2d666b52e60d Mon Sep 17 00:00:00 2001 From: Zhen Date: Thu, 15 Feb 2018 17:28:45 +0000 Subject: [PATCH 3/6] Finished adding histogram and finished connection pool metrics --- .../neo4j/driver/internal/DriverFactory.java | 4 +- .../async/pool/ConnectionPoolImpl.java | 14 ++- .../async/pool/NettyChannelTracker.java | 6 +- ...andler.java => DriverMetricsListener.java} | 4 +- ...amSanpshot.java => HistogramSnapshot.java} | 10 ++- .../InternalAbstractDriverMetrics.java | 8 +- .../InternalConnectionPoolMetrics.java | 2 +- .../metrics/InternalDriverMetrics.java | 6 ++ .../internal/metrics/InternalHistogram.java | 18 +++- ...t.java => NanoTimeBasedListenerEvent.java} | 8 +- .../internal/metrics/spi/Histogram.java | 1 + .../driver/internal/DriverFactoryTest.java | 12 +-- .../metrics/InternalHistogramTest.java | 88 +++++++++++++++++++ .../util/ChannelTrackingDriverFactory.java | 4 +- .../util/FailingConnectionDriverFactory.java | 4 +- .../v1/integration/ConnectionHandlingIT.java | 4 +- 16 files changed, 157 insertions(+), 36 deletions(-) rename driver/src/main/java/org/neo4j/driver/internal/metrics/{DriverMetricsHandler.java => DriverMetricsListener.java} (94%) rename driver/src/main/java/org/neo4j/driver/internal/metrics/{HistogramSanpshot.java => HistogramSnapshot.java} (89%) rename driver/src/main/java/org/neo4j/driver/internal/metrics/{SimpleTimerListenerEvent.java => NanoTimeBasedListenerEvent.java} (80%) create mode 100644 driver/src/test/java/org/neo4j/driver/internal/metrics/InternalHistogramTest.java diff --git a/driver/src/main/java/org/neo4j/driver/internal/DriverFactory.java b/driver/src/main/java/org/neo4j/driver/internal/DriverFactory.java index d2b54e8eda..035c6505b2 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/DriverFactory.java +++ b/driver/src/main/java/org/neo4j/driver/internal/DriverFactory.java @@ -38,7 +38,7 @@ import org.neo4j.driver.internal.cluster.loadbalancing.LoadBalancingStrategy; import org.neo4j.driver.internal.cluster.loadbalancing.RoundRobinLoadBalancingStrategy; import org.neo4j.driver.internal.logging.NettyLogging; -import org.neo4j.driver.internal.metrics.DriverMetricsHandler; +import org.neo4j.driver.internal.metrics.DriverMetricsListener; import org.neo4j.driver.internal.metrics.InternalAbstractDriverMetrics; import org.neo4j.driver.internal.metrics.InternalDriverMetrics; import org.neo4j.driver.internal.retry.ExponentialBackoffRetryLogic; @@ -94,7 +94,7 @@ public final Driver newInstance( URI uri, AuthToken authToken, RoutingSettings r return driver; } - protected ConnectionPool createConnectionPool( AuthToken authToken, SecurityPlan securityPlan, Bootstrap bootstrap, DriverMetricsHandler metrics, Config config ) + protected ConnectionPool createConnectionPool( AuthToken authToken, SecurityPlan securityPlan, Bootstrap bootstrap, DriverMetricsListener metrics, Config config ) { Clock clock = createClock(); ConnectionSettings settings = new ConnectionSettings( authToken, config.connectionTimeoutMillis() ); diff --git a/driver/src/main/java/org/neo4j/driver/internal/async/pool/ConnectionPoolImpl.java b/driver/src/main/java/org/neo4j/driver/internal/async/pool/ConnectionPoolImpl.java index 8b49376388..9e2464cacc 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/async/pool/ConnectionPoolImpl.java +++ b/driver/src/main/java/org/neo4j/driver/internal/async/pool/ConnectionPoolImpl.java @@ -36,9 +36,8 @@ import org.neo4j.driver.internal.BoltServerAddress; import org.neo4j.driver.internal.async.ChannelConnector; import org.neo4j.driver.internal.async.NettyConnection; -import org.neo4j.driver.internal.metrics.DriverMetricsHandler; +import org.neo4j.driver.internal.metrics.DriverMetricsListener; import org.neo4j.driver.internal.metrics.ListenerEvent; -import org.neo4j.driver.internal.metrics.SimpleTimerListenerEvent; import org.neo4j.driver.internal.spi.Connection; import org.neo4j.driver.internal.spi.ConnectionPool; import org.neo4j.driver.internal.util.Clock; @@ -56,19 +55,19 @@ public class ConnectionPoolImpl implements ConnectionPool private final PoolSettings settings; private final Clock clock; private final Logger log; - private DriverMetricsHandler driverMetrics; + private DriverMetricsListener driverMetrics; private final ConcurrentMap pools = new ConcurrentHashMap<>(); private final AtomicBoolean closed = new AtomicBoolean(); public ConnectionPoolImpl( ChannelConnector connector, Bootstrap bootstrap, PoolSettings settings, - DriverMetricsHandler metricsHandler, Logging logging, Clock clock ) + DriverMetricsListener metricsHandler, Logging logging, Clock clock ) { this( connector, bootstrap, new NettyChannelTracker( metricsHandler, logging ), settings, metricsHandler, logging, clock ); } ConnectionPoolImpl( ChannelConnector connector, Bootstrap bootstrap, NettyChannelTracker nettyChannelTracker, - PoolSettings settings, DriverMetricsHandler driverMetrics, Logging logging, Clock clock ) + PoolSettings settings, DriverMetricsListener driverMetrics, Logging logging, Clock clock ) { this.connector = connector; this.bootstrap = bootstrap; @@ -85,11 +84,10 @@ public CompletionStage acquire( BoltServerAddress address ) { log.trace( "Acquiring a connection from pool towards %s", address ); - // TODO no need to init if no driver metrics - ListenerEvent acquireEvent = new SimpleTimerListenerEvent(); - assertNotClosed(); ChannelPool pool = getOrCreatePool( address ); + + ListenerEvent acquireEvent = driverMetrics.createListenerEvent(); driverMetrics.beforeAcquiring( address, acquireEvent ); Future connectionFuture = pool.acquire(); diff --git a/driver/src/main/java/org/neo4j/driver/internal/async/pool/NettyChannelTracker.java b/driver/src/main/java/org/neo4j/driver/internal/async/pool/NettyChannelTracker.java index 0cc4243f45..3698d19442 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/async/pool/NettyChannelTracker.java +++ b/driver/src/main/java/org/neo4j/driver/internal/async/pool/NettyChannelTracker.java @@ -26,7 +26,7 @@ import java.util.concurrent.atomic.AtomicInteger; import org.neo4j.driver.internal.BoltServerAddress; -import org.neo4j.driver.internal.metrics.DriverMetricsHandler; +import org.neo4j.driver.internal.metrics.DriverMetricsListener; import org.neo4j.driver.v1.Logger; import org.neo4j.driver.v1.Logging; @@ -37,9 +37,9 @@ public class NettyChannelTracker implements ChannelPoolHandler private final Map addressToInUseChannelCount = new ConcurrentHashMap<>(); private final Map addressToIdleChannelCount = new ConcurrentHashMap<>(); private final Logger log; - private DriverMetricsHandler metricsHandler; + private DriverMetricsListener metricsHandler; - public NettyChannelTracker( DriverMetricsHandler metricsHandler, Logging logging ) + public NettyChannelTracker( DriverMetricsListener metricsHandler, Logging logging ) { this.metricsHandler = metricsHandler; this.log = logging.getLog( getClass().getSimpleName() ); diff --git a/driver/src/main/java/org/neo4j/driver/internal/metrics/DriverMetricsHandler.java b/driver/src/main/java/org/neo4j/driver/internal/metrics/DriverMetricsListener.java similarity index 94% rename from driver/src/main/java/org/neo4j/driver/internal/metrics/DriverMetricsHandler.java rename to driver/src/main/java/org/neo4j/driver/internal/metrics/DriverMetricsListener.java index bb5e87cf02..0a0343b7ac 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/metrics/DriverMetricsHandler.java +++ b/driver/src/main/java/org/neo4j/driver/internal/metrics/DriverMetricsListener.java @@ -21,7 +21,7 @@ import org.neo4j.driver.internal.BoltServerAddress; import org.neo4j.driver.internal.spi.ConnectionPool; -public interface DriverMetricsHandler +public interface DriverMetricsListener { void addPoolMetrics(BoltServerAddress serverAddress, ConnectionPool pool); @@ -36,4 +36,6 @@ public interface DriverMetricsHandler void beforeAcquiring( BoltServerAddress serverAddress, ListenerEvent listenerEvent ); void afterAcquired( BoltServerAddress serverAddress, ListenerEvent listenerEvent ); + + ListenerEvent createListenerEvent(); } diff --git a/driver/src/main/java/org/neo4j/driver/internal/metrics/HistogramSanpshot.java b/driver/src/main/java/org/neo4j/driver/internal/metrics/HistogramSnapshot.java similarity index 89% rename from driver/src/main/java/org/neo4j/driver/internal/metrics/HistogramSanpshot.java rename to driver/src/main/java/org/neo4j/driver/internal/metrics/HistogramSnapshot.java index 7e3ef605ed..5bfd5804bc 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/metrics/HistogramSanpshot.java +++ b/driver/src/main/java/org/neo4j/driver/internal/metrics/HistogramSnapshot.java @@ -20,17 +20,23 @@ import org.neo4j.driver.internal.metrics.spi.Histogram; -public class HistogramSanpshot implements Histogram +public class HistogramSnapshot implements Histogram { private Histogram copy; private Histogram origin; - public HistogramSanpshot( Histogram copy, Histogram origin ) + public HistogramSnapshot( Histogram copy, Histogram origin ) { this.copy = copy; this.origin = origin; } + @Override + public long min() + { + return copy.min(); + } + @Override public long max() { diff --git a/driver/src/main/java/org/neo4j/driver/internal/metrics/InternalAbstractDriverMetrics.java b/driver/src/main/java/org/neo4j/driver/internal/metrics/InternalAbstractDriverMetrics.java index f3e246f89f..834eae3353 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/metrics/InternalAbstractDriverMetrics.java +++ b/driver/src/main/java/org/neo4j/driver/internal/metrics/InternalAbstractDriverMetrics.java @@ -26,7 +26,7 @@ import org.neo4j.driver.internal.metrics.spi.DriverMetrics; import org.neo4j.driver.internal.spi.ConnectionPool; -public abstract class InternalAbstractDriverMetrics implements DriverMetrics, DriverMetricsHandler +public abstract class InternalAbstractDriverMetrics implements DriverMetrics, DriverMetricsListener { public static final InternalAbstractDriverMetrics DEV_NULL_METRICS = new InternalAbstractDriverMetrics() { @@ -72,6 +72,12 @@ public void afterAcquired( BoltServerAddress serverAddress, ListenerEvent listen } + @Override + public ListenerEvent createListenerEvent() + { + return null; + } + @Override public Map connectionPoolMetrics() { diff --git a/driver/src/main/java/org/neo4j/driver/internal/metrics/InternalConnectionPoolMetrics.java b/driver/src/main/java/org/neo4j/driver/internal/metrics/InternalConnectionPoolMetrics.java index bb440b412e..1415a99b59 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/metrics/InternalConnectionPoolMetrics.java +++ b/driver/src/main/java/org/neo4j/driver/internal/metrics/InternalConnectionPoolMetrics.java @@ -152,7 +152,7 @@ public Histogram acquisitionTimeHistogram() @Override public String toString() { - return format( "[created=%s, closed=%s, toCreate=%s, failedToCreate=%s inUse=%s, idle=%s, poolStatus=%s, acquisitionTimeHistogram=%n%s]", + return format( "[created=%s, closed=%s, toCreate=%s, failedToCreate=%s inUse=%s, idle=%s, poolStatus=%s, acquisitionTimeHistogram=%s]", created(), closed(), toCreate(), failedToCreate(), inUse(), idle(), poolStatus(), acquisitionTimeHistogram() ); } } diff --git a/driver/src/main/java/org/neo4j/driver/internal/metrics/InternalDriverMetrics.java b/driver/src/main/java/org/neo4j/driver/internal/metrics/InternalDriverMetrics.java index 8aca091b0b..cbae863ed2 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/metrics/InternalDriverMetrics.java +++ b/driver/src/main/java/org/neo4j/driver/internal/metrics/InternalDriverMetrics.java @@ -92,6 +92,12 @@ public void afterAcquired( BoltServerAddress serverAddress, ListenerEvent listen poolMetrics.afterAcquire( listenerEvent ); } + @Override + public ListenerEvent createListenerEvent() + { + return new NanoTimeBasedListenerEvent(); + } + @Override public Map connectionPoolMetrics() { diff --git a/driver/src/main/java/org/neo4j/driver/internal/metrics/InternalHistogram.java b/driver/src/main/java/org/neo4j/driver/internal/metrics/InternalHistogram.java index a9e5c7c0d1..313afe044b 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/metrics/InternalHistogram.java +++ b/driver/src/main/java/org/neo4j/driver/internal/metrics/InternalHistogram.java @@ -27,9 +27,11 @@ import org.neo4j.driver.internal.metrics.spi.Histogram; +import static java.lang.String.format; + public class InternalHistogram implements Histogram { - private static final long DEFAULT_HIGHEST_TRACKABLE_MS = Duration.ofMinutes( 10 ).toMillis(); + private static final long DEFAULT_HIGHEST_TRACKABLE_MS = Duration.ofMinutes( 10 ).toNanos(); private final AbstractHistogram delegate; @@ -54,6 +56,12 @@ public void recordValue( long value ) this.delegate.recordValue( newValue ); } + @Override + public long min() + { + return delegate.getMinValue(); + } + @Override public long max() { @@ -109,11 +117,17 @@ private static long truncateValue( long value, AbstractHistogram histogram ) public Histogram snapshot() { - return new HistogramSanpshot( new InternalHistogram( this.delegate.copy() ), this ); + return new HistogramSnapshot( new InternalHistogram( this.delegate.copy() ), this ); } @Override public String toString() + { + return format("[min=%sns, max=%sns, mean=%sns, stdDeviation=%s, totalCount=%s]", + min(), max(), mean(), stdDeviation(), totalCount()); + } + + public String printDistribution() { ByteArrayOutputStream stream = new ByteArrayOutputStream(); PrintStream writer = new PrintStream( stream ); diff --git a/driver/src/main/java/org/neo4j/driver/internal/metrics/SimpleTimerListenerEvent.java b/driver/src/main/java/org/neo4j/driver/internal/metrics/NanoTimeBasedListenerEvent.java similarity index 80% rename from driver/src/main/java/org/neo4j/driver/internal/metrics/SimpleTimerListenerEvent.java rename to driver/src/main/java/org/neo4j/driver/internal/metrics/NanoTimeBasedListenerEvent.java index 045153c470..a2c315c4fd 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/metrics/SimpleTimerListenerEvent.java +++ b/driver/src/main/java/org/neo4j/driver/internal/metrics/NanoTimeBasedListenerEvent.java @@ -19,19 +19,19 @@ package org.neo4j.driver.internal.metrics; -public class SimpleTimerListenerEvent implements ListenerEvent +public class NanoTimeBasedListenerEvent implements ListenerEvent { - private long startTimestamp; + private long startNanoTime; @Override public void start() { - startTimestamp = System.currentTimeMillis(); + startNanoTime = System.nanoTime(); } @Override public long elapsed() { - return System.currentTimeMillis() - startTimestamp; + return System.nanoTime() - startNanoTime; } } diff --git a/driver/src/main/java/org/neo4j/driver/internal/metrics/spi/Histogram.java b/driver/src/main/java/org/neo4j/driver/internal/metrics/spi/Histogram.java index 221d88bc24..00e34452e0 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/metrics/spi/Histogram.java +++ b/driver/src/main/java/org/neo4j/driver/internal/metrics/spi/Histogram.java @@ -20,6 +20,7 @@ public interface Histogram { + long min(); long max(); double mean(); double stdDeviation(); diff --git a/driver/src/test/java/org/neo4j/driver/internal/DriverFactoryTest.java b/driver/src/test/java/org/neo4j/driver/internal/DriverFactoryTest.java index e5dc4de0f5..8b334d3350 100644 --- a/driver/src/test/java/org/neo4j/driver/internal/DriverFactoryTest.java +++ b/driver/src/test/java/org/neo4j/driver/internal/DriverFactoryTest.java @@ -33,7 +33,7 @@ import org.neo4j.driver.internal.async.BootstrapFactory; import org.neo4j.driver.internal.cluster.RoutingSettings; import org.neo4j.driver.internal.cluster.loadbalancing.LoadBalancer; -import org.neo4j.driver.internal.metrics.DriverMetricsHandler; +import org.neo4j.driver.internal.metrics.DriverMetricsListener; import org.neo4j.driver.internal.metrics.InternalDriverMetrics; import org.neo4j.driver.internal.retry.RetryLogic; import org.neo4j.driver.internal.retry.RetrySettings; @@ -185,7 +185,7 @@ public void shouldNotCreateDriverMetrics() throws Throwable // Given Config config = mock( Config.class ); // When - DriverMetricsHandler handler = DriverFactory.createDriverMetrics( config ); + DriverMetricsListener handler = DriverFactory.createDriverMetrics( config ); // Then assertThat( handler, is( DEV_NULL_METRICS ) ); } @@ -197,7 +197,7 @@ public void shouldCreateDriverMetricsIfMonitoringEnabled() throws Throwable System.setProperty( "driver.metrics.enabled", "True" ); Config config = mock( Config.class ); // When - DriverMetricsHandler handler = DriverFactory.createDriverMetrics( config ); + DriverMetricsListener handler = DriverFactory.createDriverMetrics( config ); // Then assertThat( handler instanceof InternalDriverMetrics, is( true ) ); } @@ -247,7 +247,7 @@ protected InternalDriver createRoutingDriver( BoltServerAddress address, Connect } @Override - protected ConnectionPool createConnectionPool( AuthToken authToken, SecurityPlan securityPlan, Bootstrap bootstrap, DriverMetricsHandler metrics, Config config ) + protected ConnectionPool createConnectionPool( AuthToken authToken, SecurityPlan securityPlan, Bootstrap bootstrap, DriverMetricsListener metrics, Config config ) { return connectionPool; } @@ -282,7 +282,7 @@ protected SessionFactory createSessionFactory( ConnectionProvider connectionProv } @Override - protected ConnectionPool createConnectionPool( AuthToken authToken, SecurityPlan securityPlan, Bootstrap bootstrap, DriverMetricsHandler metrics, Config config ) + protected ConnectionPool createConnectionPool( AuthToken authToken, SecurityPlan securityPlan, Bootstrap bootstrap, DriverMetricsListener metrics, Config config ) { return connectionPoolMock(); } @@ -304,7 +304,7 @@ protected Bootstrap createBootstrap() } @Override - protected ConnectionPool createConnectionPool( AuthToken authToken, SecurityPlan securityPlan, Bootstrap bootstrap, DriverMetricsHandler metrics, Config config ) + protected ConnectionPool createConnectionPool( AuthToken authToken, SecurityPlan securityPlan, Bootstrap bootstrap, DriverMetricsListener metrics, Config config ) { return connectionPoolMock(); } diff --git a/driver/src/test/java/org/neo4j/driver/internal/metrics/InternalHistogramTest.java b/driver/src/test/java/org/neo4j/driver/internal/metrics/InternalHistogramTest.java new file mode 100644 index 0000000000..66e17ae2cb --- /dev/null +++ b/driver/src/test/java/org/neo4j/driver/internal/metrics/InternalHistogramTest.java @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2002-2018 "Neo Technology," + * Network Engine for Objects in Lund AB [http://neotechnology.com] + * + * This file is part of Neo4j. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.neo4j.driver.internal.metrics; + +import org.junit.Test; + +import org.neo4j.driver.internal.metrics.spi.Histogram; + +import static java.lang.Math.abs; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.lessThan; +import static org.junit.Assert.assertThat; + +public class InternalHistogramTest +{ + @Test + public void shouldRecordSmallValuesPrecisely() throws Throwable + { + // Given + InternalHistogram histogram = new InternalHistogram(); + histogram.recordValue( 0 ); + histogram.recordValue( 1 ); + histogram.recordValue( 2 ); + histogram.recordValue( 3 ); + histogram.recordValue( 4 ); + + // When + assertThat( histogram.min(), equalTo( 0L ) ); + assertThat( histogram.max(), equalTo( 4L ) ); + assertThat( histogram.mean(), equalTo( 2.0 ) ); + assertThat( histogram.totalCount(), equalTo( 5L ) ); + } + + @Test + public void shouldRecordBigValuesPrecisely() throws Throwable + { + // Given + InternalHistogram histogram = new InternalHistogram(); + histogram.recordValue( 0 ); + histogram.recordValue( 100000 ); + histogram.recordValue( 200000 ); + histogram.recordValue( 300000 ); + histogram.recordValue( 400000 ); + + // When + assertThat( histogram.min(), equalTo( 0L ) ); + assertThat( abs( histogram.max() - 400000L ), lessThan( 500L ) ); + assertThat( abs( histogram.mean() - 200000.0 ), lessThan( 500.0 ) ); + assertThat( histogram.totalCount(), equalTo( 5L ) ); + } + + @Test + public void shouldResetOnOriginalHistogram() throws Throwable + { + // Given + InternalHistogram histogram = new InternalHistogram(); + histogram.recordValue( 0 ); + histogram.recordValue( 1 ); + histogram.recordValue( 2 ); + histogram.recordValue( 3 ); + histogram.recordValue( 4 ); + + // When + assertThat( histogram.totalCount(), equalTo( 5L ) ); + Histogram snapshot = histogram.snapshot(); + snapshot.reset(); + + // Then + assertThat( histogram.totalCount(), equalTo( 0L ) ); + } + +} diff --git a/driver/src/test/java/org/neo4j/driver/internal/util/ChannelTrackingDriverFactory.java b/driver/src/test/java/org/neo4j/driver/internal/util/ChannelTrackingDriverFactory.java index a39036134e..8d78b2da2d 100644 --- a/driver/src/test/java/org/neo4j/driver/internal/util/ChannelTrackingDriverFactory.java +++ b/driver/src/test/java/org/neo4j/driver/internal/util/ChannelTrackingDriverFactory.java @@ -29,7 +29,7 @@ import org.neo4j.driver.internal.ConnectionSettings; import org.neo4j.driver.internal.async.BootstrapFactory; import org.neo4j.driver.internal.async.ChannelConnector; -import org.neo4j.driver.internal.metrics.DriverMetricsHandler; +import org.neo4j.driver.internal.metrics.DriverMetricsListener; import org.neo4j.driver.internal.security.SecurityPlan; import org.neo4j.driver.internal.spi.ConnectionPool; import org.neo4j.driver.v1.AuthToken; @@ -71,7 +71,7 @@ protected final ChannelConnector createConnector( ConnectionSettings settings, S } @Override - protected final ConnectionPool createConnectionPool( AuthToken authToken, SecurityPlan securityPlan, Bootstrap bootstrap, DriverMetricsHandler metrics, + protected final ConnectionPool createConnectionPool( AuthToken authToken, SecurityPlan securityPlan, Bootstrap bootstrap, DriverMetricsListener metrics, Config config ) { pool = super.createConnectionPool( authToken, securityPlan, bootstrap, metrics, config ); diff --git a/driver/src/test/java/org/neo4j/driver/internal/util/FailingConnectionDriverFactory.java b/driver/src/test/java/org/neo4j/driver/internal/util/FailingConnectionDriverFactory.java index 90460969bd..d688e6c206 100644 --- a/driver/src/test/java/org/neo4j/driver/internal/util/FailingConnectionDriverFactory.java +++ b/driver/src/test/java/org/neo4j/driver/internal/util/FailingConnectionDriverFactory.java @@ -27,7 +27,7 @@ import org.neo4j.driver.internal.BoltServerAddress; import org.neo4j.driver.internal.DriverFactory; -import org.neo4j.driver.internal.metrics.DriverMetricsHandler; +import org.neo4j.driver.internal.metrics.DriverMetricsListener; import org.neo4j.driver.internal.security.SecurityPlan; import org.neo4j.driver.internal.spi.Connection; import org.neo4j.driver.internal.spi.ConnectionPool; @@ -41,7 +41,7 @@ public class FailingConnectionDriverFactory extends DriverFactory private final AtomicReference nextRunFailure = new AtomicReference<>(); @Override - protected ConnectionPool createConnectionPool( AuthToken authToken, SecurityPlan securityPlan, Bootstrap bootstrap, DriverMetricsHandler metrics, Config config ) + protected ConnectionPool createConnectionPool( AuthToken authToken, SecurityPlan securityPlan, Bootstrap bootstrap, DriverMetricsListener metrics, Config config ) { ConnectionPool pool = super.createConnectionPool( authToken, securityPlan, bootstrap, metrics, config ); return new ConnectionPoolWithFailingConnections( pool, nextRunFailure ); diff --git a/driver/src/test/java/org/neo4j/driver/v1/integration/ConnectionHandlingIT.java b/driver/src/test/java/org/neo4j/driver/v1/integration/ConnectionHandlingIT.java index af0e496fa6..f532adfb34 100644 --- a/driver/src/test/java/org/neo4j/driver/v1/integration/ConnectionHandlingIT.java +++ b/driver/src/test/java/org/neo4j/driver/v1/integration/ConnectionHandlingIT.java @@ -36,7 +36,7 @@ import org.neo4j.driver.internal.async.pool.ConnectionPoolImpl; import org.neo4j.driver.internal.async.pool.PoolSettings; import org.neo4j.driver.internal.cluster.RoutingSettings; -import org.neo4j.driver.internal.metrics.DriverMetricsHandler; +import org.neo4j.driver.internal.metrics.DriverMetricsListener; import org.neo4j.driver.internal.retry.RetrySettings; import org.neo4j.driver.internal.security.SecurityPlan; import org.neo4j.driver.internal.spi.Connection; @@ -296,7 +296,7 @@ private static class DriverFactoryWithConnectionPool extends DriverFactory MemorizingConnectionPool connectionPool; @Override - protected ConnectionPool createConnectionPool( AuthToken authToken, SecurityPlan securityPlan, Bootstrap bootstrap, DriverMetricsHandler metrics, Config config ) + protected ConnectionPool createConnectionPool( AuthToken authToken, SecurityPlan securityPlan, Bootstrap bootstrap, DriverMetricsListener metrics, Config config ) { ConnectionSettings connectionSettings = new ConnectionSettings( authToken, 1000 ); PoolSettings poolSettings = new PoolSettings( config.maxConnectionPoolSize(), From 2a1c7710c037bba8d0f4cb34cb089e66ad2f7604 Mon Sep 17 00:00:00 2001 From: Zhen Date: Fri, 16 Feb 2018 16:45:55 +0000 Subject: [PATCH 4/6] Adding connection metrics --- driver/pom.xml | 19 ++-- .../internal/async/NettyConnection.java | 11 ++- .../async/pool/ConnectionPoolImpl.java | 22 ++--- .../internal/async/pool/NettyChannelPool.java | 4 +- .../async/pool/NettyChannelTracker.java | 42 ++++---- .../metrics/ConnectionMetricsListener.java | 31 ++++++ ...ava => ConnectionPoolMetricsListener.java} | 8 +- .../metrics/DriverMetricsListener.java | 74 +++++++++++++-- .../InternalAbstractDriverMetrics.java | 43 ++++++--- .../metrics/InternalConnectionMetrics.java | 95 +++++++++++++++++++ .../InternalConnectionPoolMetrics.java | 29 +++--- .../metrics/InternalDriverMetrics.java | 90 +++++++++++++----- .../internal/metrics/InternalHistogram.java | 8 +- .../internal/metrics/ListenerEvent.java | 9 ++ .../metrics/NanoTimeBasedListenerEvent.java | 5 +- .../metrics/spi/ConnectionMetrics.java | 17 ++++ .../metrics/spi/ConnectionPoolMetrics.java | 48 ++++++++++ .../internal/metrics/spi/DriverMetrics.java | 21 +++- .../internal/metrics/spi/Histogram.java | 32 +++++++ .../driver/internal/DriverFactoryTest.java | 3 +- .../internal/async/NettyConnectionTest.java | 3 +- pom.xml | 2 +- 22 files changed, 495 insertions(+), 121 deletions(-) create mode 100644 driver/src/main/java/org/neo4j/driver/internal/metrics/ConnectionMetricsListener.java rename driver/src/main/java/org/neo4j/driver/internal/metrics/{ConnectionPoolListener.java => ConnectionPoolMetricsListener.java} (80%) create mode 100644 driver/src/main/java/org/neo4j/driver/internal/metrics/InternalConnectionMetrics.java diff --git a/driver/pom.xml b/driver/pom.xml index f155d59b74..927936c9fe 100644 --- a/driver/pom.xml +++ b/driver/pom.xml @@ -29,6 +29,10 @@ io.netty netty-handler + + org.hdrhistogram + HdrHistogram + @@ -71,16 +75,6 @@ com.fasterxml.jackson.core jackson-databind - - org.hdrhistogram - HdrHistogram - 2.1.2 - - - org.hdrhistogram - HdrHistogram - 2.1.2 - @@ -218,6 +212,7 @@ io.netty:* + org.HdrHistogram:* @@ -225,6 +220,10 @@ io.netty org.neo4j.driver.internal.shaded.io.netty + + org.HdrHistogram + org.neo4j.driver.internal.shaded.org.HdrHistogram + true diff --git a/driver/src/main/java/org/neo4j/driver/internal/async/NettyConnection.java b/driver/src/main/java/org/neo4j/driver/internal/async/NettyConnection.java index 3d3bb0c9e6..c0869f562c 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/async/NettyConnection.java +++ b/driver/src/main/java/org/neo4j/driver/internal/async/NettyConnection.java @@ -34,6 +34,8 @@ import org.neo4j.driver.internal.messaging.PullAllMessage; import org.neo4j.driver.internal.messaging.ResetMessage; import org.neo4j.driver.internal.messaging.RunMessage; +import org.neo4j.driver.internal.metrics.DriverMetricsListener; +import org.neo4j.driver.internal.metrics.ListenerEvent.ConnectionListenerEvent; import org.neo4j.driver.internal.spi.Connection; import org.neo4j.driver.internal.spi.ResponseHandler; import org.neo4j.driver.internal.util.Clock; @@ -54,8 +56,10 @@ public class NettyConnection implements Connection private final Clock clock; private final AtomicReference status = new AtomicReference<>( Status.OPEN ); + private final DriverMetricsListener metricsListener; + private final ConnectionListenerEvent inUseEvent; - public NettyConnection( Channel channel, ChannelPool channelPool, Clock clock ) + public NettyConnection( Channel channel, ChannelPool channelPool, Clock clock, DriverMetricsListener driverMetricsListener ) { this.channel = channel; this.messageDispatcher = ChannelAttributes.messageDispatcher( channel ); @@ -64,6 +68,9 @@ public NettyConnection( Channel channel, ChannelPool channelPool, Clock clock ) this.channelPool = channelPool; this.releaseFuture = new CompletableFuture<>(); this.clock = clock; + this.metricsListener = driverMetricsListener; + this.inUseEvent = driverMetricsListener.createConnectionListenerEvent(); + driverMetricsListener.afterAcquiredOrCreated( this.serverAddress, this.inUseEvent ); } @Override @@ -124,6 +131,7 @@ public CompletionStage release() { if ( status.compareAndSet( Status.OPEN, Status.RELEASED ) ) { + metricsListener.afterReleased( this.serverAddress, this.inUseEvent ); ChannelReleasingResetResponseHandler handler = new ChannelReleasingResetResponseHandler( channel, channelPool, messageDispatcher, clock, releaseFuture ); @@ -137,6 +145,7 @@ public void terminateAndRelease( String reason ) { if ( status.compareAndSet( Status.OPEN, Status.TERMINATED ) ) { + metricsListener.afterReleased( this.serverAddress, this.inUseEvent ); setTerminationReason( channel, reason ); channel.close(); channelPool.release( channel ); diff --git a/driver/src/main/java/org/neo4j/driver/internal/async/pool/ConnectionPoolImpl.java b/driver/src/main/java/org/neo4j/driver/internal/async/pool/ConnectionPoolImpl.java index 9e2464cacc..23f258d6d2 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/async/pool/ConnectionPoolImpl.java +++ b/driver/src/main/java/org/neo4j/driver/internal/async/pool/ConnectionPoolImpl.java @@ -37,7 +37,7 @@ import org.neo4j.driver.internal.async.ChannelConnector; import org.neo4j.driver.internal.async.NettyConnection; import org.neo4j.driver.internal.metrics.DriverMetricsListener; -import org.neo4j.driver.internal.metrics.ListenerEvent; +import org.neo4j.driver.internal.metrics.ListenerEvent.PoolListenerEvent; import org.neo4j.driver.internal.spi.Connection; import org.neo4j.driver.internal.spi.ConnectionPool; import org.neo4j.driver.internal.util.Clock; @@ -55,26 +55,26 @@ public class ConnectionPoolImpl implements ConnectionPool private final PoolSettings settings; private final Clock clock; private final Logger log; - private DriverMetricsListener driverMetrics; + private DriverMetricsListener driverMetricsListener; private final ConcurrentMap pools = new ConcurrentHashMap<>(); private final AtomicBoolean closed = new AtomicBoolean(); public ConnectionPoolImpl( ChannelConnector connector, Bootstrap bootstrap, PoolSettings settings, - DriverMetricsListener metricsHandler, Logging logging, Clock clock ) + DriverMetricsListener metricsListener, Logging logging, Clock clock ) { - this( connector, bootstrap, new NettyChannelTracker( metricsHandler, logging ), settings, metricsHandler, logging, clock ); + this( connector, bootstrap, new NettyChannelTracker( metricsListener, logging ), settings, metricsListener, logging, clock ); } ConnectionPoolImpl( ChannelConnector connector, Bootstrap bootstrap, NettyChannelTracker nettyChannelTracker, - PoolSettings settings, DriverMetricsListener driverMetrics, Logging logging, Clock clock ) + PoolSettings settings, DriverMetricsListener metricsListener, Logging logging, Clock clock ) { this.connector = connector; this.bootstrap = bootstrap; this.nettyChannelTracker = nettyChannelTracker; this.channelHealthChecker = new NettyChannelHealthChecker( settings, clock, logging ); this.settings = settings; - this.driverMetrics = driverMetrics; + this.driverMetricsListener = metricsListener; this.clock = clock; this.log = logging.getLog( ConnectionPool.class.getSimpleName() ); } @@ -87,8 +87,8 @@ public CompletionStage acquire( BoltServerAddress address ) assertNotClosed(); ChannelPool pool = getOrCreatePool( address ); - ListenerEvent acquireEvent = driverMetrics.createListenerEvent(); - driverMetrics.beforeAcquiring( address, acquireEvent ); + PoolListenerEvent acquireEvent = driverMetricsListener.createPoolListenerEvent(); + driverMetricsListener.beforeAcquiringOrCreating( address, acquireEvent ); Future connectionFuture = pool.acquire(); return Futures.asCompletionStage( connectionFuture ).handle( ( channel, error ) -> @@ -97,11 +97,11 @@ public CompletionStage acquire( BoltServerAddress address ) { processAcquisitionError( error ); assertNotClosed( address, channel, pool ); - return new NettyConnection( channel, pool, clock ); + return new NettyConnection( channel, pool, clock, driverMetricsListener ); } finally { - driverMetrics.afterAcquired( address, acquireEvent ); + driverMetricsListener.afterAcquiringOrCreating( address, acquireEvent ); } } ); } @@ -192,7 +192,7 @@ private ChannelPool getOrCreatePool( BoltServerAddress address ) else { // We added a new pool as a result we add a new metrics for the pool too - driverMetrics.addPoolMetrics( address, this ); + driverMetricsListener.addMetrics( address, this ); } } diff --git a/driver/src/main/java/org/neo4j/driver/internal/async/pool/NettyChannelPool.java b/driver/src/main/java/org/neo4j/driver/internal/async/pool/NettyChannelPool.java index be25aacfcc..bee5f953f3 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/async/pool/NettyChannelPool.java +++ b/driver/src/main/java/org/neo4j/driver/internal/async/pool/NettyChannelPool.java @@ -26,6 +26,7 @@ import org.neo4j.driver.internal.BoltServerAddress; import org.neo4j.driver.internal.async.ChannelConnector; +import org.neo4j.driver.internal.metrics.ListenerEvent.ConnectionListenerEvent; import static java.util.Objects.requireNonNull; @@ -59,7 +60,7 @@ public NettyChannelPool( BoltServerAddress address, ChannelConnector connector, @Override protected ChannelFuture connectChannel( Bootstrap bootstrap ) { - handler.channelCreating( address ); + ConnectionListenerEvent creatingEvent = handler.beforeChannelCreating( address ); ChannelFuture channelFuture = connector.connect( address, bootstrap ); channelFuture.addListener( future -> { @@ -74,6 +75,7 @@ protected ChannelFuture connectChannel( Bootstrap bootstrap ) { handler.channelFailedToCreate( address ); } + handler.afterChannelCreating( address, creatingEvent ); } ); return channelFuture; } diff --git a/driver/src/main/java/org/neo4j/driver/internal/async/pool/NettyChannelTracker.java b/driver/src/main/java/org/neo4j/driver/internal/async/pool/NettyChannelTracker.java index 3698d19442..8277a2566c 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/async/pool/NettyChannelTracker.java +++ b/driver/src/main/java/org/neo4j/driver/internal/async/pool/NettyChannelTracker.java @@ -27,6 +27,7 @@ import org.neo4j.driver.internal.BoltServerAddress; import org.neo4j.driver.internal.metrics.DriverMetricsListener; +import org.neo4j.driver.internal.metrics.ListenerEvent.ConnectionListenerEvent; import org.neo4j.driver.v1.Logger; import org.neo4j.driver.v1.Logging; @@ -37,11 +38,11 @@ public class NettyChannelTracker implements ChannelPoolHandler private final Map addressToInUseChannelCount = new ConcurrentHashMap<>(); private final Map addressToIdleChannelCount = new ConcurrentHashMap<>(); private final Logger log; - private DriverMetricsListener metricsHandler; + private DriverMetricsListener metricsListener; - public NettyChannelTracker( DriverMetricsListener metricsHandler, Logging logging ) + public NettyChannelTracker( DriverMetricsListener metricsListener, Logging logging ) { - this.metricsHandler = metricsHandler; + this.metricsListener = metricsListener; this.log = logging.getLog( getClass().getSimpleName() ); } @@ -49,14 +50,16 @@ public NettyChannelTracker( DriverMetricsListener metricsHandler, Logging loggin public void channelReleased( Channel channel ) { log.debug( "Channel %s released back to the pool", channel ); - channelInactive( channel ); + decrementInUse( channel ); + incrementIdle( channel ); } @Override public void channelAcquired( Channel channel ) { log.debug( "Channel %s acquired from the pool", channel ); - channelActive( channel ); + incrementInUse( channel ); + decrementIdle( channel ); } @Override @@ -64,23 +67,30 @@ public void channelCreated( Channel channel ) { log.debug( "Channel %s created", channel ); incrementInUse( channel ); - metricsHandler.afterCreatedSuccessfully( serverAddress( channel ) ); + metricsListener.afterCreated( serverAddress( channel ) ); } public void channelFailedToCreate( BoltServerAddress address ) { - metricsHandler.afterFailedToCreate( address ); + metricsListener.afterFailedToCreate( address ); } - public void channelCreating( BoltServerAddress address ) + public ConnectionListenerEvent beforeChannelCreating( BoltServerAddress address ) { - metricsHandler.beforeCreating( address ); + ConnectionListenerEvent creatingEvent = metricsListener.createConnectionListenerEvent(); + metricsListener.beforeCreating( address, creatingEvent ); + return creatingEvent; + } + + public void afterChannelCreating( BoltServerAddress address, ConnectionListenerEvent creatingEvent ) + { + metricsListener.afterCreating( address, creatingEvent ); } public void channelClosed( Channel channel ) { decrementIdle( channel ); - metricsHandler.afterClosed( serverAddress( channel ) ); + metricsListener.afterClosed( serverAddress( channel ) ); } public int inUseChannelCount( BoltServerAddress address ) @@ -95,18 +105,6 @@ public int idleChannelCount( BoltServerAddress address ) return count == null ? 0 : count.get(); } - private void channelActive( Channel channel ) - { - incrementInUse( channel ); - decrementIdle( channel ); - } - - private void channelInactive( Channel channel ) - { - decrementInUse( channel ); - incrementIdle( channel ); - } - private void incrementInUse( Channel channel ) { increment( channel, addressToInUseChannelCount ); diff --git a/driver/src/main/java/org/neo4j/driver/internal/metrics/ConnectionMetricsListener.java b/driver/src/main/java/org/neo4j/driver/internal/metrics/ConnectionMetricsListener.java new file mode 100644 index 0000000000..a8b55a2787 --- /dev/null +++ b/driver/src/main/java/org/neo4j/driver/internal/metrics/ConnectionMetricsListener.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2002-2018 "Neo Technology," + * Network Engine for Objects in Lund AB [http://neotechnology.com] + * + * This file is part of Neo4j. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.neo4j.driver.internal.metrics; + + +public interface ConnectionMetricsListener +{ + void beforeCreating( ListenerEvent listenerEvent ); + + void afterCreating( ListenerEvent listenerEvent ); + + void acquiredOrCreated( ListenerEvent listenerEvent ); + + void released(ListenerEvent listenerEvent); +} diff --git a/driver/src/main/java/org/neo4j/driver/internal/metrics/ConnectionPoolListener.java b/driver/src/main/java/org/neo4j/driver/internal/metrics/ConnectionPoolMetricsListener.java similarity index 80% rename from driver/src/main/java/org/neo4j/driver/internal/metrics/ConnectionPoolListener.java rename to driver/src/main/java/org/neo4j/driver/internal/metrics/ConnectionPoolMetricsListener.java index 4ee7ad1def..93f414c7f9 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/metrics/ConnectionPoolListener.java +++ b/driver/src/main/java/org/neo4j/driver/internal/metrics/ConnectionPoolMetricsListener.java @@ -18,18 +18,18 @@ */ package org.neo4j.driver.internal.metrics; -public interface ConnectionPoolListener +public interface ConnectionPoolMetricsListener { void beforeCreating(); - void afterCreatedSuccessfully(); + void afterCreated(); void afterFailedToCreate(); void afterClosed(); - void beforeAcquire( ListenerEvent listenerEvent ); + void beforeAcquiringOrCreating( ListenerEvent listenerEvent ); - void afterAcquire( ListenerEvent listenerEvent ); + void afterAcquiringOrCreating( ListenerEvent listenerEvent ); } diff --git a/driver/src/main/java/org/neo4j/driver/internal/metrics/DriverMetricsListener.java b/driver/src/main/java/org/neo4j/driver/internal/metrics/DriverMetricsListener.java index 0a0343b7ac..d54769452c 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/metrics/DriverMetricsListener.java +++ b/driver/src/main/java/org/neo4j/driver/internal/metrics/DriverMetricsListener.java @@ -19,23 +19,79 @@ package org.neo4j.driver.internal.metrics; import org.neo4j.driver.internal.BoltServerAddress; -import org.neo4j.driver.internal.spi.ConnectionPool; +import org.neo4j.driver.internal.async.NettyConnection; +import org.neo4j.driver.internal.async.pool.ConnectionPoolImpl; +import org.neo4j.driver.internal.metrics.ListenerEvent.ConnectionListenerEvent; +import org.neo4j.driver.internal.metrics.ListenerEvent.PoolListenerEvent; public interface DriverMetricsListener { - void addPoolMetrics(BoltServerAddress serverAddress, ConnectionPool pool); + /** + * Before creating a netty channel + * @param serverAddress the server the netty channel binds to. + * @param creatingEvent a connection listener event registered when a connection is creating. + */ + void beforeCreating( BoltServerAddress serverAddress, ConnectionListenerEvent creatingEvent ); - void beforeCreating(BoltServerAddress serverAddress); + /** + * After creating a netty channel regardless succeeded or failed. + * @param serverAddress the server the netty channel binds to. + * @param creatingEvent a connection listener event registered when a connection is creating. + */ + void afterCreating( BoltServerAddress serverAddress, ConnectionListenerEvent creatingEvent ); - void afterCreatedSuccessfully(BoltServerAddress serverAddress); + /** + * After a netty channel is created successfully + * This method will not invoke {@link this#afterCreating(BoltServerAddress, ConnectionListenerEvent)} + * @param serverAddress the server the netty channel binds to + */ + void afterCreated( BoltServerAddress serverAddress ); - void afterFailedToCreate(BoltServerAddress serverAddress); + /** + * After a netty channel is created with failure + * This method will not invoke {@link this#afterCreating(BoltServerAddress, ConnectionListenerEvent)} + * @param serverAddress the server the netty channel binds to + */ + void afterFailedToCreate( BoltServerAddress serverAddress ); - void afterClosed(BoltServerAddress serverAddress); + /** + * After a netty channel is closed successfully + * @param serverAddress the server the netty channel binds to + */ + void afterClosed( BoltServerAddress serverAddress ); - void beforeAcquiring( BoltServerAddress serverAddress, ListenerEvent listenerEvent ); + /** + * Before acquiring or creating a new netty channel from pool + * @param serverAddress the server the netty channel binds to + * @param acquireEvent a pool listener event registered in pool for this acquire event + */ + void beforeAcquiringOrCreating( BoltServerAddress serverAddress, PoolListenerEvent acquireEvent ); - void afterAcquired( BoltServerAddress serverAddress, ListenerEvent listenerEvent ); + /** + * After acquiring or creating a new netty channel from pool regardless succeeded or failed + * @param serverAddress the server the netty channel binds to + * @param acquireEvent a pool listener event registered in pool for this acquire event + */ + void afterAcquiringOrCreating( BoltServerAddress serverAddress, PoolListenerEvent acquireEvent ); - ListenerEvent createListenerEvent(); + /** + * After acquiring or creating a new netty channel from pool successfully. + * This method will not invoke {@link this#afterAcquiringOrCreating(BoltServerAddress, PoolListenerEvent)} + * @param serverAddress the server the netty channel binds to + * @param inUseEvent a connection listener registered with a {@link NettyConnection} when created + */ + void afterAcquiredOrCreated( BoltServerAddress serverAddress, ConnectionListenerEvent inUseEvent ); + + /** + * After releasing a netty channel back to pool successfully + * @param serverAddress the server the netty channel binds to + * @param inUseEvent a connection listener registered with a {@link NettyConnection} when destroyed + */ + void afterReleased( BoltServerAddress serverAddress, ConnectionListenerEvent inUseEvent ); + + ConnectionListenerEvent createConnectionListenerEvent(); + + PoolListenerEvent createPoolListenerEvent(); + + void addMetrics( BoltServerAddress address, ConnectionPoolImpl connectionPool ); } diff --git a/driver/src/main/java/org/neo4j/driver/internal/metrics/InternalAbstractDriverMetrics.java b/driver/src/main/java/org/neo4j/driver/internal/metrics/InternalAbstractDriverMetrics.java index 834eae3353..9a50cf4225 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/metrics/InternalAbstractDriverMetrics.java +++ b/driver/src/main/java/org/neo4j/driver/internal/metrics/InternalAbstractDriverMetrics.java @@ -18,76 +18,93 @@ */ package org.neo4j.driver.internal.metrics; +import java.util.Collections; import java.util.Map; import org.neo4j.driver.internal.BoltServerAddress; +import org.neo4j.driver.internal.async.pool.ConnectionPoolImpl; import org.neo4j.driver.internal.metrics.spi.ConnectionMetrics; import org.neo4j.driver.internal.metrics.spi.ConnectionPoolMetrics; import org.neo4j.driver.internal.metrics.spi.DriverMetrics; -import org.neo4j.driver.internal.spi.ConnectionPool; public abstract class InternalAbstractDriverMetrics implements DriverMetrics, DriverMetricsListener { public static final InternalAbstractDriverMetrics DEV_NULL_METRICS = new InternalAbstractDriverMetrics() { + @Override - public void addPoolMetrics( BoltServerAddress serverAddress, ConnectionPool pool ) + public void beforeCreating( BoltServerAddress serverAddress, ListenerEvent.ConnectionListenerEvent creatingEvent ) { - } @Override - public void beforeCreating( BoltServerAddress serverAddress ) + public void afterCreating( BoltServerAddress serverAddress, ListenerEvent.ConnectionListenerEvent creatingEvent ) { - } @Override - public void afterCreatedSuccessfully( BoltServerAddress serverAddress ) + public void afterCreated( BoltServerAddress serverAddress ) { - } @Override public void afterFailedToCreate( BoltServerAddress serverAddress ) { - } @Override public void afterClosed( BoltServerAddress serverAddress ) { + } + @Override + public void beforeAcquiringOrCreating( BoltServerAddress serverAddress, ListenerEvent.PoolListenerEvent acquireEvent ) + { } @Override - public void beforeAcquiring( BoltServerAddress serverAddress, ListenerEvent listenerEvent ) + public void afterAcquiringOrCreating( BoltServerAddress serverAddress, ListenerEvent.PoolListenerEvent acquireEvent ) { + } + @Override + public void afterAcquiredOrCreated( BoltServerAddress serverAddress, ListenerEvent.ConnectionListenerEvent inUseEvent ) + { } @Override - public void afterAcquired( BoltServerAddress serverAddress, ListenerEvent listenerEvent ) + public void afterReleased( BoltServerAddress serverAddress, ListenerEvent.ConnectionListenerEvent inUseEvent ) { + } + @Override + public ListenerEvent.ConnectionListenerEvent createConnectionListenerEvent() + { + return null; } @Override - public ListenerEvent createListenerEvent() + public ListenerEvent.PoolListenerEvent createPoolListenerEvent() { return null; } + @Override + public void addMetrics( BoltServerAddress address, ConnectionPoolImpl connectionPool ) + { + + } + @Override public Map connectionPoolMetrics() { - return null; + return Collections.emptyMap(); } @Override public Map connectionMetrics() { - return null; + return Collections.emptyMap(); } @Override diff --git a/driver/src/main/java/org/neo4j/driver/internal/metrics/InternalConnectionMetrics.java b/driver/src/main/java/org/neo4j/driver/internal/metrics/InternalConnectionMetrics.java new file mode 100644 index 0000000000..b502031879 --- /dev/null +++ b/driver/src/main/java/org/neo4j/driver/internal/metrics/InternalConnectionMetrics.java @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2002-2018 "Neo Technology," + * Network Engine for Objects in Lund AB [http://neotechnology.com] + * + * This file is part of Neo4j. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.neo4j.driver.internal.metrics; + +import java.time.Duration; + +import org.neo4j.driver.internal.BoltServerAddress; +import org.neo4j.driver.internal.metrics.spi.ConnectionMetrics; +import org.neo4j.driver.internal.metrics.spi.Histogram; + + +public class InternalConnectionMetrics implements ConnectionMetrics, ConnectionMetricsListener +{ + private final InternalHistogram connHistogram; + private final InternalHistogram inUseHistogram; + private final BoltServerAddress serverAddress; + + public InternalConnectionMetrics( BoltServerAddress serverAddress, int connectionTimeoutMillis ) + { + this.serverAddress = serverAddress; + connHistogram = new InternalHistogram( Duration.ofMillis( connectionTimeoutMillis ).toNanos() ); + inUseHistogram = new InternalHistogram(); + } + + @Override + public String uniqueName() + { + return serverAddress.toString(); + } + + @Override + public Histogram connectionTimeHistogram() + { + return connHistogram.snapshot(); + } + + @Override + public Histogram inUseTimeHistogram() + { + return inUseHistogram.snapshot(); + } + + @Override + public void beforeCreating( ListenerEvent connEvent ) + { + // creating a conn + connEvent.start(); + } + + @Override + public void afterCreating( ListenerEvent connEvent ) + { + // finished conn creation + long elapsed = connEvent.elapsed(); + connHistogram.recordValue( elapsed ); + } + + @Override + public void acquiredOrCreated( ListenerEvent inUseEvent ) + { + // created + acquired = inUse + inUseEvent.start(); + } + + @Override + public void released(ListenerEvent inUseEvent) + { + // idle + long elapsed = inUseEvent.elapsed(); + inUseHistogram.recordValue( elapsed ); + } + + @Override + public String toString() + { + return String.format( "connectionTimeHistogram=%s, inUseTimeHistogram=%s", connectionTimeHistogram(), inUseTimeHistogram() ); + } + +} diff --git a/driver/src/main/java/org/neo4j/driver/internal/metrics/InternalConnectionPoolMetrics.java b/driver/src/main/java/org/neo4j/driver/internal/metrics/InternalConnectionPoolMetrics.java index 1415a99b59..8ddac1905c 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/metrics/InternalConnectionPoolMetrics.java +++ b/driver/src/main/java/org/neo4j/driver/internal/metrics/InternalConnectionPoolMetrics.java @@ -19,6 +19,7 @@ package org.neo4j.driver.internal.metrics; +import java.time.Duration; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; @@ -30,7 +31,7 @@ import static java.lang.String.format; import static org.neo4j.driver.internal.metrics.InternalDriverMetrics.serverAddressToUniqueName; -public class InternalConnectionPoolMetrics implements ConnectionPoolMetrics, ConnectionPoolListener +public class InternalConnectionPoolMetrics implements ConnectionPoolMetrics, ConnectionPoolMetricsListener { private final BoltServerAddress address; private final ConnectionPool pool; @@ -40,13 +41,13 @@ public class InternalConnectionPoolMetrics implements ConnectionPoolMetrics, Con private AtomicInteger toCreate = new AtomicInteger(); private AtomicLong failedToCreate = new AtomicLong(); - private InternalHistogram histogram; + private InternalHistogram acquisitionTimeHistogram; - public InternalConnectionPoolMetrics(BoltServerAddress address, ConnectionPool pool, long connAcquisitionTimeoutMs) + public InternalConnectionPoolMetrics( BoltServerAddress address, ConnectionPool pool, long connAcquisitionTimeoutMs ) { this.address = address; this.pool = pool; - this.histogram = new InternalHistogram( connAcquisitionTimeoutMs ); + this.acquisitionTimeHistogram = new InternalHistogram( Duration.ofMillis( connAcquisitionTimeoutMs ).toNanos() ); } @Override @@ -56,16 +57,16 @@ public void beforeCreating() } @Override - public void afterCreatedSuccessfully() + public void afterFailedToCreate() { - created.incrementAndGet(); + failedToCreate.incrementAndGet(); toCreate.decrementAndGet(); } @Override - public void afterFailedToCreate() + public void afterCreated() { - failedToCreate.incrementAndGet(); + created.incrementAndGet(); toCreate.decrementAndGet(); } @@ -76,16 +77,16 @@ public void afterClosed() } @Override - public void beforeAcquire( ListenerEvent listenerEvent ) + public void beforeAcquiringOrCreating( ListenerEvent listenerEvent ) { listenerEvent.start(); } @Override - public void afterAcquire( ListenerEvent listenerEvent ) + public void afterAcquiringOrCreating( ListenerEvent listenerEvent ) { long elapsed = listenerEvent.elapsed(); - histogram.recordValue( elapsed ); + acquisitionTimeHistogram.recordValue( elapsed ); } @Override @@ -146,13 +147,13 @@ public long closed() @Override public Histogram acquisitionTimeHistogram() { - return this.histogram.snapshot(); + return this.acquisitionTimeHistogram.snapshot(); } @Override public String toString() { - return format( "[created=%s, closed=%s, toCreate=%s, failedToCreate=%s inUse=%s, idle=%s, poolStatus=%s, acquisitionTimeHistogram=%s]", - created(), closed(), toCreate(), failedToCreate(), inUse(), idle(), poolStatus(), acquisitionTimeHistogram() ); + return format( "[created=%s, closed=%s, toCreate=%s, failedToCreate=%s inUse=%s, idle=%s, poolStatus=%s, acquisitionTimeHistogram=%s]", created(), + closed(), toCreate(), failedToCreate(), inUse(), idle(), poolStatus(), acquisitionTimeHistogram() ); } } diff --git a/driver/src/main/java/org/neo4j/driver/internal/metrics/InternalDriverMetrics.java b/driver/src/main/java/org/neo4j/driver/internal/metrics/InternalDriverMetrics.java index cbae863ed2..4205e1cb99 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/metrics/InternalDriverMetrics.java +++ b/driver/src/main/java/org/neo4j/driver/internal/metrics/InternalDriverMetrics.java @@ -22,6 +22,9 @@ import java.util.concurrent.ConcurrentHashMap; import org.neo4j.driver.internal.BoltServerAddress; +import org.neo4j.driver.internal.async.pool.ConnectionPoolImpl; +import org.neo4j.driver.internal.metrics.ListenerEvent.ConnectionListenerEvent; +import org.neo4j.driver.internal.metrics.ListenerEvent.PoolListenerEvent; import org.neo4j.driver.internal.metrics.spi.ConnectionMetrics; import org.neo4j.driver.internal.metrics.spi.ConnectionPoolMetrics; import org.neo4j.driver.internal.spi.ConnectionPool; @@ -44,56 +47,75 @@ public InternalDriverMetrics( Config config ) } @Override - public void addPoolMetrics( BoltServerAddress serverAddress, ConnectionPool pool ) + public void addMetrics( BoltServerAddress serverAddress, ConnectionPoolImpl pool ) { - this.connectionPoolMetrics.put( serverAddressToUniqueName( serverAddress ), - new InternalConnectionPoolMetrics( serverAddress, pool, config.connectionAcquisitionTimeoutMillis() ) ); + addPoolMetrics( serverAddress, pool ); + addConnectionMetrics( serverAddress ); + } + + @Override + public void beforeCreating( BoltServerAddress serverAddress, ConnectionListenerEvent creatingEvent ) + { + poolMetrics( serverAddress ).beforeCreating(); + connectionMetrics( serverAddress ).beforeCreating( creatingEvent ); } @Override - public void beforeCreating( BoltServerAddress serverAddress ) + public void afterCreating( BoltServerAddress serverAddress, ConnectionListenerEvent creatingEvent ) { - InternalConnectionPoolMetrics poolMetrics = getPoolMetrics( serverAddress ); - poolMetrics.beforeCreating(); + connectionMetrics( serverAddress ).afterCreating( creatingEvent ); } @Override - public void afterCreatedSuccessfully( BoltServerAddress serverAddress ) + public void afterCreated( BoltServerAddress serverAddress ) { - InternalConnectionPoolMetrics poolMetrics = getPoolMetrics( serverAddress ); - poolMetrics.afterCreatedSuccessfully(); + poolMetrics( serverAddress ).afterCreated(); } @Override public void afterFailedToCreate( BoltServerAddress serverAddress ) { - InternalConnectionPoolMetrics poolMetrics = getPoolMetrics( serverAddress ); - poolMetrics.afterFailedToCreate(); + poolMetrics( serverAddress ).afterFailedToCreate(); } @Override public void afterClosed( BoltServerAddress serverAddress ) { - InternalConnectionPoolMetrics poolMetrics = getPoolMetrics( serverAddress ); - poolMetrics.afterClosed(); + poolMetrics( serverAddress ).afterClosed(); + } + + @Override + public void beforeAcquiringOrCreating( BoltServerAddress serverAddress, PoolListenerEvent listenerEvent ) + { + poolMetrics( serverAddress ).beforeAcquiringOrCreating( listenerEvent ); + } + + @Override + public void afterAcquiringOrCreating( BoltServerAddress serverAddress, PoolListenerEvent listenerEvent ) + { + poolMetrics( serverAddress ).afterAcquiringOrCreating( listenerEvent ); + } + + @Override + public void afterAcquiredOrCreated( BoltServerAddress serverAddress, ConnectionListenerEvent inUseEvent ) + { + connectionMetrics( serverAddress ).acquiredOrCreated( inUseEvent ); } @Override - public void beforeAcquiring( BoltServerAddress serverAddress, ListenerEvent listenerEvent ) + public void afterReleased( BoltServerAddress serverAddress, ConnectionListenerEvent inUseEvent ) { - InternalConnectionPoolMetrics poolMetrics = getPoolMetrics( serverAddress ); - poolMetrics.beforeAcquire( listenerEvent ); + connectionMetrics( serverAddress ).released( inUseEvent ); } @Override - public void afterAcquired( BoltServerAddress serverAddress, ListenerEvent listenerEvent ) + public ConnectionListenerEvent createConnectionListenerEvent() { - InternalConnectionPoolMetrics poolMetrics = getPoolMetrics( serverAddress ); - poolMetrics.afterAcquire( listenerEvent ); + return new NanoTimeBasedListenerEvent(); } @Override - public ListenerEvent createListenerEvent() + public PoolListenerEvent createPoolListenerEvent() { return new NanoTimeBasedListenerEvent(); } @@ -116,19 +138,41 @@ public String toString() return format( "PoolMetrics=%s, ConnMetrics=%s", connectionPoolMetrics, connectionMetrics ); } - public static String serverAddressToUniqueName( BoltServerAddress serverAddress ) + static String serverAddressToUniqueName( BoltServerAddress serverAddress ) { return serverAddress.toString(); } - private InternalConnectionPoolMetrics getPoolMetrics( BoltServerAddress serverAddress ) + private ConnectionPoolMetricsListener poolMetrics( BoltServerAddress serverAddress ) { InternalConnectionPoolMetrics poolMetrics = (InternalConnectionPoolMetrics) this.connectionPoolMetrics.get( serverAddressToUniqueName( serverAddress ) ); if ( poolMetrics == null ) { - throw new ClientException( format( "Failed to find pool metrics for server %s in pool %s", serverAddress, this.connectionPoolMetrics ) ); + throw new ClientException( format( "Failed to find pool metrics for server `%s` in %s", serverAddress, this.connectionPoolMetrics ) ); } return poolMetrics; } + + private ConnectionMetricsListener connectionMetrics( BoltServerAddress serverAddress ) + { + InternalConnectionMetrics connMetrics = (InternalConnectionMetrics) this.connectionMetrics.get( serverAddressToUniqueName( serverAddress ) ); + if ( connMetrics == null ) + { + throw new ClientException( format( "Failed to find connection metrics for server `%s` in %s", serverAddress, this.connectionMetrics ) ); + } + return connMetrics; + } + + private void addPoolMetrics( BoltServerAddress serverAddress, ConnectionPool pool ) + { + this.connectionPoolMetrics.put( serverAddressToUniqueName( serverAddress ), + new InternalConnectionPoolMetrics( serverAddress, pool, config.connectionAcquisitionTimeoutMillis() ) ); + } + + private void addConnectionMetrics( BoltServerAddress serverAddress ) + { + this.connectionMetrics.put( serverAddressToUniqueName( serverAddress ), + new InternalConnectionMetrics( serverAddress, config.connectionTimeoutMillis() ) ); + } } diff --git a/driver/src/main/java/org/neo4j/driver/internal/metrics/InternalHistogram.java b/driver/src/main/java/org/neo4j/driver/internal/metrics/InternalHistogram.java index 313afe044b..8dca066c2d 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/metrics/InternalHistogram.java +++ b/driver/src/main/java/org/neo4j/driver/internal/metrics/InternalHistogram.java @@ -31,18 +31,18 @@ public class InternalHistogram implements Histogram { - private static final long DEFAULT_HIGHEST_TRACKABLE_MS = Duration.ofMinutes( 10 ).toNanos(); + private static final long DEFAULT_HIGHEST_TRACKABLE_NS = Duration.ofMinutes( 10 ).toNanos(); private final AbstractHistogram delegate; public InternalHistogram() { - this( DEFAULT_HIGHEST_TRACKABLE_MS ); + this( DEFAULT_HIGHEST_TRACKABLE_NS ); } - public InternalHistogram( long highestTrackableValue ) + public InternalHistogram( long highestTrackableValueNS ) { - this.delegate = createHdrHistogram( highestTrackableValue ); + this.delegate = createHdrHistogram( highestTrackableValueNS ); } public InternalHistogram( AbstractHistogram histogram ) diff --git a/driver/src/main/java/org/neo4j/driver/internal/metrics/ListenerEvent.java b/driver/src/main/java/org/neo4j/driver/internal/metrics/ListenerEvent.java index e939b40ff7..559c544322 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/metrics/ListenerEvent.java +++ b/driver/src/main/java/org/neo4j/driver/internal/metrics/ListenerEvent.java @@ -23,4 +23,13 @@ public interface ListenerEvent { void start(); long elapsed(); + + interface PoolListenerEvent extends ListenerEvent + { + } + + interface ConnectionListenerEvent extends ListenerEvent + { + } } + diff --git a/driver/src/main/java/org/neo4j/driver/internal/metrics/NanoTimeBasedListenerEvent.java b/driver/src/main/java/org/neo4j/driver/internal/metrics/NanoTimeBasedListenerEvent.java index a2c315c4fd..4310f18015 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/metrics/NanoTimeBasedListenerEvent.java +++ b/driver/src/main/java/org/neo4j/driver/internal/metrics/NanoTimeBasedListenerEvent.java @@ -19,7 +19,10 @@ package org.neo4j.driver.internal.metrics; -public class NanoTimeBasedListenerEvent implements ListenerEvent +import org.neo4j.driver.internal.metrics.ListenerEvent.ConnectionListenerEvent; +import org.neo4j.driver.internal.metrics.ListenerEvent.PoolListenerEvent; + +public class NanoTimeBasedListenerEvent implements PoolListenerEvent, ConnectionListenerEvent { private long startNanoTime; diff --git a/driver/src/main/java/org/neo4j/driver/internal/metrics/spi/ConnectionMetrics.java b/driver/src/main/java/org/neo4j/driver/internal/metrics/spi/ConnectionMetrics.java index f39289f79e..a0f5f773bb 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/metrics/spi/ConnectionMetrics.java +++ b/driver/src/main/java/org/neo4j/driver/internal/metrics/spi/ConnectionMetrics.java @@ -20,4 +20,21 @@ public interface ConnectionMetrics { + /** + * The unique name of this connection metrics among all connection metrics + * @return An unique name of this connection metrics among all connection metrics + */ + String uniqueName(); + + /** + * The connection time histogram describes how long it takes to establish a connection + * @return The connection time histogram + */ + Histogram connectionTimeHistogram (); + + /** + * The in-use time histogram records how long each connection is borrowed out of the pool + * @return The in-use time histogram + */ + Histogram inUseTimeHistogram(); } diff --git a/driver/src/main/java/org/neo4j/driver/internal/metrics/spi/ConnectionPoolMetrics.java b/driver/src/main/java/org/neo4j/driver/internal/metrics/spi/ConnectionPoolMetrics.java index ac1e14ea74..45f91f5c7d 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/metrics/spi/ConnectionPoolMetrics.java +++ b/driver/src/main/java/org/neo4j/driver/internal/metrics/spi/ConnectionPoolMetrics.java @@ -20,15 +20,63 @@ public interface ConnectionPoolMetrics { + /** + * An unique name that identifies this connection pool metrics among all others + * @return An unique name + */ String uniqueName(); + + /** + * The status of the pool + * @return The status of the pool in a string + */ String poolStatus(); + + /** + * The amount of connections that is in-use (borrowed out of the pool). + * The number is changing up and down from time to time. + * @return The amount of connections that is in-use + */ int inUse(); + + /** + * The amount of connections that is idle (buffered inside the pool). + * The number is changing up and down from time to time. + * @return The amount of connections that is idle. + */ int idle(); + + /** + * The amount of connections that is going to be created. + * The amount is increased by one when the pool noticed a request to create a new connection. + * The amount is decreased by one when the pool noticed a new connection is created regardless successfully or not. + * The number is changing up and down from time to time. + * @return The amount of connection that is to be created. + */ int toCreate(); + /** + * An increasing-only number to record how many connections have been created by this pool successfully. + * @return The amount of connections have ever been created by this pool. + */ long created(); + + /** + * An increasing-only number to record how many connections have been failed to create. + * @return The amount of connections have been failed to create by this pool. + */ long failedToCreate(); + + /** + * An increasing-only number to record how many connections have been closed by this pool. + * @return The amount of connections have been closed by this pool. + */ long closed(); + /** + * An acquisition time histogram records how long it takes to acquire an connection from this pool. + * The connection acquired from the pool could either be a connection idling inside the pool or a connection created by the pool. + * @return The acquisition time histogram. + */ Histogram acquisitionTimeHistogram(); } diff --git a/driver/src/main/java/org/neo4j/driver/internal/metrics/spi/DriverMetrics.java b/driver/src/main/java/org/neo4j/driver/internal/metrics/spi/DriverMetrics.java index 5ed778053c..6a3314ce27 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/metrics/spi/DriverMetrics.java +++ b/driver/src/main/java/org/neo4j/driver/internal/metrics/spi/DriverMetrics.java @@ -22,14 +22,25 @@ public interface DriverMetrics { - // TODO Once this interface because public, find a better way to enable metrics + // TODO Once this interface become public, find a better way to enable metrics and detect metrics availability. String DRIVER_METRICS_ENABLED_KEY = "driver.metrics.enabled"; + static boolean isDriverMetricsEnabled() + { + return Boolean.valueOf( System.getProperty( DRIVER_METRICS_ENABLED_KEY, "false" ) ); + } + /** + * A map of connection pool metrics. + * The {@link ConnectionPoolMetrics#uniqueName()} are used as the keys of the map. + * @return The connection pool metrics. + */ Map connectionPoolMetrics(); + + /*** + * A map of connection metrics. + * The {@link ConnectionMetrics#uniqueName()} are used as the keys of the map. + * @return The connection metrics. + */ Map connectionMetrics(); - public static boolean isDriverMetricsEnabled() - { - return Boolean.valueOf( System.getProperty( DRIVER_METRICS_ENABLED_KEY, "false" ) ); - } } diff --git a/driver/src/main/java/org/neo4j/driver/internal/metrics/spi/Histogram.java b/driver/src/main/java/org/neo4j/driver/internal/metrics/spi/Histogram.java index 00e34452e0..a05948d48c 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/metrics/spi/Histogram.java +++ b/driver/src/main/java/org/neo4j/driver/internal/metrics/spi/Histogram.java @@ -20,13 +20,45 @@ public interface Histogram { + /** + * The minimum value recorded in this histogram. + * @return The minimum value recorded in this histogram. + */ long min(); + + /** + * The maximum value recorded in this histogram. + * @return The maximum value recorded in this histogram. + */ long max(); + + /** + * The mean value of this histogram. + * @return The mean value. + */ double mean(); + + /** + * The standard deviation of this histogram. + * @return The standard deviation. + */ double stdDeviation(); + /** + * The total count of the values recorded in this histogram. + * @return The total number of values. + */ long totalCount(); + + /** + * Returns the value at the given percentile. + * @param percentile The interested percentile such as 50 (mean value), 80 etc. + * @return The value at the given percentile. + */ long valueAtPercentile(double percentile); + /** + * Reset cleans all the values recorded in this histogram. + */ void reset(); } diff --git a/driver/src/test/java/org/neo4j/driver/internal/DriverFactoryTest.java b/driver/src/test/java/org/neo4j/driver/internal/DriverFactoryTest.java index 8b334d3350..907b95682c 100644 --- a/driver/src/test/java/org/neo4j/driver/internal/DriverFactoryTest.java +++ b/driver/src/test/java/org/neo4j/driver/internal/DriverFactoryTest.java @@ -194,10 +194,11 @@ public void shouldNotCreateDriverMetrics() throws Throwable public void shouldCreateDriverMetricsIfMonitoringEnabled() throws Throwable { // Given - System.setProperty( "driver.metrics.enabled", "True" ); Config config = mock( Config.class ); + System.setProperty( "driver.metrics.enabled", "True" ); // When DriverMetricsListener handler = DriverFactory.createDriverMetrics( config ); + System.setProperty( "driver.metrics.enabled", "False" ); // Then assertThat( handler instanceof InternalDriverMetrics, is( true ) ); } diff --git a/driver/src/test/java/org/neo4j/driver/internal/async/NettyConnectionTest.java b/driver/src/test/java/org/neo4j/driver/internal/async/NettyConnectionTest.java index b96f39b6e8..b1791b89f0 100644 --- a/driver/src/test/java/org/neo4j/driver/internal/async/NettyConnectionTest.java +++ b/driver/src/test/java/org/neo4j/driver/internal/async/NettyConnectionTest.java @@ -60,6 +60,7 @@ import static org.neo4j.driver.internal.async.ChannelAttributes.terminationReason; import static org.neo4j.driver.internal.logging.DevNullLogging.DEV_NULL_LOGGING; import static org.neo4j.driver.internal.messaging.ResetMessage.RESET; +import static org.neo4j.driver.internal.metrics.InternalAbstractDriverMetrics.DEV_NULL_METRICS; import static org.neo4j.driver.internal.util.Iterables.single; import static org.neo4j.driver.v1.util.DaemonThreadFactory.daemon; @@ -497,7 +498,7 @@ private static NettyConnection newConnection( Channel channel ) private static NettyConnection newConnection( Channel channel, ChannelPool pool ) { - return new NettyConnection( channel, pool, new FakeClock() ); + return new NettyConnection( channel, pool, new FakeClock(), DEV_NULL_METRICS ); } private static void assertConnectionReleasedError( IllegalStateException e ) diff --git a/pom.xml b/pom.xml index 79106f645b..ddcd87b37f 100644 --- a/pom.xml +++ b/pom.xml @@ -58,7 +58,7 @@ org.hdrhistogram - hdrHistogram + HdrHistogram 2.1.10 From b0fba93370a1b15752b029502a9bcffdfe30a8ee Mon Sep 17 00:00:00 2001 From: Zhen Date: Wed, 21 Feb 2018 14:48:41 +0100 Subject: [PATCH 5/6] The metrics registration must happen before the pool creation to avoid accessing a metrics of a pool before the metrics is fully created. --- .../async/pool/ConnectionPoolImpl.java | 24 +++++++++---------- .../metrics/InternalConnectionMetrics.java | 2 ++ .../InternalConnectionPoolMetrics.java | 4 ++++ .../metrics/InternalDriverMetrics.java | 2 ++ 4 files changed, 20 insertions(+), 12 deletions(-) diff --git a/driver/src/main/java/org/neo4j/driver/internal/async/pool/ConnectionPoolImpl.java b/driver/src/main/java/org/neo4j/driver/internal/async/pool/ConnectionPoolImpl.java index 23f258d6d2..d6a45bb6b9 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/async/pool/ConnectionPoolImpl.java +++ b/driver/src/main/java/org/neo4j/driver/internal/async/pool/ConnectionPoolImpl.java @@ -179,23 +179,23 @@ public boolean isOpen() private ChannelPool getOrCreatePool( BoltServerAddress address ) { ChannelPool pool = pools.get( address ); - if ( pool == null ) + if ( pool != null ) { - pool = newPool( address ); + return pool; + } - if ( pools.putIfAbsent( address, pool ) != null ) - { - // We lost a race to create the pool, dispose of the one we created, and recurse - pool.close(); - return getOrCreatePool( address ); - } - else + synchronized ( this ) + { + pool = pools.get( address ); + if ( pool != null ) { - // We added a new pool as a result we add a new metrics for the pool too - driverMetricsListener.addMetrics( address, this ); + return pool; } - } + driverMetricsListener.addMetrics( address, this ); + pool = newPool( address ); + pools.put( address, pool ); + } return pool; } diff --git a/driver/src/main/java/org/neo4j/driver/internal/metrics/InternalConnectionMetrics.java b/driver/src/main/java/org/neo4j/driver/internal/metrics/InternalConnectionMetrics.java index b502031879..6db36f3b71 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/metrics/InternalConnectionMetrics.java +++ b/driver/src/main/java/org/neo4j/driver/internal/metrics/InternalConnectionMetrics.java @@ -19,6 +19,7 @@ package org.neo4j.driver.internal.metrics; import java.time.Duration; +import java.util.Objects; import org.neo4j.driver.internal.BoltServerAddress; import org.neo4j.driver.internal.metrics.spi.ConnectionMetrics; @@ -33,6 +34,7 @@ public class InternalConnectionMetrics implements ConnectionMetrics, ConnectionM public InternalConnectionMetrics( BoltServerAddress serverAddress, int connectionTimeoutMillis ) { + Objects.requireNonNull( serverAddress ); this.serverAddress = serverAddress; connHistogram = new InternalHistogram( Duration.ofMillis( connectionTimeoutMillis ).toNanos() ); inUseHistogram = new InternalHistogram(); diff --git a/driver/src/main/java/org/neo4j/driver/internal/metrics/InternalConnectionPoolMetrics.java b/driver/src/main/java/org/neo4j/driver/internal/metrics/InternalConnectionPoolMetrics.java index 8ddac1905c..e735bd1193 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/metrics/InternalConnectionPoolMetrics.java +++ b/driver/src/main/java/org/neo4j/driver/internal/metrics/InternalConnectionPoolMetrics.java @@ -20,6 +20,7 @@ package org.neo4j.driver.internal.metrics; import java.time.Duration; +import java.util.Objects; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; @@ -45,6 +46,9 @@ public class InternalConnectionPoolMetrics implements ConnectionPoolMetrics, Con public InternalConnectionPoolMetrics( BoltServerAddress address, ConnectionPool pool, long connAcquisitionTimeoutMs ) { + Objects.requireNonNull( address ); + Objects.requireNonNull( pool ); + this.address = address; this.pool = pool; this.acquisitionTimeHistogram = new InternalHistogram( Duration.ofMillis( connAcquisitionTimeoutMs ).toNanos() ); diff --git a/driver/src/main/java/org/neo4j/driver/internal/metrics/InternalDriverMetrics.java b/driver/src/main/java/org/neo4j/driver/internal/metrics/InternalDriverMetrics.java index 4205e1cb99..9a7d9f9727 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/metrics/InternalDriverMetrics.java +++ b/driver/src/main/java/org/neo4j/driver/internal/metrics/InternalDriverMetrics.java @@ -19,6 +19,7 @@ package org.neo4j.driver.internal.metrics; import java.util.Map; +import java.util.Objects; import java.util.concurrent.ConcurrentHashMap; import org.neo4j.driver.internal.BoltServerAddress; @@ -41,6 +42,7 @@ public class InternalDriverMetrics extends InternalAbstractDriverMetrics public InternalDriverMetrics( Config config ) { + Objects.requireNonNull( config ); this.config = config; this.connectionPoolMetrics = new ConcurrentHashMap<>(); this.connectionMetrics = new ConcurrentHashMap<>(); From f6dc9007ae38894f863a86a7eb2855dd4e282dff Mon Sep 17 00:00:00 2001 From: Zhen Date: Mon, 26 Feb 2018 17:21:42 +0100 Subject: [PATCH 6/6] Fix after review --- driver/pom.xml | 2 +- .../neo4j/driver/internal/DriverFactory.java | 52 +++++++++---------- .../neo4j/driver/internal/InternalDriver.java | 16 +++--- .../internal/async/NettyConnection.java | 16 +++--- .../async/pool/ConnectionPoolImpl.java | 22 ++++---- .../internal/async/pool/NettyChannelPool.java | 4 +- .../async/pool/NettyChannelTracker.java | 14 ++--- .../internal/metrics/HistogramSnapshot.java | 4 +- ...rics.java => InternalAbstractMetrics.java} | 25 ++++----- .../InternalConnectionPoolMetrics.java | 25 ++++----- .../internal/metrics/InternalHistogram.java | 15 +----- ...riverMetrics.java => InternalMetrics.java} | 26 ++++------ .../internal/metrics/ListenerEvent.java | 8 --- ...ricsListener.java => MetricsListener.java} | 26 ++++------ .../metrics/NanoTimeBasedListenerEvent.java | 5 +- .../metrics/spi/ConnectionPoolMetrics.java | 6 +-- .../spi/{DriverMetrics.java => Metrics.java} | 6 +-- .../internal/metrics/spi/PoolStatus.java | 24 +++++++++ .../driver/internal/DriverFactoryTest.java | 28 +++++----- .../driver/internal/InternalDriverTest.java | 3 +- .../internal/async/NettyConnectionTest.java | 2 +- .../async/pool/ConnectionPoolImplTest.java | 2 +- .../async/pool/NettyChannelPoolTest.java | 2 +- .../async/pool/NettyChannelTrackerTest.java | 2 +- .../util/ChannelTrackingDriverFactory.java | 4 +- .../util/FailingConnectionDriverFactory.java | 4 +- .../v1/integration/ConnectionHandlingIT.java | 6 +-- .../v1/stress/AbstractStressTestBase.java | 6 +-- 28 files changed, 167 insertions(+), 188 deletions(-) rename driver/src/main/java/org/neo4j/driver/internal/metrics/{InternalAbstractDriverMetrics.java => InternalAbstractMetrics.java} (75%) rename driver/src/main/java/org/neo4j/driver/internal/metrics/{InternalDriverMetrics.java => InternalMetrics.java} (88%) rename driver/src/main/java/org/neo4j/driver/internal/metrics/{DriverMetricsListener.java => MetricsListener.java} (80%) rename driver/src/main/java/org/neo4j/driver/internal/metrics/spi/{DriverMetrics.java => Metrics.java} (89%) create mode 100644 driver/src/main/java/org/neo4j/driver/internal/metrics/spi/PoolStatus.java diff --git a/driver/pom.xml b/driver/pom.xml index 927936c9fe..947d7b6f33 100644 --- a/driver/pom.xml +++ b/driver/pom.xml @@ -212,7 +212,7 @@ io.netty:* - org.HdrHistogram:* + org.hdrhistogram:* diff --git a/driver/src/main/java/org/neo4j/driver/internal/DriverFactory.java b/driver/src/main/java/org/neo4j/driver/internal/DriverFactory.java index 035c6505b2..7f0a2d533d 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/DriverFactory.java +++ b/driver/src/main/java/org/neo4j/driver/internal/DriverFactory.java @@ -38,9 +38,10 @@ import org.neo4j.driver.internal.cluster.loadbalancing.LoadBalancingStrategy; import org.neo4j.driver.internal.cluster.loadbalancing.RoundRobinLoadBalancingStrategy; import org.neo4j.driver.internal.logging.NettyLogging; -import org.neo4j.driver.internal.metrics.DriverMetricsListener; -import org.neo4j.driver.internal.metrics.InternalAbstractDriverMetrics; -import org.neo4j.driver.internal.metrics.InternalDriverMetrics; +import org.neo4j.driver.internal.metrics.MetricsListener; +import org.neo4j.driver.internal.metrics.InternalAbstractMetrics; +import org.neo4j.driver.internal.metrics.InternalMetrics; +import org.neo4j.driver.internal.metrics.spi.Metrics; import org.neo4j.driver.internal.retry.ExponentialBackoffRetryLogic; import org.neo4j.driver.internal.retry.RetryLogic; import org.neo4j.driver.internal.retry.RetrySettings; @@ -59,8 +60,8 @@ import org.neo4j.driver.v1.exceptions.ServiceUnavailableException; import static java.lang.String.format; -import static org.neo4j.driver.internal.metrics.InternalAbstractDriverMetrics.DEV_NULL_METRICS; -import static org.neo4j.driver.internal.metrics.spi.DriverMetrics.isDriverMetricsEnabled; +import static org.neo4j.driver.internal.metrics.InternalAbstractMetrics.DEV_NULL_METRICS; +import static org.neo4j.driver.internal.metrics.spi.Metrics.isMetricsEnabled; import static org.neo4j.driver.internal.security.SecurityPlan.insecure; public class DriverFactory @@ -82,19 +83,17 @@ public final Driver newInstance( URI uri, AuthToken authToken, RoutingSettings r EventExecutorGroup eventExecutorGroup = bootstrap.config().group(); RetryLogic retryLogic = createRetryLogic( retrySettings, eventExecutorGroup, config.logging() ); - InternalAbstractDriverMetrics metrics = createDriverMetrics( config ); + InternalAbstractMetrics metrics = createDriverMetrics( config ); ConnectionPool connectionPool = createConnectionPool( authToken, securityPlan, bootstrap, metrics, config ); - InternalDriver driver = createDriver( uri, address, connectionPool, config, newRoutingSettings, - eventExecutorGroup, securityPlan, retryLogic ); + InternalDriver driver = createDriver( uri, securityPlan, address, connectionPool, eventExecutorGroup, newRoutingSettings, retryLogic, metrics, config ); - driver.driverMetrics( metrics ); verifyConnectivity( driver, connectionPool, config ); return driver; } - protected ConnectionPool createConnectionPool( AuthToken authToken, SecurityPlan securityPlan, Bootstrap bootstrap, DriverMetricsListener metrics, Config config ) + protected ConnectionPool createConnectionPool( AuthToken authToken, SecurityPlan securityPlan, Bootstrap bootstrap, MetricsListener metrics, Config config ) { Clock clock = createClock(); ConnectionSettings settings = new ConnectionSettings( authToken, config.connectionTimeoutMillis() ); @@ -106,11 +105,11 @@ protected ConnectionPool createConnectionPool( AuthToken authToken, SecurityPlan return new ConnectionPoolImpl( connector, bootstrap, poolSettings, metrics, config.logging(), clock ); } - protected static InternalAbstractDriverMetrics createDriverMetrics( Config config ) + protected static InternalAbstractMetrics createDriverMetrics( Config config ) { - if( isDriverMetricsEnabled() ) + if( isMetricsEnabled() ) { - return new InternalDriverMetrics( config ); + return new InternalMetrics( config ); } else { @@ -124,9 +123,8 @@ protected ChannelConnector createConnector( ConnectionSettings settings, Securit return new ChannelConnectorImpl( settings, securityPlan, config.logging(), clock ); } - private InternalDriver createDriver( URI uri, BoltServerAddress address, - ConnectionPool connectionPool, Config config, RoutingSettings routingSettings, - EventExecutorGroup eventExecutorGroup, SecurityPlan securityPlan, RetryLogic retryLogic ) + private InternalDriver createDriver( URI uri, SecurityPlan securityPlan, BoltServerAddress address, ConnectionPool connectionPool, + EventExecutorGroup eventExecutorGroup, RoutingSettings routingSettings, RetryLogic retryLogic, Metrics metrics, Config config ) { try { @@ -135,10 +133,9 @@ private InternalDriver createDriver( URI uri, BoltServerAddress address, { case BOLT_URI_SCHEME: assertNoRoutingContext( uri, routingSettings ); - return createDirectDriver( address, config, securityPlan, retryLogic, connectionPool ); + return createDirectDriver( securityPlan, address, connectionPool, retryLogic, metrics, config ); case BOLT_ROUTING_URI_SCHEME: - return createRoutingDriver( address, connectionPool, config, routingSettings, securityPlan, retryLogic, - eventExecutorGroup ); + return createRoutingDriver( securityPlan, address, connectionPool, eventExecutorGroup, routingSettings, retryLogic, metrics, config ); default: throw new ClientException( format( "Unsupported URI scheme: %s", scheme ) ); } @@ -156,12 +153,12 @@ private InternalDriver createDriver( URI uri, BoltServerAddress address, *

* This method is protected only for testing */ - protected InternalDriver createDirectDriver( BoltServerAddress address, Config config, - SecurityPlan securityPlan, RetryLogic retryLogic, ConnectionPool connectionPool ) + protected InternalDriver createDirectDriver( SecurityPlan securityPlan, BoltServerAddress address, ConnectionPool connectionPool, RetryLogic retryLogic, + Metrics metrics, Config config ) { ConnectionProvider connectionProvider = new DirectConnectionProvider( address, connectionPool ); SessionFactory sessionFactory = createSessionFactory( connectionProvider, retryLogic, config ); - return createDriver( sessionFactory, securityPlan, config ); + return createDriver( securityPlan, sessionFactory, metrics, config ); } /** @@ -169,9 +166,8 @@ protected InternalDriver createDirectDriver( BoltServerAddress address, Config c *

* This method is protected only for testing */ - protected InternalDriver createRoutingDriver( BoltServerAddress address, ConnectionPool connectionPool, - Config config, RoutingSettings routingSettings, SecurityPlan securityPlan, RetryLogic retryLogic, - EventExecutorGroup eventExecutorGroup ) + protected InternalDriver createRoutingDriver( SecurityPlan securityPlan, BoltServerAddress address, ConnectionPool connectionPool, + EventExecutorGroup eventExecutorGroup, RoutingSettings routingSettings, RetryLogic retryLogic, Metrics metrics, Config config ) { if ( !securityPlan.isRoutingCompatible() ) { @@ -180,7 +176,7 @@ protected InternalDriver createRoutingDriver( BoltServerAddress address, Connect ConnectionProvider connectionProvider = createLoadBalancer( address, connectionPool, eventExecutorGroup, config, routingSettings ); SessionFactory sessionFactory = createSessionFactory( connectionProvider, retryLogic, config ); - return createDriver( sessionFactory, securityPlan, config ); + return createDriver( securityPlan, sessionFactory, metrics, config ); } /** @@ -188,9 +184,9 @@ protected InternalDriver createRoutingDriver( BoltServerAddress address, Connect *

* This method is protected only for testing */ - protected InternalDriver createDriver( SessionFactory sessionFactory, SecurityPlan securityPlan, Config config ) + protected InternalDriver createDriver( SecurityPlan securityPlan, SessionFactory sessionFactory, Metrics metrics, Config config ) { - return new InternalDriver( securityPlan, sessionFactory, config.logging() ); + return new InternalDriver( securityPlan, sessionFactory, metrics, config.logging() ); } /** diff --git a/driver/src/main/java/org/neo4j/driver/internal/InternalDriver.java b/driver/src/main/java/org/neo4j/driver/internal/InternalDriver.java index a4b22aa892..3378ab3531 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/InternalDriver.java +++ b/driver/src/main/java/org/neo4j/driver/internal/InternalDriver.java @@ -21,7 +21,7 @@ import java.util.concurrent.CompletionStage; import java.util.concurrent.atomic.AtomicBoolean; -import org.neo4j.driver.internal.metrics.spi.DriverMetrics; +import org.neo4j.driver.internal.metrics.spi.Metrics; import org.neo4j.driver.internal.security.SecurityPlan; import org.neo4j.driver.internal.util.Futures; import org.neo4j.driver.v1.AccessMode; @@ -39,12 +39,13 @@ public class InternalDriver implements Driver private final Logger log; private AtomicBoolean closed = new AtomicBoolean( false ); - private DriverMetrics driverMetrics; + private final Metrics metrics; - InternalDriver( SecurityPlan securityPlan, SessionFactory sessionFactory, Logging logging ) + InternalDriver( SecurityPlan securityPlan, SessionFactory sessionFactory, Metrics metrics, Logging logging ) { this.securityPlan = securityPlan; this.sessionFactory = sessionFactory; + this.metrics = metrics; this.log = logging.getLog( Driver.class.getSimpleName() ); log.info( "Driver instance %s created", this ); } @@ -146,14 +147,9 @@ private void assertOpen() } } - public DriverMetrics driverMetrics() + public Metrics metrics() { - return this.driverMetrics; - } - - void driverMetrics( DriverMetrics driverMetrics ) - { - this.driverMetrics = driverMetrics; + return this.metrics; } private static RuntimeException driverCloseException() diff --git a/driver/src/main/java/org/neo4j/driver/internal/async/NettyConnection.java b/driver/src/main/java/org/neo4j/driver/internal/async/NettyConnection.java index c0869f562c..8035010730 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/async/NettyConnection.java +++ b/driver/src/main/java/org/neo4j/driver/internal/async/NettyConnection.java @@ -34,8 +34,8 @@ import org.neo4j.driver.internal.messaging.PullAllMessage; import org.neo4j.driver.internal.messaging.ResetMessage; import org.neo4j.driver.internal.messaging.RunMessage; -import org.neo4j.driver.internal.metrics.DriverMetricsListener; -import org.neo4j.driver.internal.metrics.ListenerEvent.ConnectionListenerEvent; +import org.neo4j.driver.internal.metrics.ListenerEvent; +import org.neo4j.driver.internal.metrics.MetricsListener; import org.neo4j.driver.internal.spi.Connection; import org.neo4j.driver.internal.spi.ResponseHandler; import org.neo4j.driver.internal.util.Clock; @@ -56,10 +56,10 @@ public class NettyConnection implements Connection private final Clock clock; private final AtomicReference status = new AtomicReference<>( Status.OPEN ); - private final DriverMetricsListener metricsListener; - private final ConnectionListenerEvent inUseEvent; + private final MetricsListener metricsListener; + private final ListenerEvent inUseEvent; - public NettyConnection( Channel channel, ChannelPool channelPool, Clock clock, DriverMetricsListener driverMetricsListener ) + public NettyConnection( Channel channel, ChannelPool channelPool, Clock clock, MetricsListener metricsListener ) { this.channel = channel; this.messageDispatcher = ChannelAttributes.messageDispatcher( channel ); @@ -68,9 +68,9 @@ public NettyConnection( Channel channel, ChannelPool channelPool, Clock clock, D this.channelPool = channelPool; this.releaseFuture = new CompletableFuture<>(); this.clock = clock; - this.metricsListener = driverMetricsListener; - this.inUseEvent = driverMetricsListener.createConnectionListenerEvent(); - driverMetricsListener.afterAcquiredOrCreated( this.serverAddress, this.inUseEvent ); + this.metricsListener = metricsListener; + this.inUseEvent = metricsListener.createListenerEvent(); + metricsListener.afterAcquiredOrCreated( this.serverAddress, this.inUseEvent ); } @Override diff --git a/driver/src/main/java/org/neo4j/driver/internal/async/pool/ConnectionPoolImpl.java b/driver/src/main/java/org/neo4j/driver/internal/async/pool/ConnectionPoolImpl.java index d6a45bb6b9..474ec9e56e 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/async/pool/ConnectionPoolImpl.java +++ b/driver/src/main/java/org/neo4j/driver/internal/async/pool/ConnectionPoolImpl.java @@ -36,8 +36,8 @@ import org.neo4j.driver.internal.BoltServerAddress; import org.neo4j.driver.internal.async.ChannelConnector; import org.neo4j.driver.internal.async.NettyConnection; -import org.neo4j.driver.internal.metrics.DriverMetricsListener; -import org.neo4j.driver.internal.metrics.ListenerEvent.PoolListenerEvent; +import org.neo4j.driver.internal.metrics.ListenerEvent; +import org.neo4j.driver.internal.metrics.MetricsListener; import org.neo4j.driver.internal.spi.Connection; import org.neo4j.driver.internal.spi.ConnectionPool; import org.neo4j.driver.internal.util.Clock; @@ -55,26 +55,26 @@ public class ConnectionPoolImpl implements ConnectionPool private final PoolSettings settings; private final Clock clock; private final Logger log; - private DriverMetricsListener driverMetricsListener; + private MetricsListener metricsListener; private final ConcurrentMap pools = new ConcurrentHashMap<>(); private final AtomicBoolean closed = new AtomicBoolean(); public ConnectionPoolImpl( ChannelConnector connector, Bootstrap bootstrap, PoolSettings settings, - DriverMetricsListener metricsListener, Logging logging, Clock clock ) + MetricsListener metricsListener, Logging logging, Clock clock ) { this( connector, bootstrap, new NettyChannelTracker( metricsListener, logging ), settings, metricsListener, logging, clock ); } ConnectionPoolImpl( ChannelConnector connector, Bootstrap bootstrap, NettyChannelTracker nettyChannelTracker, - PoolSettings settings, DriverMetricsListener metricsListener, Logging logging, Clock clock ) + PoolSettings settings, MetricsListener metricsListener, Logging logging, Clock clock ) { this.connector = connector; this.bootstrap = bootstrap; this.nettyChannelTracker = nettyChannelTracker; this.channelHealthChecker = new NettyChannelHealthChecker( settings, clock, logging ); this.settings = settings; - this.driverMetricsListener = metricsListener; + this.metricsListener = metricsListener; this.clock = clock; this.log = logging.getLog( ConnectionPool.class.getSimpleName() ); } @@ -87,8 +87,8 @@ public CompletionStage acquire( BoltServerAddress address ) assertNotClosed(); ChannelPool pool = getOrCreatePool( address ); - PoolListenerEvent acquireEvent = driverMetricsListener.createPoolListenerEvent(); - driverMetricsListener.beforeAcquiringOrCreating( address, acquireEvent ); + ListenerEvent acquireEvent = metricsListener.createListenerEvent(); + metricsListener.beforeAcquiringOrCreating( address, acquireEvent ); Future connectionFuture = pool.acquire(); return Futures.asCompletionStage( connectionFuture ).handle( ( channel, error ) -> @@ -97,11 +97,11 @@ public CompletionStage acquire( BoltServerAddress address ) { processAcquisitionError( error ); assertNotClosed( address, channel, pool ); - return new NettyConnection( channel, pool, clock, driverMetricsListener ); + return new NettyConnection( channel, pool, clock, metricsListener ); } finally { - driverMetricsListener.afterAcquiringOrCreating( address, acquireEvent ); + metricsListener.afterAcquiringOrCreating( address, acquireEvent ); } } ); } @@ -192,7 +192,7 @@ private ChannelPool getOrCreatePool( BoltServerAddress address ) return pool; } - driverMetricsListener.addMetrics( address, this ); + metricsListener.addMetrics( address, this ); pool = newPool( address ); pools.put( address, pool ); } diff --git a/driver/src/main/java/org/neo4j/driver/internal/async/pool/NettyChannelPool.java b/driver/src/main/java/org/neo4j/driver/internal/async/pool/NettyChannelPool.java index bee5f953f3..e350ae0388 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/async/pool/NettyChannelPool.java +++ b/driver/src/main/java/org/neo4j/driver/internal/async/pool/NettyChannelPool.java @@ -26,7 +26,7 @@ import org.neo4j.driver.internal.BoltServerAddress; import org.neo4j.driver.internal.async.ChannelConnector; -import org.neo4j.driver.internal.metrics.ListenerEvent.ConnectionListenerEvent; +import org.neo4j.driver.internal.metrics.ListenerEvent; import static java.util.Objects.requireNonNull; @@ -60,7 +60,7 @@ public NettyChannelPool( BoltServerAddress address, ChannelConnector connector, @Override protected ChannelFuture connectChannel( Bootstrap bootstrap ) { - ConnectionListenerEvent creatingEvent = handler.beforeChannelCreating( address ); + ListenerEvent creatingEvent = handler.beforeChannelCreating( address ); ChannelFuture channelFuture = connector.connect( address, bootstrap ); channelFuture.addListener( future -> { diff --git a/driver/src/main/java/org/neo4j/driver/internal/async/pool/NettyChannelTracker.java b/driver/src/main/java/org/neo4j/driver/internal/async/pool/NettyChannelTracker.java index 8277a2566c..11e98cbad0 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/async/pool/NettyChannelTracker.java +++ b/driver/src/main/java/org/neo4j/driver/internal/async/pool/NettyChannelTracker.java @@ -26,8 +26,8 @@ import java.util.concurrent.atomic.AtomicInteger; import org.neo4j.driver.internal.BoltServerAddress; -import org.neo4j.driver.internal.metrics.DriverMetricsListener; -import org.neo4j.driver.internal.metrics.ListenerEvent.ConnectionListenerEvent; +import org.neo4j.driver.internal.metrics.ListenerEvent; +import org.neo4j.driver.internal.metrics.MetricsListener; import org.neo4j.driver.v1.Logger; import org.neo4j.driver.v1.Logging; @@ -38,9 +38,9 @@ public class NettyChannelTracker implements ChannelPoolHandler private final Map addressToInUseChannelCount = new ConcurrentHashMap<>(); private final Map addressToIdleChannelCount = new ConcurrentHashMap<>(); private final Logger log; - private DriverMetricsListener metricsListener; + private final MetricsListener metricsListener; - public NettyChannelTracker( DriverMetricsListener metricsListener, Logging logging ) + public NettyChannelTracker( MetricsListener metricsListener, Logging logging ) { this.metricsListener = metricsListener; this.log = logging.getLog( getClass().getSimpleName() ); @@ -75,14 +75,14 @@ public void channelFailedToCreate( BoltServerAddress address ) metricsListener.afterFailedToCreate( address ); } - public ConnectionListenerEvent beforeChannelCreating( BoltServerAddress address ) + public ListenerEvent beforeChannelCreating( BoltServerAddress address ) { - ConnectionListenerEvent creatingEvent = metricsListener.createConnectionListenerEvent(); + ListenerEvent creatingEvent = metricsListener.createListenerEvent(); metricsListener.beforeCreating( address, creatingEvent ); return creatingEvent; } - public void afterChannelCreating( BoltServerAddress address, ConnectionListenerEvent creatingEvent ) + public void afterChannelCreating( BoltServerAddress address, ListenerEvent creatingEvent ) { metricsListener.afterCreating( address, creatingEvent ); } diff --git a/driver/src/main/java/org/neo4j/driver/internal/metrics/HistogramSnapshot.java b/driver/src/main/java/org/neo4j/driver/internal/metrics/HistogramSnapshot.java index 5bfd5804bc..8959153abe 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/metrics/HistogramSnapshot.java +++ b/driver/src/main/java/org/neo4j/driver/internal/metrics/HistogramSnapshot.java @@ -22,8 +22,8 @@ public class HistogramSnapshot implements Histogram { - private Histogram copy; - private Histogram origin; + private final Histogram copy; + private final Histogram origin; public HistogramSnapshot( Histogram copy, Histogram origin ) { diff --git a/driver/src/main/java/org/neo4j/driver/internal/metrics/InternalAbstractDriverMetrics.java b/driver/src/main/java/org/neo4j/driver/internal/metrics/InternalAbstractMetrics.java similarity index 75% rename from driver/src/main/java/org/neo4j/driver/internal/metrics/InternalAbstractDriverMetrics.java rename to driver/src/main/java/org/neo4j/driver/internal/metrics/InternalAbstractMetrics.java index 9a50cf4225..959bfe8361 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/metrics/InternalAbstractDriverMetrics.java +++ b/driver/src/main/java/org/neo4j/driver/internal/metrics/InternalAbstractMetrics.java @@ -25,20 +25,20 @@ import org.neo4j.driver.internal.async.pool.ConnectionPoolImpl; import org.neo4j.driver.internal.metrics.spi.ConnectionMetrics; import org.neo4j.driver.internal.metrics.spi.ConnectionPoolMetrics; -import org.neo4j.driver.internal.metrics.spi.DriverMetrics; +import org.neo4j.driver.internal.metrics.spi.Metrics; -public abstract class InternalAbstractDriverMetrics implements DriverMetrics, DriverMetricsListener +public abstract class InternalAbstractMetrics implements Metrics, MetricsListener { - public static final InternalAbstractDriverMetrics DEV_NULL_METRICS = new InternalAbstractDriverMetrics() + public static final InternalAbstractMetrics DEV_NULL_METRICS = new InternalAbstractMetrics() { @Override - public void beforeCreating( BoltServerAddress serverAddress, ListenerEvent.ConnectionListenerEvent creatingEvent ) + public void beforeCreating( BoltServerAddress serverAddress, ListenerEvent creatingEvent ) { } @Override - public void afterCreating( BoltServerAddress serverAddress, ListenerEvent.ConnectionListenerEvent creatingEvent ) + public void afterCreating( BoltServerAddress serverAddress, ListenerEvent creatingEvent ) { } @@ -58,36 +58,31 @@ public void afterClosed( BoltServerAddress serverAddress ) } @Override - public void beforeAcquiringOrCreating( BoltServerAddress serverAddress, ListenerEvent.PoolListenerEvent acquireEvent ) + public void beforeAcquiringOrCreating( BoltServerAddress serverAddress, ListenerEvent acquireEvent ) { } @Override - public void afterAcquiringOrCreating( BoltServerAddress serverAddress, ListenerEvent.PoolListenerEvent acquireEvent ) + public void afterAcquiringOrCreating( BoltServerAddress serverAddress, ListenerEvent acquireEvent ) { } @Override - public void afterAcquiredOrCreated( BoltServerAddress serverAddress, ListenerEvent.ConnectionListenerEvent inUseEvent ) + public void afterAcquiredOrCreated( BoltServerAddress serverAddress, ListenerEvent inUseEvent ) { } @Override - public void afterReleased( BoltServerAddress serverAddress, ListenerEvent.ConnectionListenerEvent inUseEvent ) + public void afterReleased( BoltServerAddress serverAddress, ListenerEvent inUseEvent ) { } @Override - public ListenerEvent.ConnectionListenerEvent createConnectionListenerEvent() + public ListenerEvent createListenerEvent() { return null; } - @Override - public ListenerEvent.PoolListenerEvent createPoolListenerEvent() - { - return null; - } @Override public void addMetrics( BoltServerAddress address, ConnectionPoolImpl connectionPool ) diff --git a/driver/src/main/java/org/neo4j/driver/internal/metrics/InternalConnectionPoolMetrics.java b/driver/src/main/java/org/neo4j/driver/internal/metrics/InternalConnectionPoolMetrics.java index e735bd1193..47130fef65 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/metrics/InternalConnectionPoolMetrics.java +++ b/driver/src/main/java/org/neo4j/driver/internal/metrics/InternalConnectionPoolMetrics.java @@ -27,10 +27,11 @@ import org.neo4j.driver.internal.BoltServerAddress; import org.neo4j.driver.internal.metrics.spi.ConnectionPoolMetrics; import org.neo4j.driver.internal.metrics.spi.Histogram; +import org.neo4j.driver.internal.metrics.spi.PoolStatus; import org.neo4j.driver.internal.spi.ConnectionPool; import static java.lang.String.format; -import static org.neo4j.driver.internal.metrics.InternalDriverMetrics.serverAddressToUniqueName; +import static org.neo4j.driver.internal.metrics.InternalMetrics.serverAddressToUniqueName; public class InternalConnectionPoolMetrics implements ConnectionPoolMetrics, ConnectionPoolMetricsListener { @@ -39,7 +40,7 @@ public class InternalConnectionPoolMetrics implements ConnectionPoolMetrics, Con private AtomicLong created = new AtomicLong(); private AtomicLong closed = new AtomicLong(); - private AtomicInteger toCreate = new AtomicInteger(); + private AtomicInteger creating = new AtomicInteger(); private AtomicLong failedToCreate = new AtomicLong(); private InternalHistogram acquisitionTimeHistogram; @@ -57,21 +58,21 @@ public InternalConnectionPoolMetrics( BoltServerAddress address, ConnectionPool @Override public void beforeCreating() { - toCreate.incrementAndGet(); + creating.incrementAndGet(); } @Override public void afterFailedToCreate() { failedToCreate.incrementAndGet(); - toCreate.decrementAndGet(); + creating.decrementAndGet(); } @Override public void afterCreated() { created.incrementAndGet(); - toCreate.decrementAndGet(); + creating.decrementAndGet(); } @Override @@ -100,15 +101,15 @@ public String uniqueName() } @Override - public String poolStatus() + public PoolStatus poolStatus() { if ( pool.isOpen() ) { - return "\"Open\""; + return PoolStatus.Open; } else { - return "\"Closed\""; + return PoolStatus.Closed; } } @@ -125,9 +126,9 @@ public int idle() } @Override - public int toCreate() + public int creating() { - return toCreate.get(); + return creating.get(); } @Override @@ -157,7 +158,7 @@ public Histogram acquisitionTimeHistogram() @Override public String toString() { - return format( "[created=%s, closed=%s, toCreate=%s, failedToCreate=%s inUse=%s, idle=%s, poolStatus=%s, acquisitionTimeHistogram=%s]", created(), - closed(), toCreate(), failedToCreate(), inUse(), idle(), poolStatus(), acquisitionTimeHistogram() ); + return format( "[created=%s, closed=%s, creating=%s, failedToCreate=%s inUse=%s, idle=%s, poolStatus=%s, acquisitionTimeHistogram=%s]", created(), + closed(), creating(), failedToCreate(), inUse(), idle(), poolStatus(), acquisitionTimeHistogram() ); } } diff --git a/driver/src/main/java/org/neo4j/driver/internal/metrics/InternalHistogram.java b/driver/src/main/java/org/neo4j/driver/internal/metrics/InternalHistogram.java index 8dca066c2d..d0a89e995b 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/metrics/InternalHistogram.java +++ b/driver/src/main/java/org/neo4j/driver/internal/metrics/InternalHistogram.java @@ -21,8 +21,6 @@ import org.HdrHistogram.AbstractHistogram; import org.HdrHistogram.ConcurrentHistogram; -import java.io.ByteArrayOutputStream; -import java.io.PrintStream; import java.time.Duration; import org.neo4j.driver.internal.metrics.spi.Histogram; @@ -32,6 +30,7 @@ public class InternalHistogram implements Histogram { private static final long DEFAULT_HIGHEST_TRACKABLE_NS = Duration.ofMinutes( 10 ).toNanos(); + private static final int DEFAULT_NUMBER_OF_SIGNIFICANT_VALUE_DIGITS = 3; private final AbstractHistogram delegate; @@ -100,7 +99,7 @@ public void reset() public static ConcurrentHistogram createHdrHistogram( long highestTrackableValue ) { - return new ConcurrentHistogram( highestTrackableValue, 3 ); + return new ConcurrentHistogram( highestTrackableValue, DEFAULT_NUMBER_OF_SIGNIFICANT_VALUE_DIGITS ); } private static long truncateValue( long value, AbstractHistogram histogram ) @@ -126,14 +125,4 @@ public String toString() return format("[min=%sns, max=%sns, mean=%sns, stdDeviation=%s, totalCount=%s]", min(), max(), mean(), stdDeviation(), totalCount()); } - - public String printDistribution() - { - ByteArrayOutputStream stream = new ByteArrayOutputStream(); - PrintStream writer = new PrintStream( stream ); - delegate.outputPercentileDistribution( writer, 1.0 ); - String content = new String( stream.toByteArray() ); - writer.close(); - return content; - } } diff --git a/driver/src/main/java/org/neo4j/driver/internal/metrics/InternalDriverMetrics.java b/driver/src/main/java/org/neo4j/driver/internal/metrics/InternalMetrics.java similarity index 88% rename from driver/src/main/java/org/neo4j/driver/internal/metrics/InternalDriverMetrics.java rename to driver/src/main/java/org/neo4j/driver/internal/metrics/InternalMetrics.java index 9a7d9f9727..23b83587b7 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/metrics/InternalDriverMetrics.java +++ b/driver/src/main/java/org/neo4j/driver/internal/metrics/InternalMetrics.java @@ -24,8 +24,6 @@ import org.neo4j.driver.internal.BoltServerAddress; import org.neo4j.driver.internal.async.pool.ConnectionPoolImpl; -import org.neo4j.driver.internal.metrics.ListenerEvent.ConnectionListenerEvent; -import org.neo4j.driver.internal.metrics.ListenerEvent.PoolListenerEvent; import org.neo4j.driver.internal.metrics.spi.ConnectionMetrics; import org.neo4j.driver.internal.metrics.spi.ConnectionPoolMetrics; import org.neo4j.driver.internal.spi.ConnectionPool; @@ -34,13 +32,13 @@ import static java.lang.String.format; -public class InternalDriverMetrics extends InternalAbstractDriverMetrics +public class InternalMetrics extends InternalAbstractMetrics { private final Map connectionPoolMetrics; private final Map connectionMetrics; private final Config config; - public InternalDriverMetrics( Config config ) + public InternalMetrics( Config config ) { Objects.requireNonNull( config ); this.config = config; @@ -56,14 +54,14 @@ public void addMetrics( BoltServerAddress serverAddress, ConnectionPoolImpl pool } @Override - public void beforeCreating( BoltServerAddress serverAddress, ConnectionListenerEvent creatingEvent ) + public void beforeCreating( BoltServerAddress serverAddress, ListenerEvent creatingEvent ) { poolMetrics( serverAddress ).beforeCreating(); connectionMetrics( serverAddress ).beforeCreating( creatingEvent ); } @Override - public void afterCreating( BoltServerAddress serverAddress, ConnectionListenerEvent creatingEvent ) + public void afterCreating( BoltServerAddress serverAddress, ListenerEvent creatingEvent ) { connectionMetrics( serverAddress ).afterCreating( creatingEvent ); } @@ -87,37 +85,31 @@ public void afterClosed( BoltServerAddress serverAddress ) } @Override - public void beforeAcquiringOrCreating( BoltServerAddress serverAddress, PoolListenerEvent listenerEvent ) + public void beforeAcquiringOrCreating( BoltServerAddress serverAddress, ListenerEvent listenerEvent ) { poolMetrics( serverAddress ).beforeAcquiringOrCreating( listenerEvent ); } @Override - public void afterAcquiringOrCreating( BoltServerAddress serverAddress, PoolListenerEvent listenerEvent ) + public void afterAcquiringOrCreating( BoltServerAddress serverAddress, ListenerEvent listenerEvent ) { poolMetrics( serverAddress ).afterAcquiringOrCreating( listenerEvent ); } @Override - public void afterAcquiredOrCreated( BoltServerAddress serverAddress, ConnectionListenerEvent inUseEvent ) + public void afterAcquiredOrCreated( BoltServerAddress serverAddress, ListenerEvent inUseEvent ) { connectionMetrics( serverAddress ).acquiredOrCreated( inUseEvent ); } @Override - public void afterReleased( BoltServerAddress serverAddress, ConnectionListenerEvent inUseEvent ) + public void afterReleased( BoltServerAddress serverAddress, ListenerEvent inUseEvent ) { connectionMetrics( serverAddress ).released( inUseEvent ); } @Override - public ConnectionListenerEvent createConnectionListenerEvent() - { - return new NanoTimeBasedListenerEvent(); - } - - @Override - public PoolListenerEvent createPoolListenerEvent() + public ListenerEvent createListenerEvent() { return new NanoTimeBasedListenerEvent(); } diff --git a/driver/src/main/java/org/neo4j/driver/internal/metrics/ListenerEvent.java b/driver/src/main/java/org/neo4j/driver/internal/metrics/ListenerEvent.java index 559c544322..6eece7d235 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/metrics/ListenerEvent.java +++ b/driver/src/main/java/org/neo4j/driver/internal/metrics/ListenerEvent.java @@ -23,13 +23,5 @@ public interface ListenerEvent { void start(); long elapsed(); - - interface PoolListenerEvent extends ListenerEvent - { - } - - interface ConnectionListenerEvent extends ListenerEvent - { - } } diff --git a/driver/src/main/java/org/neo4j/driver/internal/metrics/DriverMetricsListener.java b/driver/src/main/java/org/neo4j/driver/internal/metrics/MetricsListener.java similarity index 80% rename from driver/src/main/java/org/neo4j/driver/internal/metrics/DriverMetricsListener.java rename to driver/src/main/java/org/neo4j/driver/internal/metrics/MetricsListener.java index d54769452c..41d337b1ac 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/metrics/DriverMetricsListener.java +++ b/driver/src/main/java/org/neo4j/driver/internal/metrics/MetricsListener.java @@ -21,35 +21,33 @@ import org.neo4j.driver.internal.BoltServerAddress; import org.neo4j.driver.internal.async.NettyConnection; import org.neo4j.driver.internal.async.pool.ConnectionPoolImpl; -import org.neo4j.driver.internal.metrics.ListenerEvent.ConnectionListenerEvent; -import org.neo4j.driver.internal.metrics.ListenerEvent.PoolListenerEvent; -public interface DriverMetricsListener +public interface MetricsListener { /** * Before creating a netty channel * @param serverAddress the server the netty channel binds to. * @param creatingEvent a connection listener event registered when a connection is creating. */ - void beforeCreating( BoltServerAddress serverAddress, ConnectionListenerEvent creatingEvent ); + void beforeCreating( BoltServerAddress serverAddress, ListenerEvent creatingEvent ); /** * After creating a netty channel regardless succeeded or failed. * @param serverAddress the server the netty channel binds to. * @param creatingEvent a connection listener event registered when a connection is creating. */ - void afterCreating( BoltServerAddress serverAddress, ConnectionListenerEvent creatingEvent ); + void afterCreating( BoltServerAddress serverAddress, ListenerEvent creatingEvent ); /** * After a netty channel is created successfully - * This method will not invoke {@link this#afterCreating(BoltServerAddress, ConnectionListenerEvent)} + * This method will not invoke {@link this#afterCreating(BoltServerAddress, ListenerEvent)} * @param serverAddress the server the netty channel binds to */ void afterCreated( BoltServerAddress serverAddress ); /** * After a netty channel is created with failure - * This method will not invoke {@link this#afterCreating(BoltServerAddress, ConnectionListenerEvent)} + * This method will not invoke {@link this#afterCreating(BoltServerAddress, ListenerEvent)} * @param serverAddress the server the netty channel binds to */ void afterFailedToCreate( BoltServerAddress serverAddress ); @@ -65,33 +63,31 @@ public interface DriverMetricsListener * @param serverAddress the server the netty channel binds to * @param acquireEvent a pool listener event registered in pool for this acquire event */ - void beforeAcquiringOrCreating( BoltServerAddress serverAddress, PoolListenerEvent acquireEvent ); + void beforeAcquiringOrCreating( BoltServerAddress serverAddress, ListenerEvent acquireEvent ); /** * After acquiring or creating a new netty channel from pool regardless succeeded or failed * @param serverAddress the server the netty channel binds to * @param acquireEvent a pool listener event registered in pool for this acquire event */ - void afterAcquiringOrCreating( BoltServerAddress serverAddress, PoolListenerEvent acquireEvent ); + void afterAcquiringOrCreating( BoltServerAddress serverAddress, ListenerEvent acquireEvent ); /** * After acquiring or creating a new netty channel from pool successfully. - * This method will not invoke {@link this#afterAcquiringOrCreating(BoltServerAddress, PoolListenerEvent)} + * This method will not invoke {@link this#afterAcquiringOrCreating(BoltServerAddress, ListenerEvent)} * @param serverAddress the server the netty channel binds to * @param inUseEvent a connection listener registered with a {@link NettyConnection} when created */ - void afterAcquiredOrCreated( BoltServerAddress serverAddress, ConnectionListenerEvent inUseEvent ); + void afterAcquiredOrCreated( BoltServerAddress serverAddress, ListenerEvent inUseEvent ); /** * After releasing a netty channel back to pool successfully * @param serverAddress the server the netty channel binds to * @param inUseEvent a connection listener registered with a {@link NettyConnection} when destroyed */ - void afterReleased( BoltServerAddress serverAddress, ConnectionListenerEvent inUseEvent ); + void afterReleased( BoltServerAddress serverAddress, ListenerEvent inUseEvent ); - ConnectionListenerEvent createConnectionListenerEvent(); - - PoolListenerEvent createPoolListenerEvent(); + ListenerEvent createListenerEvent(); void addMetrics( BoltServerAddress address, ConnectionPoolImpl connectionPool ); } diff --git a/driver/src/main/java/org/neo4j/driver/internal/metrics/NanoTimeBasedListenerEvent.java b/driver/src/main/java/org/neo4j/driver/internal/metrics/NanoTimeBasedListenerEvent.java index 4310f18015..a2c315c4fd 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/metrics/NanoTimeBasedListenerEvent.java +++ b/driver/src/main/java/org/neo4j/driver/internal/metrics/NanoTimeBasedListenerEvent.java @@ -19,10 +19,7 @@ package org.neo4j.driver.internal.metrics; -import org.neo4j.driver.internal.metrics.ListenerEvent.ConnectionListenerEvent; -import org.neo4j.driver.internal.metrics.ListenerEvent.PoolListenerEvent; - -public class NanoTimeBasedListenerEvent implements PoolListenerEvent, ConnectionListenerEvent +public class NanoTimeBasedListenerEvent implements ListenerEvent { private long startNanoTime; diff --git a/driver/src/main/java/org/neo4j/driver/internal/metrics/spi/ConnectionPoolMetrics.java b/driver/src/main/java/org/neo4j/driver/internal/metrics/spi/ConnectionPoolMetrics.java index 45f91f5c7d..40a8afddab 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/metrics/spi/ConnectionPoolMetrics.java +++ b/driver/src/main/java/org/neo4j/driver/internal/metrics/spi/ConnectionPoolMetrics.java @@ -30,7 +30,7 @@ public interface ConnectionPoolMetrics * The status of the pool * @return The status of the pool in a string */ - String poolStatus(); + PoolStatus poolStatus(); /** * The amount of connections that is in-use (borrowed out of the pool). @@ -51,9 +51,9 @@ public interface ConnectionPoolMetrics * The amount is increased by one when the pool noticed a request to create a new connection. * The amount is decreased by one when the pool noticed a new connection is created regardless successfully or not. * The number is changing up and down from time to time. - * @return The amount of connection that is to be created. + * @return The amount of connection that is creating. */ - int toCreate(); + int creating(); /** * An increasing-only number to record how many connections have been created by this pool successfully. diff --git a/driver/src/main/java/org/neo4j/driver/internal/metrics/spi/DriverMetrics.java b/driver/src/main/java/org/neo4j/driver/internal/metrics/spi/Metrics.java similarity index 89% rename from driver/src/main/java/org/neo4j/driver/internal/metrics/spi/DriverMetrics.java rename to driver/src/main/java/org/neo4j/driver/internal/metrics/spi/Metrics.java index 6a3314ce27..ca04a88d62 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/metrics/spi/DriverMetrics.java +++ b/driver/src/main/java/org/neo4j/driver/internal/metrics/spi/Metrics.java @@ -20,13 +20,13 @@ import java.util.Map; -public interface DriverMetrics +public interface Metrics { // TODO Once this interface become public, find a better way to enable metrics and detect metrics availability. String DRIVER_METRICS_ENABLED_KEY = "driver.metrics.enabled"; - static boolean isDriverMetricsEnabled() + static boolean isMetricsEnabled() { - return Boolean.valueOf( System.getProperty( DRIVER_METRICS_ENABLED_KEY, "false" ) ); + return Boolean.getBoolean( DRIVER_METRICS_ENABLED_KEY ); } /** diff --git a/driver/src/main/java/org/neo4j/driver/internal/metrics/spi/PoolStatus.java b/driver/src/main/java/org/neo4j/driver/internal/metrics/spi/PoolStatus.java new file mode 100644 index 0000000000..6fe7099805 --- /dev/null +++ b/driver/src/main/java/org/neo4j/driver/internal/metrics/spi/PoolStatus.java @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2002-2018 "Neo Technology," + * Network Engine for Objects in Lund AB [http://neotechnology.com] + * + * This file is part of Neo4j. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.neo4j.driver.internal.metrics.spi; + +public enum PoolStatus +{ + Open, Closed +} diff --git a/driver/src/test/java/org/neo4j/driver/internal/DriverFactoryTest.java b/driver/src/test/java/org/neo4j/driver/internal/DriverFactoryTest.java index 907b95682c..0257ee2cce 100644 --- a/driver/src/test/java/org/neo4j/driver/internal/DriverFactoryTest.java +++ b/driver/src/test/java/org/neo4j/driver/internal/DriverFactoryTest.java @@ -33,8 +33,9 @@ import org.neo4j.driver.internal.async.BootstrapFactory; import org.neo4j.driver.internal.cluster.RoutingSettings; import org.neo4j.driver.internal.cluster.loadbalancing.LoadBalancer; -import org.neo4j.driver.internal.metrics.DriverMetricsListener; -import org.neo4j.driver.internal.metrics.InternalDriverMetrics; +import org.neo4j.driver.internal.metrics.InternalMetrics; +import org.neo4j.driver.internal.metrics.MetricsListener; +import org.neo4j.driver.internal.metrics.spi.Metrics; import org.neo4j.driver.internal.retry.RetryLogic; import org.neo4j.driver.internal.retry.RetrySettings; import org.neo4j.driver.internal.security.SecurityPlan; @@ -59,7 +60,7 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -import static org.neo4j.driver.internal.metrics.InternalAbstractDriverMetrics.DEV_NULL_METRICS; +import static org.neo4j.driver.internal.metrics.InternalAbstractMetrics.DEV_NULL_METRICS; import static org.neo4j.driver.internal.util.Futures.completedWithNull; import static org.neo4j.driver.internal.util.Futures.failedFuture; import static org.neo4j.driver.v1.AccessMode.READ; @@ -185,7 +186,7 @@ public void shouldNotCreateDriverMetrics() throws Throwable // Given Config config = mock( Config.class ); // When - DriverMetricsListener handler = DriverFactory.createDriverMetrics( config ); + MetricsListener handler = DriverFactory.createDriverMetrics( config ); // Then assertThat( handler, is( DEV_NULL_METRICS ) ); } @@ -197,10 +198,10 @@ public void shouldCreateDriverMetricsIfMonitoringEnabled() throws Throwable Config config = mock( Config.class ); System.setProperty( "driver.metrics.enabled", "True" ); // When - DriverMetricsListener handler = DriverFactory.createDriverMetrics( config ); + MetricsListener handler = DriverFactory.createDriverMetrics( config ); System.setProperty( "driver.metrics.enabled", "False" ); // Then - assertThat( handler instanceof InternalDriverMetrics, is( true ) ); + assertThat( handler instanceof InternalMetrics, is( true ) ); } private Driver createDriver( DriverFactory driverFactory ) @@ -234,21 +235,20 @@ private static class ThrowingDriverFactory extends DriverFactory } @Override - protected InternalDriver createDriver( SessionFactory sessionFactory, SecurityPlan securityPlan, Config config ) + protected InternalDriver createDriver( SecurityPlan securityPlan, SessionFactory sessionFactory, Metrics metrics, Config config ) { throw new UnsupportedOperationException( "Can't create direct driver" ); } @Override - protected InternalDriver createRoutingDriver( BoltServerAddress address, ConnectionPool connectionPool, - Config config, RoutingSettings routingSettings, SecurityPlan securityPlan, RetryLogic retryLogic, - EventExecutorGroup eventExecutorGroup ) + protected InternalDriver createRoutingDriver( SecurityPlan securityPlan, BoltServerAddress address, ConnectionPool connectionPool, + EventExecutorGroup eventExecutorGroup, RoutingSettings routingSettings, RetryLogic retryLogic, Metrics metrics, Config config ) { throw new UnsupportedOperationException( "Can't create routing driver" ); } @Override - protected ConnectionPool createConnectionPool( AuthToken authToken, SecurityPlan securityPlan, Bootstrap bootstrap, DriverMetricsListener metrics, Config config ) + protected ConnectionPool createConnectionPool( AuthToken authToken, SecurityPlan securityPlan, Bootstrap bootstrap, MetricsListener metrics, Config config ) { return connectionPool; } @@ -259,7 +259,7 @@ private static class SessionFactoryCapturingDriverFactory extends DriverFactory SessionFactory capturedSessionFactory; @Override - protected InternalDriver createDriver( SessionFactory sessionFactory, SecurityPlan securityPlan, Config config ) + protected InternalDriver createDriver( SecurityPlan securityPlan, SessionFactory sessionFactory, Metrics metrics, Config config ) { InternalDriver driver = mock( InternalDriver.class ); when( driver.verifyConnectivity() ).thenReturn( completedWithNull() ); @@ -283,7 +283,7 @@ protected SessionFactory createSessionFactory( ConnectionProvider connectionProv } @Override - protected ConnectionPool createConnectionPool( AuthToken authToken, SecurityPlan securityPlan, Bootstrap bootstrap, DriverMetricsListener metrics, Config config ) + protected ConnectionPool createConnectionPool( AuthToken authToken, SecurityPlan securityPlan, Bootstrap bootstrap, MetricsListener metrics, Config config ) { return connectionPoolMock(); } @@ -305,7 +305,7 @@ protected Bootstrap createBootstrap() } @Override - protected ConnectionPool createConnectionPool( AuthToken authToken, SecurityPlan securityPlan, Bootstrap bootstrap, DriverMetricsListener metrics, Config config ) + protected ConnectionPool createConnectionPool( AuthToken authToken, SecurityPlan securityPlan, Bootstrap bootstrap, MetricsListener metrics, Config config ) { return connectionPoolMock(); } diff --git a/driver/src/test/java/org/neo4j/driver/internal/InternalDriverTest.java b/driver/src/test/java/org/neo4j/driver/internal/InternalDriverTest.java index de6ce07178..9f39189cb7 100644 --- a/driver/src/test/java/org/neo4j/driver/internal/InternalDriverTest.java +++ b/driver/src/test/java/org/neo4j/driver/internal/InternalDriverTest.java @@ -30,6 +30,7 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import static org.neo4j.driver.internal.logging.DevNullLogging.DEV_NULL_LOGGING; +import static org.neo4j.driver.internal.metrics.InternalAbstractMetrics.DEV_NULL_METRICS; import static org.neo4j.driver.internal.util.Futures.completedWithNull; import static org.neo4j.driver.v1.util.TestUtil.await; @@ -72,7 +73,7 @@ public void shouldVerifyConnectivity() private static InternalDriver newDriver( SessionFactory sessionFactory ) { - return new InternalDriver( SecurityPlan.insecure(), sessionFactory, DEV_NULL_LOGGING ); + return new InternalDriver( SecurityPlan.insecure(), sessionFactory, DEV_NULL_METRICS, DEV_NULL_LOGGING ); } private static SessionFactory sessionFactoryMock() diff --git a/driver/src/test/java/org/neo4j/driver/internal/async/NettyConnectionTest.java b/driver/src/test/java/org/neo4j/driver/internal/async/NettyConnectionTest.java index b1791b89f0..88955e8cd0 100644 --- a/driver/src/test/java/org/neo4j/driver/internal/async/NettyConnectionTest.java +++ b/driver/src/test/java/org/neo4j/driver/internal/async/NettyConnectionTest.java @@ -60,7 +60,7 @@ import static org.neo4j.driver.internal.async.ChannelAttributes.terminationReason; import static org.neo4j.driver.internal.logging.DevNullLogging.DEV_NULL_LOGGING; import static org.neo4j.driver.internal.messaging.ResetMessage.RESET; -import static org.neo4j.driver.internal.metrics.InternalAbstractDriverMetrics.DEV_NULL_METRICS; +import static org.neo4j.driver.internal.metrics.InternalAbstractMetrics.DEV_NULL_METRICS; import static org.neo4j.driver.internal.util.Iterables.single; import static org.neo4j.driver.v1.util.DaemonThreadFactory.daemon; diff --git a/driver/src/test/java/org/neo4j/driver/internal/async/pool/ConnectionPoolImplTest.java b/driver/src/test/java/org/neo4j/driver/internal/async/pool/ConnectionPoolImplTest.java index bf218db6fe..3f4f9dde66 100644 --- a/driver/src/test/java/org/neo4j/driver/internal/async/pool/ConnectionPoolImplTest.java +++ b/driver/src/test/java/org/neo4j/driver/internal/async/pool/ConnectionPoolImplTest.java @@ -59,7 +59,7 @@ import static org.mockito.Mockito.when; import static org.neo4j.driver.internal.BoltServerAddress.LOCAL_DEFAULT; import static org.neo4j.driver.internal.logging.DevNullLogging.DEV_NULL_LOGGING; -import static org.neo4j.driver.internal.metrics.InternalAbstractDriverMetrics.DEV_NULL_METRICS; +import static org.neo4j.driver.internal.metrics.InternalAbstractMetrics.DEV_NULL_METRICS; import static org.neo4j.driver.v1.util.TestUtil.await; public class ConnectionPoolImplTest diff --git a/driver/src/test/java/org/neo4j/driver/internal/async/pool/NettyChannelPoolTest.java b/driver/src/test/java/org/neo4j/driver/internal/async/pool/NettyChannelPoolTest.java index 4d6eea30ae..93ce7774c7 100644 --- a/driver/src/test/java/org/neo4j/driver/internal/async/pool/NettyChannelPoolTest.java +++ b/driver/src/test/java/org/neo4j/driver/internal/async/pool/NettyChannelPoolTest.java @@ -57,7 +57,7 @@ import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.neo4j.driver.internal.logging.DevNullLogging.DEV_NULL_LOGGING; -import static org.neo4j.driver.internal.metrics.InternalAbstractDriverMetrics.DEV_NULL_METRICS; +import static org.neo4j.driver.internal.metrics.InternalAbstractMetrics.DEV_NULL_METRICS; import static org.neo4j.driver.v1.Values.value; public class NettyChannelPoolTest diff --git a/driver/src/test/java/org/neo4j/driver/internal/async/pool/NettyChannelTrackerTest.java b/driver/src/test/java/org/neo4j/driver/internal/async/pool/NettyChannelTrackerTest.java index 1ffd077e4d..122478543e 100644 --- a/driver/src/test/java/org/neo4j/driver/internal/async/pool/NettyChannelTrackerTest.java +++ b/driver/src/test/java/org/neo4j/driver/internal/async/pool/NettyChannelTrackerTest.java @@ -30,7 +30,7 @@ import static org.junit.Assert.fail; import static org.neo4j.driver.internal.async.ChannelAttributes.setServerAddress; import static org.neo4j.driver.internal.logging.DevNullLogging.DEV_NULL_LOGGING; -import static org.neo4j.driver.internal.metrics.InternalAbstractDriverMetrics.DEV_NULL_METRICS; +import static org.neo4j.driver.internal.metrics.InternalAbstractMetrics.DEV_NULL_METRICS; public class NettyChannelTrackerTest { diff --git a/driver/src/test/java/org/neo4j/driver/internal/util/ChannelTrackingDriverFactory.java b/driver/src/test/java/org/neo4j/driver/internal/util/ChannelTrackingDriverFactory.java index 8d78b2da2d..7c7980cc9d 100644 --- a/driver/src/test/java/org/neo4j/driver/internal/util/ChannelTrackingDriverFactory.java +++ b/driver/src/test/java/org/neo4j/driver/internal/util/ChannelTrackingDriverFactory.java @@ -29,7 +29,7 @@ import org.neo4j.driver.internal.ConnectionSettings; import org.neo4j.driver.internal.async.BootstrapFactory; import org.neo4j.driver.internal.async.ChannelConnector; -import org.neo4j.driver.internal.metrics.DriverMetricsListener; +import org.neo4j.driver.internal.metrics.MetricsListener; import org.neo4j.driver.internal.security.SecurityPlan; import org.neo4j.driver.internal.spi.ConnectionPool; import org.neo4j.driver.v1.AuthToken; @@ -71,7 +71,7 @@ protected final ChannelConnector createConnector( ConnectionSettings settings, S } @Override - protected final ConnectionPool createConnectionPool( AuthToken authToken, SecurityPlan securityPlan, Bootstrap bootstrap, DriverMetricsListener metrics, + protected final ConnectionPool createConnectionPool( AuthToken authToken, SecurityPlan securityPlan, Bootstrap bootstrap, MetricsListener metrics, Config config ) { pool = super.createConnectionPool( authToken, securityPlan, bootstrap, metrics, config ); diff --git a/driver/src/test/java/org/neo4j/driver/internal/util/FailingConnectionDriverFactory.java b/driver/src/test/java/org/neo4j/driver/internal/util/FailingConnectionDriverFactory.java index d688e6c206..cdb4e27305 100644 --- a/driver/src/test/java/org/neo4j/driver/internal/util/FailingConnectionDriverFactory.java +++ b/driver/src/test/java/org/neo4j/driver/internal/util/FailingConnectionDriverFactory.java @@ -27,7 +27,7 @@ import org.neo4j.driver.internal.BoltServerAddress; import org.neo4j.driver.internal.DriverFactory; -import org.neo4j.driver.internal.metrics.DriverMetricsListener; +import org.neo4j.driver.internal.metrics.MetricsListener; import org.neo4j.driver.internal.security.SecurityPlan; import org.neo4j.driver.internal.spi.Connection; import org.neo4j.driver.internal.spi.ConnectionPool; @@ -41,7 +41,7 @@ public class FailingConnectionDriverFactory extends DriverFactory private final AtomicReference nextRunFailure = new AtomicReference<>(); @Override - protected ConnectionPool createConnectionPool( AuthToken authToken, SecurityPlan securityPlan, Bootstrap bootstrap, DriverMetricsListener metrics, Config config ) + protected ConnectionPool createConnectionPool( AuthToken authToken, SecurityPlan securityPlan, Bootstrap bootstrap, MetricsListener metrics, Config config ) { ConnectionPool pool = super.createConnectionPool( authToken, securityPlan, bootstrap, metrics, config ); return new ConnectionPoolWithFailingConnections( pool, nextRunFailure ); diff --git a/driver/src/test/java/org/neo4j/driver/v1/integration/ConnectionHandlingIT.java b/driver/src/test/java/org/neo4j/driver/v1/integration/ConnectionHandlingIT.java index f532adfb34..f2d61d885b 100644 --- a/driver/src/test/java/org/neo4j/driver/v1/integration/ConnectionHandlingIT.java +++ b/driver/src/test/java/org/neo4j/driver/v1/integration/ConnectionHandlingIT.java @@ -36,7 +36,7 @@ import org.neo4j.driver.internal.async.pool.ConnectionPoolImpl; import org.neo4j.driver.internal.async.pool.PoolSettings; import org.neo4j.driver.internal.cluster.RoutingSettings; -import org.neo4j.driver.internal.metrics.DriverMetricsListener; +import org.neo4j.driver.internal.metrics.MetricsListener; import org.neo4j.driver.internal.retry.RetrySettings; import org.neo4j.driver.internal.security.SecurityPlan; import org.neo4j.driver.internal.spi.Connection; @@ -65,7 +65,7 @@ import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; -import static org.neo4j.driver.internal.metrics.InternalAbstractDriverMetrics.DEV_NULL_METRICS; +import static org.neo4j.driver.internal.metrics.InternalAbstractMetrics.DEV_NULL_METRICS; import static org.neo4j.driver.v1.Config.defaultConfig; import static org.neo4j.driver.v1.Values.parameters; import static org.neo4j.driver.v1.util.TestUtil.await; @@ -296,7 +296,7 @@ private static class DriverFactoryWithConnectionPool extends DriverFactory MemorizingConnectionPool connectionPool; @Override - protected ConnectionPool createConnectionPool( AuthToken authToken, SecurityPlan securityPlan, Bootstrap bootstrap, DriverMetricsListener metrics, Config config ) + protected ConnectionPool createConnectionPool( AuthToken authToken, SecurityPlan securityPlan, Bootstrap bootstrap, MetricsListener metrics, Config config ) { ConnectionSettings connectionSettings = new ConnectionSettings( authToken, 1000 ); PoolSettings poolSettings = new PoolSettings( config.maxConnectionPoolSize(), diff --git a/driver/src/test/java/org/neo4j/driver/v1/stress/AbstractStressTestBase.java b/driver/src/test/java/org/neo4j/driver/v1/stress/AbstractStressTestBase.java index 6661108f12..af894c913b 100644 --- a/driver/src/test/java/org/neo4j/driver/v1/stress/AbstractStressTestBase.java +++ b/driver/src/test/java/org/neo4j/driver/v1/stress/AbstractStressTestBase.java @@ -74,7 +74,7 @@ import static org.junit.Assert.assertNull; import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; -import static org.neo4j.driver.internal.metrics.spi.DriverMetrics.DRIVER_METRICS_ENABLED_KEY; +import static org.neo4j.driver.internal.metrics.spi.Metrics.DRIVER_METRICS_ENABLED_KEY; public abstract class AbstractStressTestBase { @@ -113,12 +113,12 @@ public void setUp() @After public void tearDown() { - System.out.println( driver.driverMetrics() ); + System.out.println( driver.metrics() ); executor.shutdownNow(); if ( driver != null ) { driver.close(); - System.out.println( driver.driverMetrics() ); + System.out.println( driver.metrics() ); } }