Skip to content

Commit

Permalink
Merge pull request #2040 from CachetHQ/metric-repository-perf
Browse files Browse the repository at this point in the history
Metric repository perf
  • Loading branch information
jbrooksuk authored Oct 30, 2016
2 parents a0f2d66 + 1c00dec commit fbb59ea
Show file tree
Hide file tree
Showing 9 changed files with 220 additions and 318 deletions.
17 changes: 7 additions & 10 deletions app/Foundation/Providers/RepositoryServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@

use CachetHQ\Cachet\Dates\DateFactory;
use CachetHQ\Cachet\Repositories\Metric\MetricRepository;
use CachetHQ\Cachet\Repositories\Metric\MySqlRepository as MetricMySqlRepository;
use CachetHQ\Cachet\Repositories\Metric\PgSqlRepository as MetricPgSqlRepository;
use CachetHQ\Cachet\Repositories\Metric\SqliteRepository as MetricSqliteRepository;
use CachetHQ\Cachet\Repositories\Metric\MySqlRepository;
use CachetHQ\Cachet\Repositories\Metric\PgSqlRepository;
use CachetHQ\Cachet\Repositories\Metric\SqliteRepository;
use Illuminate\Contracts\Config\Repository as ConfigRepository;
use Illuminate\Contracts\Container\Container;
use Illuminate\Support\ServiceProvider;
Expand Down Expand Up @@ -46,14 +46,11 @@ protected function registerMetricRepository()
{
$this->app->singleton(MetricRepository::class, function (Container $app) {
$config = $app->make(ConfigRepository::class);
$driver = $config->get('database.default');

if ($driver == 'mysql') {
$repository = new MetricMySqlRepository($config);
} elseif ($driver == 'pgsql') {
$repository = new MetricPgSqlRepository($config);
} elseif ($driver == 'sqlite') {
$repository = new MetricSqliteRepository($config);
switch ($config->get('database.default')) {
case 'mysql': $repository = new MySqlRepository($config); break;
case 'pgsql': $repository = new PgSqlRepository($config); break;
case 'sqlite': $repository = new SqliteRepository($config); break;
}

$dates = $app->make(DateFactory::class);
Expand Down
18 changes: 10 additions & 8 deletions app/Http/Controllers/StatusPageController.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,20 +31,22 @@
class StatusPageController extends AbstractApiController
{
/**
* The metric repository instance.
*
* @var \CachetHQ\Cachet\Repositories\Metric\MetricRepository
*/
protected $metricRepository;
protected $metrics;

/**
* Construct a new status page controller instance.
*
* @param \CachetHQ\Cachet\Repositories\Metric\MetricRepository $metricRepository
* @param \CachetHQ\Cachet\Repositories\Metric\MetricRepository $metrics
*
* @return void
*/
public function __construct(MetricRepository $metricRepository)
public function __construct(MetricRepository $metrics)
{
$this->metricRepository = $metricRepository;
$this->metrics = $metrics;
}

/**
Expand Down Expand Up @@ -141,16 +143,16 @@ public function getMetrics(Metric $metric)

switch ($type) {
case 'last_hour':
$metricData = $this->metricRepository->listPointsLastHour($metric);
$metricData = $this->metrics->listPointsLastHour($metric);
break;
case 'today':
$metricData = $this->metricRepository->listPointsToday($metric);
$metricData = $this->metrics->listPointsToday($metric);
break;
case 'week':
$metricData = $this->metricRepository->listPointsForWeek($metric);
$metricData = $this->metrics->listPointsForWeek($metric);
break;
case 'month':
$metricData = $this->metricRepository->listPointsForMonth($metric);
$metricData = $this->metrics->listPointsForMonth($metric);
break;
}

Expand Down
24 changes: 8 additions & 16 deletions app/Presenters/MetricPresenter.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,10 @@ class MetricPresenter extends BasePresenter implements Arrayable
public function view_name()
{
switch ($this->wrappedObject->default_view) {
case 0:
return 'last_hour';
case 1:
return 'today';
case 2:
return 'week';
case 3:
return 'month';
case 0: return 'last_hour';
case 1: return 'today';
case 2: return 'week';
case 3: return 'month';
}
}

Expand All @@ -56,14 +52,10 @@ public function default_view_name()
public function trans_string_name()
{
switch ($this->wrappedObject->default_view) {
case 0:
return 'last_hour';
case 1:
return 'hourly';
case 2:
return 'weekly';
case 3:
return 'monthly';
case 0: return 'last_hour';
case 1: return 'hourly';
case 2: return 'weekly';
case 3: return 'monthly';
}
}

Expand Down
62 changes: 61 additions & 1 deletion app/Repositories/Metric/AbstractMetricRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

use CachetHQ\Cachet\Models\Metric;
use Illuminate\Contracts\Config\Repository;
use Illuminate\Support\Collection;

/**
* This is the abstract metric repository class.
Expand Down Expand Up @@ -52,12 +53,71 @@ public function __construct(Repository $config)
*
* @return string
*/
protected function getTableName()
protected function getMetricsTable()
{
$driver = $this->config->get('database.default');
$connection = $this->config->get('database.connections.'.$driver);
$prefix = $connection['prefix'];

return $prefix.'metrics';
}

/**
* Get the metric points table name.
*
* @return string
*/
protected function getMetricPointsTable()
{
$driver = $this->config->get('database.default');
$connection = $this->config->get('database.connections.'.$driver);
$prefix = $connection['prefix'];

return $prefix.'metric_points';
}

/**
* Return the query type.
*
* @param \CachetHQ\Cachet\Models\Metric $metric
*
* @return string
*/
protected function getQueryType(Metric $metric)
{
if (!isset($metric->calc_type) || $metric->calc_type == Metric::CALC_SUM) {
return "sum({$this->getMetricPointsTable()}.value * {$this->getMetricPointsTable()}.counter) AS value";
} elseif ($metric->calc_type == Metric::CALC_AVG) {
return "avg({$this->getMetricPointsTable()}.value * {$this->getMetricPointsTable()}.counter) AS value";
} else {
return "sum({$this->getMetricPointsTable()}.value * {$this->getMetricPointsTable()}.counter) AS value";
}
}

/**
* Map the result set.
*
* @param \CachetHQ\Cachet\Models\Metric $metric
* @param array $results
*
* @return \Illuminate\Support\Collection
*/
protected function mapResults(Metric $metric, array $results)
{
$results = Collection::make($results);

return $results->map(function ($point) use ($metric) {
if (!$point->value) {
$point->value = $metric->default_value;
}

if ($point->value === 0 && $metric->default_value != $value) {
$point->value = $metric->default_value;
}

$point->value = round($point->value, $metric->places);

return $point;
});
}
}
26 changes: 15 additions & 11 deletions app/Repositories/Metric/MetricInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,36 +13,40 @@

use CachetHQ\Cachet\Models\Metric;

/**
* This is the metric interface.
*
* @author James Brooks <james@alt-three.com>
*/
interface MetricInterface
{
/**
* Returns metrics for the last hour.
* Returns metrics since given minutes.
*
* @param \CachetHQ\Cachet\Models\Metric $metric
* @param int $hour
* @param int $minute
* @param int $minutes
*
* @return int
* @return \Illuminate\Support\Collection
*/
public function getPointsLastHour(Metric $metric, $hour, $minute);
public function getPointsSinceMinutes(Metric $metric, $minutes);

/**
* Returns metrics for a given hour.
* Returns metrics since given hour.
*
* @param \CachetHQ\Cachet\Models\Metric $metric
* @param int $hour
*
* @return int
* @return \Illuminate\Support\Collection
*/
public function getPointsByHour(Metric $metric, $hour);
public function getPointsSinceHour(Metric $metric, $hour);

/**
* Returns metrics for the week.
* Returns metrics since given day.
*
* @param \CachetHQ\Cachet\Models\Metric $metric
* @param int $day
*
* @return int
* @return \Illuminate\Support\Collection
*/
public function getPointsForDayInWeek(Metric $metric, $day);
public function getPointsSinceDay(Metric $metric, $day);
}
68 changes: 42 additions & 26 deletions app/Repositories/Metric/MetricRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@
use CachetHQ\Cachet\Models\Metric;
use DateInterval;

/**
* This is the metric repository class.
*
* @author James Brooks <james@alt-three.com>
*/
class MetricRepository
{
/**
Expand Down Expand Up @@ -50,22 +55,25 @@ public function __construct(MetricInterface $repository, DateFactory $dates)
*
* @param \CachetHQ\Cachet\Models\Metric $metric
*
* @return array
* @return \Illuminate\Support\Collection
*/
public function listPointsLastHour(Metric $metric)
{
$dateTime = $this->dates->make();

$points = [];

$pointKey = $dateTime->format('H:i');
$points = $this->repository->getPointsSinceMinutes($metric, 60)->pluck('value', 'key');

for ($i = 0; $i <= 60; $i++) {
$points[$pointKey] = $this->repository->getPointsLastHour($metric, 0, $i);
if (!$points->has($pointKey)) {
$points->put($pointKey, $metric->default_value);
}

$pointKey = $dateTime->sub(new DateInterval('PT1M'))->format('H:i');
}

return array_reverse($points);
return $points->sortBy(function ($point, $key) use ($points) {
return $key;
});
}

/**
Expand All @@ -79,17 +87,20 @@ public function listPointsLastHour(Metric $metric)
public function listPointsToday(Metric $metric, $hours = 12)
{
$dateTime = $this->dates->make();

$points = [];

$pointKey = $dateTime->format('H:00');
$points = $this->repository->getPointsSinceHour($metric, $hours)->pluck('value', 'key');

for ($i = 0; $i <= $hours; $i++) {
$points[$pointKey] = $this->repository->getPointsByHour($metric, $i);
if (!$points->has($pointKey)) {
$points->put($pointKey, $metric->default_value);
}

$pointKey = $dateTime->sub(new DateInterval('PT1H'))->format('H:00');
}

return array_reverse($points);
return $points->sortBy(function ($point, $key) use ($points) {
return $key;
});
}

/**
Expand All @@ -102,17 +113,20 @@ public function listPointsToday(Metric $metric, $hours = 12)
public function listPointsForWeek(Metric $metric)
{
$dateTime = $this->dates->make();

$points = [];

$pointKey = $dateTime->format('D jS M');
$pointKey = $dateTime->format('Y-m-d');
$points = $this->repository->getPointsSinceDay($metric, 7)->pluck('value', 'key');

for ($i = 0; $i <= 7; $i++) {
$points[$pointKey] = $this->repository->getPointsForDayInWeek($metric, $i);
$pointKey = $dateTime->sub(new DateInterval('P1D'))->format('D jS M');
if (!$points->has($pointKey)) {
$points->put($pointKey, $metric->default_value);
}

$pointKey = $dateTime->sub(new DateInterval('P1D'))->format('Y-m-d');
}

return array_reverse($points);
return $points->sortBy(function ($point, $key) use ($points) {
return $key;
});
}

/**
Expand All @@ -125,18 +139,20 @@ public function listPointsForWeek(Metric $metric)
public function listPointsForMonth(Metric $metric)
{
$dateTime = $this->dates->make();

$pointKey = $dateTime->format('Y-m-d');
$daysInMonth = $dateTime->format('t');

$points = [];

$pointKey = $dateTime->format('jS M');
$points = $this->repository->getPointsSinceDay($metric, $daysInMonth)->pluck('value', 'key');

for ($i = 0; $i <= $daysInMonth; $i++) {
$points[$pointKey] = $this->repository->getPointsForDayInWeek($metric, $i);
$pointKey = $dateTime->sub(new DateInterval('P1D'))->format('jS M');
if (!$points->has($pointKey)) {
$points->put($pointKey, $metric->default_value);
}

$pointKey = $dateTime->sub(new DateInterval('P1D'))->format('Y-m-d');
}

return array_reverse($points);
return $points->sortBy(function ($point, $key) use ($points) {
return $key;
});
}
}
Loading

0 comments on commit fbb59ea

Please sign in to comment.