Search in sources :

Example 36 with ContainerStorageStats

use of com.github.ambry.server.storagestats.ContainerStorageStats in project ambry by linkedin.

the class AccountStatsMySqlStoreIntegrationTest method testEmptyStatsWhenReadingPreviousStatsFromMysqlDb.

@Test
public void testEmptyStatsWhenReadingPreviousStatsFromMysqlDb() throws Exception {
    // write a new stats into database.
    AccountStatsMySqlStore mySqlStore = createAccountStatsMySqlStore(clusterName1, hostname1, port1);
    HostAccountStorageStatsWrapper stats = generateHostAccountStorageStatsWrapper(1, 1, 1, StatsReportType.ACCOUNT_REPORT);
    mySqlStore.storeHostAccountStorageStats(stats);
    HostAccountStorageStatsWrapper obtainedStats = mySqlStore.queryHostAccountStorageStatsByHost(hostname1, port1);
    assertTrue(obtainedStats.getStats().getStorageStats().containsKey((long) 0));
    // initialized the mySqlStore and write a new stats with the same partition.
    mySqlStore = createAccountStatsMySqlStore(clusterName1, hostname1, port1);
    assertTrue(mySqlStore.getPreviousHostAccountStorageStatsWrapper().getStats().getStorageStats().containsKey((long) 0));
    HostAccountStorageStatsWrapper stats2 = generateHostAccountStorageStatsWrapper(0, 0, 0, StatsReportType.ACCOUNT_REPORT);
    Map<Long, Map<Short, Map<Short, ContainerStorageStats>>> newStorageStats = new HashMap<>(stats2.getStats().getStorageStats());
    newStorageStats.put((long) 0, // Remove partition 0's storage stats data, this would remove entire partition from database
    new HashMap<>());
    mySqlStore.storeHostAccountStorageStats(new HostAccountStorageStatsWrapper(stats2.getHeader(), new HostAccountStorageStats(newStorageStats)));
    // empty stats should remove all the data in the database
    obtainedStats = mySqlStore.queryHostAccountStorageStatsByHost(hostname1, port1);
    assertFalse(obtainedStats.getStats().getStorageStats().containsKey((long) 0));
}
Also used : HostAccountStorageStatsWrapper(com.github.ambry.server.HostAccountStorageStatsWrapper) ContainerStorageStats(com.github.ambry.server.storagestats.ContainerStorageStats) HostAccountStorageStats(com.github.ambry.server.storagestats.HostAccountStorageStats) HashMap(java.util.HashMap) HashMap(java.util.HashMap) Map(java.util.Map) Test(org.junit.Test) StorageStatsUtilTest(com.github.ambry.server.StorageStatsUtilTest)

Example 37 with ContainerStorageStats

use of com.github.ambry.server.storagestats.ContainerStorageStats in project ambry by linkedin.

the class AccountReportsDao method queryStorageUsageForHost.

/**
 * Query container storage usage for given {@code clusterName} and {@code hostname}. The result will be applied to the
 * {@link ContainerStorageStatsFunction}.
 * @param clusterName The clusterName.
 * @param hostname The hostname.
 * @param func The {@link ContainerStorageStatsFunction} to call to process each container storage usage.
 * @throws SQLException
 */
void queryStorageUsageForHost(String clusterName, String hostname, ContainerStorageStatsFunction func) throws SQLException {
    try (Connection connection = dataSource.getConnection()) {
        try (PreparedStatement queryStatement = connection.prepareStatement(querySqlForClusterAndHost)) {
            long startTimeMs = System.currentTimeMillis();
            queryStatement.setString(1, clusterName);
            queryStatement.setString(2, hostname);
            try (ResultSet resultSet = queryStatement.executeQuery()) {
                while (resultSet.next()) {
                    int partitionId = resultSet.getInt(PARTITION_ID_COLUMN);
                    int accountId = resultSet.getInt(ACCOUNT_ID_COLUMN);
                    int containerId = resultSet.getInt(CONTAINER_ID_COLUMN);
                    long storageUsage = resultSet.getLong(STORAGE_USAGE_COLUMN);
                    final long physicalStorageUsage = resultSet.getLong(PHYSICAL_STORAGE_USAGE_COLUMN);
                    final long numberOfBlobs = resultSet.getLong(NUMBER_OF_BLOBS_COLUMN);
                    long updatedAtMs = resultSet.getTimestamp(UPDATED_AT_COLUMN).getTime();
                    func.apply(partitionId, (short) accountId, new ContainerStorageStats((short) containerId, storageUsage, physicalStorageUsage, numberOfBlobs), updatedAtMs);
                }
            }
            metrics.readTimeMs.update(System.currentTimeMillis() - startTimeMs);
            metrics.readSuccessCount.inc();
        }
    } catch (SQLException e) {
        metrics.readFailureCount.inc();
        logger.error(String.format("Failed to execute query on %s, with parameter %s %s", ACCOUNT_REPORTS_TABLE, clusterName, hostname), e);
        throw e;
    }
}
Also used : ContainerStorageStats(com.github.ambry.server.storagestats.ContainerStorageStats) SQLException(java.sql.SQLException) Connection(java.sql.Connection) ResultSet(java.sql.ResultSet) PreparedStatement(java.sql.PreparedStatement)

Example 38 with ContainerStorageStats

use of com.github.ambry.server.storagestats.ContainerStorageStats in project ambry by linkedin.

the class AccountStatsMySqlStore method queryHostPartitionClassStorageStatsByHost.

@Override
public HostPartitionClassStorageStatsWrapper queryHostPartitionClassStorageStatsByHost(String hostname, int port, Map<String, Set<Integer>> partitionNameAndIds) throws SQLException {
    long startTimeMs = System.currentTimeMillis();
    hostname = hostnameHelper.simplifyHostname(hostname, port);
    Map<Integer, Map<Short, Map<Short, ContainerStorageStats>>> partitionAccountContainerUsage = new HashMap<>();
    AtomicLong timestamp = new AtomicLong(0);
    accountReportsDao.queryStorageUsageForHost(clusterName, hostname, (partitionId, accountId, containerStats, updatedAtMs) -> {
        partitionAccountContainerUsage.computeIfAbsent(partitionId, pid -> new HashMap<>()).computeIfAbsent(accountId, aid -> new HashMap<>()).put(containerStats.getContainerId(), containerStats);
        timestamp.set(Math.max(timestamp.get(), updatedAtMs));
    });
    // Here partitionAccountContainerUsage has partition id, account id and container id as keys of map at each level,
    // the value is the storage usage.
    // As indicated by the comments above, we have to know the partition class name for each partition id. Luckily, we
    // have all the partition ids and we have a map partitionNameAndIds whose key is the partition class name and the
    // value is the list of all partition ids belong to the partition class name.
    Set<Integer> partitionIds = partitionAccountContainerUsage.keySet();
    Map<String, Set<Integer>> partitionNameAndIdsForHost = new HashMap<>();
    for (int partitionId : partitionIds) {
        boolean found = false;
        for (Map.Entry<String, Set<Integer>> namesAndIdsEntry : partitionNameAndIds.entrySet()) {
            if (namesAndIdsEntry.getValue().contains(partitionId)) {
                partitionNameAndIdsForHost.computeIfAbsent(namesAndIdsEntry.getKey(), k -> new HashSet<>()).add(partitionId);
                found = true;
                break;
            }
        }
        if (!found) {
            storeMetrics.missingPartitionClassNameErrorCount.inc();
            logger.error("Can't find partition class name for partition id {}", partitionId);
        }
    }
    HostPartitionClassStorageStats hostPartitionClassStorageStats = new HostPartitionClassStorageStats();
    for (Map.Entry<String, Set<Integer>> nameAndIdsEntry : partitionNameAndIdsForHost.entrySet()) {
        String partitionClassName = nameAndIdsEntry.getKey();
        for (int partitionId : nameAndIdsEntry.getValue()) {
            Map<Short, Map<Short, ContainerStorageStats>> accountContainerUsage = partitionAccountContainerUsage.get(partitionId);
            for (short accountId : accountContainerUsage.keySet()) {
                Map<Short, ContainerStorageStats> containerUsage = accountContainerUsage.get(accountId);
                containerUsage.values().stream().forEach(containerStats -> hostPartitionClassStorageStats.addContainerStorageStats(partitionClassName, partitionId, accountId, containerStats));
            }
        }
    }
    storeMetrics.queryPartitionClassStatsTimeMs.update(System.currentTimeMillis() - startTimeMs);
    return new HostPartitionClassStorageStatsWrapper(new StatsHeader(StatsHeader.StatsDescription.STORED_DATA_SIZE, timestamp.get(), partitionAccountContainerUsage.size(), partitionAccountContainerUsage.size(), null), hostPartitionClassStorageStats);
}
Also used : HostPartitionClassStorageStats(com.github.ambry.server.storagestats.HostPartitionClassStorageStats) Histogram(com.codahale.metrics.Histogram) HostAccountStorageStatsWrapper(com.github.ambry.server.HostAccountStorageStatsWrapper) Connection(java.sql.Connection) AggregatedPartitionClassStorageStats(com.github.ambry.server.storagestats.AggregatedPartitionClassStorageStats) StatsHeader(com.github.ambry.server.StatsHeader) Strings(joptsimple.internal.Strings) LoggerFactory(org.slf4j.LoggerFactory) HostAccountStorageStats(com.github.ambry.server.storagestats.HostAccountStorageStats) HashMap(java.util.HashMap) ContainerStorageStats(com.github.ambry.server.storagestats.ContainerStorageStats) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) SQLException(java.sql.SQLException) Map(java.util.Map) Counter(com.codahale.metrics.Counter) DataSource(javax.sql.DataSource) MetricRegistry(com.codahale.metrics.MetricRegistry) Logger(org.slf4j.Logger) ObjectMapper(com.fasterxml.jackson.databind.ObjectMapper) Set(java.util.Set) Utils(com.github.ambry.utils.Utils) IOException(java.io.IOException) Collectors(java.util.stream.Collectors) File(java.io.File) AccountStatsMySqlConfig(com.github.ambry.config.AccountStatsMySqlConfig) AggregatedAccountStorageStats(com.github.ambry.server.storagestats.AggregatedAccountStorageStats) AtomicLong(java.util.concurrent.atomic.AtomicLong) List(java.util.List) MySqlMetrics(com.github.ambry.mysql.MySqlMetrics) Statement(java.sql.Statement) Optional(java.util.Optional) SerializationFeature(com.fasterxml.jackson.databind.SerializationFeature) HostPartitionClassStorageStatsWrapper(com.github.ambry.server.HostPartitionClassStorageStatsWrapper) Collections(java.util.Collections) HashSet(java.util.HashSet) Set(java.util.Set) HashMap(java.util.HashMap) StatsHeader(com.github.ambry.server.StatsHeader) HostPartitionClassStorageStats(com.github.ambry.server.storagestats.HostPartitionClassStorageStats) ContainerStorageStats(com.github.ambry.server.storagestats.ContainerStorageStats) AtomicLong(java.util.concurrent.atomic.AtomicLong) HostPartitionClassStorageStatsWrapper(com.github.ambry.server.HostPartitionClassStorageStatsWrapper) HashMap(java.util.HashMap) Map(java.util.Map) HashSet(java.util.HashSet)

Example 39 with ContainerStorageStats

use of com.github.ambry.server.storagestats.ContainerStorageStats in project ambry by linkedin.

the class StatsManagerTest method testStatsManagerWithProblematicStores.

/**
 * Test to verify the behavior when dealing with {@link Store} that is null and when {@link StoreException} is thrown.
 * @throws Exception
 */
@Test
public void testStatsManagerWithProblematicStores() throws Exception {
    DataNodeId dataNodeId = new MockDataNodeId(Collections.singletonList(new Port(6667, PortType.PLAINTEXT)), Collections.singletonList("/tmp"), "DC1");
    Map<PartitionId, Store> problematicStoreMap = new HashMap<>();
    PartitionId partitionId1 = new MockPartitionId(1, MockClusterMap.DEFAULT_PARTITION_CLASS, Collections.singletonList((MockDataNodeId) dataNodeId), 0);
    PartitionId partitionId2 = new MockPartitionId(2, MockClusterMap.DEFAULT_PARTITION_CLASS, Collections.singletonList((MockDataNodeId) dataNodeId), 0);
    problematicStoreMap.put(partitionId1, null);
    Store exceptionStore = new MockStore(new MockStoreStats(new HashMap<>(), true));
    problematicStoreMap.put(partitionId2, exceptionStore);
    StatsManager testStatsManager = new StatsManager(new MockStorageManager(problematicStoreMap, dataNodeId), Arrays.asList(partitionId1.getReplicaIds().get(0), partitionId2.getReplicaIds().get(0)), new MetricRegistry(), statsManagerConfig, new MockTime(), null, null, inMemoryAccountService);
    List<PartitionId> unreachablePartitions = new ArrayList<>();
    Map<Long, Map<Short, Map<Short, ContainerStorageStats>>> hostAccountStorageStatsMap = new HashMap<>();
    for (PartitionId partitionId : problematicStoreMap.keySet()) {
        testStatsManager.collectAndAggregateAccountStorageStats(hostAccountStorageStatsMap, partitionId, unreachablePartitions);
    }
    assertEquals("Aggregated map should not contain any value", 0L, hostAccountStorageStatsMap.size());
    assertEquals("Unreachable store count mismatch with expected value", 2, unreachablePartitions.size());
    StatsManager.AccountStatsPublisher publisher = testStatsManager.new AccountStatsPublisher(accountStatsStore);
    publisher.run();
    HostAccountStorageStatsWrapper statsWrapper = accountStatsStore.queryHostAccountStorageStatsByHost("localhost", 0);
    List<String> unreachableStores = statsWrapper.getHeader().getUnreachableStores();
    assertTrue("The unreachable store list should contain Partition1 and Partition2", unreachableStores.containsAll(Arrays.asList(partitionId1.toPathString(), partitionId2.toPathString())));
    // test for the scenario where some stores are healthy and some are bad
    Map<PartitionId, Store> mixedStoreMap = new HashMap<>(storeMap);
    unreachablePartitions.clear();
    PartitionId partitionId3 = new MockPartitionId(3, MockClusterMap.DEFAULT_PARTITION_CLASS, Collections.singletonList((MockDataNodeId) dataNodeId), 0);
    PartitionId partitionId4 = new MockPartitionId(4, MockClusterMap.DEFAULT_PARTITION_CLASS, Collections.singletonList((MockDataNodeId) dataNodeId), 0);
    mixedStoreMap.put(partitionId3, null);
    mixedStoreMap.put(partitionId4, exceptionStore);
    testStatsManager = new StatsManager(new MockStorageManager(mixedStoreMap, dataNodeId), Arrays.asList(partitionId3.getReplicaIds().get(0), partitionId4.getReplicaIds().get(0)), new MetricRegistry(), statsManagerConfig, new MockTime(), null, null, inMemoryAccountService);
    hostAccountStorageStatsMap.clear();
    for (PartitionId partitionId : mixedStoreMap.keySet()) {
        testStatsManager.collectAndAggregateAccountStorageStats(hostAccountStorageStatsMap, partitionId, unreachablePartitions);
    }
    assertEquals("Unreachable store count mismatch with expected value", 2, unreachablePartitions.size());
    // test fetchSnapshot method in StatsManager
    unreachablePartitions.clear();
    // partition 0, 1, 2 are healthy stores, partition 3, 4 are bad ones.
    for (PartitionId partitionId : mixedStoreMap.keySet()) {
        Map<Short, Map<Short, ContainerStorageStats>> containerStatsMapForPartition = hostAccountStorageStatsMap.get(partitionId.getId());
        if (partitionId.getId() < 3) {
            assertEquals("Actual map does not match with expected snapshot with partition id " + partitionId.toPathString(), hostAccountStorageStats.getStorageStats().get(partitionId.getId()), containerStatsMapForPartition);
        }
    }
}
Also used : HashMap(java.util.HashMap) Port(com.github.ambry.network.Port) ArrayList(java.util.ArrayList) InmemoryAccountStatsStore(com.github.ambry.accountstats.InmemoryAccountStatsStore) Store(com.github.ambry.store.Store) ContainerStorageStats(com.github.ambry.server.storagestats.ContainerStorageStats) MockTime(com.github.ambry.utils.MockTime) MockPartitionId(com.github.ambry.clustermap.MockPartitionId) MetricRegistry(com.codahale.metrics.MetricRegistry) MockPartitionId(com.github.ambry.clustermap.MockPartitionId) PartitionId(com.github.ambry.clustermap.PartitionId) MockDataNodeId(com.github.ambry.clustermap.MockDataNodeId) DataNodeId(com.github.ambry.clustermap.DataNodeId) MockDataNodeId(com.github.ambry.clustermap.MockDataNodeId) Map(java.util.Map) HashMap(java.util.HashMap) MockClusterMap(com.github.ambry.clustermap.MockClusterMap) Test(org.junit.Test)

Aggregations

ContainerStorageStats (com.github.ambry.server.storagestats.ContainerStorageStats)39 HashMap (java.util.HashMap)36 Map (java.util.Map)36 Test (org.junit.Test)20 HostAccountStorageStats (com.github.ambry.server.storagestats.HostAccountStorageStats)16 HostAccountStorageStatsWrapper (com.github.ambry.server.HostAccountStorageStatsWrapper)12 StorageStatsUtilTest (com.github.ambry.server.StorageStatsUtilTest)12 StatsHeader (com.github.ambry.server.StatsHeader)10 AggregatedAccountStorageStats (com.github.ambry.server.storagestats.AggregatedAccountStorageStats)10 Pair (com.github.ambry.utils.Pair)8 ArrayList (java.util.ArrayList)7 LinkedHashMap (java.util.LinkedHashMap)7 HostPartitionClassStorageStats (com.github.ambry.server.storagestats.HostPartitionClassStorageStats)6 Utils (com.github.ambry.utils.Utils)6 MetricRegistry (com.codahale.metrics.MetricRegistry)5 AggregatedPartitionClassStorageStats (com.github.ambry.server.storagestats.AggregatedPartitionClassStorageStats)5 Collections (java.util.Collections)5 HashSet (java.util.HashSet)5 NavigableMap (java.util.NavigableMap)5 Set (java.util.Set)5