diff --git a/enterprise/metrics/pom.xml b/enterprise/metrics/pom.xml
index 28fe79734bb7a..175e6498a6b11 100644
--- a/enterprise/metrics/pom.xml
+++ b/enterprise/metrics/pom.xml
@@ -100,7 +100,7 @@
org.neo4j
- neo4j-kernel
+ neo4j-ha
${project.version}
test
test-jar
@@ -137,5 +137,10 @@
hamcrest-all
test
+
+ org.mockito
+ mockito-core
+ test
+
diff --git a/enterprise/metrics/src/main/java/org/neo4j/metrics/MetricsExtension.java b/enterprise/metrics/src/main/java/org/neo4j/metrics/MetricsExtension.java
index 160343de6768f..63639455ad2fe 100644
--- a/enterprise/metrics/src/main/java/org/neo4j/metrics/MetricsExtension.java
+++ b/enterprise/metrics/src/main/java/org/neo4j/metrics/MetricsExtension.java
@@ -22,9 +22,11 @@
import com.codahale.metrics.MetricRegistry;
import org.neo4j.cluster.ClusterSettings;
+import org.neo4j.graphdb.DependencyResolver;
import org.neo4j.io.pagecache.monitoring.PageCacheMonitor;
import org.neo4j.kernel.IdGeneratorFactory;
import org.neo4j.kernel.configuration.Config;
+import org.neo4j.kernel.ha.cluster.member.ClusterMembers;
import org.neo4j.kernel.impl.api.LogRotationMonitor;
import org.neo4j.kernel.impl.logging.LogService;
import org.neo4j.kernel.impl.transaction.TransactionCounters;
@@ -49,7 +51,7 @@ public class MetricsExtension implements Lifecycle
private final CheckPointerMonitor checkPointerMonitor;
private final IdGeneratorFactory idGeneratorFactory;
private final LogRotationMonitor logRotationMonitor;
-
+ private final DependencyResolver dependencyResolver;
public MetricsExtension( MetricsKernelExtensionFactory.Dependencies dependencies )
{
@@ -62,6 +64,7 @@ public MetricsExtension( MetricsKernelExtensionFactory.Dependencies dependencies
checkPointerMonitor = dependencies.checkPointerCounters();
logRotationMonitor = dependencies.logRotationCounters();
idGeneratorFactory = dependencies.idGeneratorFactory();
+ dependencyResolver = dependencies.getDependencyResolver();
}
@Override
@@ -83,7 +86,8 @@ public void init() throws Throwable
// Setup metric gathering
Neo4jMetricsFactory factory = new Neo4jMetricsFactory( registry, configuration, monitors,
- transactionCounters, pageCacheCounters, checkPointerMonitor, logRotationMonitor, idGeneratorFactory );
+ transactionCounters, pageCacheCounters, checkPointerMonitor, logRotationMonitor, idGeneratorFactory,
+ dependencyResolver, logService);
life.add( factory.newInstance() );
life.init();
diff --git a/enterprise/metrics/src/main/java/org/neo4j/metrics/MetricsKernelExtensionFactory.java b/enterprise/metrics/src/main/java/org/neo4j/metrics/MetricsKernelExtensionFactory.java
index 11bf9725266a8..f87c9bfc4bf31 100644
--- a/enterprise/metrics/src/main/java/org/neo4j/metrics/MetricsKernelExtensionFactory.java
+++ b/enterprise/metrics/src/main/java/org/neo4j/metrics/MetricsKernelExtensionFactory.java
@@ -19,6 +19,7 @@
*/
package org.neo4j.metrics;
+import org.neo4j.graphdb.DependencyResolver;
import org.neo4j.io.pagecache.monitoring.PageCacheMonitor;
import org.neo4j.kernel.IdGeneratorFactory;
import org.neo4j.kernel.configuration.Config;
@@ -51,6 +52,8 @@ public interface Dependencies
IdGeneratorFactory idGeneratorFactory();
Monitors monitors();
+
+ DependencyResolver getDependencyResolver();
}
public MetricsKernelExtensionFactory()
diff --git a/enterprise/metrics/src/main/java/org/neo4j/metrics/source/ClusterMetrics.java b/enterprise/metrics/src/main/java/org/neo4j/metrics/source/ClusterMetrics.java
index 9c840b59fce07..1df81d8f9e1a8 100644
--- a/enterprise/metrics/src/main/java/org/neo4j/metrics/source/ClusterMetrics.java
+++ b/enterprise/metrics/src/main/java/org/neo4j/metrics/source/ClusterMetrics.java
@@ -25,39 +25,57 @@
import java.io.IOException;
import java.util.concurrent.atomic.AtomicLong;
+import org.neo4j.function.Predicate;
+import org.neo4j.function.Predicates;
+import org.neo4j.graphdb.DependencyResolver;
import org.neo4j.kernel.configuration.Config;
import org.neo4j.kernel.ha.SlaveUpdatePuller;
+import org.neo4j.kernel.ha.cluster.member.ClusterMembers;
+import org.neo4j.kernel.impl.logging.LogService;
import org.neo4j.kernel.lifecycle.LifecycleAdapter;
import org.neo4j.kernel.monitoring.Monitors;
import org.neo4j.metrics.MetricsSettings;
import static com.codahale.metrics.MetricRegistry.name;
+import static org.neo4j.kernel.ha.cluster.modeswitch.HighAvailabilityModeSwitcher.MASTER;
+import static org.neo4j.kernel.ha.cluster.modeswitch.HighAvailabilityModeSwitcher.UNKNOWN;
public class ClusterMetrics extends LifecycleAdapter
{
private static final String NAME_PREFIX = "neo4j.cluster";
private static final String SLAVE_PULL_UPDATES = name( NAME_PREFIX, "slave_pull_updates" );
private static final String SLAVE_PULL_UPDATE_UP_TO_TX = name( NAME_PREFIX, "slave_pull_update_up_to_tx" );
+ static final String IS_MASTER = name( NAME_PREFIX, "is_master" );
+ static final String IS_AVAILABLE = name( NAME_PREFIX, "is_available" );
private final Config config;
private final Monitors monitors;
private final MetricRegistry registry;
+ private final DependencyResolver dependencyResolver;
+ private final LogService logService;
private final SlaveUpdatePullerMonitor monitor = new SlaveUpdatePullerMonitor();
+ private ClusterMembers clusterMembers = null;
- public ClusterMetrics( Config config, Monitors monitors, MetricRegistry registry )
+ public ClusterMetrics( Config config, Monitors monitors, MetricRegistry registry,
+ DependencyResolver dependencyResolver, LogService logService )
{
this.config = config;
this.monitors = monitors;
this.registry = registry;
+ this.dependencyResolver = dependencyResolver;
+ this.logService = logService;
}
@Override
public void start() throws Throwable
{
- if ( config.get( MetricsSettings.neoClusterEnabled ) )
+ if ( config.get( MetricsSettings.neoClusterEnabled ) && resolveClusterMembersDependencyOrLogWarning() )
{
monitors.addMonitorListener( monitor );
+ registry.register( IS_MASTER, new RoleGauge( Predicates.equalTo( MASTER ) ) );
+ registry.register( IS_AVAILABLE, new RoleGauge( Predicates.not( Predicates.equalTo( UNKNOWN ) ) ) );
+
registry.register( SLAVE_PULL_UPDATES, new Gauge()
{
@Override
@@ -75,17 +93,36 @@ public Long getValue()
return monitor.lastAppliedTxId;
}
} );
+
+ }
+ }
+
+ private boolean resolveClusterMembersDependencyOrLogWarning()
+ {
+ try
+ {
+ clusterMembers = dependencyResolver.resolveDependency( ClusterMembers.class );
+ return true;
+ }
+ catch ( IllegalArgumentException e )
+ {
+ logService.getUserLog( getClass() ).warn( "Cluster metrics was enabled but the graph database" +
+ "is not in HA mode." );
+ return false;
}
}
@Override
public void stop() throws IOException
{
- if ( config.get( MetricsSettings.neoClusterEnabled ) )
+ if ( config.get( MetricsSettings.neoClusterEnabled ) && (clusterMembers != null) )
{
registry.remove( SLAVE_PULL_UPDATES );
registry.remove( SLAVE_PULL_UPDATE_UP_TO_TX );
+ registry.remove( IS_MASTER );
+ registry.remove( IS_AVAILABLE );
+
monitors.removeMonitorListener( monitor );
}
}
@@ -102,4 +139,24 @@ public void pulledUpdates( long lastAppliedTxId )
this.lastAppliedTxId = lastAppliedTxId;
}
}
+
+ private class RoleGauge implements Gauge
+ {
+ private Predicate rolePredicate;
+
+ public RoleGauge( Predicate rolePredicate )
+ {
+ this.rolePredicate = rolePredicate;
+ }
+
+ public Integer getValue()
+ {
+ int value = 0;
+ if ( clusterMembers != null )
+ {
+ value = rolePredicate.test( clusterMembers.getCurrentMemberRole() ) ? 1 : 0;
+ }
+ return value;
+ }
+ }
}
diff --git a/enterprise/metrics/src/main/java/org/neo4j/metrics/source/Neo4jMetricsFactory.java b/enterprise/metrics/src/main/java/org/neo4j/metrics/source/Neo4jMetricsFactory.java
index f78aa621affde..c900816aff133 100644
--- a/enterprise/metrics/src/main/java/org/neo4j/metrics/source/Neo4jMetricsFactory.java
+++ b/enterprise/metrics/src/main/java/org/neo4j/metrics/source/Neo4jMetricsFactory.java
@@ -24,10 +24,12 @@
import java.io.IOException;
import org.neo4j.function.Factory;
+import org.neo4j.graphdb.DependencyResolver;
import org.neo4j.io.pagecache.monitoring.PageCacheMonitor;
import org.neo4j.kernel.IdGeneratorFactory;
import org.neo4j.kernel.configuration.Config;
import org.neo4j.kernel.impl.api.LogRotationMonitor;
+import org.neo4j.kernel.impl.logging.LogService;
import org.neo4j.kernel.impl.transaction.TransactionCounters;
import org.neo4j.kernel.impl.transaction.log.checkpoint.CheckPointerMonitor;
import org.neo4j.kernel.lifecycle.Lifecycle;
@@ -44,11 +46,13 @@ public class Neo4jMetricsFactory implements Factory
private final CheckPointerMonitor checkPointerMonitor;
private final LogRotationMonitor logRotationMonitor;
private final IdGeneratorFactory idGeneratorFactory;
+ private final DependencyResolver dependencyResolver;
+ private final LogService logService;
public Neo4jMetricsFactory( MetricRegistry registry, Config config, Monitors monitors,
TransactionCounters transactionCounters, PageCacheMonitor pageCacheCounters,
CheckPointerMonitor checkPointerMonitor, LogRotationMonitor logRotationMonitor,
- IdGeneratorFactory idGeneratorFactory )
+ IdGeneratorFactory idGeneratorFactory, DependencyResolver dependencyResolver, LogService logService )
{
this.registry = registry;
this.config = config;
@@ -58,6 +62,8 @@ public Neo4jMetricsFactory( MetricRegistry registry, Config config, Monitors mon
this.checkPointerMonitor = checkPointerMonitor;
this.logRotationMonitor = logRotationMonitor;
this.idGeneratorFactory = idGeneratorFactory;
+ this.dependencyResolver = dependencyResolver;
+ this.logService = logService;
}
@Override
@@ -66,9 +72,10 @@ public Lifecycle newInstance()
final DBMetrics dbMetrics = new DBMetrics( registry, config,
transactionCounters, pageCacheCounters, checkPointerMonitor, logRotationMonitor, idGeneratorFactory );
final NetworkMetrics networkMetrics = new NetworkMetrics( config, monitors, registry );
- final ClusterMetrics clusterMetrics = new ClusterMetrics( config, monitors, registry );
- final JvmMetrics jvmMetrics = new JvmMetrics( config, registry );
+ final ClusterMetrics clusterMetrics = new ClusterMetrics( config, monitors, registry, dependencyResolver,
+ logService );
final CypherMetrics cypherMetrics = new CypherMetrics( config, monitors, registry );
+ final JvmMetrics jvmMetrics = new JvmMetrics( config, registry );
return new LifecycleAdapter()
{
@Override
diff --git a/enterprise/metrics/src/test/java/org/neo4j/metrics/MetricsKernelExtensionFactoryIT.java b/enterprise/metrics/src/test/java/org/neo4j/metrics/MetricsKernelExtensionFactoryIT.java
index 13753c99b3d3a..7edadc81d891c 100644
--- a/enterprise/metrics/src/test/java/org/neo4j/metrics/MetricsKernelExtensionFactoryIT.java
+++ b/enterprise/metrics/src/test/java/org/neo4j/metrics/MetricsKernelExtensionFactoryIT.java
@@ -19,7 +19,6 @@
*/
package org.neo4j.metrics;
-import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -27,24 +26,27 @@
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
-import java.io.IOException;
import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
import java.util.UUID;
import org.neo4j.graphdb.DynamicLabel;
-import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.Transaction;
-import org.neo4j.graphdb.factory.GraphDatabaseFactory;
-import org.neo4j.graphdb.factory.GraphDatabaseSettings;
import org.neo4j.helpers.Settings;
+import org.neo4j.kernel.ha.HighlyAvailableGraphDatabase;
+import org.neo4j.kernel.impl.ha.ClusterManager;
import org.neo4j.metrics.source.CypherMetrics;
import org.neo4j.test.TargetDirectory;
+import org.neo4j.test.ha.ClusterRule;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.Matchers.greaterThanOrEqualTo;
import static org.junit.Assert.assertThat;
+import static org.neo4j.graphdb.factory.GraphDatabaseSettings.cypher_min_replan_interval;
+import static org.neo4j.kernel.impl.ha.ClusterManager.clusterOfSize;
import static org.neo4j.metrics.MetricsSettings.CsvFile.single;
import static org.neo4j.metrics.MetricsSettings.csvEnabled;
import static org.neo4j.metrics.MetricsSettings.csvFile;
@@ -54,34 +56,32 @@ public class MetricsKernelExtensionFactoryIT
{
@Rule
public final TargetDirectory.TestDirectory folder = TargetDirectory.testDirForTest( getClass() );
+ @Rule
+ public final ClusterRule clusterRule = new ClusterRule( getClass() );
- GraphDatabaseService db;
private File outputFile;
+ private ClusterManager.ManagedCluster cluster;
+ private HighlyAvailableGraphDatabase db;
@Before
- public void setup() throws IOException
+ public void setup() throws Exception
{
- String dbPath = folder.directory( "data" ).getAbsolutePath();
outputFile = folder.file( "metrics.csv" );
- db = new GraphDatabaseFactory().newEmbeddedDatabaseBuilder( dbPath ).
- setConfig( GraphDatabaseSettings.allow_store_upgrade, Settings.TRUE ).
- setConfig( GraphDatabaseSettings.cypher_min_replan_interval, "0" ).
- setConfig( csvEnabled, Settings.TRUE ).
- setConfig( csvFile, single.name() ).
- setConfig( csvPath, outputFile.getAbsolutePath() ).newGraphDatabase();
- }
-
- @After
- public void shutdown()
- {
- db.shutdown();
+ Map config = new HashMap<>();
+ config.put( csvEnabled.name(), Settings.TRUE );
+ config.put( cypher_min_replan_interval.name(), "0" );
+ config.put( csvFile.name(), single.name() );
+ config.put( csvPath.name(), outputFile.getAbsolutePath() );
+ cluster = clusterRule.withSharedConfig( config ).withProvider( clusterOfSize( 1 ) ).startCluster();
+ db = cluster.getMaster();
}
@Test
- public void mustLoadMetricsExtensionWhenConfigured() throws Exception
+ public void mustLoadMetricsExtensionWhenConfigured() throws Throwable
{
// Create some activity that will show up in the metrics data.
addNodes( 1000 );
+ cluster.stop();
// Awesome. Let's get some metric numbers.
// We should at least have a "timestamp" column, and a "neo4j.transaction.committed" column
@@ -106,12 +106,12 @@ public void mustLoadMetricsExtensionWhenConfigured() throws Exception
}
@Test
- public void showReplanEvents() throws Exception
+ public void showReplanEvents() throws Throwable
{
//do a simple query to populate cache
try ( Transaction tx = db.beginTx() )
{
- db.execute( "match (n:Label {name: 'Pontus'}) return n.name");
+ db.execute( "match (n:Label {name: 'Pontus'}) return n.name" );
tx.success();
}
//add some data, should make plan stale
@@ -124,12 +124,13 @@ public void showReplanEvents() throws Exception
}
//add more data just to make sure metrics are flushed
addNodes( 1000 );
+ cluster.stop();
//now we should have one replan event
try ( BufferedReader reader = new BufferedReader( new FileReader( outputFile ) ) )
{
String[] headers = reader.readLine().split( "," );
- int replanColumn = Arrays.binarySearch( headers, CypherMetrics.REPLAN_EVENTS);
+ int replanColumn = Arrays.binarySearch( headers, CypherMetrics.REPLAN_EVENTS );
assertThat( replanColumn, is( not( -1 ) ) );
// Now we can verify that the number of committed transactions should never decrease.
@@ -147,7 +148,8 @@ public void showReplanEvents() throws Exception
}
}
- private void addNodes( int numberOfNodes ) {
+ private void addNodes( int numberOfNodes )
+ {
for ( int i = 0; i < numberOfNodes; i++ )
{
try ( Transaction tx = db.beginTx() )
@@ -158,5 +160,4 @@ private void addNodes( int numberOfNodes ) {
}
}
}
-
}
diff --git a/enterprise/metrics/src/test/java/org/neo4j/metrics/source/ClusterMetricsTest.java b/enterprise/metrics/src/test/java/org/neo4j/metrics/source/ClusterMetricsTest.java
new file mode 100644
index 0000000000000..2e8e7fceae9af
--- /dev/null
+++ b/enterprise/metrics/src/test/java/org/neo4j/metrics/source/ClusterMetricsTest.java
@@ -0,0 +1,199 @@
+/*
+ * Copyright (c) 2002-2015 "Neo Technology,"
+ * Network Engine for Objects in Lund AB [http://neotechnology.com]
+ *
+ * This file is part of Neo4j.
+ *
+ * Neo4j is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+package org.neo4j.metrics.source;
+
+import com.codahale.metrics.Counter;
+import com.codahale.metrics.Gauge;
+import com.codahale.metrics.Histogram;
+import com.codahale.metrics.Meter;
+import com.codahale.metrics.MetricFilter;
+import com.codahale.metrics.MetricRegistry;
+import com.codahale.metrics.ScheduledReporter;
+import com.codahale.metrics.Timer;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+import java.util.SortedMap;
+import java.util.concurrent.TimeUnit;
+
+import org.neo4j.cluster.InstanceId;
+import org.neo4j.graphdb.DependencyResolver;
+import org.neo4j.helpers.Settings;
+import org.neo4j.kernel.configuration.Config;
+import org.neo4j.kernel.ha.cluster.HighAvailabilityMemberState;
+import org.neo4j.kernel.ha.cluster.HighAvailabilityMemberStateMachine;
+import org.neo4j.kernel.ha.cluster.member.ClusterMember;
+import org.neo4j.kernel.ha.cluster.member.ClusterMembers;
+import org.neo4j.kernel.ha.cluster.member.ObservedClusterMembers;
+import org.neo4j.kernel.ha.cluster.modeswitch.HighAvailabilityModeSwitcher;
+import org.neo4j.kernel.impl.logging.LogService;
+import org.neo4j.kernel.lifecycle.LifeSupport;
+import org.neo4j.kernel.monitoring.Monitors;
+import org.neo4j.metrics.MetricsSettings;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+import static org.neo4j.helpers.collection.MapUtil.stringMap;
+
+
+public class ClusterMetricsTest
+{
+ @Rule
+ public ExpectedException thrown = ExpectedException.none();
+
+ @Test
+ public void clusterMetricsReportMasterAvailable()
+ {
+ // given
+ MetricRegistry metricRegistry = new MetricRegistry();
+ Config config = new Config( stringMap( MetricsSettings.neoClusterEnabled.name(), Settings.TRUE ) );
+ Monitors monitors = new Monitors();
+ LifeSupport life = new LifeSupport();
+ ClusterMembers clusterMembers =
+ getClusterMembers( HighAvailabilityModeSwitcher.MASTER, HighAvailabilityMemberState.MASTER );
+ DependencyResolver dependencyResolver = mock( DependencyResolver.class );
+ when( dependencyResolver.resolveDependency( ClusterMembers.class ) ).thenReturn( clusterMembers );
+ LogService logService = mock( LogService.class );
+
+ life.add( new ClusterMetrics( config, monitors, metricRegistry, dependencyResolver, logService ) );
+ life.start();
+
+ // when
+ TestReporter reporter = new TestReporter( metricRegistry );
+ reporter.start( 10, TimeUnit.MILLISECONDS );
+
+ // then wait for the reporter to get a report
+ reporter.report();
+ assertEquals( 1, reporter.isMasterValue );
+ assertEquals( 1, reporter.isAvailableValue );
+ }
+
+ @Test
+ public void clusterMetricsReportSlaveAvailable()
+ {
+ // given
+ MetricRegistry metricRegistry = new MetricRegistry();
+ Config config = new Config( stringMap( MetricsSettings.neoClusterEnabled.name(), Settings.TRUE ) );
+ ClusterMembers clusterMembers =
+ getClusterMembers( HighAvailabilityModeSwitcher.SLAVE, HighAvailabilityMemberState.SLAVE );
+ DependencyResolver dependencyResolver = mock( DependencyResolver.class );
+ when( dependencyResolver.resolveDependency( ClusterMembers.class ) ).thenReturn( clusterMembers );
+ LogService logService = mock( LogService.class );
+
+ Monitors monitors = new Monitors();
+ LifeSupport life = new LifeSupport();
+ life.add( new ClusterMetrics( config, monitors, metricRegistry, dependencyResolver, logService ) );
+ life.start();
+
+ // when
+ TestReporter reporter = new TestReporter( metricRegistry );
+ reporter.start( 10, TimeUnit.MILLISECONDS );
+
+ //then wait for the reporter to get a report
+ reporter.report();
+ assertEquals( 0, reporter.isMasterValue );
+ assertEquals( 1, reporter.isAvailableValue );
+ }
+
+ @Test
+ public void testClusterMemberNotEnabled()
+ {
+ // given
+ MetricRegistry metricRegistry = new MetricRegistry();
+ Config config = new Config( stringMap( MetricsSettings.neoClusterEnabled.name(), Settings.FALSE ) );
+ ClusterMembers clusterMembers =
+ getClusterMembers( HighAvailabilityModeSwitcher.SLAVE, HighAvailabilityMemberState.SLAVE );
+ DependencyResolver dependencyResolver = mock( DependencyResolver.class );
+ when( dependencyResolver.resolveDependency( ClusterMembers.class ) ).thenReturn( clusterMembers );
+ LogService logService = mock( LogService.class );
+
+ Monitors monitors = new Monitors();
+ LifeSupport life = new LifeSupport();
+ life.add( new ClusterMetrics( config, monitors, metricRegistry, dependencyResolver, logService ) );
+ life.start();
+
+ // when
+ TestReporter reporter = new TestReporter( metricRegistry );
+ reporter.start( 10, TimeUnit.MILLISECONDS );
+
+ //then the reporter should fail
+ thrown.expect( NullPointerException.class );
+ reporter.report();
+ }
+
+ @Test
+ public void testClusterMembersNull()
+ {
+ // given
+ MetricRegistry metricRegistry = new MetricRegistry();
+ Config config = new Config( stringMap( MetricsSettings.neoClusterEnabled.name(), Settings.TRUE ) );
+ ClusterMembers clusterMembers = null;
+ DependencyResolver dependencyResolver = mock( DependencyResolver.class );
+ when( dependencyResolver.resolveDependency( ClusterMembers.class ) ).thenReturn( clusterMembers );
+ LogService logService = mock( LogService.class );
+
+ Monitors monitors = new Monitors();
+ LifeSupport life = new LifeSupport();
+ life.add( new ClusterMetrics( config, monitors, metricRegistry, dependencyResolver, logService ) );
+ life.start();
+
+ // when
+ TestReporter reporter = new TestReporter( metricRegistry );
+ reporter.start( 10, TimeUnit.MILLISECONDS );
+
+ //then the reporter should fail
+ reporter.report();
+ assertEquals( 0, reporter.isMasterValue );
+ assertEquals( 0, reporter.isAvailableValue );
+ }
+
+ ClusterMembers getClusterMembers( String memberRole, HighAvailabilityMemberState memberState )
+ {
+ HighAvailabilityMemberStateMachine stateMachine = mock( HighAvailabilityMemberStateMachine.class );
+ when( stateMachine.getCurrentState() ).thenReturn( memberState );
+ ClusterMember clusterMember = spy( new ClusterMember( new InstanceId( 1 ) ) );
+ when( clusterMember.getHARole() ).thenReturn( memberRole );
+ ObservedClusterMembers observedClusterMembers = mock( ObservedClusterMembers.class );
+ when( observedClusterMembers.getCurrentMember() ).thenReturn( clusterMember );
+ return new ClusterMembers( observedClusterMembers, stateMachine );
+ }
+
+ class TestReporter extends ScheduledReporter
+ {
+ private int isMasterValue, isAvailableValue;
+
+ protected TestReporter( MetricRegistry registry )
+ {
+ super( registry, "TestReporter", MetricFilter.ALL, TimeUnit.MILLISECONDS, TimeUnit.MILLISECONDS );
+ }
+
+ @Override
+ public void report( SortedMap gauges, SortedMap counters,
+ SortedMap histograms, SortedMap meters, SortedMap timers )
+ {
+ isMasterValue = (Integer) gauges.get( ClusterMetrics.IS_MASTER ).getValue();
+ isAvailableValue = (Integer) gauges.get( ClusterMetrics.IS_AVAILABLE ).getValue();
+ }
+ }
+
+}