From 6c5af9138625741cb82a7a93143d5283d94ff3af Mon Sep 17 00:00:00 2001 From: Clemens Schwaighofer Date: Thu, 5 Jun 2025 15:32:39 +0900 Subject: [PATCH] Add new Logging option to turn on error_log write On default the level for error_log write is Emergency. This can be changed either on class creation or via set/get methods. If logging is skipped because the logging level does not match the main logging level the error_log write is also skipped. Added MARK fields in the Logging class --- .../Logging/CoreLibsLoggingLoggingTest.php | 67 ++++++++- www/admin/class_test.logging.php | 1 + www/lib/CoreLibs/Logging/Logging.php | 135 +++++++++++++++--- 3 files changed, 180 insertions(+), 23 deletions(-) diff --git a/4dev/tests/Logging/CoreLibsLoggingLoggingTest.php b/4dev/tests/Logging/CoreLibsLoggingLoggingTest.php index 3d2b3894..13b888fe 100644 --- a/4dev/tests/Logging/CoreLibsLoggingLoggingTest.php +++ b/4dev/tests/Logging/CoreLibsLoggingLoggingTest.php @@ -249,7 +249,7 @@ final class CoreLibsLoggingLoggingTest extends TestCase $this->assertFalse( $log->loggingLevelIsDebug() ); - // not set, should be debug] + // not set, should be debug $log = new \CoreLibs\Logging\Logging([ 'log_file_id' => 'testSetLoggingLevel', 'log_folder' => self::LOG_FOLDER, @@ -297,6 +297,71 @@ final class CoreLibsLoggingLoggingTest extends TestCase $log->setLoggingLevel('NotGood'); } + /** + * Undocumented function + * + * @covers ::setErrorLogWriteLevel + * @covers ::getErrorLogWriteLevel + * @testdox setErrorLogWriteLevel set/get checks + * + * @return void + */ + public function testSetErrorLogWriteLevel(): void + { + // valid that is not Debug + $log = new \CoreLibs\Logging\Logging([ + 'log_file_id' => 'testSetErrorLogWriteLevel', + 'log_folder' => self::LOG_FOLDER, + 'error_log_write_level' => Level::Error + ]); + $this->assertEquals( + Level::Error, + $log->getErrorLogWriteLevel() + ); + // not set on init + $log = new \CoreLibs\Logging\Logging([ + 'log_file_id' => 'testSetErrorLogWriteLevel', + 'log_folder' => self::LOG_FOLDER, + ]); + $this->assertEquals( + Level::Emergency, + $log->getErrorLogWriteLevel() + ); + // invalid, should be Emergency, will throw excpetion too + $this->expectException(\InvalidArgumentException::class); + $this->expectExceptionMessage( + 'Option: "error_log_write_level" is not of instance \CoreLibs\Logging\Logger\Level' + ); + $log = new \CoreLibs\Logging\Logging([ + 'log_file_id' => 'testSetLoggingLevel', + 'log_folder' => self::LOG_FOLDER, + 'error_log_write_level' => 'I' + ]); + $this->assertEquals( + Level::Emergency, + $log->getErrorLogWriteLevel() + ); + // set valid then change + $log = new \CoreLibs\Logging\Logging([ + 'log_file_id' => 'testSetErrorLogWriteLevel', + 'log_folder' => self::LOG_FOLDER, + 'error_log_write_level' => Level::Error + ]); + $this->assertEquals( + Level::Error, + $log->getErrorLogWriteLevel() + ); + $log->setErrorLogWriteLevel(Level::Notice); + $this->assertEquals( + Level::Notice, + $log->getErrorLogWriteLevel() + ); + // illegal logging level + $this->expectException(\Psr\Log\InvalidArgumentException::class); + $this->expectExceptionMessageMatches("/^Level \"NotGood\" is not defined, use one of: /"); + $log->setErrorLogWriteLevel('NotGood'); + } + // setLogFileId // getLogFileId diff --git a/www/admin/class_test.logging.php b/www/admin/class_test.logging.php index e1c71bfa..77a47426 100644 --- a/www/admin/class_test.logging.php +++ b/www/admin/class_test.logging.php @@ -82,6 +82,7 @@ $log->error('Cannot process data', ['error' => 'log']); $log->critical('Critical message', ['critical' => 'log']); $log->alert('Alert message', ['Alert' => 'log']); $log->emergency('Emergency message', ['Emergency' => 'log']); +error_log('TRIGGER ERROR LOG MANUAL: Emergency'); print "Log File: " . $log->getLogFile() . "
"; $log->setLogFlag(Flag::per_run); diff --git a/www/lib/CoreLibs/Logging/Logging.php b/www/lib/CoreLibs/Logging/Logging.php index 7476ef56..0f9c498b 100644 --- a/www/lib/CoreLibs/Logging/Logging.php +++ b/www/lib/CoreLibs/Logging/Logging.php @@ -35,6 +35,7 @@ class Logging /** @var string log file block separator, not changeable */ private const LOG_FILE_BLOCK_SEPARATOR = '.'; + // MARK: OPTION array // NOTE: the second party array{} hs some errors /** @var array>|array{string:array{type:string,type_info?:string,mandatory:true,alias?:string,default:string|bool|Level,deprecated:bool,use?:string}} */ private const OPTIONS = [ @@ -50,6 +51,7 @@ class Logging 'type' => 'string', 'mandatory' => false, 'default' => '', 'deprecated' => true, 'use' => 'log_file_id' ], + // log level 'log_level' => [ 'type' => 'instance', 'type_info' => '\CoreLibs\Logging\Logger\Level', @@ -57,6 +59,14 @@ class Logging 'default' => Level::Debug, 'deprecated' => false ], + // level to trigger write to error_log + 'error_log_write_level' => [ + 'type' => 'instance', + 'type_info' => '\CoreLibs\Logging\Logger\Level', + 'mandatory' => false, + 'default' => Level::Emergency, + 'deprecated' => false, + ], // options 'log_per_run' => [ 'type' => 'bool', 'mandatory' => false, @@ -92,8 +102,10 @@ class Logging /** @var array */ private array $options = []; - /** @var Level set level */ + /** @var Level set logging level */ private Level $log_level; + /** @var Level set level for writing to error_log, will not write if log level lower than error log write level */ + private Level $error_log_write_level; // page and host name /** @var string */ @@ -145,12 +157,13 @@ class Logging ]; /** - * Init logger + * MARK: Init logger * * options array layout * - log_folder: * - log_file_id / file_id (will be deprecated): * - log_level: + * - error_log_write_level: at what level we write to error_log * * - log_per_run: * - log_per_date: (was print_file_date) @@ -172,6 +185,8 @@ class Logging // set log level $this->initLogLevel(); + // set error log write level + $this->initErrorLogWriteLevel(); // set log folder from options $this->initLogFolder(); // set per run UID for logging @@ -190,8 +205,10 @@ class Logging // PRIVATE METHODS // ********************************************************************* + // MARK: options check + /** - * Undocumented function + * validate options * * @param array $options * @return bool @@ -263,6 +280,8 @@ class Logging return true; } + // MARK: init log elvels + /** * init log level, just a wrapper to auto set from options * @@ -280,6 +299,24 @@ class Logging $this->setLoggingLevel($this->options['log_level']); } + /** + * init error log write level + * + * @return void + */ + private function initErrorLogWriteLevel() + { + if ( + empty($this->options['error_log_write_level']) || + !$this->options['error_log_write_level'] instanceof Level + ) { + $this->options['error_log_write_level'] = Level::Emergency; + } + $this->setErrorLogWriteLevel($this->options['error_log_write_level']); + } + + // MARK: set log folder + /** * Set the log folder * If folder is not writeable the script will throw an E_USER_ERROR @@ -321,6 +358,8 @@ class Logging return $status; } + // MARK: set host name + /** * Set the hostname and port * If port is not defaul 80 it will be added to the host name @@ -337,6 +376,8 @@ class Logging } } + // MARK: set log file id (file) + /** * set log file prefix id * @@ -395,6 +436,8 @@ class Logging return $status; } + // MARK init log flags and levels + /** * set flags from options and option flags connection internal settings * @@ -423,6 +466,19 @@ class Logging return $this->log_level->includes($level); } + /** + * Checks that given level is matchins error_log write level + * + * @param Level $level + * @return bool + */ + private function checkErrorLogWriteLevel(Level $level): bool + { + return $this->error_log_write_level->includes($level); + } + + // MARK: build log ifle name + /** * Build the file name for writing * @@ -490,6 +546,8 @@ class Logging return $fn; } + // MARK: master write log to file + /** * writes error msg data to file for current level * @@ -507,6 +565,10 @@ class Logging if (!$this->checkLogLevel($level)) { return false; } + // if we match level then write to error_log + if ($this->checkErrorLogWriteLevel($level)) { + error_log((string)$message); + } // build logging file name // fn is log folder + file name @@ -531,6 +593,8 @@ class Logging return true; } + // MARK: master prepare log + /** * Prepare the log message with all needed info blocks: * [timestamp] [host name] [file path + file::row number] [running uid] {class::/->method} @@ -610,6 +674,7 @@ class Logging // PUBLIC STATIC METHJODS // ********************************************************************* + // MARK: set log level /** * set the log level * @@ -670,7 +735,7 @@ class Logging // **** GET/SETTER - // log level set and get + // MARK: log level /** * set new log level @@ -705,7 +770,30 @@ class Logging ); } - // log file id set (file name prefix) + // MARK: error log write level + + /** + * set the error_log write level + * + * @param string|int|Level $level + * @return void + */ + public function setErrorLogWriteLevel(string|int|Level $level): void + { + $this->error_log_write_level = $this->processLogLevel($level); + } + + /** + * get the current level for error_log write + * + * @return Level + */ + public function getErrorLogWriteLevel(): Level + { + return $this->error_log_write_level; + } + + // MARK: log file id set (file name prefix) /** * sets the internal log file prefix id @@ -733,7 +821,7 @@ class Logging return $this->log_file_id; } - // log unique id set (for per run) + // MARK: log unique id set (for per run) /** * Sets a unique id based on current date (y/m/d, h:i:s) and a unique id (8 chars) @@ -768,7 +856,7 @@ class Logging return $this->log_file_unique_id; } - // general log date + // MARK: general log date /** * set the log file date to Y-m-d @@ -791,7 +879,7 @@ class Logging return $this->log_file_date; } - // general flag set + // MARK: general flag set /** * set one of the basic flags @@ -846,7 +934,7 @@ class Logging return $this->log_flags; } - // log folder/file + // MARK: log folder/file /** * set new log folder, check that folder is writeable @@ -890,7 +978,7 @@ class Logging return $this->log_file_name; } - // max log file size + // MARK: max log file size /** * set mag log file size @@ -921,7 +1009,7 @@ class Logging } // ********************************************************************* - // OPTIONS CALLS + // MARK: OPTIONS CALLS // ********************************************************************* /** @@ -939,6 +1027,8 @@ class Logging // MAIN CALLS // ********************************************************************* + // MARK: main log call + /** * Commong log interface * @@ -976,7 +1066,7 @@ class Logging } /** - * DEBUG: 100 + * MARK: DEBUG: 100 * * write debug data to error_msg array * @@ -1008,7 +1098,7 @@ class Logging } /** - * INFO: 200 + * MARK: INFO: 200 * * @param string|Stringable $message * @param mixed[] $context @@ -1027,7 +1117,7 @@ class Logging } /** - * NOTICE: 250 + * MARK: NOTICE: 250 * * @param string|Stringable $message * @param mixed[] $context @@ -1046,7 +1136,7 @@ class Logging } /** - * WARNING: 300 + * MARK: WARNING: 300 * * @param string|Stringable $message * @param mixed[] $context @@ -1065,7 +1155,7 @@ class Logging } /** - * ERROR: 400 + * MARK: ERROR: 400 * * @param string|Stringable $message * @param mixed[] $context @@ -1084,7 +1174,7 @@ class Logging } /** - * CTRITICAL: 500 + * MARK: CTRITICAL: 500 * * @param string|Stringable $message * @param mixed[] $context @@ -1103,7 +1193,7 @@ class Logging } /** - * ALERT: 550 + * MARK: ALERT: 550 * * @param string|Stringable $message * @param mixed[] $context @@ -1122,7 +1212,7 @@ class Logging } /** - * EMERGENCY: 600 + * MARK: EMERGENCY: 600 * * @param string|Stringable $message * @param mixed[] $context @@ -1141,7 +1231,7 @@ class Logging } // ********************************************************************* - // DEPRECATED SUPPORT CALLS + // MARK: DEPRECATED SUPPORT CALLS // ********************************************************************* // legacy, but there are too many implemented @@ -1199,7 +1289,7 @@ class Logging } // ********************************************************************* - // DEPRECATED METHODS + // MARK: DEPRECATED METHODS // ********************************************************************* /** @@ -1365,7 +1455,7 @@ class Logging } // ********************************************************************* - // DEBUG METHODS + // MARK: DEBUG METHODS // ********************************************************************* /** @@ -1398,6 +1488,7 @@ class Logging } // back to options level $this->initLogLevel(); + $this->initErrorLogWriteLevel(); print "OPT set level: " . $this->getLoggingLevel()->getName() . "
"; } }