rajagopr commented on code in PR #15008: URL: https://github.com/apache/pinot/pull/15008#discussion_r1956477566
########## pinot-controller/src/main/java/org/apache/pinot/controller/BaseControllerStarter.java: ########## @@ -873,7 +884,8 @@ protected List<PeriodicTask> setupControllerPeriodicTasks() { periodicTasks.add(_offlineSegmentIntervalChecker); _realtimeSegmentValidationManager = new RealtimeSegmentValidationManager(_config, _helixResourceManager, _leadControllerManager, - _pinotLLCRealtimeSegmentManager, _validationMetrics, _controllerMetrics, _storageQuotaChecker); + _pinotLLCRealtimeSegmentManager, _validationMetrics, _controllerMetrics, _storageQuotaChecker, Review Comment: The similar use case around `StorageQuota` check is already part of the validation manager and hence we decided to keep this together instead of creating a new periodic job for pause/resume. Anyways, this is not a one-way door decision and we can choose to create a separate periodic job when we evolve this further. ########## pinot-controller/src/main/java/org/apache/pinot/controller/ControllerConf.java: ########## @@ -299,6 +299,14 @@ private static long getRandomInitialDelayInSeconds() { private static final String REALTIME_SEGMENT_METADATA_COMMIT_NUMLOCKS = "controller.realtime.segment.metadata.commit.numLocks"; private static final String ENABLE_STORAGE_QUOTA_CHECK = "controller.enable.storage.quota.check"; + private static final String DISK_UTILIZATION_THRESHOLD = "controller.disk.utilization.threshold"; Review Comment: done. ########## pinot-common/src/main/java/org/apache/pinot/common/metrics/ControllerGauge.java: ########## @@ -187,7 +187,10 @@ public enum ControllerGauge implements AbstractMetrics.Gauge { TABLE_REBALANCE_IN_PROGRESS("tableRebalanceInProgress", false), // Number of reingested segments getting uploaded - REINGESTED_SEGMENT_UPLOADS_IN_PROGRESS("reingestedSegmentUploadsInProgress", true); + REINGESTED_SEGMENT_UPLOADS_IN_PROGRESS("reingestedSegmentUploadsInProgress", true), + + // Resource utilization is within limits or not for a table + RESOURCE_UTILIZATION_LIMIT_EXCEEDED("ResourceUtilizationLimitExceeded", false); Review Comment: The alert that we want to raise is that the ingestion is paused/task generation would be skipped. I agree that we don't want another disk alert as we already have it. ########## pinot-controller/src/main/java/org/apache/pinot/controller/validation/ResourceUtilizationChecker.java: ########## @@ -0,0 +1,94 @@ +/** + * 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.pinot.controller.validation; + +import com.google.common.collect.BiMap; +import java.util.HashSet; +import java.util.Properties; +import java.util.Set; +import java.util.concurrent.Executor; +import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager; +import org.apache.pinot.common.metrics.ControllerMeter; +import org.apache.pinot.common.metrics.ControllerMetrics; +import org.apache.pinot.controller.ControllerConf; +import org.apache.pinot.controller.LeadControllerManager; +import org.apache.pinot.controller.helix.core.PinotHelixResourceManager; +import org.apache.pinot.controller.util.CompletionServiceHelper; +import org.apache.pinot.core.periodictask.BasePeriodicTask; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +/** + * This class is responsible for checking resource utilization for Pinot instances. To begin with, it checks + * disk utilization for all server instances. The computed disk utilization is stored in the class + * <code>org.apache.pinot.controller.validation.ResourceUtilizationInfo</code>. + */ +public class ResourceUtilizationChecker extends BasePeriodicTask { + private static final Logger LOGGER = LoggerFactory.getLogger(ResourceUtilizationChecker.class); + private final static String TASK_NAME = ResourceUtilizationChecker.class.getSimpleName(); + + private final PoolingHttpClientConnectionManager _connectionManager; + private final ControllerMetrics _controllerMetrics; + private final DiskUtilizationChecker _diskUtilizationChecker; + private final Executor _executor; + private final PinotHelixResourceManager _helixResourceManager; + private final LeadControllerManager _leadControllerManager; + + public ResourceUtilizationChecker(ControllerConf config, PoolingHttpClientConnectionManager connectionManager, + ControllerMetrics controllerMetrics, DiskUtilizationChecker diskUtilizationChecker, Executor executor, + PinotHelixResourceManager pinotHelixResourceManager, LeadControllerManager leadControllerManager) { + super(TASK_NAME, config.getResourceUtilizationCheckerFrequency(), + config.getResourceUtilizationCheckerInitialDelay()); + _connectionManager = connectionManager; + _controllerMetrics = controllerMetrics; + _diskUtilizationChecker = diskUtilizationChecker; + _executor = executor; + _helixResourceManager = pinotHelixResourceManager; + _leadControllerManager = leadControllerManager; + } + + @Override + protected final void runTask(Properties periodicTaskProperties) { + // Run the task only if this controller is the leader + if (!_leadControllerManager.isLeaderForTable(TASK_NAME)) { Review Comment: I will be removing this as we want to run this periodic task in every controller. Passing TASK_NAME ensures that this job is run only on the lead controller. I'm removing this check since the validation manager is one that would actually pause the tables and we want the resource info as part of every controller. ########## pinot-server/src/main/java/org/apache/pinot/server/api/resources/InstanceResource.java: ########## @@ -97,4 +103,22 @@ public Map<String, String> getInstancePools() { Map<String, String> pools = instanceConfig.getRecord().getMapField(InstanceUtils.POOL_KEY); return pools == null ? Collections.emptyMap() : pools; } + + @GET + @Produces(MediaType.APPLICATION_JSON) + @Path("/diskUtilization") Review Comment: Yes, we can extend the same notion to the servers as well. I plan to address this as a follow-up. ########## pinot-controller/src/main/java/org/apache/pinot/controller/validation/RealtimeSegmentValidationManager.java: ########## @@ -135,6 +138,18 @@ private boolean shouldEnsureConsuming(String tableNameWithType) { if (isTablePaused && pauseStatus.getReasonCode().equals(PauseState.ReasonCode.ADMINISTRATIVE)) { return false; } + try { + boolean isResourceUtilizationWithinLimits = + _resourceUtilizationManager.isResourceUtilizationWithinLimits(tableNameWithType); + if (!isResourceUtilizationWithinLimits) { + LOGGER.warn("Resource utilization limit exceeded for table: {}", tableNameWithType); + _llcRealtimeSegmentManager.pauseConsumption(tableNameWithType, Review Comment: @9aman – I understand that lack of disk can lead to issues as you have noted here. When disk utilization breaches the threshold is there any downside if we pause consumption on the table? We are pausing ingestion such that we don't run into the case where there is no disk space left. Are you suggesting that we lower the threshold from the default `99%`? We need to strike a balance between false alerts and hitting the rare scenario of running out of disk from all replicas. ########## pinot-controller/src/main/java/org/apache/pinot/controller/validation/DiskUtilizationChecker.java: ########## @@ -0,0 +1,140 @@ +/** + * 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.pinot.controller.validation; + +import com.google.common.collect.BiMap; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import org.apache.commons.lang3.StringUtils; +import org.apache.pinot.common.restlet.resources.DiskUsageInfo; +import org.apache.pinot.controller.ControllerConf; +import org.apache.pinot.controller.helix.core.PinotHelixResourceManager; +import org.apache.pinot.controller.util.CompletionServiceHelper; +import org.apache.pinot.spi.config.table.TableConfig; +import org.apache.pinot.spi.config.table.TableType; +import org.apache.pinot.spi.utils.JsonUtils; +import org.apache.pinot.spi.utils.builder.TableNameBuilder; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +public class DiskUtilizationChecker { + private static final Logger LOGGER = LoggerFactory.getLogger(DiskUtilizationChecker.class); + private final int _resourceUtilizationCheckTimeoutMs; + private final long _resourceUtilizationCheckerFrequencyMs; + private final double _diskUtilizationThreshold; + private final String _diskUtilizationPath; + private static final String DISK_UTILIZATION_API_PATH = "/instance/diskUtilization"; Review Comment: done. -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: commits-unsubscr...@pinot.apache.org For queries about this service, please contact Infrastructure at: us...@infra.apache.org --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@pinot.apache.org For additional commands, e-mail: commits-h...@pinot.apache.org