Skip to content

Commit 3f2194f

Browse files
committed
PHP warnings handling
1 parent 6c18eaa commit 3f2194f

File tree

4 files changed

+75
-31
lines changed

4 files changed

+75
-31
lines changed

README.md

+2
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,8 @@ Methods for configure:
237237
PSR-3 channel.
238238
* ```$logUncaughtErrors``` (default ```false```) - registers shutdown function for log uncaught exceptions such as PHP
239239
fatal errors or incorrect task settings.
240+
* ```$logPhpWarningsToError``` (default ```false```) - If true, PHP non-fatal warnings will be sent to the error
241+
channel, otherwise to the debug channel.
240242
* ```$logMessageFormat``` (default ```null```) - formatting template for task logger. Pass ```null``` for set default
241243
formatting (```"[{{task_id}}. {{TASK_TYPE}} '{{task_name}}']: {{message}}"```). Available variables:
242244
* ```{{task_id}}```

src/Config.php

+25-8
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,11 @@ class Config
2828
* @var bool
2929
*/
3030
private $logUncaughtErrors;
31+
/**
32+
* If true, PHP warnings will be sent to the error channel, otherwise - to the debug channel
33+
* @var bool
34+
*/
35+
private $logPhpWarningsToError;
3136
/**
3237
* Log message formatting string.
3338
* Available variables: {{task_id}}, {{task_type}}, {{TASK_TYPE}}, {{task_name}}, {{TASK_NAME}},
@@ -104,20 +109,21 @@ class Config
104109
* @param ?LoggerInterface $logger PSR-3 is a compatible logger. If null - the log will be sent to the STDOUT/STDERR.
105110
* @param mixed $debugLog False/null - debug log disabled. True - enabled (STDOUT/DEBUG). Or set custom PSR-3 level.
106111
* @param mixed $errorLog False/null - error log disabled. True - enabled (STDERR/ERROR). Or set custom PSR-3 level.
107-
* @param bool $logUncaughtErrors Registers shutdown function for logging PHP runtime fatal errors
112+
* @param bool $logUncaughtErrors Registers shutdown function for logging PHP runtime fatal errors.
113+
* @param bool $logPhpWarningsToError If true, PHP warnings will be sent to the error channel, otherwise - to the debug channel.
108114
* @param ?string $logMessageFormat Log message formatting string. Available {{task_id}}, {{task_type}}, {{task_name}},
109115
* {{message}} and {{task_description}} variables. Lowercase for regular case, uppercase - for forced uppercase.
110-
* Pass null for default formatting: "[{{task_id}}. {{TASK_TYPE}} '{{task_name}}']: {{message}}"
116+
* Pass null for default formatting: "[{{task_id}}. {{TASK_TYPE}} '{{task_name}}']: {{message}}".
111117
* @param ?int $maxLogMsgLength The maximum length of the log message (the longer one will be truncated)
112118
* @param ?array $exceptionLogMatching Mapping specific exceptions to PSR-3 log channels (class => level).
113119
* @param ?string $logExceptionFormat Exception formatting string. Available {{header}}, {{code}}, {{class}},
114120
* {{message}} and {{stacktrace}} variables. Pass null for default formatting:
115-
* "{{header}}\n[code]: {{code}}\n[exception]: {{class}}\n[message]: {{message}}\n[stacktrace]:\n{{stacktrace}}"
116-
* @param ?int $maxExceptionMsgLength The maximum length of the exception message (the longer one will be truncated)
117-
* @param bool $defaultPreventOverlapping Determines if an overlapping task can be run launched
118-
* @param int $defaultLockResetTimeout Locking reset timeout in minutes (to prevent freezing tasks)
119-
* @param int $defaultTries The number of attempts to execute the task in case of an error
120-
* @param int $defaultTryDelay Delay before new try
121+
* "{{header}}\n[code]: {{code}}\n[exception]: {{class}}\n[message]: {{message}}\n[stacktrace]:\n{{stacktrace}}".
122+
* @param ?int $maxExceptionMsgLength The maximum length of the exception message (the longer one will be truncated).
123+
* @param bool $defaultPreventOverlapping Determines if an overlapping task can be run launched.
124+
* @param int $defaultLockResetTimeout Locking reset timeout in minutes (to prevent freezing tasks).
125+
* @param int $defaultTries The number of attempts to execute the task in case of an error.
126+
* @param int $defaultTryDelay Delay before new try.
121127
* @param int $minimumIntervalLength Minimum interval in minutes for task's addInterval method.
122128
* ATTENTION: a low value can cause to skipped tasks, change at your own risk.
123129
* @throws Exception
@@ -127,6 +133,7 @@ public function __construct(
127133
$debugLog = false,
128134
$errorLog = true,
129135
bool $logUncaughtErrors = false,
136+
bool $logPhpWarningsToError = false,
130137
?string $logMessageFormat = null,
131138
?int $maxLogMsgLength = null,
132139
?array $exceptionLogMatching = [],
@@ -144,6 +151,7 @@ public function __construct(
144151
$this->debugLog = $debugLog;
145152
$this->errorLog = $errorLog;
146153
$this->logUncaughtErrors = $logUncaughtErrors;
154+
$this->logPhpWarningsToError = $logPhpWarningsToError;
147155
$this->logMessageFormat = $logMessageFormat ?? "[{{task_id}}. {{TASK_TYPE}} '{{task_name}}']: {{message}}";
148156

149157
if ($maxLogMsgLength !== null && $maxLogMsgLength <= 0) {
@@ -224,6 +232,15 @@ public function getLogUncaughtErrors(): bool
224232
return $this->logUncaughtErrors;
225233
}
226234

235+
/**
236+
* If true, PHP warnings will be sent to the error channel, otherwise - to the debug channel
237+
* @return bool
238+
*/
239+
public function getLogPhpWarningsToError(): bool
240+
{
241+
return $this->logPhpWarningsToError;
242+
}
243+
227244
/**
228245
* Log message formatting string.
229246
* Available variables: {{task_id}}, {{task_type}}, {{TASK_TYPE}}, {{task_name}}, {{TASK_NAME}},

src/Constant/PhpErrors.php

+13
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,19 @@ final class PhpErrors
1414
E_RECOVERABLE_ERROR => 'E_RECOVERABLE_ERROR',
1515
];
1616

17+
/** @var array PHP non-fatal errors */
18+
public const SOFT = [
19+
E_WARNING => 'E_WARNING',
20+
E_NOTICE => 'E_NOTICE',
21+
E_CORE_WARNING => 'E_CORE_WARNING',
22+
E_COMPILE_WARNING => 'E_COMPILE_WARNING',
23+
E_USER_WARNING => 'E_USER_WARNING',
24+
E_USER_NOTICE => 'E_USER_NOTICE',
25+
E_STRICT => 'E_STRICT',
26+
E_DEPRECATED => 'E_DEPRECATED',
27+
E_USER_DEPRECATED => 'E_USER_DEPRECATED',
28+
];
29+
1730
/**
1831
* Returns mask of all fatal PHP errors
1932
* @return int

src/Wrapper/TaskWrapper.php

+35-23
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,9 @@ class TaskWrapper
5050
/** @var LoggerWrapper */
5151
private $log;
5252

53+
/** @var ?string */
54+
private $oldErrorHandler;
55+
5356
/**
5457
* Task wrapper containing the scheduler parameters and launch logic.
5558
* @param LockHandlerInterface $handler
@@ -182,11 +185,10 @@ public function dispatch(): void
182185
*/
183186
private function launchTask(Carbon $startTime, int $launchId = null, int $try = 1): void
184187
{
185-
set_error_handler(
188+
$this->oldErrorHandler = set_error_handler(
186189
function ($code, $message, $file, $line) {
187-
$this->phpFatalHandler($code, $message, $file, $line);
188-
},
189-
PhpErrors::fatalMask()
190+
$this->phpErrorHandler($code, $message, $file, $line);
191+
}
190192
);
191193

192194
if ($launchId === null) {
@@ -484,25 +486,25 @@ private function prepareSettingsArray(array $arr): array
484486
*/
485487
public function logDebug(string $message): void
486488
{
487-
$this->log($message);
489+
$formattedMessage = Formatter::logMessage(
490+
$this->config->getLogMessageFormat(),
491+
$this->config->getMaxLogMsgLength(),
492+
$this->taskId,
493+
$this->task->getType(),
494+
$this->name,
495+
$message,
496+
$this->description
497+
);
498+
499+
$this->log->debug($formattedMessage);
488500
}
489501

490502
/**
491503
* Log message to error channel
492504
* @param string $header
493-
* @param Throwable $e
494-
*/
495-
public function logError(string $header, Throwable $e): void
496-
{
497-
$this->log($header, $e);
498-
}
499-
500-
/**
501-
* Log message wrapper
502-
* @param string $message
503505
* @param Throwable|null $e
504506
*/
505-
private function log(string $message, ?Throwable $e = null): void
507+
public function logError(string $message, ?Throwable $e = null): void
506508
{
507509
if ($e !== null) {
508510
$message = Formatter::exception(
@@ -512,6 +514,7 @@ private function log(string $message, ?Throwable $e = null): void
512514
$e
513515
);
514516
}
517+
515518
$formattedMessage = Formatter::logMessage(
516519
$this->config->getLogMessageFormat(),
517520
$this->config->getMaxLogMsgLength(),
@@ -522,10 +525,7 @@ private function log(string $message, ?Throwable $e = null): void
522525
$this->description
523526
);
524527

525-
$e === null ?
526-
$this->log->debug($formattedMessage) :
527-
$this->log->error($formattedMessage, $e);
528-
528+
$this->log->error($formattedMessage, $e);
529529
}
530530

531531
/**
@@ -535,9 +535,21 @@ private function log(string $message, ?Throwable $e = null): void
535535
* @param $line
536536
* @throws Exception
537537
*/
538-
private function phpFatalHandler($code, $message, $file, $line): void
538+
private function phpErrorHandler($code, $message, $file, $line): void
539539
{
540-
$errName = PhpErrors::FATAL[$code];
541-
throw new Exception("(ATTENTION: PHP $errName) - $message", $code);
540+
if ($this->oldErrorHandler !== null) {
541+
call_user_func($this->oldErrorHandler, $code, $message, $file, $line);
542+
}
543+
544+
if (array_key_exists($code, PhpErrors::FATAL)) {
545+
$errName = PhpErrors::FATAL[$code];
546+
throw new Exception("(ATTENTION: PHP $errName) - $message", $code);
547+
} else {
548+
$message = (PhpErrors::SOFT[$code] ?? 0) . " - $message (code $code, file $file, line $line)";
549+
$this->config->getLogPhpWarningsToError() ?
550+
$this->logError($message) :
551+
$this->logDebug($message);
552+
553+
}
542554
}
543555
}

0 commit comments

Comments
 (0)