diff --git a/classes/metric/yearly_active_users_metric.php b/classes/metric/yearly_active_users_metric.php index 4a53735..7bd3a5d 100644 --- a/classes/metric/yearly_active_users_metric.php +++ b/classes/metric/yearly_active_users_metric.php @@ -16,6 +16,9 @@ namespace tool_cloudmetrics\metric; +use progress_bar; +use tool_cloudmetrics\lib; + /** * Metric class for 12 months yearly active users. * @@ -26,6 +29,19 @@ */ class yearly_active_users_metric extends builtin_user_base { + + /** @var int The interval config for which data is displayed in seconds (eg: 5 minutes = 300). */ + public $interval; + + /** @var int The minimal timestamp representing earliest date retrieved in DB. */ + public $mintimestamp; + + /** @var int The maximal timestamp representing latest date retrieved in DB. */ + public $maxtimestamp; + + /** @var bool True if config used is same as one requested. */ + public $sameconfig; + /** * The metric's name. * @@ -72,6 +88,15 @@ public function set_frequency(int $freq) { // Do nothing. } + /** + * Metric's ability to be backfilled. + * + * @return bool + */ + public function is_backfillable(): bool { + return true; + } + /** * Generates the metric items from the source data. * @@ -91,4 +116,91 @@ public function generate_metric_item(int $starttime, int $finishtime): metric_it ); return new metric_item($this->get_name(), $finishtime, $users, $this); } + + /** + * Returns records for backfilled metric. + * + * @param int $backwardperiod Time from which sample is to be retrieved. + * @param int|null $finishtime If data is being completed argument is passed here. + * @param progress_bar|null $progress + * + * @return array + */ + public function generate_metric_items(int $backwardperiod, ?int $finishtime = null, ?progress_bar $progress = null): array { + global $DB; + $metricitems = []; + $finishtime = ($finishtime === -1) ? null : $finishtime; + $finishtime = $finishtime ?? time(); + $starttime = $finishtime - $backwardperiod; + // Back to last year from start time. + $lastyear = $starttime - YEARSECS; + // Get aggregation interval. + $frequency = $this->get_frequency(); + $interval = lib::FREQ_TIMES[$frequency]; + if ($finishtime < $starttime) { + return []; + } + $sql = 'SELECT floor(timecreated / :interval ) * :intervaldup AS timestamp, + userid + FROM {logstore_standard_log} + WHERE timecreated >= :lastyear + AND timecreated <= :finishtime + GROUP BY timestamp, userid + ORDER BY timestamp DESC'; + $results = $DB->get_recordset_sql( + $sql, + ['interval' => $interval, 'intervaldup' => $interval, 'lastyear' => $lastyear, 'finishtime' => $finishtime] + ); + $buffer = []; + + foreach ($results as $record) { + $buffer[] = $record; + } + $results->close(); + + // Variables for updating progress. + $count = 0; + $total = ($finishtime - $starttime) / $interval; + // Build a metric for each day from starttime to finishtime. + while ($starttime <= $finishtime) { + $distinctusers = []; + $lastyear = $starttime - YEARSECS; + foreach ($buffer as $r) { + // Count active users in a 12 months period. + if ($r->timestamp >= $lastyear && + $r->timestamp <= $starttime && + !array_key_exists($r->userid, $distinctusers)) { + $distinctusers[$r->userid] = true; + } + } + $metricitems[] = new metric_item($this->get_name(), $starttime, count($distinctusers), $this); + $starttime = $starttime + $interval; + $count++; + if ($progress) { + $progress->update( + $count, + $total, + get_string('backfillgenerating', 'tool_cloudmetrics', $this->get_label()) + ); + } + } + $this->mintimestamp = !empty($metricitems) ? $metricitems[0]->time : null; + $this->maxtimestamp = !empty($metricitems) ? end($metricitems)->time : null; + $this->interval = $frequency; + return $metricitems; + } + + /** + * Stores what data has been sent to collector. + * + */ + public function set_data_sent_config(): void { + // Store what data has been sent min, max timestamp range and interval. + $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); + } + } }