From 2e37f8f1ac13bf6d1a9a91fde02c43d783f96ddf Mon Sep 17 00:00:00 2001 From: Francis Devine Date: Mon, 21 Oct 2024 16:00:57 +1300 Subject: [PATCH] Add ability to allow list which tasks you want to fail check This requires turning on the allow list then configuring the list of allowed tasks as a list of classnames --- classes/check/failingtaskcheck.php | 34 ++++++++++++++++++++++++++---- lang/en/tool_heartbeat.php | 8 +++++++ settings.php | 25 ++++++++++++++++++++++ 3 files changed, 63 insertions(+), 4 deletions(-) diff --git a/classes/check/failingtaskcheck.php b/classes/check/failingtaskcheck.php index 97683ea..c84fed8 100644 --- a/classes/check/failingtaskcheck.php +++ b/classes/check/failingtaskcheck.php @@ -40,11 +40,19 @@ class failingtaskcheck extends check { /** @var \stdClass $task Record of task that is failing **/ private $task; + /** @var string[] $allowlist List of classnames we are allowed to check */ + private $allowlist = []; + + /** @var bool $allowlistchecking Should we validate if the task classname is in the passed in allow list configuration when checking if it failed */ + private $allowlistchecking = false; + /** * Constructor */ - public function __construct($task = null) { + public function __construct($task = null, $allowlistchecking = false, $allowlist = []) { $this->task = $task; + $this->allowlist = $allowlist; + $this->allowlistchecking = $allowlistchecking; } @@ -71,6 +79,11 @@ public function get_result() : result { return new result(result::OK, get_string('checkfailingtaskok', 'tool_heartbeat', $count), ''); } + // If allow list behaviour is enabled, check if the task is in the allowed list we can check and report on. + if ($this->allowlistchecking && (!in_array($this->task->classname, $this->allowlist))) { + return new result(result::OK, get_string('taskfailureignored', 'tool_heartbeat'), ''); + } + // Find the largest faildelay out of both adhoc and scheduled tasks. $maxdelaymins = !empty($this->task->faildelay) ? $this->task->faildelay / 60 : 0; @@ -117,22 +130,35 @@ public function get_ref(): string { return trim(str_replace('\\', '_', $this->task->classname), '_'); } + public static function parse_allowlist_config_setting() { + $list = get_config('tool_heartbeat', 'failedtasks_allowlist'); + $split = explode(PHP_EOL, $list); + $final = []; + foreach ($split as $classname) { + $final[] = trim($classname); + } + return $final; + } /** * Gets an array of all failing tasks, stored as \stdClass. * * @return array of failing tasks */ public static function get_failing_tasks(): array { - global $DB; + GLOBAL $DB; $tasks = []; + // Parse the allow list configuration to pass into each task. + $allowlist = self::parse_allowlist_config_setting(); + // Is allow list checking turned on all. + $allowlistenabled = get_config('tool_heartbeat', 'failedtasks_enableallowlist'); // Instead of using task API here, we read directly from the database. // This stops errors originating from broken tasks. $scheduledtasks = $DB->get_records_sql("SELECT * FROM {task_scheduled} WHERE faildelay > 0 AND disabled = 0"); foreach ($scheduledtasks as $task) { $task->message = "SCHEDULED TASK: {$task->classname} Delay: {$task->faildelay}\n"; - $tasks[] = new \tool_heartbeat\check\failingtaskcheck($task); + $tasks[] = new \tool_heartbeat\check\failingtaskcheck($task, $allowlistenabled, $allowlist); } // Instead of using task API here, we read directly from the database. @@ -147,7 +173,7 @@ public static function get_failing_tasks(): array { // Only add duplicate message if there are more than 1. $duplicatemsg = $record->count > 1 ? " ({$record->count} duplicates!!!)" : ''; $record->message = "ADHOC TASK: {$record->classname} Delay: {$record->faildelay} {$duplicatemsg}\n"; - $tasks[] = new \tool_heartbeat\check\failingtaskcheck($record); + $tasks[] = new \tool_heartbeat\check\failingtaskcheck($record, $allowlistenabled, $allowlist); } return $tasks; } diff --git a/lang/en/tool_heartbeat.php b/lang/en/tool_heartbeat.php index 509e052..e0e61c4 100644 --- a/lang/en/tool_heartbeat.php +++ b/lang/en/tool_heartbeat.php @@ -123,3 +123,11 @@ $string['privacy:metadata:tool_heartbeat_overrides:usermodified'] = 'User who modified the override'; $string['privacy:metadata:tool_heartbeat_overrides:timecreated'] = 'Timestamp when the override was created'; $string['privacy:metadata:tool_heartbeat_overrides:timemodified'] = 'Timestamp when the override was modified'; + + +$string['taskfailureignored'] = 'Task {$a} fail delay was ignored due to the task not being in the configured allow list'; +$string['settings:failedtaskcheckheadings'] = 'Failing tasks check configuration'; +$string['settings:failedtasks_enableallowlist:heading'] = 'Enable allow list for failed tasks'; +$string['settings:failedtasks_enableallowlist:desc'] = 'Enable the behaviour of only reporting on failed tasks that are in the following allow list configuration'; +$string["settings:failedtasks_allowlist:heading"] = 'Allow list for reporting'; +$string["settings:failedtasks_allowlist:desc"] = "A list of task classnames that can be reported as failing, each classname must appear on a new line"; \ No newline at end of file diff --git a/settings.php b/settings.php index 4567a27..e0c3f34 100644 --- a/settings.php +++ b/settings.php @@ -141,5 +141,30 @@ // So its defaulted to off unless turned on for specific debugging. 0 )); + + // Failed task settings + $settings->add(new admin_setting_heading('tool_heartbeat/failedtaskchecksettings', + get_string('settings:failedtaskcheckheadings', 'tool_heartbeat'), + '' + )); + // Enable allow list of failed tasks to report. + $settings->add( + new admin_setting_configcheckbox( + 'tool_heartbeat/failedtasks_enableallowlist', + get_string('settings:failedtasks_enableallowlist:heading', 'tool_heartbeat'), + get_string('settings:failedtasks_enableallowlist:desc', 'tool_heartbeat'), + 0 + ) + ); + + // List of allowed tasks + $settings->add( + new admin_setting_configtextarea( + 'tool_heartbeat/failedtasks_allowlist', + get_string('settings:failedtasks_allowlist:heading', 'tool_heartbeat'), + get_string('settings:failedtasks_allowlist:desc', 'tool_heartbeat'), + '' + ) + ); } }