Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Metric repository perf #2040

Merged
merged 3 commits into from
Oct 30, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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