This is an automated email from the ASF dual-hosted git repository.
dahn pushed a commit to branch 4.19
in repository https://gitbox.apache.org/repos/asf/cloudstack.git
The following commit(s) were added to refs/heads/4.19 by this push:
new ae3fa5d0de3 Add configuration to limit the number of rows deleted from
vm_stats (#8740)
ae3fa5d0de3 is described below
commit ae3fa5d0de3407a63e173cb367af3b517691039d
Author: João Jandre <[email protected]>
AuthorDate: Thu Jun 20 09:26:36 2024 -0300
Add configuration to limit the number of rows deleted from vm_stats (#8740)
Co-authored-by: João Jandre <[email protected]>
---
.../src/main/java/com/cloud/vm/dao/VmStatsDao.java | 6 ++++--
.../main/java/com/cloud/vm/dao/VmStatsDaoImpl.java | 21 ++++++++++++++++++---
.../main/java/com/cloud/utils/db/GenericDao.java | 8 ++++++++
.../java/com/cloud/utils/db/GenericDaoBase.java | 12 +++++++++++-
.../main/java/com/cloud/server/StatsCollector.java | 12 +++++++-----
.../java/com/cloud/server/StatsCollectorTest.java | 8 ++++----
.../test/java/com/cloud/user/MockUsageEventDao.java | 5 +++++
7 files changed, 57 insertions(+), 15 deletions(-)
diff --git a/engine/schema/src/main/java/com/cloud/vm/dao/VmStatsDao.java
b/engine/schema/src/main/java/com/cloud/vm/dao/VmStatsDao.java
index 879faaf5c90..0d7aa703a8c 100644
--- a/engine/schema/src/main/java/com/cloud/vm/dao/VmStatsDao.java
+++ b/engine/schema/src/main/java/com/cloud/vm/dao/VmStatsDao.java
@@ -75,8 +75,10 @@ public interface VmStatsDao extends GenericDao<VmStatsVO,
Long> {
/**
* Removes (expunges) all VM stats with {@code timestamp} less than
* a given Date.
- * @param limit the maximum date to keep stored. Records that exceed this
limit will be removed.
+ * @param limitDate the maximum date to keep stored. Records that exceed
this limit will be removed.
+ * @param limitPerQuery the maximum amount of rows to be removed in a
single query. We loop if there are still rows to be removed after a given query.
+ * If 0 or negative, no limit is used.
*/
- void removeAllByTimestampLessThan(Date limit);
+ void removeAllByTimestampLessThan(Date limitDate, long limitPerQuery);
}
diff --git a/engine/schema/src/main/java/com/cloud/vm/dao/VmStatsDaoImpl.java
b/engine/schema/src/main/java/com/cloud/vm/dao/VmStatsDaoImpl.java
index 1bef8f0626c..a98302e2136 100644
--- a/engine/schema/src/main/java/com/cloud/vm/dao/VmStatsDaoImpl.java
+++ b/engine/schema/src/main/java/com/cloud/vm/dao/VmStatsDaoImpl.java
@@ -21,6 +21,7 @@ import java.util.List;
import javax.annotation.PostConstruct;
+import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;
import com.cloud.utils.db.Filter;
@@ -33,6 +34,8 @@ import com.cloud.vm.VmStatsVO;
@Component
public class VmStatsDaoImpl extends GenericDaoBase<VmStatsVO, Long> implements
VmStatsDao {
+ protected Logger logger = Logger.getLogger(getClass());
+
protected SearchBuilder<VmStatsVO> vmIdSearch;
protected SearchBuilder<VmStatsVO> vmIdTimestampGreaterThanEqualSearch;
protected SearchBuilder<VmStatsVO> vmIdTimestampLessThanEqualSearch;
@@ -113,10 +116,22 @@ public class VmStatsDaoImpl extends
GenericDaoBase<VmStatsVO, Long> implements V
}
@Override
- public void removeAllByTimestampLessThan(Date limit) {
+ public void removeAllByTimestampLessThan(Date limitDate, long
limitPerQuery) {
SearchCriteria<VmStatsVO> sc = timestampSearch.create();
- sc.setParameters("timestamp", limit);
- expunge(sc);
+ sc.setParameters("timestamp", limitDate);
+
+ logger.debug(String.format("Starting to remove all vm_stats rows older
than [%s].", limitDate));
+
+ long totalRemoved = 0;
+ long removed;
+
+ do {
+ removed = expunge(sc, limitPerQuery);
+ totalRemoved += removed;
+ logger.trace(String.format("Removed [%s] vm_stats rows on the last
update and a sum of [%s] vm_stats rows older than [%s] until now.", removed,
totalRemoved, limitDate));
+ } while (limitPerQuery > 0 && removed >= limitPerQuery);
+
+ logger.info(String.format("Removed a total of [%s] vm_stats rows older
than [%s].", totalRemoved, limitDate));
}
}
diff --git a/framework/db/src/main/java/com/cloud/utils/db/GenericDao.java
b/framework/db/src/main/java/com/cloud/utils/db/GenericDao.java
index 2fc02301cb7..b9199468bd1 100644
--- a/framework/db/src/main/java/com/cloud/utils/db/GenericDao.java
+++ b/framework/db/src/main/java/com/cloud/utils/db/GenericDao.java
@@ -229,6 +229,14 @@ public interface GenericDao<T, ID extends Serializable> {
*/
int expunge(final SearchCriteria<T> sc);
+ /**
+ * Delete the entity beans specified by the search criteria with a given
limit
+ * @param sc Search criteria
+ * @param limit Maximum number of rows that will be affected
+ * @return Number of rows deleted
+ */
+ int expunge(SearchCriteria<T> sc, long limit);
+
/**
* expunge the removed rows.
*/
diff --git a/framework/db/src/main/java/com/cloud/utils/db/GenericDaoBase.java
b/framework/db/src/main/java/com/cloud/utils/db/GenericDaoBase.java
index 0eb45439769..3b950e1983d 100644
--- a/framework/db/src/main/java/com/cloud/utils/db/GenericDaoBase.java
+++ b/framework/db/src/main/java/com/cloud/utils/db/GenericDaoBase.java
@@ -1226,9 +1226,14 @@ public abstract class GenericDaoBase<T, ID extends
Serializable> extends Compone
}
}
- // FIXME: Does not work for joins.
@Override
public int expunge(final SearchCriteria<T> sc) {
+ return expunge(sc, -1);
+ }
+
+ // FIXME: Does not work for joins.
+ @Override
+ public int expunge(final SearchCriteria<T> sc, long limit) {
if (sc == null) {
throw new CloudRuntimeException("Call to throw new expunge with
null search Criteria");
}
@@ -1241,6 +1246,11 @@ public abstract class GenericDaoBase<T, ID extends
Serializable> extends Compone
str.append(sc.getWhereClause());
}
+ if (limit > 0) {
+ str.append(" LIMIT ");
+ str.append(limit);
+ }
+
final String sql = str.toString();
final TransactionLegacy txn = TransactionLegacy.currentTxn();
diff --git a/server/src/main/java/com/cloud/server/StatsCollector.java
b/server/src/main/java/com/cloud/server/StatsCollector.java
index 5aa6dd0a214..070508f2502 100644
--- a/server/src/main/java/com/cloud/server/StatsCollector.java
+++ b/server/src/main/java/com/cloud/server/StatsCollector.java
@@ -114,9 +114,6 @@ import com.cloud.org.Cluster;
import com.cloud.resource.ResourceManager;
import com.cloud.resource.ResourceState;
import com.cloud.serializer.GsonHelper;
-import com.cloud.server.StatsCollector.AbstractStatsCollector;
-import com.cloud.server.StatsCollector.AutoScaleMonitor;
-import com.cloud.server.StatsCollector.StorageCollector;
import com.cloud.storage.ImageStoreDetailsUtil;
import com.cloud.storage.ScopeType;
import com.cloud.storage.Storage;
@@ -287,6 +284,11 @@ public class StatsCollector extends ManagerBase implements
ComponentMethodInterc
protected static ConfigKey<Boolean> vmStatsCollectUserVMOnly = new
ConfigKey<>("Advanced", Boolean.class, "vm.stats.user.vm.only", "false",
"When set to 'false' stats for system VMs will be collected
otherwise stats collection will be done only for user VMs", true);
+ protected static ConfigKey<Long> vmStatsRemoveBatchSize = new
ConfigKey<>("Advanced", Long.class, "vm.stats.remove.batch.size", "0",
"Indicates the" +
+ " limit applied to delete vm_stats entries while running the
clean-up task. With this, ACS will run the delete query, applying the limit, as
many times as necessary" +
+ " to delete all entries older than the value defined in
vm.stats.max.retention.time. This is advised when retaining several days of
records, which can lead to slowness" +
+ " on the delete query. Zero (0) means that no limit will be
applied, therefore, the query will run once and without limit, keeping the
default behavior.", true);
+
protected static ConfigKey<Boolean> vmDiskStatsRetentionEnabled = new
ConfigKey<>("Advanced", Boolean.class, "vm.disk.stats.retention.enabled",
"false",
"When set to 'true' stats for VM disks will be stored in the
database otherwise disk stats will not be stored", true);
@@ -1965,7 +1967,7 @@ public class StatsCollector extends ManagerBase
implements ComponentMethodInterc
LOGGER.trace("Removing older VM stats records.");
Date now = new Date();
Date limit = DateUtils.addMinutes(now, -maxRetentionTime);
- vmStatsDao.removeAllByTimestampLessThan(limit);
+ vmStatsDao.removeAllByTimestampLessThan(limit,
vmStatsRemoveBatchSize.value());
}
/**
@@ -2139,7 +2141,7 @@ public class StatsCollector extends ManagerBase
implements ComponentMethodInterc
@Override
public ConfigKey<?>[] getConfigKeys() {
- return new ConfigKey<?>[] {vmDiskStatsInterval,
vmDiskStatsIntervalMin, vmNetworkStatsInterval, vmNetworkStatsIntervalMin,
StatsTimeout, statsOutputUri,
+ return new ConfigKey<?>[] {vmDiskStatsInterval,
vmDiskStatsIntervalMin, vmNetworkStatsInterval, vmNetworkStatsIntervalMin,
StatsTimeout, statsOutputUri, vmStatsRemoveBatchSize,
vmStatsIncrementMetrics, vmStatsMaxRetentionTime,
vmStatsCollectUserVMOnly, vmDiskStatsRetentionEnabled,
vmDiskStatsMaxRetentionTime,
MANAGEMENT_SERVER_STATUS_COLLECTION_INTERVAL,
DATABASE_SERVER_STATUS_COLLECTION_INTERVAL,
diff --git a/server/src/test/java/com/cloud/server/StatsCollectorTest.java
b/server/src/test/java/com/cloud/server/StatsCollectorTest.java
index 1f6a35cfbae..2b2451c66c7 100644
--- a/server/src/test/java/com/cloud/server/StatsCollectorTest.java
+++ b/server/src/test/java/com/cloud/server/StatsCollectorTest.java
@@ -28,7 +28,7 @@ import com.cloud.user.VmDiskStatisticsVO;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.vm.VmStats;
import com.cloud.vm.VmStatsVO;
-import com.cloud.vm.dao.VmStatsDao;
+import com.cloud.vm.dao.VmStatsDaoImpl;
import com.google.gson.Gson;
import com.tngtech.java.junit.dataprovider.DataProvider;
import com.tngtech.java.junit.dataprovider.DataProviderRunner;
@@ -81,7 +81,7 @@ public class StatsCollectorTest {
private static final String DEFAULT_DATABASE_NAME = "cloudstack";
@Mock
- VmStatsDao vmStatsDaoMock = Mockito.mock(VmStatsDao.class);
+ VmStatsDaoImpl vmStatsDaoMock;
@Mock
VmStatsEntry statsForCurrentIterationMock;
@@ -304,7 +304,7 @@ public class StatsCollectorTest {
statsCollector.cleanUpVirtualMachineStats();
- Mockito.verify(vmStatsDaoMock,
Mockito.never()).removeAllByTimestampLessThan(Mockito.any());
+ Mockito.verify(vmStatsDaoMock,
Mockito.never()).removeAllByTimestampLessThan(Mockito.any(), Mockito.anyLong());
}
@Test
@@ -313,7 +313,7 @@ public class StatsCollectorTest {
statsCollector.cleanUpVirtualMachineStats();
-
Mockito.verify(vmStatsDaoMock).removeAllByTimestampLessThan(Mockito.any());
+
Mockito.verify(vmStatsDaoMock).removeAllByTimestampLessThan(Mockito.any(),
Mockito.anyLong());
}
@Test
diff --git a/server/src/test/java/com/cloud/user/MockUsageEventDao.java
b/server/src/test/java/com/cloud/user/MockUsageEventDao.java
index 52e1b1a02b4..4769126fdcb 100644
--- a/server/src/test/java/com/cloud/user/MockUsageEventDao.java
+++ b/server/src/test/java/com/cloud/user/MockUsageEventDao.java
@@ -210,6 +210,11 @@ public class MockUsageEventDao implements UsageEventDao{
return 0;
}
+ @Override
+ public int expunge(SearchCriteria<UsageEventVO> sc, long limit) {
+ return 0;
+ }
+
@Override
public void expunge() {