Exemplo n.º 1
0
 /**
  * Gets period data for top farms
  *
  * @param   int        $accountId       The current client id
  * @param   array      $allowedEnvs     Array of allowed environments' ids for current user
  * @param   string     $mode            The mode (week, month, quarter, year)
  * @param   string     $startDate       The start date of the period in UTC ('Y-m-d')
  * @param   string     $endDate         The end date of the period in UTC ('Y-m-d')
  * @param   int        $farmCount       Top farms count
  * @return  array      Returns cost analytics data for environment scope
  */
 public function getTopFarmsPeriodData($accountId, array $allowedEnvs, $mode, $startDate, $endDate, $farmCount = 5)
 {
     $utcTz = new DateTimeZone('UTC');
     $iterator = ChartPeriodIterator::create($mode, new DateTime($startDate, $utcTz), new DateTime($endDate, $utcTz), 'UTC');
     $start = $iterator->getStart();
     $end = $iterator->getEnd();
     //Interval which is used in the database query for grouping
     $queryInterval = preg_replace('/^1 /', '', $iterator->getInterval());
     $criteria = !empty($allowedEnvs) ? ['envId' => $allowedEnvs] : [];
     //Requests data for the specified period
     $rawUsage = $this->getFarmData($accountId, $criteria, $start, $end, [$queryInterval, TagEntity::TAG_ID_FARM], true);
     //Requests data for the previous period
     $rawPrevUsage = $this->getFarmData($accountId, $criteria, $iterator->getPreviousStart(), $iterator->getPreviousEnd(), [$queryInterval, TagEntity::TAG_ID_FARM], true);
     //Calculates top five farms for the specified period
     $topFarms = [];
     $arr = (new AggregationCollection(['farmId'], ['cost' => 'sum']))->load($rawUsage)->getArrayCopy();
     if (!empty($arr['data']) && count($arr['data']) > $farmCount + 1) {
         uasort($arr['data'], function ($a, $b) {
             if ($a['cost'] == $b['cost']) {
                 return 0;
             }
             return $a['cost'] < $b['cost'] ? 1 : -1;
         });
         $i = 0;
         foreach ($arr['data'] as $farmId => $v) {
             $topFarms[$farmId] = $farmId;
             if (++$i >= $farmCount) {
                 break;
             }
         }
     }
     //Subtotals by farms
     $usage = new AggregationCollection(['farmId'], ['cost' => 'sum']);
     //Previous period subtotals by farms
     $prevUsage = new AggregationCollection(['farmId'], ['cost' => 'sum']);
     if (empty($topFarms)) {
         //Loads current period
         foreach ($rawUsage as $item) {
             $usage->append($item);
         }
         //Loads previous period
         foreach ($rawPrevUsage as $item) {
             $prevUsage->append($item);
         }
     } else {
         //Loads current period and aggregates top 5 farms
         foreach ($rawUsage as $item) {
             if (array_key_exists($item['farmId'], $topFarms)) {
                 $usage->append($item);
             }
         }
         //Loads previous period and aggregates top 5 farms
         foreach ($rawPrevUsage as $item) {
             if (array_key_exists($item['farmId'], $topFarms)) {
                 $prevUsage->append($item);
             }
         }
     }
     //Calculates percentage
     $usage->calculatePercentage();
     if ($iterator->getWholePreviousPeriodEnd() != $iterator->getPreviousEnd()) {
         $rawPrevUsageWhole = $this->getFarmData($accountId, ['envId' => $allowedEnvs], $iterator->getPreviousStart(), $iterator->getWholePreviousPeriodEnd(), [TagEntity::TAG_ID_FARM], true);
         //Previous whole period usage subtotals by farm
         $prevUsageWhole = (new AggregationCollection(['farmId'], ['cost' => 'sum']))->load($rawPrevUsageWhole);
     } else {
         $prevUsageWhole = $prevUsage;
     }
     //Build farms total
     $farmsTotal = [];
     $it = $usage->getIterator();
     foreach ($it as $farmId => $p) {
         $pp = isset($prevUsage['data'][$farmId]) ? $prevUsage['data'][$farmId] : null;
         $pw = isset($prevUsageWhole['data'][$farmId]) ? $prevUsageWhole['data'][$farmId] : null;
         $cl = $this->getTotalDataArray($farmId, $this->fetchFarmName($farmId), $p, $pp, $pw, [], null, true);
         $farmsTotal[] = $cl;
     }
     return $farmsTotal;
 }
Exemplo n.º 2
0
 /**
  * Gets detailed top 5 usage by farms for specified project on date
  *
  * @param   string|null $projectId    The identifier of the project
  * @param   string      $platform     The cloud platform
  * @param   string      $mode         The mode
  * @param   string      $date         The UTC date within period ('Y-m-d H:00')
  * @param   string      $start        The start date of the period in UTC ('Y-m-d')
  * @param   string      $end          The end date of the period in UTC ('Y-m-d')
  * @param   string      $ccId         optional The identifier of the cost center (It is used only when project is null)
  * @return  array       Returns detailed top 5 usage by farms for specified project on date
  * @throws  AnalyticsException
  * @throws  OutOfBoundsException
  */
 public function getProjectFarmsTopUsageOnDate($projectId, $platform, $mode, $date, $start, $end, $ccId = null)
 {
     $projectId = empty($projectId) ? null : $projectId;
     $iterator = new ChartPeriodIterator($mode, $start, $end ?: null, 'UTC');
     //Interval which is used in the database query for grouping
     $queryInterval = preg_replace('/^1 /', '', $iterator->getInterval());
     if ($projectId !== null) {
         $project = ProjectEntity::findPk($projectId);
         if ($project === null) {
             if (empty($ccId)) {
                 throw new AnalyticsException(sprintf("Project %s does not exist. Please provide ccId.", $projectId));
             }
         } else {
             $ccId = $project->ccId;
         }
     }
     //Requests data for the specified period
     $rawUsage = $this->get(['projectId' => $projectId], $iterator->getStart(), $iterator->getEnd(), [$queryInterval, TagEntity::TAG_ID_PLATFORM, TagEntity::TAG_ID_FARM], true);
     //Requests data for the previous period
     $rawPrevUsage = $this->get(['projectId' => $projectId], $iterator->getPreviousStart(), $iterator->getPreviousEnd(), [$queryInterval, TagEntity::TAG_ID_PLATFORM, TagEntity::TAG_ID_FARM], true);
     //We do not need to calculate the percentage here
     $usg = (new AggregationCollection(['period', 'platform', 'farmId' => ['envId']], ['cost' => 'sum']))->load($rawUsage);
     $prevUsg = (new AggregationCollection(['period', 'platform', 'farmId'], ['cost' => 'sum']))->load($rawPrevUsage)->calculatePercentage();
     //Previous chart point
     $prevcp = null;
     //Finds the key for current label
     foreach ($iterator as $chartPoint) {
         //FIXME rewrite search a point
         if ($chartPoint->dt->format('Y-m-d H:00') !== $date) {
             $prevcp = $chartPoint;
             continue;
         }
         $cp = $chartPoint;
         break;
     }
     if (!isset($cp)) {
         throw new OutOfRangeException(sprintf('Requested date (%s) is out of the range. Last point date is %s', $date, isset($prevcp->dt) ? $prevcp->dt->format('Y-m-d H:00') : 'undefined'));
     }
     $result = [];
     //Maximum number of the farms without grouping
     $max = 5;
     $sEverything = self::EVERYTHING_ELSE;
     if (!empty($usg['data'][$cp->key]['data'][$platform]['data'])) {
         $usgFarms = new AggregationCollection(['farmId' => ['envId']], ['cost' => 'sum']);
         $ptr = $usg['data'][$cp->key]['data'][$platform]['data'];
         uasort($ptr, function ($a, $b) {
             if ($a['cost'] == $b['cost']) {
                 return 0;
             }
             return $a['cost'] > $b['cost'] ? -1 : 1;
         });
         //Aggregates farms if its number more then max + 1
         if (count($ptr) > $max + 1) {
             $this->otherFarmsQuantity = count($ptr) - $max;
             $new = [];
             $i = 0;
             foreach ($ptr as $farmId => $v) {
                 $v['cost_percentage'] = round($usg['data'][$cp->key]['data'][$platform]['cost'] == 0 ? 0 : $v['cost'] * 100 / $usg['data'][$cp->key]['data'][$platform]['cost'], 0);
                 if ($i < $max) {
                     $new[$farmId] = $v;
                 } elseif (!isset($new[self::EVERYTHING_ELSE])) {
                     $v['id'] = self::EVERYTHING_ELSE;
                     $new[self::EVERYTHING_ELSE] = $v;
                 } else {
                     $new[self::EVERYTHING_ELSE]['cost'] += $v['cost'];
                 }
                 $i++;
             }
             $new[self::EVERYTHING_ELSE]['cost_percentage'] = round($usg['data'][$cp->key]['data'][$platform]['cost'] == 0 ? 0 : $new[self::EVERYTHING_ELSE]['cost'] * 100 / $usg['data'][$cp->key]['data'][$platform]['cost'], 0);
             $usgFarms->setArray(['data' => $new]);
         } else {
             $usgFarms->setArray($usg['data'][$cp->key]['data'][$platform])->calculatePercentage();
         }
         //Forms result data array
         foreach ($usgFarms->getIterator() as $farmId => $pv) {
             $record = $this->getDetailedPointDataArray($farmId, $this->fetchFarmName($farmId), $pv, isset($prevUsg['data'][$cp->previousPeriodKey]['data'][$platform]['data'][$farmId]) ? $prevUsg['data'][$cp->previousPeriodKey]['data'][$platform]['data'][$farmId] : null, isset($usg['data'][$cp->key]['data'][$platform]['data'][$farmId]) ? $usg['data'][$cp->key]['data'][$platform]['data'][$farmId] : null);
             if ($farmId && $farmId != self::EVERYTHING_ELSE && !empty($pv['envId'])) {
                 $record['environment'] = ['id' => (int) $pv['envId'], 'name' => AccountTagEntity::fetchName($pv['envId'], TagEntity::TAG_ID_ENVIRONMENT)];
             }
             $result[] = $record;
         }
     }
     return ['data' => $result];
 }