diff --git a/classes/admin_setting_manage_metrics.php b/classes/admin_setting_manage_metrics.php index 85fb39e..57d52c1 100644 --- a/classes/admin_setting_manage_metrics.php +++ b/classes/admin_setting_manage_metrics.php @@ -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 { diff --git a/classes/collector/base.php b/classes/collector/base.php index 3c70506..89b7c3f 100644 --- a/classes/collector/base.php +++ b/classes/collector/base.php @@ -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; } } diff --git a/classes/metric/base.php b/classes/metric/base.php index 0b13688..eda02fc 100644 --- a/classes/metric/base.php +++ b/classes/metric/base.php @@ -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'); } @@ -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; } diff --git a/classes/metric/online_users_metric.php b/classes/metric/online_users_metric.php index 9cfb9cd..6e104ec 100644 --- a/classes/metric/online_users_metric.php +++ b/classes/metric/online_users_metric.php @@ -55,7 +55,7 @@ public function get_name(): string { * * @return bool */ - public function supports_backfillable_metrics(): bool { + public function is_backfillable(): bool { return true; } @@ -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 { @@ -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); } diff --git a/classes/output/renderer.php b/classes/output/renderer.php index 1df4b5e..7fcdd6b 100644 --- a/classes/output/renderer.php +++ b/classes/output/renderer.php @@ -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); + } } diff --git a/collector/database/backfill.php b/collector/database/backfill.php new file mode 100644 index 0000000..de6795d --- /dev/null +++ b/collector/database/backfill.php @@ -0,0 +1,111 @@ +. + +/** + * Menu displaying available retrievable metric data and form. + * + * @package cltr_database + * @author Ghaly Marc-Alexandre + * @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(); diff --git a/collector/database/chart.php b/collector/database/chart.php index 7d784b3..5079859 100644 --- a/collector/database/chart.php +++ b/collector/database/chart.php @@ -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) { @@ -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(); @@ -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 = [ @@ -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; @@ -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'); diff --git a/collector/database/classes/collector.php b/collector/database/classes/collector.php index 74b1639..11f9a99 100644 --- a/collector/database/classes/collector.php +++ b/collector/database/classes/collector.php @@ -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; } } diff --git a/collector/database/classes/form/metric_backfill_form.php b/collector/database/classes/form/metric_backfill_form.php index 08649f5..f00bbfa 100644 --- a/collector/database/classes/form/metric_backfill_form.php +++ b/collector/database/classes/form/metric_backfill_form.php @@ -36,6 +36,7 @@ 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) { @@ -43,7 +44,7 @@ public function definition() { } } $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'); } diff --git a/collector/database/lang/en/cltr_database.php b/collector/database/lang/en/cltr_database.php index 2dbda92..24fa50f 100644 --- a/collector/database/lang/en/cltr_database.php +++ b/collector/database/lang/en/cltr_database.php @@ -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.'; @@ -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.'; diff --git a/collector/database/settings.php b/collector/database/settings.php index 4506b12..bdf1436 100644 --- a/collector/database/settings.php +++ b/collector/database/settings.php @@ -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( diff --git a/collector/database/tests/cltr_database_test.php b/collector/database/tests/cltr_database_test.php index f227f87..59a914a 100644 --- a/collector/database/tests/cltr_database_test.php +++ b/collector/database/tests/cltr_database_test.php @@ -136,8 +136,8 @@ public function test_backfillable_metric() { $activemetric = new active_users_metric(); $collector = new collector(); - $onlinebackfill = $onlinemetric->supports_backfillable_metrics(); - $activemetricbackfill = $activemetric->supports_backfillable_metrics(); + $onlinebackfill = $onlinemetric->is_backfillable(); + $activemetricbackfill = $activemetric->is_backfillable(); $rec = $DB->get_records(lib::TABLE); $this->assertEquals(0, count($rec)); diff --git a/lang/en/tool_cloudmetrics.php b/lang/en/tool_cloudmetrics.php index 22e6b89..4592e0a 100644 --- a/lang/en/tool_cloudmetrics.php +++ b/lang/en/tool_cloudmetrics.php @@ -103,6 +103,7 @@ $string['two_year'] = '2 years'; // Chart length only. // Error and status messages. +$string['backfill_not_supported'] = 'Metric \'{$a}\' does not support backfilling'; $string['metric_not_enabled'] = 'Metric \'{$a}\' not enabled'; $string['metric_not_found'] = 'Metric \'{$a}\' not found'; $string['collector_failed'] = 'Collector \'{$a->name}\' failed {$a->time}'; diff --git a/templates/backfill_page.mustache b/templates/backfill_page.mustache new file mode 100644 index 0000000..d8d2ddc --- /dev/null +++ b/templates/backfill_page.mustache @@ -0,0 +1,71 @@ + {{! + 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 . +}} +{{! + @template tool_cloudmetrics/backfill_page + + This template renders metrics backfill page. + + Context variables for this template: + * metriclabel String - Label for the metric. + * form String - Form for retrieving data. + * linktochart String - Url redirecting to chart display. + * emptydb String | Boolean - Whether metric has already been backfilled in db. + * dataindb String - Already retrieved data stored. + * isdifferentfreq Boolean - Whether frequency change since last data retrieval. + * dataperiod String - Available data to retrieve for logstore log standard table. + + Example context (json): + { + "metriclabel": "Online users", + "form": "
...
", + "linktochart": "http://moodle.com/admin/tool/cloudmetrics/collector/database/chart.php?metric=onlineusers", + "emptydb": false, + "dataindb": "Your database contains data from 2 Jun 2021, 20:00 to 9 Feb 2022, 19:00.", + "isdifferentfreq": false, + "dataperiod": "Current information shows data can be retrieved from 22 Oct 2020, 17:10 to 3 Jun 2022, 08:33." + } +}} +

+ {{metriclabel}} +

+
+ {{{form}}} +
+ + {{#str}} return_to_chart, tool_cloudmetrics, {{metriclabel}} {{/str}} + +
+
+

+ {{^emptydb}} + {{dataperiod}} + {{/emptydb}} + {{#emptydb}} + {{emptydb}} + {{/emptydb}} +

+

+ {{dataindb}} +
+
+ {{^isdifferentfreq}} + {{#str}} same_freq, tool_cloudmetrics {{/str}} + {{/isdifferentfreq}} + {{#isdifferentfreq}} + {{#str}} different_freq, tool_cloudmetrics {{/str}} + {{/isdifferentfreq}} +

diff --git a/templates/chart_page.mustache b/templates/chart_page.mustache index 96b1a14..343232d 100644 --- a/templates/chart_page.mustache +++ b/templates/chart_page.mustache @@ -20,83 +20,40 @@ This template renders chart for different metrics. Context variables for this template: - * isbackfilled Boolean Whether to display backfilled metric form or chart. - * metriclabel String - Label for the metric. - * metricdescription String - Description for the metric. - * selector String - Metric selector. - * periodselect String - Chart period selector. - * chart String - Chart display for metric data. - * backfillable Boolean - Whether or not selected metric supports data retrieval. - * backfillurl String - Url redirecting to backfill form. - * form String - Form for retrieving data. - * linktochart String - Url redirecting to chart display. - * emptydb String | Boolean - Whether metric has already been backfilled in db. - * dataperiod String - Available data to retrieve for logstore log standard table. - * dataindb String - Already retrieved data stored. - * isdifferentfreq Boolean - Whether frequency change since last data retrieval. + * metriclabel - Label for the metric. + * metricdescription - Description for the metric. + * selector - Metric selector. + * periodselect - Chart period selector. + * chart - Chart display for metric data. + * backfillable - Whether or not selected metric supports data retrieval. + * backfillurl - Url redirecting to backfill form. + * metriclabeltolower - Same as metriclabel but lower case. Example context (json): { - "isbackfilled": "false", "metriclabel": "Online users", "metricdescription": "Users that are currently online.", "selector": true, - "periodselect": "
...
", - "chart": "
", + "periodselect": "
...
", + "chart": "
", "backfillable": true, - "backfillurl": "http://moodle.com/admin/tool/cloudmetrics/collector/database/chart.php?metric=onlineusers&metric_backfill=1", - "form": "
...
", - "linktochart": "http://moodle.com/admin/tool/cloudmetrics/collector/database/chart.php?metric=onlineusers", - "emptydb": false, - "dataperiod": "Current information shows data can be retrieved from 22 Oct 2020, 17:10 to 3 Jun 2022, 08:33.", - "dataindb": "Your database contains data from 2 Jun 2021, 20:00 to 9 Feb 2022, 19:00.", - "isdifferentfreq": false + "backfillurl": "http://moodle.com/admin/tool/cloudmetrics/collector/database/backfill.php?metric=onlineusers", + "metriclabeltolower": "online users" } }} -{{^isbackfilled}} -

- {{metriclabel}} -

-

- {{metricdescription}} -

- {{{selector}}} -
- {{{periodselect}}} -
- {{{chart}}} - {{#backfillable}} - - {{#str}} return_to_backfill, tool_cloudmetrics, {{metriclabel}} {{/str}} - - {{/backfillable}} -{{/isbackfilled}} -{{#isbackfilled}} -
- {{{form}}} -
- - {{#str}} return_to_chart, tool_cloudmetrics, {{metriclabel}} {{/str}} - -
-
-

- {{^emptydb}} - {{dataperiod}} - {{/emptydb}} - {{#emptydb}} - {{emptydb}} - {{/emptydb}} -

-

- {{dataindb}} -
-
- {{^isdifferentfreq}} - {{#str}} same_freq, tool_cloudmetrics {{/str}} - {{/isdifferentfreq}} - {{#isdifferentfreq}} - {{#str}} different_freq, tool_cloudmetrics {{/str}} - {{/isdifferentfreq}} -

-{{/isbackfilled}} +

+ {{metriclabel}} +

+

+ {{metricdescription}} +

+{{{selector}}} +
+{{{periodselect}}} +
+{{{chart}}} +{{#backfillable}} + + {{#str}} return_to_backfill, tool_cloudmetrics, {{metriclabeltolower}} {{/str}} + +{{/backfillable}}