in docker/services/recomendation_service.py [0:0]
def process_instance(self, metric_file_path, algorithm: Algorithm,
reports_dir, instance_meta_mapping=None,
parent_meta: Union[None, ParentMeta] = None):
_LOG.debug(f'Parsing entity names from metrics file path '
f'\'{metric_file_path}\'')
df = None
schedule = None
recommended_sizes = None
resize_action = None
savings = None
advanced = None
customer, cloud, tenant, region, _, instance_id = self._parse_folders(
metric_file_path=metric_file_path
)
if cloud.upper() != CloudEnum.CLOUD_GOOGLE.value:
instance_os = OSEnum.OS_LINUX.value
else:
# use Linux pricing as a default for all clouds except GCP
instance_os = None
instance_meta = {}
if instance_meta_mapping:
instance_meta = instance_meta_mapping.get(instance_id)
_LOG.debug(f'Instance meta: {instance_meta}')
_LOG.debug(f'Loading past recommendation with feedback')
past_recommendations = self.recommendation_history_service. \
get_recommendation_with_feedback(instance_id=instance_id)
applied_recommendations = self.recommendation_history_service. \
filter_applied(recommendations=past_recommendations)
try:
_LOG.debug(f'Loading adjustments from meta')
meta_adjustments = self.meta_service.to_adjustments(
instance_meta=instance_meta
)
applied_recommendations.extend(meta_adjustments)
_LOG.debug(f'Loading df')
df = self.metrics_service.load_df(
path=metric_file_path,
algorithm=algorithm,
applied_recommendations=applied_recommendations,
instance_meta=instance_meta
)
_LOG.debug(f'Extracting instance type name')
instance_type = self.metrics_service.get_instance_type(
metric_file_path=metric_file_path,
algorithm=algorithm
)
_LOG.debug(f'Dividing into periods with different load')
shutdown_periods, low_periods, medium_periods, \
high_periods, centroids = \
self.metrics_service.divide_on_periods(
df=df,
algorithm=algorithm)
_LOG.debug(f'Got {len(high_periods)} high-load, '
f'{len(low_periods)} low-load periods')
non_straight_periods, total_length = self.get_non_straight_periods(
df=df,
grouped_periods=(low_periods, medium_periods, high_periods)
)
if non_straight_periods and total_length:
_LOG.debug(f'Calculating resize trends for several loads')
trends = self.metrics_service. \
calculate_instance_trend_multiple(
algorithm=algorithm,
non_straight_periods=non_straight_periods,
total_length=total_length
)
else:
_LOG.debug(f'Generating resize trend')
if any((low_periods, medium_periods, high_periods)):
df_ = pd.concat([*low_periods, *medium_periods,
*high_periods])
else:
df_ = df
trends = self.metrics_service.calculate_instance_trend(
df=df_,
algorithm=algorithm
)
trends = [trends]
_LOG.debug(f'Resize trend for instance \'{instance_id}\' has been '
f'calculated. ')
_LOG.debug(
f'Got {len(shutdown_periods)} shutdown periods to process')
_LOG.debug(f'Generating schedule for instance \'{instance_id}\'')
if not low_periods and not medium_periods and not high_periods:
schedule = []
else:
schedule = self.schedule_service.generate_schedule(
shutdown_periods=shutdown_periods,
recommendation_settings=algorithm.recommendation_settings,
instance_id=instance_id,
df=df,
instance_meta=instance_meta,
past_recommendations=applied_recommendations
)
_LOG.debug(f'Searching for resize action')
resize_action = ResizeTrend.get_resize_action(trends=trends)
_LOG.debug(f'Searching for better-fix instance types')
compatibility_rule = algorithm.recommendation_settings. \
shape_compatibility_rule
past_resize_recommendations = self.recommendation_history_service. \
filter_resize(recommendations=applied_recommendations)
if len(trends) == 1:
max_recommended_shapes = algorithm.recommendation_settings. \
max_recommended_shapes
recommended_sizes = self.resize_service.recommend_size(
trend=trends[0],
instance_type=instance_type,
algorithm=algorithm,
cloud=cloud.upper(),
instance_meta=instance_meta,
resize_action=resize_action,
parent_meta=parent_meta,
max_results=max_recommended_shapes,
shape_compatibility_rule=compatibility_rule,
past_resize_recommendations=past_resize_recommendations
)
else:
recommended_sizes = []
for trend in trends:
recommended_size = self.resize_service.recommend_size(
trend=trend,
instance_type=instance_type,
algorithm=algorithm,
cloud=cloud.upper(),
instance_meta=instance_meta,
resize_action=resize_action,
parent_meta=parent_meta,
max_results=1,
shape_compatibility_rule=compatibility_rule,
past_resize_recommendations=past_resize_recommendations
)
recommended_sizes.extend(recommended_size)
recommended_sizes = self.resize_service.add_price(
instances=recommended_sizes,
customer=customer,
region=region,
os=instance_os)
recommended_sizes = self._cleanup_recommended_shapes(
recommended_sizes=recommended_sizes,
current_instance_type=instance_type,
allow_same_shape=resize_action == ACTION_SPLIT
)
recommended_sizes = self.resize_service.sort_shapes(
shapes=recommended_sizes,
sort_option=algorithm.recommendation_settings.shape_sorting
)
_LOG.debug(f'Got {len(recommended_sizes)} '
f'recommended instance types')
_LOG.debug(f'Calculate instance stats')
stats = self.calculate_instance_stats(df=df)
advanced = self.calculate_advanced_stats(
df=df,
centroids=centroids,
algorithm=algorithm
)
general_action = self.get_general_action(
schedule=schedule,
shapes=recommended_sizes,
resize_action=resize_action,
stats=stats,
past_recommendations=past_recommendations
)
if not algorithm.recommendation_settings.ignore_savings:
_LOG.debug(f'Calculating savings')
savings = self.saving_service.calculate_savings(
general_actions=general_action,
current_shape=instance_type,
recommended_shapes=recommended_sizes,
schedule=schedule,
customer=customer,
region=region,
os=instance_os
)
try:
_LOG.debug(f'Saving recommendation to history')
history_items = self.recommendation_history_service.create(
instance_id=instance_id,
job_id=self.environment_service.get_batch_job_id(),
customer=customer,
tenant=tenant,
region=region,
schedule=schedule,
recommended_shapes=recommended_sizes,
current_instance_type=instance_type,
savings=savings,
actions=general_action,
instance_meta=instance_meta
)
if history_items:
_LOG.debug(
f'Saving \'{len(history_items)}\' history items')
self.recommendation_history_service.batch_save(
recommendations=history_items)
except Exception as e:
_LOG.error(f'Exception occurred while saving recommendation '
f'to history: {str(e)}')
except Exception as e:
_LOG.debug(f'Calculate instance stats with exception')
stats = self.calculate_instance_stats(df=df, exception=e)
general_action = self.get_general_action(
schedule=schedule,
shapes=recommended_sizes,
resize_action=resize_action,
stats=stats)
_LOG.debug(f'Dumping instance results')
item = self.dump_reports(
reports_dir=reports_dir,
instance_id=instance_id,
schedule=schedule,
recommended_sizes=recommended_sizes,
stats=stats,
customer=customer,
cloud=cloud,
tenant=tenant,
region=region,
meta=instance_meta,
general_action=general_action,
savings=savings,
advanced=advanced
)
return item