diff --git a/classes/lib.php b/classes/lib.php index a46d73d..fb48b19 100644 --- a/classes/lib.php +++ b/classes/lib.php @@ -100,5 +100,33 @@ public static function record_cache_checked(int $valueincache, int $valueindb, s error_log("Heartbeat cache was checked: " . json_encode($details)); // @codingStandardsIgnoreEnd } + + /** + * Handles error logging pinging. This happens on a regular schedule e.g. every 30 mins. + * This is used in conjunction with external monitoring services to monitor if the error log is fresh + * (or alternatively if it is stale, because the logs are not coming through anymore). + */ + public static function process_error_log_ping() { + $lastpinged = get_config('tool_heartbeat', 'errorloglastpinged') ?: 0; + $errorperiod = get_config('tool_heartbeat', 'errorlog'); + + // If zero/null - disabled - don't do anything. + if (empty($errorperiod)) { + return; + } + + if (($lastpinged + $errorperiod) < time()) { + // Update the last pinged time. + set_config('errorloglastpinged', time(), 'tool_heartbeat'); + + // Log to error_log. + $now = userdate(time()); + $period = format_time($errorperiod); + + // @codingStandardsIgnoreStart + error_log("Heartbeat error log test $now, next test expected in $period"); + // @codingStandardsIgnoreEnd + } + } } diff --git a/croncheck.php b/croncheck.php index 43b1838..394d824 100644 --- a/croncheck.php +++ b/croncheck.php @@ -57,6 +57,8 @@ } use tool_heartbeat\checker; +use tool_heartbeat\lib; + global $PAGE; if (isset($CFG->mnet_dispatcher_mode) and $CFG->mnet_dispatcher_mode !== 'off') { @@ -68,6 +70,8 @@ // The checker class collects this, and if anything it output it shows a warning. ob_start(); +lib::process_error_log_ping(); + $messages = checker::get_check_messages(); // Construct the output message. diff --git a/tests/lib_test.php b/tests/lib_test.php index fdd487a..9858aa3 100644 --- a/tests/lib_test.php +++ b/tests/lib_test.php @@ -47,4 +47,63 @@ public function test_get_allowed_ips() { set_config('allowedips_forced', '', 'tool_heartbeat'); $this->assertEquals('', lib::get_allowed_ips()); } + + /** + * Provides values to test error log ping. + * @return array + */ + public function process_error_log_ping_provider(): array { + return [ + 'no period set - disabled' => [ + 'errorloglastpinged' => null, + 'errorlog' => null, + 'expectedtimebefore' => null, + ], + 'only period set' => [ + 'errorloglastpinged' => null, + 'errorlog' => 1 * MINSECS, + // Update to latest time. + 'expectedtimebefore' => time() + 10, + ], + 'period has passed, time should change' => [ + 'errorloglastpinged' => 1, + 'errorlog' => 1 * MINSECS, + // Update to latest time. + 'expectedtimebefore' => time() + 10, + ], + 'period not passed yet, time unchanged' => [ + 'errorloglastpinged' => time(), + 'errorlog' => 1 * MINSECS, + // Remain unchanged, i.e. exactly equal. + 'expectedtimebefore' => time(), + ], + ]; + } + + /** + * Tests process_error_log_ping function + * + * @param int|null $errorloglastpinged next error value to set + * @param int|null $errorlog error log value to set + * @param bool $expectrun + * @dataProvider process_error_log_ping_provider + */ + public function test_process_error_log_ping(?int $errorloglastpinged, ?int $errorlog, ?int $expectedtimebefore) { + $this->resetAfterTest(true); + set_config('errorloglastpinged', $errorloglastpinged, 'tool_heartbeat'); + set_config('errorlog', $errorlog, 'tool_heartbeat'); + lib::process_error_log_ping(); + + $valueafter = get_config('tool_heartbeat', 'errorloglastpinged'); + + // Assert the time was not set at all. + if (is_null($expectedtimebefore)) { + $this->assertFalse($valueafter); + } else { + // New value should have set current time as the last pinged time. + // We use less than and add some buffer in the test cases to account + // for tests that might happen over a few seconds. + $this->assertLessThanOrEqual($expectedtimebefore, $valueafter); + } + } } diff --git a/version.php b/version.php index 1a5ae2c..4ae0b96 100644 --- a/version.php +++ b/version.php @@ -24,8 +24,8 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2024080200; -$plugin->release = 2024080200; // Match release exactly to version. +$plugin->version = 2024111400; +$plugin->release = 2024111400; // Match release exactly to version. $plugin->requires = 2020061500; // Support for 3.9 and above, due to the Check API. $plugin->supported = [39, 404]; $plugin->component = 'tool_heartbeat';