diff --git a/app/Http/Controllers/HomeController.php b/app/Http/Controllers/HomeController.php index 0eef67fb..0c40a042 100644 --- a/app/Http/Controllers/HomeController.php +++ b/app/Http/Controllers/HomeController.php @@ -16,6 +16,7 @@ use CachetHQ\Cachet\Models\Component; use CachetHQ\Cachet\Models\ComponentGroup; use CachetHQ\Cachet\Models\Incident; use CachetHQ\Cachet\Models\Metric; +use CachetHQ\Cachet\Repositories\MetricRepository; use Exception; use GrahamCampbell\Binput\Facades\Binput; use GrahamCampbell\Markdown\Facades\Markdown; @@ -27,7 +28,24 @@ use Jenssegers\Date\Date; class HomeController extends Controller { /** - * Returns the rendered Blade templates. + * @var \CachetHQ\Cachet\Repositories\MetricRepository + */ + protected $metricRepository; + + /** + * Construct a new home controller instance. + * + * @param \CachetHQ\Cachet\Repositories\MetricRepository $metricRepository + * + * @return void + */ + public function __construct(MetricRepository $metricRepository) + { + $this->metricRepository = $metricRepository; + } + + /** + * Displays the status page. * * @return \Illuminate\View\View */ @@ -52,9 +70,17 @@ class HomeController extends Controller } $metrics = null; - + $metricData = []; if ($displayMetrics = Setting::get('display_graphs')) { $metrics = Metric::where('display_chart', 1)->get(); + + $metrics->map(function ($metric) use (&$metricData) { + $metricData[$metric->id] = [ + 'today' => $this->metricRepository->listPointsToday($metric), + 'week' => $this->metricRepository->listPointsForWeek($metric), + 'month' => $this->metricRepository->listPointsForMonth($metric), + ]; + }); } $daysToShow = Setting::get('app_incident_days') ?: 7; @@ -98,6 +124,7 @@ class HomeController extends Controller ->withUngroupedComponents($ungroupedComponents) ->withDisplayMetrics($displayMetrics) ->withMetrics($metrics) + ->withMetricData($metricData) ->withAllIncidents($allIncidents) ->withScheduledMaintenance($scheduledMaintenance) ->withAboutApp(Markdown::convertToHtml(Setting::get('app_about'))) diff --git a/app/Models/Metric.php b/app/Models/Metric.php index 18aa4f20..995fffac 100644 --- a/app/Models/Metric.php +++ b/app/Models/Metric.php @@ -12,13 +12,8 @@ namespace CachetHQ\Cachet\Models; use AltThree\Validator\ValidatingTrait; -use CachetHQ\Cachet\Facades\Setting as SettingFacade; use CachetHQ\Cachet\Presenters\MetricPresenter; -use DateInterval; use Illuminate\Database\Eloquent\Model; -use Illuminate\Support\Facades\Config; -use Illuminate\Support\Facades\DB; -use Jenssegers\Date\Date; use McCool\LaravelAutoPresenter\HasPresenter; class Metric extends Model implements HasPresenter @@ -86,58 +81,6 @@ class Metric extends Model implements HasPresenter return $this->hasMany(MetricPoint::class, 'metric_id', 'id'); } - /** - * Returns the sum of all values a metric has by the hour. - * - * @param int $hour - * - * @return int - */ - public function getValuesByHour($hour) - { - $dateTimeZone = SettingFacade::get('app_timezone'); - $dateTime = (new Date())->setTimezone($dateTimeZone)->sub(new DateInterval('PT'.$hour.'H')); - - $hourInterval = $dateTime->format('YmdH'); - - if (Config::get('database.default') === 'mysql') { - if (!isset($this->calc_type) || $this->calc_type == self::CALC_SUM) { - $value = $this->points() - ->whereRaw('DATE_FORMAT(created_at, "%Y%m%d%H") = '.$hourInterval) - ->groupBy(DB::raw('HOUR(created_at)'))->sum('value'); - } elseif ($this->calc_type == self::CALC_AVG) { - $value = $this->points() - ->whereRaw('DATE_FORMAT(created_at, "%Y%m%d%H") = '.$hourInterval) - ->groupBy(DB::raw('HOUR(created_at)'))->avg('value'); - } - } else { - // Default metrics calculations. - if (!isset($this->calc_type) || $this->calc_type == self::CALC_SUM) { - $queryType = 'sum(metric_points.value)'; - } elseif ($this->calc_type == self::CALC_AVG) { - $queryType = 'avg(metric_points.value)'; - } else { - $queryType = 'sum(metric_points.value)'; - } - - $query = DB::select("select {$queryType} as aggregate FROM metrics JOIN metric_points ON metric_points.metric_id = metrics.id WHERE metric_points.metric_id = {$this->id} AND to_char(metric_points.created_at, 'YYYYMMDDHH24') = :timestamp GROUP BY to_char(metric_points.created_at, 'H')", [ - 'timestamp' => $hourInterval, - ]); - - if (isset($query[0])) { - $value = $query[0]->aggregate; - } else { - $value = 0; - } - } - - if ($value === 0 && $this->default_value != $value) { - return $this->default_value; - } - - return round($value, $this->places); - } - /** * Determines whether a chart should be shown. * diff --git a/app/Repositories/MetricRepository.php b/app/Repositories/MetricRepository.php new file mode 100644 index 00000000..a6d2caf2 --- /dev/null +++ b/app/Repositories/MetricRepository.php @@ -0,0 +1,207 @@ +dateTimeZone = SettingFacade::get('app_timezone'); + } + + /** + * Returns all points as an array, by x hours. + * + * @param \CachetHQ\Cachet\Models\Metric $metric + * @param int $hours + * + * @return array + */ + public function listPointsToday(Metric $metric, $hours = 12) + { + $dateTime = (new Date())->setTimezone($this->dateTimeZone); + $points = []; + + $pointKey = $dateTime->format('H:00'); + for ($i = 0; $i <= $hours; $i++) { + $points[$pointKey] = $this->getPointsByHour($metric, $i + 1); + $pointKey = $dateTime->sub(new DateInterval('PT1H'))->format('H:00'); + } + + return array_reverse($points); + } + + /** + * Returns all points as an array, in the last week. + * + * @param \CachetHQ\Cachet\Models\Metric $metric + * + * @return array + */ + public function listPointsForWeek(Metric $metric) + { + $dateTime = (new Date())->setTimezone($this->dateTimeZone); + $points = []; + + $pointKey = $dateTime->format('jS M'); + for ($i = 0; $i <= 7; $i++) { + $points[$pointKey] = $this->getPointsForDayInWeek($metric, $i); + $pointKey = $dateTime->sub(new DateInterval('P1D'))->format('D jS M'); + } + + return array_reverse($points); + } + + /** + * Returns all points as an array, in the last month. + * + * @param \CachetHQ\Cachet\Models\Metric $metric + * + * @return array + */ + public function listPointsForMonth(Metric $metric) + { + $dateTime = (new Date())->setTimezone($this->dateTimeZone); + $daysInMonth = $dateTime->format('t'); + $points = []; + + $pointKey = $dateTime->format('jS M'); + for ($i = 0; $i <= $daysInMonth; $i++) { + $points[$pointKey] = $this->getPointsForDayInWeek($metric, $i); + $pointKey = $dateTime->sub(new DateInterval('P1D'))->format('jS M'); + } + + return array_reverse($points); + } + + /** + * Returns metrics for a given hour. + * + * @param \CachetHQ\Cachet\Models\Metric $metric + * @param int $hour + * + * @return int + */ + protected function getPointsByHour(Metric $metric, $hour) + { + $dateTime = (new Date())->setTimezone($this->dateTimeZone); + $dateTime->sub(new DateInterval('PT'.$hour.'H')); + $hourInterval = $dateTime->format('YmdH'); + + if (Config::get('database.default') === 'mysql') { + $points = $metric->points() + ->whereRaw('DATE_FORMAT(created_at, "%Y%m%d%H") = '.$hourInterval) + ->groupBy(DB::raw('HOUR(created_at)')); + + if (!isset($metric->calc_type) || $metric->calc_type == Metric::CALC_SUM) { + $value = $points->sum('value'); + } elseif ($metric->calc_type == Metric::CALC_AVG) { + $value = $points->avg('value'); + } + } else { + // Default metrics calculations. + if (!isset($metric->calc_type) || $metric->calc_type == Metric::CALC_SUM) { + $queryType = 'sum(metric_points.value)'; + } elseif ($metric->calc_type == Metric::CALC_AVG) { + $queryType = 'avg(metric_points.value)'; + } else { + $queryType = 'sum(metric_points.value)'; + } + + $query = DB::select("select {$queryType} as aggregate FROM metrics JOIN metric_points ON metric_points.metric_id = metrics.id WHERE metric_points.metric_id = {$metric->id} AND to_char(metric_points.created_at, 'YYYYMMDDHH24') = :timestamp GROUP BY to_char(metric_points.created_at, 'H')", [ + 'timestamp' => $hourInterval, + ]); + + if (isset($query[0])) { + $value = $query[0]->aggregate; + } else { + $value = 0; + } + } + + if ($value === 0 && $metric->default_value != $value) { + return $metric->default_value; + } + + return round($value, $metric->places); + } + + /** + * Returns metrics for the week. + * + * @param \CachetHQ\Cachet\Models\Metric $metric + * + * @return int + */ + protected function getPointsForDayInWeek(Metric $metric, $day) + { + $dateTime = (new Date())->setTimezone($this->dateTimeZone); + $dateTime->sub(new DateInterval('P'.$day.'D')); + + if (Config::get('database.default') === 'mysql') { + $points = $metric->points() + ->whereRaw('created_at BETWEEN DATE_SUB(created_at, INTERVAL 1 WEEK) AND NOW()') + ->whereRaw('DATE_FORMAT(created_at, "%Y%m%d") = '.$dateTime->format('Ymd')) + ->groupBy(DB::raw('DATE_FORMAT(created_at, "%Y%m%d")')); + + if (!isset($metric->calc_type) || $metric->calc_type == Metric::CALC_SUM) { + $value = $points->sum('value'); + } elseif ($metric->calc_type == Metric::CALC_AVG) { + $value = $points->avg('value'); + } + } else { + // Default metrics calculations. + if (!isset($metric->calc_type) || $metric->calc_type == Metric::CALC_SUM) { + $queryType = 'sum(metric_points.value)'; + } elseif ($metric->calc_type == Metric::CALC_AVG) { + $queryType = 'avg(metric_points.value)'; + } else { + $queryType = 'sum(metric_points.value)'; + } + + $query = DB::select("select {$queryType} as aggregate FROM metrics JOIN metric_points ON metric_points.metric_id = metrics.id WHERE metric_points.metric_id = {$metric->id} AND to_char(metric_points.created_at, 'YYYYMMDD') = :timestamp GROUP BY to_char(metric_points.created_at, 'YYYYMMDD')", [ + 'timestamp' => $hourInterval, + ]); + + if (isset($query[0])) { + $value = $query[0]->aggregate; + } else { + $value = 0; + } + } + + if ($value === 0 && $metric->default_value != $value) { + return $metric->default_value; + } + + return round($value, $metric->places); + } +} diff --git a/resources/lang/de/cachet.php b/resources/lang/de/cachet.php index 46e846f7..2826f08a 100755 --- a/resources/lang/de/cachet.php +++ b/resources/lang/de/cachet.php @@ -52,9 +52,9 @@ return [ // Metrics 'metrics' => [ 'filter' => [ - 'hourly' => 'Stündlich', - 'daily' => 'Täglich', - 'monthly' => 'Monatlich', + 'hourly' => 'Last 12 Hours', + 'weekly' => 'Week', + 'monthly' => 'Month', ], ], diff --git a/resources/lang/en/cachet.php b/resources/lang/en/cachet.php index 550de41c..946cf141 100755 --- a/resources/lang/en/cachet.php +++ b/resources/lang/en/cachet.php @@ -52,9 +52,9 @@ return [ // Metrics 'metrics' => [ 'filter' => [ - 'hourly' => 'Hourly', - 'daily' => 'Daily', - 'monthly' => 'Monthly', + 'hourly' => 'Last 12 Hours', + 'weekly' => 'Week', + 'monthly' => 'Month', ], ], diff --git a/resources/lang/es/cachet.php b/resources/lang/es/cachet.php index 1657a8c1..c5aa6635 100755 --- a/resources/lang/es/cachet.php +++ b/resources/lang/es/cachet.php @@ -50,9 +50,9 @@ return [ // Metrics 'metrics' => [ 'filter' => [ - 'hourly' => 'Hourly', - 'daily' => 'Daily', - 'monthly' => 'Monthly', + 'hourly' => 'Last 12 Hours', + 'weekly' => 'Week', + 'monthly' => 'Month', ], ], diff --git a/resources/lang/fr/cachet.php b/resources/lang/fr/cachet.php index 490a7877..7e36abd5 100755 --- a/resources/lang/fr/cachet.php +++ b/resources/lang/fr/cachet.php @@ -52,9 +52,9 @@ return [ // Metrics 'metrics' => [ 'filter' => [ - 'hourly' => 'Toutes les heures', - 'daily' => 'Tous les jours', - 'monthly' => 'Mensuel', + 'hourly' => 'Last 12 Hours', + 'weekly' => 'Week', + 'monthly' => 'Month', ], ], diff --git a/resources/lang/id/cachet.php b/resources/lang/id/cachet.php index cbe8640c..22a41bb3 100755 --- a/resources/lang/id/cachet.php +++ b/resources/lang/id/cachet.php @@ -52,9 +52,9 @@ return [ // Metrics 'metrics' => [ 'filter' => [ - 'hourly' => 'Per jam', - 'daily' => 'Harian', - 'monthly' => 'Bulanan', + 'hourly' => 'Last 12 Hours', + 'weekly' => 'Week', + 'monthly' => 'Month', ], ], diff --git a/resources/lang/ko/cachet.php b/resources/lang/ko/cachet.php index 8b8019f8..31fe8e20 100755 --- a/resources/lang/ko/cachet.php +++ b/resources/lang/ko/cachet.php @@ -52,9 +52,9 @@ return [ // Metrics 'metrics' => [ 'filter' => [ - 'hourly' => '시간별', - 'daily' => '일별', - 'monthly' => '월별', + 'hourly' => 'Last 12 Hours', + 'weekly' => 'Week', + 'monthly' => 'Month', ], ], diff --git a/resources/lang/nl/cachet.php b/resources/lang/nl/cachet.php index b3e5a9ab..189625b9 100755 --- a/resources/lang/nl/cachet.php +++ b/resources/lang/nl/cachet.php @@ -52,9 +52,9 @@ return [ // Metrics 'metrics' => [ 'filter' => [ - 'hourly' => 'Ieder uur', - 'daily' => 'Dagelijks', - 'monthly' => 'Maandelijks', + 'hourly' => 'Last 12 Hours', + 'weekly' => 'Week', + 'monthly' => 'Month', ], ], diff --git a/resources/lang/pl/cachet.php b/resources/lang/pl/cachet.php index ec7d9170..c31cebb0 100755 --- a/resources/lang/pl/cachet.php +++ b/resources/lang/pl/cachet.php @@ -52,9 +52,9 @@ return [ // Metrics 'metrics' => [ 'filter' => [ - 'hourly' => 'Godzinowo', - 'daily' => 'Dziennie', - 'monthly' => 'Miesięcznie', + 'hourly' => 'Last 12 Hours', + 'weekly' => 'Week', + 'monthly' => 'Month', ], ], diff --git a/resources/lang/pt-BR/cachet.php b/resources/lang/pt-BR/cachet.php index 3e9732e3..0da0379e 100755 --- a/resources/lang/pt-BR/cachet.php +++ b/resources/lang/pt-BR/cachet.php @@ -52,9 +52,9 @@ return [ // Metrics 'metrics' => [ 'filter' => [ - 'hourly' => '', - 'daily' => '', - 'monthly' => '', + 'hourly' => 'Last 12 Hours', + 'weekly' => 'Week', + 'monthly' => 'Month', ], ], diff --git a/resources/lang/ru/cachet.php b/resources/lang/ru/cachet.php index f794ef2e..6e1f2456 100644 --- a/resources/lang/ru/cachet.php +++ b/resources/lang/ru/cachet.php @@ -52,9 +52,9 @@ return [ // Metrics 'metrics' => [ 'filter' => [ - 'hourly' => 'Ежечасно', - 'daily' => 'Ежедневно', - 'monthly' => 'Ежемесячно', + 'hourly' => 'Last 12 Hours', + 'weekly' => 'Week', + 'monthly' => 'Month', ], ], diff --git a/resources/lang/zh-CN/cachet.php b/resources/lang/zh-CN/cachet.php index 04b2ad35..6365340e 100755 --- a/resources/lang/zh-CN/cachet.php +++ b/resources/lang/zh-CN/cachet.php @@ -52,9 +52,9 @@ return [ // Metrics 'metrics' => [ 'filter' => [ - 'hourly' => '每小时的', - 'daily' => '每日的', - 'monthly' => '每月的', + 'hourly' => 'Last 12 Hours', + 'weekly' => 'Week', + 'monthly' => 'Month', ], ], diff --git a/resources/views/partials/metrics.blade.php b/resources/views/partials/metrics.blade.php index f8411286..86879b48 100644 --- a/resources/views/partials/metrics.blade.php +++ b/resources/views/partials/metrics.blade.php @@ -1,14 +1,7 @@ @if($metrics->count() > 0) + + @endif