public function getFarmCostMetering($accountId, $farmId, $mode = 'custom', $startDate = null, $endDate = null)
{
$utcTz = new DateTimeZone('UTC');
if (empty($startDate) || empty($endDate)) {
$startDate = (new DateTime('yesterday', $utcTz))->modify('-6 days');
$endDate = new DateTime('yesterday', $utcTz);
} else {
$startDate = new DateTime($startDate, $utcTz);
$endDate = new DateTime($endDate, $utcTz);
}
$iterator = ChartPeriodIterator::create($mode, $startDate, $endDate, 'UTC');
//Interval which is used in the database query for grouping
$queryInterval = preg_replace('/^1 /', '', $iterator->getInterval());
$criteria = ['farmId' => $farmId];
//Current period data
$farmUsageCurrent = $this->getFarmData($accountId, $criteria, $iterator->getStart(), $iterator->getEnd(), [$queryInterval, TagEntity::TAG_ID_FARM_ROLE, 'distributionType', 'usageItem'], true);
//Previous period data
$farmUsagePrevious = $this->getFarmData($accountId, $criteria, $iterator->getPreviousStart(), $iterator->getPreviousEnd(), [$queryInterval, TagEntity::TAG_ID_FARM_ROLE, 'distributionType', 'usageItem'], true);
$farmUsageCurrentCollection = (new AggregationCollection(['period', 'farmRoleId', 'distributionType', 'usageItem' => ['envId', 'platform', 'cloudLocation', 'id']], ['cost' => 'sum', 'minUsage' => 'min', 'maxUsage' => 'max', 'usageHours' => 'sum', 'workingHours' => 'sum']))->load($farmUsageCurrent)->calculatePercentage();
$farmUsagePreviousCollection = (new AggregationCollection(['period', 'farmRoleId', 'distributionType', 'usageItem'], ['cost' => 'sum', 'minUsage' => 'min', 'maxUsage' => 'max', 'usageHours' => 'sum', 'workingHours' => 'sum']))->load($farmUsagePrevious)->calculatePercentage();
$collection = new AggregationCollectionSet(['farmUsageCurrent' => $farmUsageCurrentCollection, 'farmUsagePrevious' => $farmUsagePreviousCollection]);
$timeline = [];
$farmRoles = [];
$prevPointKey = null;
foreach ($iterator as $chartPoint) {
/* @var $chartPoint \Scalr\Stats\CostAnalytics\ChartPointInfo */
$i = $chartPoint->i;
$timeline[] = array('datetime' => $chartPoint->dt->format('Y-m-d 00:00'), 'label' => $chartPoint->label, 'onchart' => $chartPoint->label, 'cost' => round(isset($collection['farmUsageCurrent']['data'][$chartPoint->key]['cost']) ? $collection['farmUsageCurrent']['data'][$chartPoint->key]['cost'] : 0, 2));
if (!isset($collection['farmUsageCurrent']['data'][$chartPoint->key]['data'])) {
foreach ($farmRoles as $farmRoleId => $roleData) {
if (!$iterator->isFuture()) {
//Previous period details
if (isset($collection['farmUsagePrevious']['data'][$chartPoint->previousPeriodKey]['data'][$farmRoleId])) {
$pp = $collection['farmUsagePrevious']['data'][$chartPoint->previousPeriodKey]['data'][$farmRoleId];
} else {
$pp = null;
}
//Previous point details
if (isset($collection['farmUsageCurrent']['data'][$prevPointKey]['data'][$farmRoleId])) {
$ppt = $collection['farmUsageCurrent']['data'][$prevPointKey]['data'][$farmRoleId];
} else {
$ppt = null;
}
$costData = $this->getPointDataArray(null, $pp, $ppt);
$costData['hours'] = [];
$farmRoles[$farmRoleId]['data'][] = $costData;
} else {
$farmRoles[$farmRoleId]['data'][] = null;
}
}
} else {
//Initializes with empty values to prevent data shifts on charts.
if (!isset($collection['farmUsageCurrent']['data'][$chartPoint->key]['data'])) {
$collection['farmUsageCurrent']['data'][$chartPoint->key]['data'] = [];
}
$combined =& $collection['farmUsageCurrent']['data'][$chartPoint->key]['data'];
if (!empty($farmRoles)) {
foreach ($farmRoles as $farmRoleId => $t) {
if (!array_key_exists($farmRoleId, $combined)) {
$combined[$farmRoleId] = [];
}
}
}
foreach ($combined as $farmRoleId => $roleData) {
if (!isset($farmRoles[$farmRoleId]) && $i > 0) {
$farmRoles[$farmRoleId]['name'] = AccountTagEntity::fetchName($farmRoleId, TagEntity::TAG_ID_FARM_ROLE);
$farmRoles[$farmRoleId]['data'] = array_fill(0, $i, null);
}
if (!$iterator->isFuture()) {
//Previous period details
if (isset($collection['farmUsagePrevious']['data'][$chartPoint->previousPeriodKey]['data'][$farmRoleId])) {
$pp = $collection['farmUsagePrevious']['data'][$chartPoint->previousPeriodKey]['data'][$farmRoleId];
} else {
$pp = null;
}
//Previous point details
if (isset($collection['farmUsageCurrent']['data'][$prevPointKey]['data'][$farmRoleId])) {
$ppt = $collection['farmUsageCurrent']['data'][$prevPointKey]['data'][$farmRoleId];
} else {
$ppt = null;
}
$farmRoles[$farmRoleId]['name'] = AccountTagEntity::fetchName($farmRoleId, TagEntity::TAG_ID_FARM_ROLE);
$costData = $this->getPointDataArray($roleData, $pp, $ppt);
$costData['hours'] = [];
if (isset($roleData['data'])) {
foreach ($roleData['data'] as $distrType => $distrUsage) {
if ($distrType != UsageTypeEntity::COST_DISTR_TYPE_COMPUTE) {
continue;
}
foreach ($distrUsage['data'] as $usageItem => $usage) {
$usageItemName = $this->getInstanceTypeName($usageItem, $usage['envId'], $usage['platform'], $usage['cloudLocation']);
$costData['hours'][$usageItemName] = ['hours' => $usage['usageHours'], 'min' => $usage['minUsage'], 'max' => $usage['maxUsage'], 'avg' => !empty($usage['workingHours']) ? round($usage['usageHours'] / $usage['workingHours']) : 0];
}
}
}
$farmRoles[$farmRoleId]['data'][] = $costData;
} else {
$farmRoles[$farmRoleId]['data'][] = null;
}
}
}
$prevPointKey = $chartPoint->key;
}
$cntpoints = count($timeline);
foreach ($farmRoles as $farmRoleId => $v) {
if (($j = count($v['data'])) < $cntpoints) {
while ($j < $cntpoints) {
$farmRoles[$farmRoleId]['data'][] = null;
$j++;
}
}
}
$data = ['timeline' => $timeline, 'totals' => ['cost' => $collection['farmUsageCurrent']['cost'], 'growth' => round($collection['farmUsageCurrent']['cost'] - $collection['farmUsagePrevious']['cost'], 2), 'growthPct' => $collection['farmUsagePrevious']['cost'] == 0 ? null : round(abs(($collection['farmUsageCurrent']['cost'] - $collection['farmUsagePrevious']['cost']) / $collection['farmUsagePrevious']['cost'] * 100), 0)], 'farmroles' => $farmRoles];
return $data;
}