def process_instance()

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