Search in sources :

Example 6 with StatsSnapshot

use of com.github.ambry.server.StatsSnapshot in project ambry by linkedin.

the class HelixClusterAggregatorTest method testDoWorkWithDiffNodeStats.

/**
 * Tests to verify cluster aggregation with node stats that contain different partition stats.
 * @throws IOException
 */
@Test
public void testDoWorkWithDiffNodeStats() throws IOException {
    long seed = 1234;
    for (StatsReportType type : EnumSet.of(StatsReportType.ACCOUNT_REPORT, StatsReportType.PARTITION_CLASS_REPORT)) {
        List<StatsSnapshot> greaterStoreSnapshots = new ArrayList<>();
        List<StatsSnapshot> smallerStoreSnapshots = new ArrayList<>();
        List<StatsSnapshot> mediumStoreSnapshots = new ArrayList<>();
        greaterStoreSnapshots.add(TestUtils.generateStoreStats(6, 3, new Random(seed), type));
        mediumStoreSnapshots.add(TestUtils.generateStoreStats(5, 3, new Random(seed), type));
        smallerStoreSnapshots.add(TestUtils.generateStoreStats(5, 3, new Random(seed), type));
        StatsWrapper greaterNodeStats = TestUtils.generateNodeStats(greaterStoreSnapshots, DEFAULT_TIMESTAMP, type);
        StatsWrapper mediumNodeStats = TestUtils.generateNodeStats(mediumStoreSnapshots, DEFAULT_TIMESTAMP, type);
        StatsWrapper smallerNodeStats = TestUtils.generateNodeStats(smallerStoreSnapshots, DEFAULT_TIMESTAMP, type);
        StatsWrapper emptyNodeStats = TestUtils.generateNodeStats(Collections.emptyList(), DEFAULT_TIMESTAMP, type);
        Map<String, String> instanceToStatsMap = new LinkedHashMap<>();
        instanceToStatsMap.put("Instance_0", mapper.writeValueAsString(smallerNodeStats));
        instanceToStatsMap.put("Instance_1", mapper.writeValueAsString(greaterNodeStats));
        instanceToStatsMap.put("Instance_2", mapper.writeValueAsString(mediumNodeStats));
        instanceToStatsMap.put("Instance_3", mapper.writeValueAsString(emptyNodeStats));
        instanceToStatsMap.put(EXCEPTION_INSTANCE_NAME, "");
        Pair<StatsSnapshot, StatsSnapshot> aggregatedRawAndValidStats = clusterAggregator.doWork(instanceToStatsMap, type);
        StatsSnapshot expectedRawSnapshot = new StatsSnapshot(0L, new HashMap<>());
        StatsSnapshot expectedValidSnapshot = null;
        switch(type) {
            case ACCOUNT_REPORT:
                StatsSnapshot.aggregate(expectedRawSnapshot, smallerStoreSnapshots.get(0));
                StatsSnapshot.aggregate(expectedRawSnapshot, mediumStoreSnapshots.get(0));
                StatsSnapshot.aggregate(expectedRawSnapshot, greaterStoreSnapshots.get(0));
                expectedValidSnapshot = greaterStoreSnapshots.get(0);
                break;
            case PARTITION_CLASS_REPORT:
                expectedValidSnapshot = HelixClusterAggregator.reduceByPartitionClass(greaterNodeStats.getSnapshot());
                StatsSnapshot.aggregate(expectedRawSnapshot, mediumNodeStats.getSnapshot());
                StatsSnapshot.aggregate(expectedRawSnapshot, smallerNodeStats.getSnapshot());
                StatsSnapshot.aggregate(expectedRawSnapshot, greaterNodeStats.getSnapshot());
                expectedRawSnapshot = HelixClusterAggregator.reduceByPartitionClass(expectedRawSnapshot);
                break;
        }
        // verify cluster wide aggregation on raw data with different node stats
        StatsSnapshot rawSnapshot = mapper.readValue(mapper.writeValueAsString(aggregatedRawAndValidStats.getFirst()), StatsSnapshot.class);
        assertTrue("Mismatch in the raw aggregated snapshot for " + type, expectedRawSnapshot.equals(rawSnapshot));
        // verify cluster wide aggregation on valid data with different node stats
        StatsSnapshot actualSnapshot = mapper.readValue(mapper.writeValueAsString(aggregatedRawAndValidStats.getSecond()), StatsSnapshot.class);
        assertTrue("Mismatch in the valid aggregated snapshot for " + type, expectedValidSnapshot.equals(actualSnapshot));
        // verify aggregator keeps track of instances where exception occurred.
        assertEquals("Mismatch in instances where exception occurred", Collections.singletonList(EXCEPTION_INSTANCE_NAME), clusterAggregator.getExceptionOccurredInstances(type));
    }
}
Also used : Random(java.util.Random) ArrayList(java.util.ArrayList) StatsWrapper(com.github.ambry.server.StatsWrapper) StatsReportType(com.github.ambry.server.StatsReportType) StatsSnapshot(com.github.ambry.server.StatsSnapshot) LinkedHashMap(java.util.LinkedHashMap) Test(org.junit.Test)

Example 7 with StatsSnapshot

use of com.github.ambry.server.StatsSnapshot in project ambry by linkedin.

the class HelixClusterAggregatorTest method testDoWorkBasic.

/**
 * Basic tests to verify the cluster wide raw data and valid data aggregation. The tests also verify stats aggregation
 * for all types of stats reports.
 * @throws IOException
 */
@Test
public void testDoWorkBasic() throws IOException {
    int nodeCount = 3;
    Random random = new Random();
    // For each type of report, create snapshots for 3 stores with 3 accounts, 4 accounts and 5 accounts respectively.
    for (StatsReportType type : EnumSet.of(StatsReportType.ACCOUNT_REPORT, StatsReportType.PARTITION_CLASS_REPORT)) {
        List<StatsSnapshot> storeSnapshots = new ArrayList<>();
        for (int i = 3; i < 6; i++) {
            storeSnapshots.add(TestUtils.generateStoreStats(i, 3, random, type));
        }
        StatsWrapper nodeStats = TestUtils.generateNodeStats(storeSnapshots, DEFAULT_TIMESTAMP, type);
        String nodeStatsJSON = mapper.writeValueAsString(nodeStats);
        StatsWrapper emptyNodeStats = TestUtils.generateNodeStats(Collections.emptyList(), DEFAULT_TIMESTAMP, type);
        String emptyStatsJSON = mapper.writeValueAsString(emptyNodeStats);
        Map<String, String> instanceToStatsMap = new HashMap<>();
        // selects the replica with highest value.
        for (int i = 0; i < nodeCount; i++) {
            instanceToStatsMap.put("Instance_" + i, nodeStatsJSON);
        }
        // Add two special cases into instance-to-stats map for testing:
        // (1) empty stats report from certain instance
        // (2) corrupted/invalid stats report from certain instance (this is simulated by empty string)
        instanceToStatsMap.put("Instance_" + nodeCount, emptyStatsJSON);
        instanceToStatsMap.put(EXCEPTION_INSTANCE_NAME, "");
        // 1. Aggregate all snapshots into the first snapshot in snapshots list. The intention is to get expected aggregated snapshot.
        // 2. Then invoke clusterAggregator to do work on stats across all instances.
        // 3. Verify both raw stats and valid stats after aggregation
        Pair<StatsSnapshot, StatsSnapshot> aggregatedRawAndValidStats = clusterAggregator.doWork(instanceToStatsMap, type);
        StatsSnapshot expectedSnapshot = null;
        switch(type) {
            case ACCOUNT_REPORT:
                // we expect for valid data aggregation.
                for (int i = 1; i < storeSnapshots.size(); i++) {
                    StatsSnapshot.aggregate(storeSnapshots.get(0), storeSnapshots.get(i));
                }
                expectedSnapshot = storeSnapshots.get(0);
                break;
            case PARTITION_CLASS_REPORT:
                // Invoke reduceByPartitionClass to remove partition level and only keep the partition class and account_container entries
                expectedSnapshot = HelixClusterAggregator.reduceByPartitionClass(nodeStats.getSnapshot());
                break;
        }
        // Verify cluster wide raw stats aggregation
        StatsSnapshot rawSnapshot = mapper.readValue(mapper.writeValueAsString(aggregatedRawAndValidStats.getFirst()), StatsSnapshot.class);
        assertEquals("Mismatch in total value of " + type, nodeCount * expectedSnapshot.getValue(), rawSnapshot.getValue());
        if (type == StatsReportType.ACCOUNT_REPORT) {
            verifyAggregatedRawStatsForAccountReport(rawSnapshot, expectedSnapshot, nodeCount);
        } else if (type == StatsReportType.PARTITION_CLASS_REPORT) {
            verifyAggregatedRawStatsForPartitionClassReport(rawSnapshot, expectedSnapshot, nodeCount);
        }
        // Verify cluster wide stats aggregation
        StatsSnapshot actualSnapshot = mapper.readValue(mapper.writeValueAsString(aggregatedRawAndValidStats.getSecond()), StatsSnapshot.class);
        assertTrue("Mismatch in the aggregated snapshot", expectedSnapshot.equals(actualSnapshot));
        // Verify aggregator keeps track of instances where exception occurred.
        assertEquals("Mismatch in instances where exception occurred", Collections.singletonList(EXCEPTION_INSTANCE_NAME), clusterAggregator.getExceptionOccurredInstances(type));
    }
}
Also used : Random(java.util.Random) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) ArrayList(java.util.ArrayList) StatsWrapper(com.github.ambry.server.StatsWrapper) StatsReportType(com.github.ambry.server.StatsReportType) StatsSnapshot(com.github.ambry.server.StatsSnapshot) Test(org.junit.Test)

Example 8 with StatsSnapshot

use of com.github.ambry.server.StatsSnapshot in project ambry by linkedin.

the class HelixClusterAggregatorTest method testStatsAggregationWithAllEmptyNodes.

/**
 * Tests to verify cluster aggregation with all empty nodes.
 * @throws IOException
 */
@Test
public void testStatsAggregationWithAllEmptyNodes() throws IOException {
    int nodeCount = 3;
    for (StatsReportType type : EnumSet.of(StatsReportType.ACCOUNT_REPORT, StatsReportType.PARTITION_CLASS_REPORT)) {
        StatsWrapper emptyNodeStats = TestUtils.generateNodeStats(Collections.emptyList(), DEFAULT_TIMESTAMP, type);
        String emptyStatsJSON = mapper.writeValueAsString(emptyNodeStats);
        Map<String, String> instanceToStatsMap = new HashMap<>();
        for (int i = 0; i < nodeCount; i++) {
            instanceToStatsMap.put("Instance_" + i, emptyStatsJSON);
        }
        Pair<StatsSnapshot, StatsSnapshot> aggregatedRawAndValidStats = clusterAggregator.doWork(instanceToStatsMap, type);
        StatsSnapshot expectedSnapshot = new StatsSnapshot(0L, null);
        StatsSnapshot rawSnapshot = mapper.readValue(mapper.writeValueAsString(aggregatedRawAndValidStats.getFirst()), StatsSnapshot.class);
        StatsSnapshot validSnapshot = mapper.readValue(mapper.writeValueAsString(aggregatedRawAndValidStats.getSecond()), StatsSnapshot.class);
        assertTrue("Mismatch in raw snapshot", expectedSnapshot.equals(rawSnapshot));
        assertTrue("Mismatch in valid snapshot", expectedSnapshot.equals(validSnapshot));
    }
}
Also used : HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) StatsWrapper(com.github.ambry.server.StatsWrapper) StatsReportType(com.github.ambry.server.StatsReportType) StatsSnapshot(com.github.ambry.server.StatsSnapshot) Test(org.junit.Test)

Example 9 with StatsSnapshot

use of com.github.ambry.server.StatsSnapshot in project ambry by linkedin.

the class HelixHealthReportAggregationTaskTest method initializeNodeReports.

/**
 * Initialize the reports and create instances in helix if not exists.
 * @param type The type of reports to create
 * @param numNode The number of nodes to initiate.
 * @param startingPort The starting port number, which will then be incremented to represent different nodes.
 * @throws IOException
 */
private void initializeNodeReports(StatsReportType type, int numNode, int startingPort) throws IOException {
    String healthReportName = type == StatsReportType.ACCOUNT_REPORT ? HEALTH_REPORT_NAME_ACCOUNT : HEALTH_REPORT_NAME_PARTITION;
    String statsFieldName = type == StatsReportType.ACCOUNT_REPORT ? STATS_FIELD_NAME_ACCOUNT : STATS_FIELD_NAME_PARTITION;
    List<StatsSnapshot> storeSnapshots = new ArrayList<>();
    Random random = new Random();
    for (int i = 3; i < 6; i++) {
        storeSnapshots.add(TestUtils.generateStoreStats(i, 3, random, type));
    }
    StatsWrapper nodeStats = TestUtils.generateNodeStats(storeSnapshots, 1000, type);
    String nodeStatsJSON = mapper.writeValueAsString(nodeStats);
    HelixDataAccessor dataAccessor = mockHelixManager.getHelixDataAccessor();
    for (int i = 0; i < numNode; i++) {
        String instanceName = ClusterMapUtils.getInstanceName("localhost", startingPort);
        InstanceConfig instanceConfig = new InstanceConfig(instanceName);
        instanceConfig.setHostName("localhost");
        instanceConfig.setPort(Integer.toString(startingPort));
        mockHelixAdmin.addInstance(CLUSTER_NAME, instanceConfig);
        PropertyKey key = dataAccessor.keyBuilder().healthReport(instanceName, healthReportName);
        ZNRecord znRecord = new ZNRecord(instanceName);
        // Set the same reports for all instances
        znRecord.setSimpleField(statsFieldName, nodeStatsJSON);
        HelixProperty helixProperty = new HelixProperty(znRecord);
        dataAccessor.setProperty(key, helixProperty);
        startingPort++;
    }
}
Also used : HelixDataAccessor(org.apache.helix.HelixDataAccessor) Random(java.util.Random) InstanceConfig(org.apache.helix.model.InstanceConfig) HelixProperty(org.apache.helix.HelixProperty) ArrayList(java.util.ArrayList) StatsWrapper(com.github.ambry.server.StatsWrapper) PropertyKey(org.apache.helix.PropertyKey) ZNRecord(org.apache.helix.zookeeper.datamodel.ZNRecord) StatsSnapshot(com.github.ambry.server.StatsSnapshot)

Example 10 with StatsSnapshot

use of com.github.ambry.server.StatsSnapshot in project ambry by linkedin.

the class AccountStatsMySqlStoreIntegrationTest method testHostPartitionClassStorageStats.

/**
 * Test methods to store and fetch partition class, partition name partition id and partition class storage stats.
 * @throws Exception
 */
@Test
public void testHostPartitionClassStorageStats() throws Exception {
    // First write some stats to account reports
    testMultiStoreStats();
    HostAccountStorageStatsWrapper accountStats1 = mySqlStore.queryHostAccountStorageStatsByHost(hostname1, port1);
    HostAccountStorageStatsWrapper accountStats2 = mySqlStore.queryHostAccountStorageStatsByHost(hostname2, port2);
    AccountStatsMySqlStore mySqlStore3 = createAccountStatsMySqlStore(clusterName2, hostname3, port3);
    HostAccountStorageStatsWrapper accountStats3 = mySqlStore3.queryHostAccountStorageStatsByHost(hostname3, port3);
    // From this account stats, create partition class stats;
    Set<Long> allPartitionKeys = new HashSet<Long>() {

        {
            addAll(accountStats1.getStats().getStorageStats().keySet());
            addAll(accountStats2.getStats().getStorageStats().keySet());
            addAll(accountStats3.getStats().getStorageStats().keySet());
        }
    };
    List<String> partitionClassNames = Arrays.asList("default", "new");
    Map<Long, String> partitionIdToClassName = new HashMap<>();
    int ind = 0;
    for (long partitionId : allPartitionKeys) {
        partitionIdToClassName.put(partitionId, partitionClassNames.get(ind % partitionClassNames.size()));
        ind++;
    }
    HostPartitionClassStorageStatsWrapper partitionClassStats1 = convertHostAccountStorageStatsToHostPartitionClassStorageStats(accountStats1, partitionIdToClassName);
    HostPartitionClassStorageStatsWrapper partitionClassStats2 = convertHostAccountStorageStatsToHostPartitionClassStorageStats(accountStats2, partitionIdToClassName);
    HostPartitionClassStorageStatsWrapper partitionClassStats3 = convertHostAccountStorageStatsToHostPartitionClassStorageStats(accountStats3, partitionIdToClassName);
    mySqlStore.storeHostPartitionClassStorageStats(partitionClassStats1);
    mySqlStore.storeHostPartitionClassStorageStats(partitionClassStats2);
    mySqlStore3.storeHostPartitionClassStorageStats(partitionClassStats3);
    Map<String, Set<Integer>> partitionNameAndIds = mySqlStore.queryPartitionNameAndIds();
    assertEquals(new HashSet<>(partitionClassNames), partitionNameAndIds.keySet());
    Map<Long, String> dbPartitionKeyToClassName = partitionNameAndIds.entrySet().stream().flatMap(ent -> ent.getValue().stream().map(pid -> new Pair<>(ent.getKey(), (long) pid))).collect(Collectors.toMap(Pair::getSecond, Pair::getFirst));
    assertEquals(partitionIdToClassName, dbPartitionKeyToClassName);
    // Fetch HostPartitionClassStorageStats
    HostPartitionClassStorageStatsWrapper obtainedStats1 = mySqlStore.queryHostPartitionClassStorageStatsByHost(hostname1, port1, partitionNameAndIds);
    assertEquals(partitionClassStats1.getStats().getStorageStats(), obtainedStats1.getStats().getStorageStats());
    HostPartitionClassStorageStatsWrapper obtainedStats2 = mySqlStore.queryHostPartitionClassStorageStatsByHost(hostname2, port2, partitionNameAndIds);
    assertEquals(partitionClassStats2.getStats().getStorageStats(), obtainedStats2.getStats().getStorageStats());
    HostPartitionClassStorageStatsWrapper obtainedStats3 = mySqlStore3.queryHostPartitionClassStorageStatsByHost(hostname3, port3, partitionNameAndIds);
    assertEquals(partitionClassStats3.getStats().getStorageStats(), obtainedStats3.getStats().getStorageStats());
    // Fetch StatsSnapshot
    StatsWrapper obtainedStats = mySqlStore.queryPartitionClassStatsByHost(hostname1, port1, partitionNameAndIds);
    assertEquals(StorageStatsUtil.convertHostPartitionClassStorageStatsToStatsSnapshot(obtainedStats1.getStats(), false), obtainedStats.getSnapshot());
    mySqlStore3.shutdown();
}
Also used : HostPartitionClassStorageStats(com.github.ambry.server.storagestats.HostPartitionClassStorageStats) HostAccountStorageStatsWrapper(com.github.ambry.server.HostAccountStorageStatsWrapper) Arrays(java.util.Arrays) Connection(java.sql.Connection) AggregatedPartitionClassStorageStats(com.github.ambry.server.storagestats.AggregatedPartitionClassStorageStats) StatsHeader(com.github.ambry.server.StatsHeader) RunWith(org.junit.runner.RunWith) HostAccountStorageStats(com.github.ambry.server.storagestats.HostAccountStorageStats) HashMap(java.util.HashMap) Random(java.util.Random) ContainerStorageStats(com.github.ambry.server.storagestats.ContainerStorageStats) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) SQLException(java.sql.SQLException) TestUtils(com.github.ambry.utils.TestUtils) ResultSet(java.sql.ResultSet) Map(java.util.Map) After(org.junit.After) Path(java.nio.file.Path) Parameterized(org.junit.runners.Parameterized) StatsWrapper(com.github.ambry.server.StatsWrapper) Before(org.junit.Before) MetricRegistry(com.codahale.metrics.MetricRegistry) Properties(java.util.Properties) Pair(com.github.ambry.utils.Pair) Files(java.nio.file.Files) VerifiableProperties(com.github.ambry.config.VerifiableProperties) Set(java.util.Set) Utils(com.github.ambry.utils.Utils) IOException(java.io.IOException) Test(org.junit.Test) Collectors(java.util.stream.Collectors) AccountStatsMySqlConfig(com.github.ambry.config.AccountStatsMySqlConfig) AggregatedAccountStorageStats(com.github.ambry.server.storagestats.AggregatedAccountStorageStats) List(java.util.List) StorageStatsUtil(com.github.ambry.server.StorageStatsUtil) StatsReportType(com.github.ambry.server.StatsReportType) StatsSnapshot(com.github.ambry.server.StatsSnapshot) ClusterMapConfig(com.github.ambry.config.ClusterMapConfig) Statement(java.sql.Statement) Assert(org.junit.Assert) HostPartitionClassStorageStatsWrapper(com.github.ambry.server.HostPartitionClassStorageStatsWrapper) Collections(java.util.Collections) StorageStatsUtilTest(com.github.ambry.server.StorageStatsUtilTest) HostAccountStorageStatsWrapper(com.github.ambry.server.HostAccountStorageStatsWrapper) HashSet(java.util.HashSet) ResultSet(java.sql.ResultSet) Set(java.util.Set) HashMap(java.util.HashMap) HostPartitionClassStorageStatsWrapper(com.github.ambry.server.HostPartitionClassStorageStatsWrapper) HostAccountStorageStatsWrapper(com.github.ambry.server.HostAccountStorageStatsWrapper) StatsWrapper(com.github.ambry.server.StatsWrapper) HostPartitionClassStorageStatsWrapper(com.github.ambry.server.HostPartitionClassStorageStatsWrapper) HashSet(java.util.HashSet) Test(org.junit.Test) StorageStatsUtilTest(com.github.ambry.server.StorageStatsUtilTest)

Aggregations

StatsSnapshot (com.github.ambry.server.StatsSnapshot)35 HashMap (java.util.HashMap)26 Map (java.util.Map)18 Test (org.junit.Test)18 StatsWrapper (com.github.ambry.server.StatsWrapper)14 Random (java.util.Random)10 ArrayList (java.util.ArrayList)9 StatsReportType (com.github.ambry.server.StatsReportType)6 StorageStatsUtilTest (com.github.ambry.server.StorageStatsUtilTest)6 LinkedHashMap (java.util.LinkedHashMap)6 StatsHeader (com.github.ambry.server.StatsHeader)5 VerifiableProperties (com.github.ambry.config.VerifiableProperties)4 HostAccountStorageStatsWrapper (com.github.ambry.server.HostAccountStorageStatsWrapper)4 Pair (com.github.ambry.utils.Pair)4 HashSet (java.util.HashSet)4 ObjectMapper (com.fasterxml.jackson.databind.ObjectMapper)3 AccountStatsMySqlStore (com.github.ambry.accountstats.AccountStatsMySqlStore)3 StorageQuotaConfig (com.github.ambry.config.StorageQuotaConfig)3 HostPartitionClassStorageStatsWrapper (com.github.ambry.server.HostPartitionClassStorageStatsWrapper)3 AggregatedAccountStorageStats (com.github.ambry.server.storagestats.AggregatedAccountStorageStats)3