Skip to content

Commit

Permalink
Backfill - Chart split - fixed 0 user gaps
Browse files Browse the repository at this point in the history
  • Loading branch information
marcghaly committed Jun 8, 2022
1 parent d897be9 commit 433f260
Show file tree
Hide file tree
Showing 15 changed files with 277 additions and 151 deletions.
4 changes: 2 additions & 2 deletions classes/admin_setting_manage_metrics.php
Original file line number Diff line number Diff line change
Expand Up @@ -133,9 +133,9 @@ public function output_html($data, $query='') {
$attributes
);

$backfillurl = new \moodle_url('/admin/tool/cloudmetrics/collector/database/chart.php', ['metric' => $metric->get_name(), 'metric_backfill' => 1]);
$backfillurl = new \moodle_url('/admin/tool/cloudmetrics/collector/database/backfill.php', ['metric' => $metric->get_name()]);
// Metric backfill support and if so - link.
if ($metric->supports_backfillable_metrics()) {
if ($metric->is_backfillable()) {
$class = '';
$backfilllink = \html_writer::link($backfillurl->out(false), $metric->get_label() . ' backfill');
} else {
Expand Down
2 changes: 1 addition & 1 deletion classes/collector/base.php
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ public function is_ready(): bool {
*
* @return bool
*/
public function supports_saved_metric_record(): bool {
public function supports_backfillable_metrics(): bool {
return false;
}
}
9 changes: 5 additions & 4 deletions classes/metric/base.php
Original file line number Diff line number Diff line change
Expand Up @@ -136,15 +136,16 @@ public function get_range_retrieved() {
if (count($config) !== 3) {
return [-1, -1, -1];
}
return [$config[0], $config[1], $config[2]];
return [(int)$config[0], (int)$config[1], (int)$config[2]];
}

/**
* Sets the range for which a backfilled metric has retrieved data.
*
* @param string $currentconfig Config containing min and max timestamps plus interval.
* @param array $currentconfig Config containing min and max timestamps plus interval.
*/
public function set_range_retrieved(string $currentconfig) {
public function set_range_retrieved(array $currentconfig) {
$currentconfig = implode('-', $currentconfig);
set_config($this->get_name() . '_range', $currentconfig, 'tool_cloudmetrics');
}

Expand Down Expand Up @@ -183,7 +184,7 @@ abstract public function generate_metric_item(int $starttime, int $finishtime):
*
* @return bool
*/
public function supports_backfillable_metrics(): bool {
public function is_backfillable(): bool {
return false;
}

Expand Down
11 changes: 6 additions & 5 deletions classes/metric/online_users_metric.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ public function get_name(): string {
*
* @return bool
*/
public function supports_backfillable_metrics(): bool {
public function is_backfillable(): bool {
return true;
}

Expand Down Expand Up @@ -110,9 +110,9 @@ public function generate_metric_items($backwardperiod, $finishtime = null): arra
$metricitems = [];
$count = 0;
foreach ($rs as $r) {
if ($count !== 0 && $metricitems[$count-1]->time + $interval !== (int)$r->time) {
if ($count !== 0 && $metricitems[$count - 1]->time + $interval !== (int)$r->time) {
// Code to add times where no user have been concurrently active.
for ($i = $metricitems[$count-1]->time + $interval; $i <= $r->time; $i+=$interval) {
for ($i = $metricitems[$count - 1]->time + $interval; $i <= $r->time; $i += $interval) {
if ($i === (int)$r->time) {
$metricitems[] = new metric_item($this->get_name(), $r->time, $r->value, $this);
} else {
Expand Down Expand Up @@ -141,8 +141,9 @@ public function generate_metric_items($backwardperiod, $finishtime = null): arra
*/
public function set_data_sent_config() {
// Store what data has been sent min, max timestamp range and interval.
$currentconfig = $this->mintimestamp . '-' . $this->maxtimestamp . '-' . $this->interval;
$this->sameconfig = (implode('-', $this->get_range_retrieved()) === $currentconfig);
$currentconfig = [$this->mintimestamp, $this->maxtimestamp, $this->interval];
$rangeretrieved = $this->get_range_retrieved();
$this->sameconfig = ($rangeretrieved === $currentconfig);
if (!$this->sameconfig && isset($this->mintimestamp) && isset($this->maxtimestamp) && isset($this->interval)) {
$this->set_range_retrieved($currentconfig);
}
Expand Down
9 changes: 9 additions & 0 deletions classes/output/renderer.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,13 @@ class renderer extends \plugin_renderer_base {
public function render_chart_page($data) {
return $this->render_from_template('tool_cloudmetrics/chart_page', $data);
}

/**
* Render the backfill page.
*
* @param array $data
*/
public function render_backfill_page($data) {
return $this->render_from_template('tool_cloudmetrics/backfill_page', $data);
}
}
111 changes: 111 additions & 0 deletions collector/database/backfill.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.

/**
* Menu displaying available retrievable metric data and form.
*
* @package cltr_database
* @author Ghaly Marc-Alexandre <[email protected]>
* @copyright 2022, Catalyst IT
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/

require_once(__DIR__.'/../../../../../config.php');
require_once($CFG->libdir . '/adminlib.php');

use tool_cloudmetrics\metric\manager;
use cltr_database\collector;
use cltr_database\form\metric_backfill_form;

admin_externalpage_setup('cltr_database_backfill');

$ctx = context_system::instance();

$url = new moodle_url('/admin/tool/cloudmetrics/collector/database/backfill.php');

$PAGE->set_context($ctx);
$PAGE->set_url($url);

$metricname = optional_param('metric', 'onlineusers', PARAM_ALPHANUMEXT);
$tochart = new moodle_url('/admin/tool/cloudmetrics/collector/database/chart.php', ['metric' => $metricname]);

$metrics = manager::get_metrics(true);
$collector = new collector();

// Error management if metric is not enabled.
if (!isset($metrics[$metricname])) {
throw new moodle_exception('metric_not_enabled', 'tool_cloudmetrics', '', $metricname);
}
if (!$metrics[$metricname]->is_backfillable()) {
throw new moodle_exception('backfill_not_supported', 'tool_cloudmetrics', '', $metricname);
}
if (!$collector->supports_backfillable_metrics()) {
throw new moodle_exception('collector_not_supported', 'cltr_database', '', get_class($collector));
}

$periods = [
HOURSECS => get_string('one_hour', 'tool_cloudmetrics'),
DAYSECS => get_string('one_day', 'tool_cloudmetrics'),
WEEKSECS => get_string('one_week', 'tool_cloudmetrics'),
WEEKSECS * 2 => get_string('two_week', 'tool_cloudmetrics'),
DAYSECS * 30 => get_string('one_month', 'tool_cloudmetrics'),
DAYSECS * 61 => get_string('two_month', 'tool_cloudmetrics'),
DAYSECS * 122 => get_string('four_month', 'tool_cloudmetrics'),
DAYSECS * 183 => get_string('six_month', 'tool_cloudmetrics'),
YEARSECS => get_string('twelve_month', 'tool_cloudmetrics'),
YEARSECS * 2 => get_string('two_year', 'tool_cloudmetrics'),
];

// Gets already saved data range and interval.
[$mintmptmp, $maxtmpstmp, $freqretrieved] = $metrics[$metricname]->get_range_retrieved();
if ($mintmptmp != -1) {
$backfilledfrom = userdate($mintmptmp, get_string('strftimedatetime', 'cltr_database'), $CFG->timezone);
$backfilledto = userdate($maxtmpstmp, get_string('strftimedatetime', 'cltr_database'), $CFG->timezone);
$backfilledinterval = (int)$freqretrieved;
if ($backfilledinterval !== $metrics[$metricname]->get_frequency()) {
$isdifferentfreq = true;
} else {
$isdifferentfreq = false;
}
$context['dataindb'] = get_string('data_in_db', 'tool_cloudmetrics',
['dbstart' => $backfilledfrom, 'dbend' => $backfilledto]);
} else {
$emptydb = get_string('data_empty', 'tool_cloudmetrics');
}
// Gets available data to backfill.
$daterange = $metrics[$metricname]->get_range_log_available();
$startdate = userdate($daterange->min, get_string('strftimedatetime', 'cltr_database'), $CFG->timezone);
$enddate = userdate($daterange->max, get_string('strftimedatetime', 'cltr_database'), $CFG->timezone);
$mform = new metric_backfill_form(null, [$daterange, $periods, $metricname]);
$context['form'] = $mform->render();
if ($fromform = $mform->get_data()) {
$periodretrieval = $fromform->periodretrieval;
$metricitems = $metrics[$metricname]->generate_metric_items($periodretrieval, $mintmptmp);
$collector->record_saved_metrics($metrics[$metricname], $metricitems);
}

$context['dataperiod'] = get_string('data_period', 'tool_cloudmetrics',
['startdate' => $startdate ?? 0, 'enddate' => $enddate ?? 0]);
$context['emptydb'] = $emptydb ?? false;
$context['linktochart'] = $tochart;
$context['metriclabel'] = $metrics[$metricname]->get_label();
$context['isdifferentfreq'] = $isdifferentfreq ?? null;

$renderer = $PAGE->get_renderer('tool_cloudmetrics');

echo $OUTPUT->header();
echo $renderer->render_backfill_page($context);
echo $OUTPUT->footer();
88 changes: 24 additions & 64 deletions collector/database/chart.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@
$PAGE->set_url($url);

$metricname = optional_param('metric', 'activeusers', PARAM_ALPHANUMEXT);
$metricbackfill = optional_param('metric_backfill', 0, PARAM_INT);

$defaultperiod = optional_param('graphperiod', -1, PARAM_INT);
if ($defaultperiod === -1) {
Expand All @@ -57,6 +56,10 @@
}

$metrics = metric\manager::get_metrics(true);
// Error management if metric is not enabled.
if (!isset($metrics[$metricname])) {
throw new moodle_exception('metric_not_enabled', 'tool_cloudmetrics', '', $metricname);
}
$metriclabels = [];
foreach ($metrics as $m) {
$metriclabels[$m->get_name()] = $m->get_label();
Expand All @@ -73,10 +76,6 @@
);
$select->set_label(get_string('select_metric_for_display', 'cltr_database'));
$context = [];
// Error management if metric is not enabled.
if (!isset($metrics[$metricname])) {
throw new moodle_exception('metric_not_enabled', 'tool_cloudmetrics', '', $metricname);
}

// Prepare time window selector.
$periods = [
Expand All @@ -92,39 +91,7 @@
YEARSECS * 2 => get_string('two_year', 'tool_cloudmetrics'),
];

$backfilledmetric = $metrics[$metricname]->supports_backfillable_metrics();
$collector = new \cltr_database\collector();
if ($backfilledmetric) {
// Gets already saved data range and interval.
[$mintmptmp, $maxtmpstmp, $freqretrieved] = $metrics[$metricname]->get_range_retrieved();
if ($mintmptmp) {
$backfilledfrom = userdate($mintmptmp, get_string('strftimedatetime', 'cltr_database'), $CFG->timezone);
$backfilledto = userdate($maxtmpstmp, get_string('strftimedatetime', 'cltr_database'), $CFG->timezone);
$backfilledinterval = (int)$freqretrieved;
if ($backfilledinterval !== $metrics[$metricname]->get_frequency()) {
$isdifferentfreq = true;
} else {
$isdifferentfreq = false;
}
$context['dataindb'] = get_string('data_in_db', 'tool_cloudmetrics',
['dbstart' => $backfilledfrom, 'dbend' => $backfilledto]);
} else {
$emptydb = get_string('data_empty', 'tool_cloudmetrics');
}
// Gets available data to backfill.
$daterange = $metrics[$metricname]->get_range_log_available();
$startdate = userdate($daterange->min, get_string('strftimedatetime', 'cltr_database'), $CFG->timezone);
$enddate = userdate($daterange->max, get_string('strftimedatetime', 'cltr_database'), $CFG->timezone);
$mform = new metric_backfill_form(null, [$daterange, $periods]);
$context['form'] = $mform->render();
if ($fromform = $mform->get_data()) {
$periodretrieval = $fromform->periodretrieval;
$metricitems = $metrics[$metricname]->generate_metric_items($periodretrieval, $mintmptmp);
if ($collector->supports_saved_metric_record()) {
$collector->record_saved_metrics($metrics[$metricname], $metricitems);
}
}
}

// Create a new URL object to avoid poisoning the existing one.
$url = clone $url;
Expand All @@ -135,40 +102,33 @@
$periods,
$defaultperiod
);
$backfillurl = clone $url;
$backfillurl->param('metric_backfill', 1);

$periodselect->set_label(get_string('select_graph_period', 'cltr_database'));
$backfillurl = new moodle_url('/admin/tool/cloudmetrics/collector/database/backfill.php', ['metric' => $metricname]);

if ($metricbackfill != 1) {
$records = $collector->get_metrics($metricname, $defaultperiod);
$values = [];
$labels = [];
$periodselect->set_label(get_string('select_graph_period', 'cltr_database'));

foreach ($records as $record) {
$values[] = (float) $record->value;
$labels[] = userdate($record->time, get_string('strftimedatetime', 'cltr_database'), $CFG->timezone);
}
$records = $collector->get_metrics($metricname, $defaultperiod);
$values = [];
$labels = [];

$chartseries = new chart_series($metriclabels[$metricname], $values);
$chart = new chart_line();
$chart->add_series($chartseries);
$chart->set_labels($labels);
$context['chart'] = $OUTPUT->render($chart);
$context['selector'] = $OUTPUT->render($select);
$context['periodselect'] = $OUTPUT->render($periodselect);
foreach ($records as $record) {
$values[] = (float) $record->value;
$labels[] = userdate($record->time, get_string('strftimedatetime', 'cltr_database'), $CFG->timezone);
}

$context['dataperiod'] = get_string('data_period', 'tool_cloudmetrics',
['startdate' => $startdate ?? 0, 'enddate' => $enddate ?? 0]);
$context['emptydb'] = $emptydb ?? false;
$context['linktochart'] = $url;
$context['metriclabel'] = $metric->get_label();
$context['metricdescription'] = $metric->get_description();
$context['isbackfilled'] = ($metricbackfill == 1 && $backfilledmetric && is_siteadmin()) ? true : false;
$chartseries = new chart_series($metriclabels[$metricname], $values);
$chart = new chart_line();
$chart->add_series($chartseries);
$chart->set_labels($labels);

$context['chart'] = $OUTPUT->render($chart);
$context['selector'] = $OUTPUT->render($select);
$context['periodselect'] = $OUTPUT->render($periodselect);
$context['backfillurl'] = $backfillurl;
$context['isdifferentfreq'] = $isdifferentfreq ?? null;
$context['backfillable'] = $backfilledmetric;
$context['backfillable'] = $metrics[$metricname]->is_backfillable();
$context['metriclabel'] = $metric->get_label();
$context['metricdescription'] = $metrics[$metricname]->get_description();
$context['metriclabeltolower'] = strtolower($metric->get_label());

$renderer = $PAGE->get_renderer('tool_cloudmetrics');

Expand Down
2 changes: 1 addition & 1 deletion collector/database/classes/collector.php
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ public function record_saved_metrics(\tool_cloudmetrics\metric\base $metricclass
*
* @return bool
*/
public function supports_saved_metric_record(): bool {
public function supports_backfillable_metrics(): bool {
return true;
}
}
3 changes: 2 additions & 1 deletion collector/database/classes/form/metric_backfill_form.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,15 @@ public function definition() {
$maxbackwardsdate = $this->_customdata[0]->min;
$maxperiod = time() - $maxbackwardsdate;
$periods = $this->_customdata[1];
$metric = $this->_customdata[2];
// Prevent display of bigger periods selection than necessary.
foreach ($periods as $period => $value) {
if ($period > $maxperiod) {
unset($periods[$period]);
}
}
$mform->addElement('select', 'periodretrieval', get_string('period_select', 'tool_cloudmetrics'), $periods);
$mform->addElement('hidden', 'metric', 'onlineusers');
$mform->addElement('hidden', 'metric', $metric);
$mform->setType('metric', PARAM_ALPHANUMEXT);
$this->add_action_buttons(false, 'Backfill data');
}
Expand Down
4 changes: 4 additions & 0 deletions collector/database/lang/en/cltr_database.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@

// Chart display.
$string['metric_display'] = 'Cloudmetrics Charts';
$string['metric_backfill'] = 'Cloudmetrics Backfill';
$string['select_metric_for_display'] = 'Select metric for display.';
$string['select_graph_period'] = 'Select graph period.';

Expand All @@ -45,3 +46,6 @@

// Time format.
$string['strftimedatetime'] = '%d %h %Y, %H:%M';

// Error.
$string['collector_not_supported'] = 'Collector \'{$a}\' does not support backfilled data collection.';
10 changes: 10 additions & 0 deletions collector/database/settings.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,16 @@
)
);

$ADMIN->add(
'reports',
new admin_externalpage(
'cltr_database_backfill',
get_string('metric_backfill', 'cltr_database'),
new moodle_url('/admin/tool/cloudmetrics/collector/database/backfill.php'),
'moodle/site:config'
)
);

if ($ADMIN->fulltree) {
$settings->add(
new admin_setting_configduration(
Expand Down
Loading

0 comments on commit 433f260

Please sign in to comment.