/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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.apache.ignite.internal; import java.io.Serializable; import java.util.UUID; import java.util.concurrent.CountDownLatch; import org.apache.ignite.GridTestTask; import org.apache.ignite.Ignite; import org.apache.ignite.IgniteCache; import org.apache.ignite.IgniteCheckedException; import org.apache.ignite.cache.eviction.fifo.FifoEvictionPolicy; import org.apache.ignite.cluster.ClusterMetrics; import org.apache.ignite.configuration.CacheConfiguration; import org.apache.ignite.configuration.IgniteConfiguration; import org.apache.ignite.events.Event; import org.apache.ignite.internal.processors.cache.database.MemoryMetricsImpl; import org.apache.ignite.internal.processors.task.GridInternal; import org.apache.ignite.internal.util.lang.GridAbsPredicate; import org.apache.ignite.lang.IgnitePredicate; import org.apache.ignite.messaging.MessagingListenActor; import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi; import org.apache.ignite.spi.discovery.tcp.ipfinder.TcpDiscoveryIpFinder; import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder; import org.apache.ignite.testframework.GridTestUtils; import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest; import org.apache.ignite.testframework.junits.common.GridCommonTest; import static org.apache.ignite.events.EventType.EVT_NODE_METRICS_UPDATED; /** * Grid node metrics self test. */ @GridCommonTest(group = "Kernal Self") public class ClusterNodeMetricsSelfTest extends GridCommonAbstractTest { /** */ private static final TcpDiscoveryIpFinder IP_FINDER = new TcpDiscoveryVmIpFinder(true); /** Test message size. */ private static final int MSG_SIZE = 1024; /** Number of messages. */ private static final int MSG_CNT = 3; /** Size of value in bytes. */ private static final int VAL_SIZE = 512 * 1024; /** Amount of cache entries. */ private static final int MAX_VALS_AMOUNT = 400; /** Cache name. */ private final String CACHE_NAME = "cache1"; /** {@inheritDoc} */ @Override protected void beforeTest() throws Exception { startGrid(); } /** {@inheritDoc} */ @Override protected void afterTest() throws Exception { stopAllGrids(); } /** {@inheritDoc} */ @Override protected IgniteConfiguration getConfiguration(String igniteInstanceName) throws Exception { IgniteConfiguration cfg = super.getConfiguration(igniteInstanceName); TcpDiscoverySpi spi = new TcpDiscoverySpi(); spi.setIpFinder(IP_FINDER); cfg.setDiscoverySpi(spi); cfg.setCacheConfiguration(); cfg.setMetricsUpdateFrequency(500); CacheConfiguration<Integer, Object> ccfg = defaultCacheConfiguration(); ccfg.setName(CACHE_NAME); ccfg.setStatisticsEnabled(true); FifoEvictionPolicy plc = new FifoEvictionPolicy(); plc.setMaxMemorySize(MAX_VALS_AMOUNT * VAL_SIZE); plc.setMaxSize(0); ccfg.setEvictionPolicy(plc); ccfg.setOnheapCacheEnabled(true); return cfg.setCacheConfiguration(ccfg); } /** * @throws Exception If failed. */ public void testAllocatedMemory() throws Exception { IgniteEx ignite = grid(); final IgniteCache cache = ignite.getOrCreateCache(CACHE_NAME); MemoryMetricsImpl memMetrics = getDefaultMemoryPolicyMetrics(ignite); memMetrics.enableMetrics(); int pageSize = getPageSize(ignite); assertEquals(0, memMetrics.getTotalAllocatedPages()); fillCache(cache); assertTrue(memMetrics.getTotalAllocatedPages() * pageSize > MAX_VALS_AMOUNT * VAL_SIZE); } /** * @param ignite Ignite instance. */ private MemoryMetricsImpl getDefaultMemoryPolicyMetrics(IgniteEx ignite) throws IgniteCheckedException { return ignite.context().cache().context().database().memoryPolicy(null).memoryMetrics(); } /** * @param ignite Ignite instance. */ private int getPageSize(IgniteEx ignite) { return ignite.context().cache().context().database().pageSize(); } /** * Fill cache with values. * @param cache Ignite cache. * @throws Exception If failed. */ private void fillCache(final IgniteCache<Integer, Object> cache) throws Exception{ final byte[] val = new byte[VAL_SIZE]; for (int i = 0; i < MAX_VALS_AMOUNT * 4; i++) cache.put(i, val); // Let metrics update twice. final CountDownLatch latch = new CountDownLatch(2); grid().events().localListen(new IgnitePredicate<Event>() { @Override public boolean apply(Event evt) { assert evt.type() == EVT_NODE_METRICS_UPDATED; latch.countDown(); return true; } }, EVT_NODE_METRICS_UPDATED); // Wait for metrics update. latch.await(); } /** * @throws Exception If failed. */ public void testSingleTaskMetrics() throws Exception { Ignite ignite = grid(); final CountDownLatch taskLatch = new CountDownLatch(2); ignite.compute().executeAsync(new GridTestTask(taskLatch), "testArg"); // Let metrics update twice. final CountDownLatch latch = new CountDownLatch(3); ignite.events().localListen(new IgnitePredicate<Event>() { @Override public boolean apply(Event evt) { assert evt.type() == EVT_NODE_METRICS_UPDATED; latch.countDown(); taskLatch.countDown(); return true; } }, EVT_NODE_METRICS_UPDATED); // Wait for metrics update. latch.await(); ClusterMetrics metrics = ignite.cluster().localNode().metrics(); info("Node metrics: " + metrics); assert metrics.getAverageActiveJobs() > 0; assert metrics.getAverageCancelledJobs() == 0; assert metrics.getAverageJobExecuteTime() >= 0; assert metrics.getAverageJobWaitTime() >= 0; assert metrics.getAverageRejectedJobs() == 0; assert metrics.getAverageWaitingJobs() == 0; assert metrics.getCurrentActiveJobs() == 0; assert metrics.getCurrentCancelledJobs() == 0; assert metrics.getCurrentJobExecuteTime() > 0; assert metrics.getCurrentJobWaitTime() == 0; assert metrics.getCurrentWaitingJobs() == 0; assert metrics.getMaximumActiveJobs() == 1; assert metrics.getMaximumCancelledJobs() == 0; assert metrics.getMaximumJobExecuteTime() >= 0; assert metrics.getMaximumJobWaitTime() >= 0; assert metrics.getMaximumRejectedJobs() == 0; assert metrics.getMaximumWaitingJobs() == 0; assert metrics.getTotalCancelledJobs() == 0; assert metrics.getTotalExecutedJobs() == 1; assert metrics.getTotalRejectedJobs() == 0; assert metrics.getTotalExecutedTasks() == 1; assertTrue("MaximumJobExecuteTime=" + metrics.getMaximumJobExecuteTime() + " is less than AverageJobExecuteTime=" + metrics.getAverageJobExecuteTime(), metrics.getMaximumJobExecuteTime() >= metrics.getAverageJobExecuteTime()); } /** * @throws Exception If failed. */ public void testInternalTaskMetrics() throws Exception { Ignite ignite = grid(); // Visor task is internal and should not affect metrics. ignite.compute().withName("visor-test-task").execute(new TestInternalTask(), "testArg"); // Let metrics update twice. final CountDownLatch latch = new CountDownLatch(2); ignite.events().localListen(new IgnitePredicate<Event>() { @Override public boolean apply(Event evt) { assert evt.type() == EVT_NODE_METRICS_UPDATED; latch.countDown(); return true; } }, EVT_NODE_METRICS_UPDATED); // Wait for metrics update. latch.await(); ClusterMetrics metrics = ignite.cluster().localNode().metrics(); info("Node metrics: " + metrics); assert metrics.getAverageActiveJobs() == 0; assert metrics.getAverageCancelledJobs() == 0; assert metrics.getAverageJobExecuteTime() == 0; assert metrics.getAverageJobWaitTime() == 0; assert metrics.getAverageRejectedJobs() == 0; assert metrics.getAverageWaitingJobs() == 0; assert metrics.getCurrentActiveJobs() == 0; assert metrics.getCurrentCancelledJobs() == 0; assert metrics.getCurrentJobExecuteTime() == 0; assert metrics.getCurrentJobWaitTime() == 0; assert metrics.getCurrentWaitingJobs() == 0; assert metrics.getMaximumActiveJobs() == 0; assert metrics.getMaximumCancelledJobs() == 0; assert metrics.getMaximumJobExecuteTime() == 0; assert metrics.getMaximumJobWaitTime() == 0; assert metrics.getMaximumRejectedJobs() == 0; assert metrics.getMaximumWaitingJobs() == 0; assert metrics.getTotalCancelledJobs() == 0; assert metrics.getTotalExecutedJobs() == 0; assert metrics.getTotalRejectedJobs() == 0; assert metrics.getTotalExecutedTasks() == 0; assertTrue("MaximumJobExecuteTime=" + metrics.getMaximumJobExecuteTime() + " is less than AverageJobExecuteTime=" + metrics.getAverageJobExecuteTime(), metrics.getMaximumJobExecuteTime() >= metrics.getAverageJobExecuteTime()); } /** * @throws Exception If failed. */ public void testIoMetrics() throws Exception { Ignite ignite0 = grid(); Ignite ignite1 = startGrid(1); Object msg = new TestMessage(); int size = ignite0.configuration().getMarshaller().marshal(msg).length; assert size > MSG_SIZE; final CountDownLatch latch = new CountDownLatch(MSG_CNT); ignite0.message().localListen(null, new MessagingListenActor<TestMessage>() { @Override protected void receive(UUID nodeId, TestMessage rcvMsg) throws Throwable { latch.countDown(); } }); ignite1.message().localListen(null, new MessagingListenActor<TestMessage>() { @Override protected void receive(UUID nodeId, TestMessage rcvMsg) throws Throwable { respond(rcvMsg); } }); for (int i = 0; i < MSG_CNT; i++) message(ignite0.cluster().forRemotes()).send(null, msg); latch.await(); ClusterMetrics metrics = ignite0.cluster().localNode().metrics(); info("Node 0 metrics: " + metrics); // Time sync messages are being sent. assert metrics.getSentMessagesCount() >= MSG_CNT; assert metrics.getSentBytesCount() > size * MSG_CNT; assert metrics.getReceivedMessagesCount() >= MSG_CNT; assert metrics.getReceivedBytesCount() > size * MSG_CNT; metrics = ignite1.cluster().localNode().metrics(); info("Node 1 metrics: " + metrics); // Time sync messages are being sent. assert metrics.getSentMessagesCount() >= MSG_CNT; assert metrics.getSentBytesCount() > size * MSG_CNT; assert metrics.getReceivedMessagesCount() >= MSG_CNT; assert metrics.getReceivedBytesCount() > size * MSG_CNT; } /** * @throws Exception If failed. */ public void testClusterNodeMetrics() throws Exception { final Ignite ignite0 = grid(); final Ignite ignite1 = startGrid(1); GridTestUtils.waitForCondition(new GridAbsPredicate() { @Override public boolean apply() { return ignite0.cluster().nodes().size() == 2 && ignite1.cluster().nodes().size() == 2; } }, 3000L); ClusterMetrics metrics0 = ignite0.cluster().localNode().metrics(); ClusterMetrics nodesMetrics = ignite0.cluster().forNode(ignite0.cluster().localNode(), ignite1.cluster().localNode()).metrics(); assertEquals(metrics0.getTotalCpus(), nodesMetrics.getTotalCpus()); assertEquals(1, metrics0.getTotalNodes()); assertEquals(2, nodesMetrics.getTotalNodes()); assert metrics0.getHeapMemoryUsed() > 0; assert metrics0.getHeapMemoryTotal() > 0; } /** * Test message. */ @SuppressWarnings("UnusedDeclaration") private static class TestMessage implements Serializable { /** */ private final byte[] arr = new byte[MSG_SIZE]; } /** * Test internal task. */ @GridInternal private static class TestInternalTask extends GridTestTask { // No-op. } }