"""Throttlers.""" from datetime import datetime, timezone import random import time import psutil import sentry_sdk from video import config from video.connectors import cloudwatch as cloudwatch_connector from video.constants import exceptions from video.utils import exception as exception_utils def _is_resource_utilization_ok(): """Check if resource utilization is ok.""" cpu_utilization_percent = psutil.cpu_percent() memory_utilization_percent = psutil.virtual_memory().percent cpu_utilization_ok = ( cpu_utilization_percent <= config.MAX_ALLOWED_CPU_UTILIZATION_PERCENT) memory_utilization_ok = ( memory_utilization_percent <= config.MAX_ALLOWED_MEMORY_UTILIZATION_PERCENT) # noqa _log_custom_metrics_to_cloudwatch( cpu_utilization_percent, memory_utilization_percent) return cpu_utilization_ok and memory_utilization_ok def is_handling_worker_activated(): """Indicate if handler worker is activated.""" time.sleep( config.MAX_TIMEOUT_BEFORE_PICKING_UP_WORK_SECONDS * random.random()) while not _is_resource_utilization_ok(): time.sleep( config.MAX_TIMEOUT_BETWEEN_RESOURCE_UTILIZATION_CHECKS_SECONDS * random.random()) # noqa return True def is_polling_worker_activated(): """Indicate if polling worker is activated.""" while not _is_resource_utilization_ok(): time.sleep( config.MAX_TIMEOUT_BETWEEN_RESOURCE_UTILIZATION_CHECKS_SECONDS * random.random()) # noqa return True def handling_worker_throttler(): """Throttle handler worker.""" time.sleep( random.random() * config.MAX_TIMEOUT_BETWEEN_PICKING_UP_WORK_AND_HANDLING_SECONDS) # noqa if not _is_resource_utilization_ok(): exception_utils.raise_exception(exceptions.NotCurrentlyAcceptingWork) def _log_custom_metrics_to_cloudwatch( cpu_utilization_percent, memory_utilization_percent): """Log custom metrics to cloudwatch. Args: cpu_utilization_percent: CPU utilization percent. memory_utilization_percent: Memory utilization percent. """ cloudwatch_client = cloudwatch_connector.get_cloudwatch_client() try: cloudwatch_client.put_metric_data( Namespace=config.CLOUDWATCH_NAMESPACE, MetricData=[ { 'MetricName': config.CUSTOM_METRIC_CPU_USAGE_PERCENT, 'Dimensions': [ { 'Name': 'Environment', 'Value': config.ENVIRONMENT }, ], 'Timestamp': datetime.now(timezone.utc).replace(tzinfo=None), 'Value': cpu_utilization_percent, 'Unit': 'Percent', 'StorageResolution': 1, }, { 'MetricName': config.CUSTOM_METRIC_MEMORY_USAGE_PERCENT, 'Dimensions': [ { 'Name': 'Environment', 'Value': config.ENVIRONMENT }, ], 'Timestamp': datetime.now(timezone.utc).replace(tzinfo=None), 'Value': memory_utilization_percent, 'Unit': 'Percent', 'StorageResolution': 1, }, ] ) except Exception: sentry_sdk.capture_exception()