metrics: speed up list zones and cluster metrics APIs

Also add a flag to disable on-the-fly metrics computation when the
list metrics APIs for zones and clusters are called.

Signed-off-by: Rohit Yadav <rohit.yadav@shapeblue.com>
This commit is contained in:
Rohit Yadav 2024-05-04 15:48:26 +05:30
parent 72b841567e
commit 807cd6a830
6 changed files with 125 additions and 43 deletions

View File

@ -45,6 +45,10 @@ public interface ClusterDao extends GenericDao<ClusterVO, Long> {
List<Long> listClustersWithDisabledPods(long zoneId);
Integer countAllByDcId(long zoneId);
Integer countAllManagedAndEnabledByDcId(long zoneId);
List<ClusterVO> listClustersByDcId(long zoneId);
List<Long> listAllClusters(Long zoneId);

View File

@ -22,6 +22,7 @@ import com.cloud.dc.ClusterVO;
import com.cloud.dc.HostPodVO;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.org.Grouping;
import com.cloud.org.Managed;
import com.cloud.utils.db.GenericDaoBase;
import com.cloud.utils.db.GenericSearchBuilder;
import com.cloud.utils.db.JoinBuilder;
@ -94,6 +95,8 @@ public class ClusterDaoImpl extends GenericDaoBase<ClusterVO, Long> implements C
ZoneClusterSearch = createSearchBuilder();
ZoneClusterSearch.and("dataCenterId", ZoneClusterSearch.entity().getDataCenterId(), SearchCriteria.Op.EQ);
ZoneClusterSearch.and("allocationState", ZoneClusterSearch.entity().getAllocationState(), Op.EQ);
ZoneClusterSearch.and("managedState", ZoneClusterSearch.entity().getManagedState(), Op.EQ);
ZoneClusterSearch.done();
ClusterIdSearch = createSearchBuilder(Long.class);
@ -252,6 +255,23 @@ public class ClusterDaoImpl extends GenericDaoBase<ClusterVO, Long> implements C
return customSearch(sc, null);
}
@Override
public Integer countAllByDcId(long zoneId) {
SearchCriteria<ClusterVO> sc = ZoneClusterSearch.create();
sc.setParameters("dataCenterId", zoneId);
return getCount(sc);
}
@Override
public Integer countAllManagedAndEnabledByDcId(long zoneId) {
SearchCriteria<ClusterVO> sc = ZoneClusterSearch.create();
sc.setParameters("dataCenterId", zoneId);
sc.setParameters("allocationState", Grouping.AllocationState.Enabled);
sc.setParameters("managedState", Managed.ManagedState.Managed);
return getCount(sc);
}
@Override
public List<ClusterVO> listClustersByDcId(long zoneId) {
SearchCriteria<ClusterVO> sc = ZoneClusterSearch.create();

View File

@ -39,6 +39,8 @@ public interface HostDao extends GenericDao<HostVO, Long>, StateDao<Status, Stat
Integer countAllByType(final Host.Type type);
Integer countAllInClusterByTypeAndStates(Long clusterId, final Host.Type type, List<Status> status);
Integer countAllByTypeInZone(long zoneId, final Host.Type type);
Integer countUpAndEnabledHostsInZone(long zoneId);

View File

@ -122,6 +122,7 @@ public class HostDaoImpl extends GenericDaoBase<HostVO, Long> implements HostDao
protected SearchBuilder<HostVO> UnmanagedApplianceSearch;
protected SearchBuilder<HostVO> MaintenanceCountSearch;
protected SearchBuilder<HostVO> HostTypeCountSearch;
protected SearchBuilder<HostVO> HostTypeClusterCountSearch;
protected SearchBuilder<HostVO> ResponsibleMsCountSearch;
protected SearchBuilder<HostVO> HostTypeZoneCountSearch;
protected SearchBuilder<HostVO> ClusterStatusSearch;
@ -187,6 +188,13 @@ public class HostDaoImpl extends GenericDaoBase<HostVO, Long> implements HostDao
ResponsibleMsCountSearch.and("managementServerId", ResponsibleMsCountSearch.entity().getManagementServerId(), SearchCriteria.Op.EQ);
ResponsibleMsCountSearch.done();
HostTypeClusterCountSearch = createSearchBuilder();
HostTypeClusterCountSearch.and("cluster", HostTypeClusterCountSearch.entity().getClusterId(), SearchCriteria.Op.EQ);
HostTypeClusterCountSearch.and("type", HostTypeClusterCountSearch.entity().getType(), SearchCriteria.Op.EQ);
HostTypeClusterCountSearch.and("status", HostTypeClusterCountSearch.entity().getStatus(), SearchCriteria.Op.IN);
HostTypeClusterCountSearch.and("removed", HostTypeClusterCountSearch.entity().getRemoved(), SearchCriteria.Op.NULL);
HostTypeClusterCountSearch.done();
HostTypeZoneCountSearch = createSearchBuilder();
HostTypeZoneCountSearch.and("type", HostTypeZoneCountSearch.entity().getType(), SearchCriteria.Op.EQ);
HostTypeZoneCountSearch.and("dc", HostTypeZoneCountSearch.entity().getDataCenterId(), SearchCriteria.Op.EQ);
@ -462,8 +470,7 @@ public class HostDaoImpl extends GenericDaoBase<HostVO, Long> implements HostDao
sc.setParameters("resourceState", (Object[])states);
sc.setParameters("cluster", clusterId);
List<HostVO> hosts = listBy(sc);
return hosts.size();
return getCount(sc);
}
@Override
@ -473,6 +480,21 @@ public class HostDaoImpl extends GenericDaoBase<HostVO, Long> implements HostDao
return getCount(sc);
}
@Override
public Integer countAllInClusterByTypeAndStates(Long clusterId, final Host.Type type, List<Status> status) {
SearchCriteria<HostVO> sc = HostTypeClusterCountSearch.create();
if (clusterId != null) {
sc.setParameters("cluster", clusterId);
}
if (type != null) {
sc.setParameters("type", type);
}
if (status != null) {
sc.setParameters("status", status.toArray());
}
return getCount(sc);
}
@Override
public Integer countAllByTypeInZone(long zoneId, Type type) {
SearchCriteria<HostVO> sc = HostTypeCountSearch.create();

View File

@ -30,6 +30,7 @@ import org.apache.cloudstack.api.response.StoragePoolResponse;
import org.apache.cloudstack.api.response.UserVmResponse;
import org.apache.cloudstack.api.response.VolumeResponse;
import org.apache.cloudstack.api.response.ZoneResponse;
import org.apache.cloudstack.framework.config.ConfigKey;
import org.apache.cloudstack.response.ClusterMetricsResponse;
import org.apache.cloudstack.response.DbMetricsResponse;
import org.apache.cloudstack.response.HostMetricsResponse;
@ -47,6 +48,11 @@ import com.cloud.utils.Pair;
import com.cloud.utils.component.PluggableService;
public interface MetricsService extends PluggableService {
ConfigKey<Boolean> AllowListMetricsComputation = new ConfigKey<>("Advanced", Boolean.class, "allow.list.metrics.computation", "true",
"Whether the list zones and cluster metrics APIs are allowed metrics computation. Large environments may disabled this.",
true, ConfigKey.Scope.Global);
InfrastructureResponse listInfrastructure();
ListResponse<VmMetricsStatsResponse> searchForVmMetricsStats(ListVMsUsageHistoryCmd cmd);
@ -56,10 +62,10 @@ public interface MetricsService extends PluggableService {
List<VmMetricsResponse> listVmMetrics(List<UserVmResponse> vmResponses);
List<StoragePoolMetricsResponse> listStoragePoolMetrics(List<StoragePoolResponse> poolResponses);
List<HostMetricsResponse> listHostMetrics(List<HostResponse> poolResponses);
List<ManagementServerMetricsResponse> listManagementServerMetrics(List<ManagementServerResponse> poolResponses);
List<ClusterMetricsResponse> listClusterMetrics(Pair<List<ClusterResponse>, Integer> clusterResponses);
List<ZoneMetricsResponse> listZoneMetrics(List<ZoneResponse> poolResponses);
List<ManagementServerMetricsResponse> listManagementServerMetrics(List<ManagementServerResponse> poolResponses);
UsageServerMetricsResponse listUsageServerMetrics();
DbMetricsResponse listDbMetrics();
}

View File

@ -58,6 +58,8 @@ import org.apache.cloudstack.api.response.UserVmResponse;
import org.apache.cloudstack.api.response.VolumeResponse;
import org.apache.cloudstack.api.response.ZoneResponse;
import org.apache.cloudstack.context.CallContext;
import org.apache.cloudstack.framework.config.ConfigKey;
import org.apache.cloudstack.framework.config.Configurable;
import org.apache.cloudstack.management.ManagementServerHost.State;
import org.apache.cloudstack.response.ClusterMetricsResponse;
import org.apache.cloudstack.response.DbMetricsResponse;
@ -107,8 +109,6 @@ import com.cloud.host.Status;
import com.cloud.host.dao.HostDao;
import com.cloud.network.router.VirtualRouter;
import com.cloud.org.Cluster;
import com.cloud.org.Grouping;
import com.cloud.org.Managed;
import com.cloud.server.DbStatsCollection;
import com.cloud.server.ManagementServerHostStats;
import com.cloud.server.StatsCollector;
@ -138,7 +138,7 @@ import com.cloud.vm.dao.VMInstanceDao;
import com.cloud.vm.dao.VmStatsDao;
import com.google.gson.Gson;
public class MetricsServiceImpl extends MutualExclusiveIdsManagerBase implements MetricsService {
public class MetricsServiceImpl extends MutualExclusiveIdsManagerBase implements MetricsService, Configurable {
private static final Logger LOGGER = Logger.getLogger(MetricsServiceImpl.class);
@Inject
@ -192,7 +192,6 @@ public class MetricsServiceImpl extends MutualExclusiveIdsManagerBase implements
}
private void updateHostMetrics(final HostMetrics hostMetrics, final HostJoinVO host) {
hostMetrics.incrTotalHosts();
hostMetrics.addCpuAllocated(host.getCpuReservedCapacity() + host.getCpuUsedCapacity());
hostMetrics.addMemoryAllocated(host.getMemReservedCapacity() + host.getMemUsedCapacity());
final HostStats hostStats = ApiDBUtils.getHostStatistics(host.getId());
@ -570,7 +569,7 @@ public class MetricsServiceImpl extends MutualExclusiveIdsManagerBase implements
}
}
response.setCpuSockets(cpuSockets);
response.setManagementServers(managementServerHostDao.listAll().size());
response.setManagementServers(managementServerHostDao.countAll());
return response;
}
@ -747,28 +746,36 @@ public class MetricsServiceImpl extends MutualExclusiveIdsManagerBase implements
}
final Long clusterId = cluster.getId();
// CPU and memory capacities
final CapacityDaoImpl.SummedCapacity cpuCapacity = getCapacity((int) Capacity.CAPACITY_TYPE_CPU, null, clusterId);
final CapacityDaoImpl.SummedCapacity memoryCapacity = getCapacity((int) Capacity.CAPACITY_TYPE_MEMORY, null, clusterId);
final HostMetrics hostMetrics = new HostMetrics(cpuCapacity, memoryCapacity);
hostMetrics.setUpResources(Long.valueOf(hostDao.countAllInClusterByTypeAndStates(clusterId, Host.Type.Routing, List.of(Status.Up))));
hostMetrics.setTotalResources(Long.valueOf(hostDao.countAllInClusterByTypeAndStates(clusterId, Host.Type.Routing, null)));
hostMetrics.setTotalHosts(hostMetrics.getTotalResources());
for (final Host host: hostDao.findByClusterId(clusterId)) {
if (host == null || host.getType() != Host.Type.Routing) {
continue;
if (AllowListMetricsComputation.value()) {
for (final Host host : hostDao.findByClusterId(clusterId)) {
if (host == null || host.getType() != Host.Type.Routing) {
continue;
}
updateHostMetrics(hostMetrics, hostJoinDao.findById(host.getId()));
}
if (host.getStatus() == Status.Up) {
hostMetrics.incrUpResources();
} else {
if (cpuCapacity != null) {
hostMetrics.setCpuAllocated(cpuCapacity.getAllocatedCapacity());
}
if (memoryCapacity != null) {
hostMetrics.setMemoryAllocated(memoryCapacity.getAllocatedCapacity());
}
hostMetrics.incrTotalResources();
updateHostMetrics(hostMetrics, hostJoinDao.findById(host.getId()));
}
metricsResponse.setState(clusterResponse.getAllocationState(), clusterResponse.getManagedState());
metricsResponse.setResources(hostMetrics.getUpResources(), hostMetrics.getTotalResources());
addHostCpuMetricsToResponse(metricsResponse, clusterId, hostMetrics);
addHostMemoryMetricsToResponse(metricsResponse, clusterId, hostMetrics);
metricsResponse.setHasAnnotation(clusterResponse.hasAnnotation());
metricsResponse.setState(clusterResponse.getAllocationState(), clusterResponse.getManagedState());
metricsResponse.setResources(hostMetrics.getUpResources(), hostMetrics.getTotalResources());
metricsResponses.add(metricsResponse);
}
return metricsResponses;
@ -915,35 +922,38 @@ public class MetricsServiceImpl extends MutualExclusiveIdsManagerBase implements
final CapacityDaoImpl.SummedCapacity cpuCapacity = getCapacity((int) Capacity.CAPACITY_TYPE_CPU, zoneId, null);
final CapacityDaoImpl.SummedCapacity memoryCapacity = getCapacity((int) Capacity.CAPACITY_TYPE_MEMORY, zoneId, null);
final HostMetrics hostMetrics = new HostMetrics(cpuCapacity, memoryCapacity);
hostMetrics.setUpResources(Long.valueOf(clusterDao.countAllManagedAndEnabledByDcId(zoneId)));
hostMetrics.setTotalResources(Long.valueOf(clusterDao.countAllByDcId(zoneId)));
hostMetrics.setTotalHosts(Long.valueOf(hostDao.countAllByTypeInZone(zoneId, Host.Type.Routing)));
for (final Cluster cluster : clusterDao.listClustersByDcId(zoneId)) {
if (cluster == null) {
continue;
}
hostMetrics.incrTotalResources();
if (cluster.getAllocationState() == Grouping.AllocationState.Enabled
&& cluster.getManagedState() == Managed.ManagedState.Managed) {
hostMetrics.incrUpResources();
}
for (final Host host: hostDao.findByClusterId(cluster.getId())) {
if (host == null || host.getType() != Host.Type.Routing) {
if (AllowListMetricsComputation.value()) {
for (final Cluster cluster : clusterDao.listClustersByDcId(zoneId)) {
if (cluster == null) {
continue;
}
updateHostMetrics(hostMetrics, hostJoinDao.findById(host.getId()));
for (final Host host: hostDao.findByClusterId(cluster.getId())) {
if (host == null || host.getType() != Host.Type.Routing) {
continue;
}
updateHostMetrics(hostMetrics, hostJoinDao.findById(host.getId()));
}
}
} else {
if (cpuCapacity != null) {
hostMetrics.setCpuAllocated(cpuCapacity.getAllocatedCapacity());
}
if (memoryCapacity != null) {
hostMetrics.setMemoryAllocated(memoryCapacity.getAllocatedCapacity());
}
}
addHostCpuMetricsToResponse(metricsResponse, null, hostMetrics);
addHostMemoryMetricsToResponse(metricsResponse, null, hostMetrics);
metricsResponse.setHasAnnotation(zoneResponse.hasAnnotation());
metricsResponse.setState(zoneResponse.getAllocationState());
metricsResponse.setResource(hostMetrics.getUpResources(), hostMetrics.getTotalResources());
final Long totalHosts = hostMetrics.getTotalHosts();
// CPU
addHostCpuMetricsToResponse(metricsResponse, null, hostMetrics);
// Memory
addHostMemoryMetricsToResponse(metricsResponse, null, hostMetrics);
metricsResponses.add(metricsResponse);
}
return metricsResponses;
@ -1081,6 +1091,16 @@ public class MetricsServiceImpl extends MutualExclusiveIdsManagerBase implements
return cmdList;
}
@Override
public String getConfigComponentName() {
return MetricsService.class.getSimpleName();
}
@Override
public ConfigKey<?>[] getConfigKeys() {
return new ConfigKey<?>[] {AllowListMetricsComputation};
}
private class HostMetrics {
// CPU metrics
private Long totalCpu = 0L;
@ -1106,6 +1126,14 @@ public class MetricsServiceImpl extends MutualExclusiveIdsManagerBase implements
}
}
public void setCpuAllocated(Long cpuAllocated) {
this.cpuAllocated = cpuAllocated;
}
public void setMemoryAllocated(Long memoryAllocated) {
this.memoryAllocated = memoryAllocated;
}
public void addCpuAllocated(Long cpuAllocated) {
this.cpuAllocated += cpuAllocated;
}
@ -1134,16 +1162,16 @@ public class MetricsServiceImpl extends MutualExclusiveIdsManagerBase implements
}
}
public void incrTotalHosts() {
this.totalHosts++;
public void setTotalHosts(Long totalHosts) {
this.totalHosts = totalHosts;
}
public void incrTotalResources() {
this.totalResources++;
public void setTotalResources(Long totalResources) {
this.totalResources = totalResources;
}
public void incrUpResources() {
this.upResources++;
public void setUpResources(Long upResources) {
this.upResources = upResources;
}
public Long getTotalCpu() {