Merge pull request #2040 from CachetHQ/metric-repository-perf

Metric repository perf
This commit is contained in:
James Brooks 2016-10-30 17:36:01 +00:00 committed by GitHub
commit fbb59ea66e
9 changed files with 220 additions and 318 deletions

View File

@ -13,9 +13,9 @@ namespace CachetHQ\Cachet\Foundation\Providers;
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;
@ -46,14 +46,11 @@ class RepositoryServiceProvider extends ServiceProvider
{
$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);

View File

@ -31,20 +31,22 @@ use McCool\LaravelAutoPresenter\Facades\AutoPresenter;
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;
}
/**
@ -141,16 +143,16 @@ class StatusPageController extends AbstractApiController
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;
}

View File

@ -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';
}
}
@ -56,14 +52,10 @@ class MetricPresenter extends BasePresenter implements Arrayable
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';
}
}

View File

@ -13,6 +13,7 @@ namespace CachetHQ\Cachet\Repositories\Metric;
use CachetHQ\Cachet\Models\Metric;
use Illuminate\Contracts\Config\Repository;
use Illuminate\Support\Collection;
/**
* This is the abstract metric repository class.
@ -52,7 +53,7 @@ abstract class AbstractMetricRepository
*
* @return string
*/
protected function getTableName()
protected function getMetricsTable()
{
$driver = $this->config->get('database.default');
$connection = $this->config->get('database.connections.'.$driver);
@ -60,4 +61,63 @@ abstract class AbstractMetricRepository
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;
});
}
}

View File

@ -13,36 +13,40 @@ namespace CachetHQ\Cachet\Repositories\Metric;
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);
}

View File

@ -15,6 +15,11 @@ use CachetHQ\Cachet\Dates\DateFactory;
use CachetHQ\Cachet\Models\Metric;
use DateInterval;
/**
* This is the metric repository class.
*
* @author James Brooks <james@alt-three.com>
*/
class MetricRepository
{
/**
@ -50,22 +55,25 @@ class MetricRepository
*
* @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;
});
}
/**
@ -79,17 +87,20 @@ class MetricRepository
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;
});
}
/**
@ -102,17 +113,20 @@ class MetricRepository
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;
});
}
/**
@ -125,18 +139,20 @@ class MetricRepository
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;
});
}
}

View File

@ -12,9 +12,7 @@
namespace CachetHQ\Cachet\Repositories\Metric;
use CachetHQ\Cachet\Models\Metric;
use DateInterval;
use Illuminate\Support\Facades\DB;
use Jenssegers\Date\Date;
/**
* This is the mysql repository class.
@ -24,112 +22,59 @@ use Jenssegers\Date\Date;
class MySqlRepository extends AbstractMetricRepository implements 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)
{
$dateTime = (new Date())->sub(new DateInterval('PT'.$hour.'H'))->sub(new DateInterval('PT'.$minute.'M'));
$timeInterval = $dateTime->format('YmdHi');
if (!isset($metric->calc_type) || $metric->calc_type == Metric::CALC_SUM) {
$queryType = 'SUM(mp.`value` * mp.`counter`) AS `value`';
} elseif ($metric->calc_type == Metric::CALC_AVG) {
$queryType = 'AVG(mp.`value` * mp.`counter`) AS `value`';
}
$value = 0;
$points = DB::select("SELECT {$queryType} FROM {$this->getTableName()} m INNER JOIN metric_points mp ON m.id = mp.metric_id WHERE m.id = :metricId AND DATE_FORMAT(mp.`created_at`, '%Y%m%d%H%i') = :timeInterval GROUP BY HOUR(mp.`created_at`), MINUTE(mp.`created_at`)", [
'metricId' => $metric->id,
'timeInterval' => $timeInterval,
$queryType = $this->getQueryType($metric);
$points = DB::select("SELECT DATE_FORMAT({$this->getMetricPointsTable()}.`created_at`, '%H:%i') AS `key`, {$queryType} FROM {$this->getMetricsTable()} INNER JOIN {$this->getMetricPointsTable()} ON metrics.id = {$this->getMetricPointsTable()}.metric_id WHERE metrics.id = :metricId AND {$this->getMetricPointsTable()}.`created_at` >= DATE_SUB(NOW(), INTERVAL :minutes MINUTE) GROUP BY HOUR({$this->getMetricPointsTable()}.`created_at`), MINUTE({$this->getMetricPointsTable()}.`created_at`) ORDER BY {$this->getMetricPointsTable()}.`created_at`", [
'metricId' => $metric->id,
'minutes' => $minutes,
]);
if (isset($points[0]) && !($value = $points[0]->value)) {
$value = 0;
}
if ($value === 0 && $metric->default_value != $value) {
return $metric->default_value;
}
return round($value, $metric->places);
return $this->mapResults($metric, $points);
}
/**
* 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)
{
$dateTime = (new Date())->sub(new DateInterval('PT'.$hour.'H'));
$hourInterval = $dateTime->format('YmdH');
if (!isset($metric->calc_type) || $metric->calc_type == Metric::CALC_SUM) {
$queryType = 'SUM(mp.`value` * mp.`counter`) AS `value`';
} elseif ($metric->calc_type == Metric::CALC_AVG) {
$queryType = 'AVG(mp.`value` * mp.`counter`) AS `value`';
}
$value = 0;
$points = DB::select("SELECT {$queryType} FROM {$this->getTableName()} m INNER JOIN metric_points mp ON m.id = mp.metric_id WHERE m.id = :metricId AND DATE_FORMAT(mp.`created_at`, '%Y%m%d%H') = :hourInterval GROUP BY HOUR(mp.`created_at`)", [
'metricId' => $metric->id,
'hourInterval' => $hourInterval,
$queryType = $this->getQueryType($metric);
$points = DB::select("SELECT DATE_FORMAT({$this->getMetricPointsTable()}.`created_at`, '%H:00') AS `key`, {$queryType} FROM {$this->getMetricsTable()} INNER JOIN {$this->getMetricPointsTable()} ON metrics.id = {$this->getMetricPointsTable()}.metric_id WHERE metrics.id = :metricId AND {$this->getMetricPointsTable()}.`created_at` >= DATE_SUB(NOW(), INTERVAL :hour HOUR) GROUP BY HOUR({$this->getMetricPointsTable()}.`created_at`) ORDER BY {$this->getMetricPointsTable()}.`created_at`", [
'metricId' => $metric->id,
'hour' => $hour,
]);
if (isset($points[0]) && !($value = $points[0]->value)) {
$value = 0;
}
if ($value === 0 && $metric->default_value != $value) {
return $metric->default_value;
}
return round($value, $metric->places);
return $this->mapResults($metric, $points);
}
/**
* 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)
{
$dateTime = (new Date())->sub(new DateInterval('P'.$day.'D'));
if (!isset($metric->calc_type) || $metric->calc_type == Metric::CALC_SUM) {
$queryType = 'SUM(mp.`value` * mp.`counter`) AS `value`';
} elseif ($metric->calc_type == Metric::CALC_AVG) {
$queryType = 'AVG(mp.`value` * mp.`counter`) AS `value`';
}
$value = 0;
$points = DB::select("SELECT {$queryType} FROM {$this->getTableName()} m INNER JOIN metric_points mp ON m.id = mp.metric_id WHERE m.id = :metricId AND mp.`created_at` BETWEEN DATE_SUB(mp.`created_at`, INTERVAL 1 WEEK) AND DATE_ADD(NOW(), INTERVAL 1 DAY) AND DATE_FORMAT(mp.`created_at`, '%Y%m%d') = :timeInterval GROUP BY DATE_FORMAT(mp.`created_at`, '%Y%m%d')", [
'metricId' => $metric->id,
'timeInterval' => $dateTime->format('Ymd'),
$queryType = $this->getQueryType($metric);
$points = DB::select("SELECT DATE_FORMAT({$this->getMetricPointsTable()}.`created_at`, '%Y-%m-%d') AS `key`, {$queryType} FROM {$this->getMetricsTable()} INNER JOIN {$this->getMetricPointsTable()} ON metrics.id = {$this->getMetricPointsTable()}.metric_id WHERE metrics.id = :metricId AND {$this->getMetricPointsTable()}.`created_at` >= DATE_SUB(NOW(), INTERVAL :day DAY) GROUP BY DATE({$this->getMetricPointsTable()}.`created_at`) ORDER BY {$this->getMetricPointsTable()}.`created_at`", [
'metricId' => $metric->id,
'day' => $day,
]);
if (isset($points[0]) && !($value = $points[0]->value)) {
$value = 0;
}
if ($value === 0 && $metric->default_value != $value) {
return $metric->default_value;
}
return round($value, $metric->places);
return $this->mapResults($metric, $points);
}
}

View File

@ -12,7 +12,6 @@
namespace CachetHQ\Cachet\Repositories\Metric;
use CachetHQ\Cachet\Models\Metric;
use DateInterval;
use Illuminate\Support\Facades\DB;
use Jenssegers\Date\Date;
@ -24,113 +23,56 @@ use Jenssegers\Date\Date;
class PgSqlRepository extends AbstractMetricRepository implements 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)
{
$dateTime = (new Date())->sub(new DateInterval('PT'.$hour.'H'))->sub(new DateInterval('PT'.$minute.'M'));
// Default metrics calculations.
if (!isset($metric->calc_type) || $metric->calc_type == Metric::CALC_SUM) {
$queryType = 'sum(metric_points.value * metric_points.counter)';
} elseif ($metric->calc_type == Metric::CALC_AVG) {
$queryType = 'avg(metric_points.value * metric_points.counter)';
} else {
$queryType = 'sum(metric_points.value * metric_points.counter)';
}
$value = 0;
$query = DB::select("select {$queryType} as value FROM {$this->getTableName()} m JOIN metric_points ON metric_points.metric_id = m.id WHERE m.id = :metricId AND to_char(metric_points.created_at, 'YYYYMMDDHH24MI') = :timeInterval GROUP BY to_char(metric_points.created_at, 'HHMI')", [
'metricId' => $metric->id,
'timeInterval' => $dateTime->format('YmdHi'),
$queryType = $this->getQueryType($metric);
$points = DB::select("SELECT to_char({$this->getMetricPointsTable()}.created_at, 'HH24:MI') AS key, {$queryType} FROM {$this->getMetricsTable()} INNER JOIN {$this->getMetricPointsTable()} ON metrics.id = {$this->getMetricPointsTable()}.metric_id WHERE metrics.id = :metricId AND {$this->getMetricPointsTable()}.created_at >= (NOW() - INTERVAL '{$minutes}' MINUTE) GROUP BY to_char({$this->getMetricPointsTable()}.created_at, 'HH24:MI') ORDER BY to_char({$this->getMetricPointsTable()}.created_at, 'HH24:MI')", [
'metricId' => $metric->id,
]);
if (isset($query[0])) {
$value = $query[0]->value;
}
if ($value === 0 && $metric->default_value != $value) {
return $metric->default_value;
}
return round($value, $metric->places);
return $this->mapResults($metric, $points);
}
/**
* 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)
{
$dateTime = (new Date())->sub(new DateInterval('PT'.$hour.'H'));
// Default metrics calculations.
if (!isset($metric->calc_type) || $metric->calc_type == Metric::CALC_SUM) {
$queryType = 'sum(metric_points.value * metric_points.counter)';
} elseif ($metric->calc_type == Metric::CALC_AVG) {
$queryType = 'avg(metric_points.value * metric_points.counter)';
} else {
$queryType = 'sum(metric_points.value * metric_points.counter)';
}
$value = 0;
$query = DB::select("select {$queryType} as value FROM {$this->getTableName()} m JOIN metric_points ON metric_points.metric_id = m.id WHERE metric_points.metric_id = :metricId AND to_char(metric_points.created_at, 'YYYYMMDDHH24') = :timeInterval GROUP BY to_char(metric_points.created_at, 'H')", [
'metricId' => $metric->id,
'timeInterval' => $dateTime->format('YmdH'),
$queryType = $this->getQueryType($metric);
$points = DB::select("SELECT to_char({$this->getMetricPointsTable()}.created_at, 'HH24:00') AS key, {$queryType} FROM {$this->getMetricsTable()} INNER JOIN {$this->getMetricPointsTable()} ON metrics.id = {$this->getMetricPointsTable()}.metric_id WHERE metrics.id = :metricId AND {$this->getMetricPointsTable()}.created_at >= (NOW() - INTERVAL '{$hour}' HOUR) GROUP BY to_char({$this->getMetricPointsTable()}.created_at, 'HH24:00') ORDER BY to_char({$this->getMetricPointsTable()}.created_at, 'HH24:00')", [
'metricId' => $metric->id,
]);
if (isset($query[0])) {
$value = $query[0]->value;
}
if ($value === 0 && $metric->default_value != $value) {
return $metric->default_value;
}
return round($value, $metric->places);
return $this->mapResults($metric, $points);
}
/**
* 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)
{
$dateTime = (new Date())->sub(new DateInterval('P'.$day.'D'));
if (!isset($metric->calc_type) || $metric->calc_type == Metric::CALC_SUM) {
$queryType = 'sum(mp.value * mp.counter) AS value';
} elseif ($metric->calc_type == Metric::CALC_AVG) {
$queryType = 'avg(mp.value * mp.counter) AS value';
}
$value = 0;
$points = DB::select("SELECT {$queryType} FROM {$this->getTableName()} m INNER JOIN metric_points mp ON m.id = mp.metric_id WHERE m.id = :metricId AND mp.created_at BETWEEN (mp.created_at - interval '1 week') AND (now() + interval '1 day') AND to_char(mp.created_at, 'YYYYMMDD') = :timeInterval GROUP BY to_char(mp.created_at, 'YYYYMMDD')", [
'metricId' => $metric->id,
'timeInterval' => $dateTime->format('Ymd'),
$queryType = $this->getQueryType($metric);
$points = DB::select("SELECT DATE({$this->getMetricPointsTable()}.created_at) AS key, {$queryType} FROM {$this->getMetricsTable()} INNER JOIN {$this->getMetricPointsTable()} ON metrics.id = {$this->getMetricPointsTable()}.metric_id WHERE metrics.id = :metricId AND {$this->getMetricPointsTable()}.created_at >= (DATE(NOW()) - INTERVAL '{$day}' DAY) GROUP BY DATE({$this->getMetricPointsTable()}.created_at) ORDER BY DATE({$this->getMetricPointsTable()}.created_at)", [
'metricId' => $metric->id,
]);
if (isset($points[0]) && !($value = $points[0]->value)) {
$value = 0;
}
if ($value === 0 && $metric->default_value != $value) {
return $metric->default_value;
}
return round($value, $metric->places);
return $this->mapResults($metric, $points);
}
}

View File

@ -12,123 +12,67 @@
namespace CachetHQ\Cachet\Repositories\Metric;
use CachetHQ\Cachet\Models\Metric;
use DateInterval;
use Illuminate\Support\Facades\DB;
use Jenssegers\Date\Date;
/**
* This is the sqlite repository class.
*
* @author James Brooks <james@alt-three.com>
*/
class SqliteRepository extends AbstractMetricRepository implements 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)
{
$dateTime = (new Date())->sub(new DateInterval('PT'.$hour.'H'))->sub(new DateInterval('PT'.$minute.'M'));
// Default metrics calculations.
if (!isset($metric->calc_type) || $metric->calc_type == Metric::CALC_SUM) {
$queryType = 'sum(metric_points.value * metric_points.counter)';
} elseif ($metric->calc_type == Metric::CALC_AVG) {
$queryType = 'avg(metric_points.value * metric_points.counter)';
} else {
$queryType = 'sum(metric_points.value * metric_points.counter)';
}
$value = 0;
$query = DB::select("select {$queryType} as value FROM {$this->getTableName()} m JOIN metric_points ON metric_points.metric_id = m.id WHERE m.id = :metricId AND strftime('%Y%m%d%H%M', metric_points.created_at) = :timeInterval GROUP BY strftime('%H%M', metric_points.created_at)", [
'metricId' => $metric->id,
'timeInterval' => $dateTime->format('YmdHi'),
$queryType = $this->getQueryType($metric);
$points = DB::select("SELECT strftime('%H:%M', {$this->getMetricPointsTable()}.`created_at`) AS `key`, {$queryType} FROM {$this->getMetricsTable()} INNER JOIN {$this->getMetricPointsTable()} ON metrics.id = {$this->getMetricPointsTable()}.metric_id WHERE metrics.id = :metricId AND {$this->getMetricPointsTable()}.`created_at` >= datetime('now', '-{$minutes} minutes') GROUP BY strftime('%H', {$this->getMetricPointsTable()}.`created_at`), strftime('%M', {$this->getMetricPointsTable()}.`created_at`) ORDER BY {$this->getMetricPointsTable()}.`created_at`", [
'metricId' => $metric->id,
]);
if (isset($query[0])) {
$value = $query[0]->value;
}
if ($value === 0 && $metric->default_value != $value) {
return $metric->default_value;
}
return round($value, $metric->places);
return $this->mapResults($metric, $points);
}
/**
* 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)
{
$dateTime = (new Date())->sub(new DateInterval('PT'.$hour.'H'));
// Default metrics calculations.
if (!isset($metric->calc_type) || $metric->calc_type == Metric::CALC_SUM) {
$queryType = 'sum(metric_points.value * metric_points.counter)';
} elseif ($metric->calc_type == Metric::CALC_AVG) {
$queryType = 'avg(metric_points.value * metric_points.counter)';
} else {
$queryType = 'sum(metric_points.value * metric_points.counter)';
}
$value = 0;
$query = DB::select("select {$queryType} as value FROM {$this->getTableName()} m JOIN metric_points ON metric_points.metric_id = m.id WHERE m.id = :metricId AND strftime('%Y%m%d%H', metric_points.created_at) = :timeInterval GROUP BY strftime('%H', metric_points.created_at)", [
'metricId' => $metric->id,
'timeInterval' => $dateTime->format('YmdH'),
$queryType = $this->getQueryType($metric);
$points = DB::select("SELECT strftime('%H:00', {$this->getMetricPointsTable()}.`created_at`) AS `key`, {$queryType} FROM {$this->getMetricsTable()} INNER JOIN {$this->getMetricPointsTable()} ON metrics.id = {$this->getMetricPointsTable()}.metric_id WHERE metrics.id = :metricId AND {$this->getMetricPointsTable()}.`created_at` >= datetime('now', '-{$hour} hours') GROUP BY strftime('%H', {$this->getMetricPointsTable()}.`created_at`) ORDER BY {$this->getMetricPointsTable()}.`created_at`", [
'metricId' => $metric->id,
]);
if (isset($query[0])) {
$value = $query[0]->value;
}
if ($value === 0 && $metric->default_value != $value) {
return $metric->default_value;
}
return round($value, $metric->places);
return $this->mapResults($metric, $points);
}
/**
* 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)
{
$dateTime = (new Date())->sub(new DateInterval('P'.$day.'D'));
// Default metrics calculations.
if (!isset($metric->calc_type) || $metric->calc_type == Metric::CALC_SUM) {
$queryType = 'sum(metric_points.value * metric_points.counter)';
} elseif ($metric->calc_type == Metric::CALC_AVG) {
$queryType = 'avg(metric_points.value * metric_points.counter)';
} else {
$queryType = 'sum(metric_points.value * metric_points.counter)';
}
$value = 0;
$query = DB::select("select {$queryType} as value FROM {$this->getTableName()} m JOIN metric_points ON metric_points.metric_id = m.id WHERE m.id = :metricId AND metric_points.created_at > date('now', '-7 day') AND strftime('%Y%m%d', metric_points.created_at) = :timeInterval GROUP BY strftime('%Y%m%d', metric_points.created_at)", [
'metricId' => $metric->id,
'timeInterval' => $dateTime->format('Ymd'),
$queryType = $this->getQueryType($metric);
$points = DB::select("SELECT strftime('%Y-%m-%d', {$this->getMetricPointsTable()}.`created_at`) AS `key`, {$queryType} FROM {$this->getMetricsTable()} INNER JOIN {$this->getMetricPointsTable()} ON metrics.id = {$this->getMetricPointsTable()}.metric_id WHERE metrics.id = :metricId AND {$this->getMetricPointsTable()}.`created_at` >= datetime('now', '-{$day} days') GROUP BY DATE({$this->getMetricPointsTable()}.`created_at`) ORDER BY {$this->getMetricPointsTable()}.`created_at`", [
'metricId' => $metric->id,
]);
if (isset($query[0])) {
$value = $query[0]->value;
}
if ($value === 0 && $metric->default_value != $value) {
return $metric->default_value;
}
return round($value, $metric->places);
return $this->mapResults($metric, $points);
}
}