Well, I was trying to parse the PHP Error Log. Hence I built the following class:
<?php
/**
* Created by PhpStorm.
* User: toton
* Date: 2/29/2016
* Time: 8:16 AM
*/
final class error_parser
{
private $log_file_path;
private $current_line;
private $recent;
/**
* error_parser constructor.
* Takes in the path of the error log file of PHP ERROR LOG FILE.
* And another param for checking to get the direction to traverse the file.
* @param string $log_file_path
* @param bool $recent
*/
public function __construct($log_file_path, $recent = true)
{
$this->log_file_path = $log_file_path;
$this->recent = $recent;
$this->_parse();
return true;
}
/**
* Parses the PHP ERROR LOG, and pushes an array with the following structure:
* array(
* "date" => {DATE},
* "severity" => {SEVERITY},
* "message" => {message},
* "stack_trace" => array(each({STACK_TRACE})) || false;
* );
* to the main array.
* !!!! IMPORTANT !!!!
* STACK TRACE IS NOT SUPPORTED AT THIS MOMENT
* TODO: IMPLEMENT STACK TRACE
* MILESTONE: NEXT_MAJOR RELEASE
*/
private function _parse() {
$contents = file_get_contents($this->log_file_path);
if(!$contents){
throw new Exception("Log file does not exist.", 2);
}
$lines = explode("\n", $contents);
if($this->recent) {
$lines = array_reverse($lines);
}
for($this->current_line = 0; $this->current_line < count($lines); $this->current_line++) {
parse_loop:
$current_line = trim($lines[$this->current_line]);
if(strlen($current_line) == 0) {
//If the line is empty throw it to the dustbin.
// SORRY, FOR THE GOTO.
// GOD PLEASE FORGIVE ME!
$this->current_line = $this->current_line + 1;
goto parse_loop;
}
if($current_line[0] != "[") {
// NOT SUPPORTING STACK TRACES AT THE MOMENT
$this->current_line = $this->current_line + 1;
goto parse_loop;
}
$dateArr = array();
preg_match('~^\[(.*?)\]~', $current_line, $dateArr);
$date = array(
"date" => explode(" ", $dateArr[1])[0],
"time" => explode(" ", $dateArr[1])[1]
);
$severity = "";
if(strpos($current_line, "PHP Warning")) {
$severity = "WARNING";
} elseif(strpos($current_line, "PHP Notice")) {
$severity = "NOTICE";
} elseif(strpos($current_line, "PHP Fatal error")) {
$severity = "FATAL";
} elseif(strpos($current_line, "PHP Parse error")) {
$severity = "SYNTAX_ERROR";
} else {
$severity = "UNIDENTIFIED_ERROR";
}
}
}
}
(Well, there maybe some bad-practises there in the code :-P)
One error for example could be this - [28-Dec-2015 07:51:31 UTC] PHP Warning: PHP Startup: Unable to load dynamic library 'C:\xampp\php\ext\php_pspell.dll' - The specified module could not be found.
Anyway, I was able to extract the date and the type of the error. But I cannot find a way to parse the error message.
So my question is, how do I parse the error message out of the PHP Error Log?
Thanks in Advance, Cheers!
Look for the entry Configuration File (php. Find the Error handling and logging section of the php. ini file. Make sure that both display_errors = On, display_startup_errors = On and log_errors = On are present and uncommented. Check the value of error_log - this tells you the location of the file errors are logged to.
Parse errors are caused by misused or missing symbols in a syntax. The compiler catches the error and terminates the script. Parse errors are caused by: Unclosed brackets or quotes. Missing or extra semicolons or parentheses.
The quickest way to display all php errors and warnings is to add these lines to your PHP code file: ini_set('display_errors', 1); ini_set('display_startup_errors', 1); error_reporting(E_ALL); The ini_set function will try to override the configuration found in your php.
PHP error_log() Function The error_log() function sends an error message to a log, to a file, or to a mail account.
Here’s how: Set the error_log entry to the desired path of the log file. For example, you might use error_log = /logs/php-errors.log. Note this, though: you must restart your server for the changes to the php.ini file to take effect.
Possible values: 0 - Default. Message is sent to PHP's system logger, using the OS' system logging mechanism or a file, depending on what the error_log configuration is set to in php.ini Optional. Specifies the destination of the error message.
A: Monolog is one of the best PHP error logging libraries available in the market. It provides advanced logging operations for different handlers including database, browser console, chats solutions, and others. Q: What to do if the PHP error log is not working?
Laravel configures several of these handlers for you, allowing you to choose between a single PHP error log file, rotating log files, and writing error information to the system log. In the config/app.php file, you can configure the PHP debug option to log the errors on the display of the user.
I'm a bit late but that's my solution (it supports stack traces too):
<?php
use DateTime;
use DateTimeZone;
class ErrorLog {
private $logFilePath;
/**
* ErrorLog constructor.
*
* @param string $logFilePath
*/
public function __construct(string $logFilePath) {
$this->logFilePath = $logFilePath;
}
/**
* Parses the PHP error log to an array.
*
* @return \Generator
*/
public function getParsedLogFile(): \Generator {
$parsedLogs = [];
$logFileHandle = fopen($this->logFilePath, 'rb');
while (!feof($logFileHandle)) {
$currentLine = str_replace(PHP_EOL, '', fgets($logFileHandle));
// Normal error log line starts with the date & time in []
if ('[' === $currentLine[0]) {
if (10000 === \count($parsedLogs)) {
yield $parsedLogs;
$parsedLogs = [];
}
// Get the datetime when the error occurred and convert it to berlin timezone
try {
$dateArr = [];
preg_match('~^\[(.*?)\]~', $currentLine, $dateArr);
$currentLine = str_replace($dateArr[0], '', $currentLine);
$currentLine = trim($currentLine);
$errorDateTime = new DateTime($dateArr[1]);
$errorDateTime->setTimezone(new DateTimeZone('Europe/Berlin'));
$errorDateTime = $errorDateTime->format('Y-m-d H:i:s');
} catch (\Exception $e) {
$errorDateTime = '';
}
// Get the type of the error
if (false !== strpos($currentLine, 'PHP Warning')) {
$currentLine = str_replace('PHP Warning:', '', $currentLine);
$currentLine = trim($currentLine);
$errorType = 'WARNING';
} else if (false !== strpos($currentLine, 'PHP Notice')) {
$currentLine = str_replace('PHP Notice:', '', $currentLine);
$currentLine = trim($currentLine);
$errorType = 'NOTICE';
} else if (false !== strpos($currentLine, 'PHP Fatal error')) {
$currentLine = str_replace('PHP Fatal error:', '', $currentLine);
$currentLine = trim($currentLine);
$errorType = 'FATAL';
} else if (false !== strpos($currentLine, 'PHP Parse error')) {
$currentLine = str_replace('PHP Parse error:', '', $currentLine);
$currentLine = trim($currentLine);
$errorType = 'SYNTAX';
} else if (false !== strpos($currentLine, 'PHP Exception')) {
$currentLine = str_replace('PHP Exception:', '', $currentLine);
$currentLine = trim($currentLine);
$errorType = 'EXCEPTION';
} else {
$errorType = 'UNKNOWN';
}
if (false !== strpos($currentLine, ' on line ')) {
$errorLine = explode(' on line ', $currentLine);
$errorLine = trim($errorLine[1]);
$currentLine = str_replace(' on line ' . $errorLine, '', $currentLine);
} else {
$errorLine = substr($currentLine, strrpos($currentLine, ':') + 1);
$currentLine = str_replace(':' . $errorLine, '', $currentLine);
}
$errorFile = explode(' in /', $currentLine);
$errorFile = '/' . trim($errorFile[1]);
$currentLine = str_replace(' in ' . $errorFile, '', $currentLine);
// The message of the error
$errorMessage = trim($currentLine);
$parsedLogs[] = [
'dateTime' => $errorDateTime,
'type' => $errorType,
'file' => $errorFile,
'line' => (int)$errorLine,
'message' => $errorMessage,
'stackTrace' => []
];
} // Stack trace beginning line
else if ('Stack trace:' === $currentLine) {
$stackTraceLineNumber = 0;
while (!feof($logFileHandle)) {
$currentLine = str_replace(PHP_EOL, '', fgets($logFileHandle));
// If the current line is a stack trace line
if ('#' === $currentLine[0]) {
$parsedLogsLastKey = key($parsedLogs);
$currentLine = str_replace('#' . $stackTraceLineNumber, '', $currentLine);
$parsedLogs[$parsedLogsLastKey]['stackTrace'][] = trim($currentLine);
$stackTraceLineNumber++;
} // If the current line is the last stack trace ('thrown in...')
else {
break;
}
}
}
}
yield $parsedLogs;
}
}
You can define your own Exception and Error handler in PHP, this way users won't see errors and instead you could provide them with a nice error message informing them that something went wrong.
//Exception Handler
function my_exception_handler($exception) {
echo "<p>App Exception {" , $exception->getMessage(), "}</p>\n";
}
\set_exception_handler('my_exception_handler');
//Error handler
function my_error_handler($errno, $errstr, $errfile, $errline){
echo '<p style="color:darkred">App Error {'.$errno.', '.$errstr.'}</p>'."\n";
}
\set_error_handler('my_error_handler');
you can remove "\" in the beginning of the set_error_.. functions if you are not using any namespaces, or you can leave it, it ensures your code works from a custom namespace.
Customize those echo statements inside functions, do DB save, or simply use PHP's error_log function there to save your errors.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With