Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions classes/metric/manager.php
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ public static function get_frequency_labels(): array {
'newusers' => self::FREQ_DAY,
'onlineusers' => self::FREQ_5MIN,
'dailyusers' => self::FREQ_DAY,
'yearlyactiveusers' => self::FREQ_DAY,
];

/**
Expand All @@ -99,6 +100,7 @@ public static function get_metrics(bool $enabledonly = true): array {
'newusers' => new new_users_metric(),
'onlineusers' => new online_users_metric(),
'dailyusers' => new daily_users_metric(),
'yearlyactiveusers' => new yearly_active_users_metric(),
];

// Find metrics from plugins.
Expand Down
94 changes: 94 additions & 0 deletions classes/metric/yearly_active_users_metric.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
<?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/>.

namespace tool_cloudmetrics\metric;

/**
* Metric class for 12 months yearly active users.
*
* @package tool_cloudmetrics
* @author Dustin Huynh <dustinhuynh@catalyst-au.net>
* @copyright 2025, Catalyst IT
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class yearly_active_users_metric extends builtin_user_base {

/**
* The metric's name.
*
* @return string
*/
public function get_name(): string {
return 'yearlyactiveusers';
}

/**
* Unique colour to represent the metric
*
* @return string - The colour in RGB hex.
*/
public function get_colour(): string {
return '#FFA500'; // Orange.
}

/**
* Returns true if frequency cannot be changed.
*
* @return bool
*/
public function is_frequency_fixed(): bool {
return true;
}

/**
* The frequency of the metric's sampling.
*
* @return int
*/
public function get_frequency(): int {
// Fixed at one day.
return $this->get_frequency_default();
}

/**
* Set frequency of the metric's sampling.
*
* @param int $freq
*/
public function set_frequency(int $freq) {
// Do nothing.
}

/**
* Generates the metric items from the source data.
*
* Uses $starttime to $finishtime to draw from the source data.
*
* @param int $starttime
* @param int $finishtime
* @return metric_item
*/
public function generate_metric_item(int $starttime, int $finishtime): metric_item {
global $DB;
$lastyear = $finishtime - (60 * 60 * 24 * 365);
$users = $DB->count_records_select(
'user',
'confirmed = 1 AND (lastlogin > ? OR currentlogin > ?)',
[$lastyear, $lastyear]
);
return new metric_item($this->get_name(), $finishtime, $users, $this);
}
}
2 changes: 2 additions & 0 deletions lang/en/tool_cloudmetrics.php
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@
$string['newusers_desc'] = 'Users who have signed up recently.';
$string['dailyusers'] = 'Daily users';
$string['dailyusers_desc'] = 'Unique users over a day (fixed frequency).';
$string['yearlyactiveusers'] = 'Yearly active users';
$string['yearlyactiveusers_desc'] = 'Users that have been active within the past 365 days from today.';

// User selection labels.
$string['data_empty'] = 'Your database for this metric is empty.';
Expand Down
17 changes: 13 additions & 4 deletions tests/tool_cloudmetrics_collect_metrics_test.php
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,11 @@ class helper_collect_metrics_task extends collect_metrics_task {
/** @var mock_receiver Mock receiver */
private $mock;

/**
* @var object mock variable
*/
public $mock;

/**
* Constructer for helper_collect_metrics_task
*
Expand Down Expand Up @@ -112,7 +117,7 @@ protected function setUp(): void {
* @covers \tool_cloudmetrics\task\collect_metrics_task
* @throws Exception
*/
public function test_execute(string $timestr, array $meta, array $expected) {
public function test_execute(string $timestr, array $meta, array $expected): void {
$tz = \core_date::get_server_timezone_object();
$this->disable_metrics($expected);
foreach ($meta as $metric => $data) {
Expand Down Expand Up @@ -169,6 +174,7 @@ public static function execute_provider(): array {
'online_users_metric' => [manager::FREQ_5MIN, 'midnight +75 minutes'],
'active_users_metric' => [manager::FREQ_HOUR, 'midnight'],
'daily_users_metric' => [manager::FREQ_DAY, 'midnight'],
'yearly_active_users_metric' => [manager::FREQ_DAY, 'midnight'],
],
['activeusers', 'newusers'],
],
Expand All @@ -179,6 +185,7 @@ public static function execute_provider(): array {
'online_users_metric' => [manager::FREQ_DAY, '2020-03-01T00:00:00'],
'active_users_metric' => [manager::FREQ_MONTH, '2020-03-01T00:00:00'],
'daily_users_metric' => [manager::FREQ_DAY, '2020-03-01T00:00:00'],
'yearly_active_users_metric' => [manager::FREQ_DAY, '2020-03-01T00:00:00'],
],
[],
],
Expand All @@ -189,8 +196,9 @@ public static function execute_provider(): array {
'online_users_metric' => [manager::FREQ_DAY, '2020-02-01T00:00:00'],
'active_users_metric' => [manager::FREQ_MONTH, '2020-02-01T00:00:00'],
'daily_users_metric' => [manager::FREQ_DAY, '2020-02-01T00:00:00'],
'yearly_active_users_metric' => [manager::FREQ_DAY, '2020-02-01T00:00:00'],
],
['activeusers', 'dailyusers', 'newusers', 'onlineusers'],
['activeusers', 'dailyusers', 'newusers', 'onlineusers', 'yearlyactiveusers'],
],
[
'2020-02-02T00:02:00',
Expand All @@ -199,13 +207,14 @@ public static function execute_provider(): array {
'online_users_metric' => [manager::FREQ_DAY, '2020-02-01T00:00:00'],
'active_users_metric' => [manager::FREQ_MONTH, '2020-02-01T00:00:00'],
'daily_users_metric' => [manager::FREQ_DAY, '2020-02-01T00:00:00'],
'yearly_active_users_metric' => [manager::FREQ_DAY, '2020-02-01T00:00:00'],
],
['dailyusers', 'newusers', 'onlineusers'],
['dailyusers', 'newusers', 'onlineusers', 'yearlyactiveusers'],
],
[
'2020-02-02T00:03:00',
['new_users_metric' => [manager::FREQ_5MIN, null]],
['activeusers', 'dailyusers', 'newusers', 'onlineusers'],
['activeusers', 'dailyusers', 'newusers', 'onlineusers', 'yearlyactiveusers'],
],
];
}
Expand Down
73 changes: 68 additions & 5 deletions tests/tool_cloudmetrics_users_test.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
use tool_cloudmetrics\metric\new_users_metric;
use tool_cloudmetrics\metric\active_users_metric;
use tool_cloudmetrics\metric\online_users_metric;
use tool_cloudmetrics\metric\yearly_active_users_metric;

/**
* Unit tests to test the builtin user metric types.
Expand All @@ -29,7 +30,7 @@
* @copyright 2022, Catalyst IT
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class tool_cloudmetrics_users_test extends \advanced_testcase {
final class tool_cloudmetrics_users_test extends \advanced_testcase {

/**
* Set up before each test
Expand All @@ -38,6 +39,8 @@ protected function setUp(): void {
parent::setUp();
$this->resetAfterTest();
}
/** @var integer Seconds in a day. */
public const SECOND_IN_DAY = 86400;

/** @var array[] Sample user DB data to be used in tests. */
public const USER_DATA = [
Expand All @@ -53,6 +56,20 @@ protected function setUp(): void {
['username' => 'j', 'firstaccess' => 13000, 'lastaccess' => 12950, 'lastlogin' => 12500],
];

/** @var array[] Sample active user DB data to be used in tests. */
public const ACTIVE_USER_DATA = [
['username' => 'a', 'confirmed' => 1 , 'lastlogin' => self::SECOND_IN_DAY + 1000],
['username' => 'b', 'confirmed' => 1 , 'lastlogin' => (self::SECOND_IN_DAY * 2) + 1000],
['username' => 'c', 'confirmed' => 1 , 'lastlogin' => (self::SECOND_IN_DAY * 2) + 2000],
['username' => 'd', 'confirmed' => 1 , 'lastlogin' => (self::SECOND_IN_DAY * 2) + 3000],
['username' => 'e', 'confirmed' => 1 , 'lastlogin' => (self::SECOND_IN_DAY * 3) + 1000],
['username' => 'f', 'confirmed' => 1 , 'lastlogin' => (self::SECOND_IN_DAY * 3) + 2000],
['username' => 'g', 'confirmed' => 1 , 'lastlogin' => (self::SECOND_IN_DAY * 4) + 1000],
['username' => 'h', 'confirmed' => 1 , 'lastlogin' => (self::SECOND_IN_DAY * 4) + 2000],
['username' => 'i', 'confirmed' => 1 , 'lastlogin' => (self::SECOND_IN_DAY * 5) + 1000],
['username' => 'j', 'confirmed' => 1 , 'lastlogin' => (self::SECOND_IN_DAY * 5) + 2000],
];

/**
* Tests generate_metric_items() for the builtin user metrics.
*
Expand All @@ -62,7 +79,7 @@ protected function setUp(): void {
* @param array $expected List of metric items that expect to be generated.
* @throws \dml_exception
*/
public function test_generate_metrics(string $metricname, int $frequency, array $expected) {
public function test_generate_metrics(string $metricname, int $frequency, array $expected): void {
global $DB;

foreach (self::USER_DATA as $row) {
Expand All @@ -85,6 +102,33 @@ public function test_generate_metrics(string $metricname, int $frequency, array
$this->assertEquals($expected, $items);
}


/**
* Tests test_generate_yearly_active_users_metric() for the builtin user metrics.
*
* @dataProvider data_for_test_generate_yearly_active_users_metric
* @param string $metricname The name of the metric to be tested.
* @param array $expected List of metric items that expect to be generated.
* @throws \dml_exception
*/
public function test_generate_yearly_active_users_metric(string $metricname, array $expected): void {
global $DB;

foreach (self::ACTIVE_USER_DATA as $row) {
$DB->insert_record('user', (object) $row);
}
$time = self::SECOND_IN_DAY * 366;
$endtime = $time + (4 * lib::FREQ_TIMES[metric\manager::FREQ_DAY]);
$metrictypes = metric\manager::get_metrics(false);
$metric = $metrictypes[$metricname];
$this->assertEquals($metricname, $metric->get_name());
while ($time <= $endtime) {
$items[] = $metric->generate_metric_item(0, $time);
$time = lib::get_next_time($time, metric\manager::FREQ_DAY);
}
$this->assertEquals($expected, $items);

}
/**
* Data provider for test_generate_metrics.
*
Expand All @@ -101,24 +145,43 @@ public function data_for_test_generate_metrics(): array {
new metric_item('newusers', 12400, 0, $newusersmetric),
new metric_item('newusers', 12700, 3, $newusersmetric),
new metric_item('newusers', 13000, 2, $newusersmetric),
]
],
],
[ 'activeusers', metric\manager::FREQ_MIN, [
new metric_item('activeusers', 12760, 2, $activeusersmetric),
new metric_item('activeusers', 12820, 3, $activeusersmetric),
new metric_item('activeusers', 12880, 3, $activeusersmetric),
new metric_item('activeusers', 12940, 5, $activeusersmetric),
new metric_item('activeusers', 13000, 6, $activeusersmetric),
]
],
],
[ 'onlineusers', metric\manager::FREQ_15MIN, [
new metric_item('onlineusers', 9400, 0, $onlineusersmetric),
new metric_item('onlineusers', 10300, 1, $onlineusersmetric),
new metric_item('onlineusers', 11200, 1, $onlineusersmetric),
new metric_item('onlineusers', 12100, 0, $onlineusersmetric),
new metric_item('onlineusers', 13000, 2, $onlineusersmetric),
]
],
],
];
}

/**
* Data provider for test_generate_yearly_active_users_metric.
*
* @return array[]
*/
public function data_for_test_generate_yearly_active_users_metric(): array {
$yearlyactiveusers = new yearly_active_users_metric();

return [
['yearlyactiveusers', [
new metric_item('yearlyactiveusers', self::SECOND_IN_DAY * 366 , 10, $yearlyactiveusers),
new metric_item('yearlyactiveusers', self::SECOND_IN_DAY * 367, 9, $yearlyactiveusers),
new metric_item('yearlyactiveusers', self::SECOND_IN_DAY * 368, 6, $yearlyactiveusers),
new metric_item('yearlyactiveusers', self::SECOND_IN_DAY * 369, 4, $yearlyactiveusers),
new metric_item('yearlyactiveusers', self::SECOND_IN_DAY * 370, 2, $yearlyactiveusers)],
],
];
}
}
Loading