PluginProbe
Search Atlas SEO – OTTO AI SEO Automation for WordPress / 2.7.2
Search Atlas SEO – OTTO AI SEO Automation for WordPress v2.7.2
2.7.1 2.7.2 2.7.0 2.6.26 2.6.25 2.6.24 2.6.23 2.6.22 2.6.21 2.6.20 2.6.19 2.6.18 2.6.17 2.6.16 2.6.15 2.6.14 2.6.13 2.6.12 2.6.11 2.6.10 2.6.9 2.6.8 2.6.7 2.6.6 2.6.5 All 141 releases
metasync / includes / class-metasync-errorlogs.php

class-metasync-errorlogs.php in Search Atlas SEO – OTTO AI SEO Automation for WordPress 2.7.2, at includes/class-metasync-errorlogs.php

162 lines 7.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 class ErrorLog {
3 private $logFilePath;
4
5 /**
6 * ErrorLog constructor.
7 *
8 * @param string $logFilePath
9 */
10 public function __construct() {
11 $this->logFilePath = ini_get('error_log');
12 }
13
14 public function getParsedLogFile() {
15 $parsedLogs = [];
16 $logFilePath = $this->logFilePath;
17
18 // error_log can be disabled (empty ini value), set to "syslog", or
19 // point at a file that no longer exists — there is nothing to parse,
20 // and file_get_contents would warn on those values.
21 if (empty($logFilePath) || !is_string($logFilePath) || 'syslog' === $logFilePath || !is_file($logFilePath)) {
22 return $parsedLogs;
23 }
24
25 // A long-lived error log can grow to gigabytes; parsing it whole
26 // exhausts memory on the request that reads it. Read only the
27 // trailing window — recent entries are what the admin UI shows.
28 $tail_bytes = 1024 * 1024;
29 $size = filesize($logFilePath);
30 $content = false;
31 if (false !== $size && $size > $tail_bytes) {
32 $handle = @fopen($logFilePath, 'rb'); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fopen -- streaming file I/O; WP_Filesystem cannot return a raw stream handle
33 if (false !== $handle) {
34 fseek($handle, $size - $tail_bytes);
35 $content = stream_get_contents($handle);
36 fclose($handle); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fclose -- operates on a native stream handle
37 // Drop the leading partial line the window cut into.
38 if (false !== $content && false !== strpos($content, "\n")) {
39 $content = substr($content, strpos($content, "\n") + 1);
40 }
41 }
42 } else {
43 $content = @file_get_contents($logFilePath);
44 }
45 if (false === $content || '' === $content) {
46 return $parsedLogs;
47 }
48
49 $logFileHandle = explode("\n", $content);
50
51 foreach ($logFileHandle as $id => $currentLine) {
52 // Normal error log line starts with the date & time in []
53 if ('[' === ($currentLine[0] ?? '')) {
54 // if (10000 === \count($parsedLogs)) {
55 // return $parsedLogs;
56 // }
57
58 // Get the datetime when the error occurred and convert it to
59 // the site's timezone.
60 try {
61 $dateArr = [];
62 preg_match('~^\[(.*?)\]~', $currentLine, $dateArr);
63 $errorDateTime = '';
64 if (!empty($dateArr[1])) {
65 $currentLine = str_replace($dateArr[0], '', $currentLine);
66 $currentLine = trim($currentLine);
67 $errorDateTime = new DateTime($dateArr[1]);
68 $timezone = function_exists('wp_timezone') ? wp_timezone() : new DateTimeZone('UTC');
69 $errorDateTime->setTimezone($timezone);
70 $errorDateTime = $errorDateTime->format('Y-m-d H:i:s');
71 }
72 } catch (\Exception $e) {
73 $errorDateTime = '';
74 }
75
76 // Get the type of the error
77 if (false !== strpos($currentLine, 'PHP Warning')) {
78 $currentLine = str_replace('PHP Warning:', '', $currentLine);
79 $currentLine = trim($currentLine);
80 $errorType = 'WARNING';
81 } else if (false !== strpos($currentLine, 'PHP Notice')) {
82 $currentLine = str_replace('PHP Notice:', '', $currentLine);
83 $currentLine = trim($currentLine);
84 $errorType = 'NOTICE';
85 } else if (false !== strpos($currentLine, 'PHP Fatal error')) {
86 $currentLine = str_replace('PHP Fatal error:', '', $currentLine);
87 $currentLine = trim($currentLine);
88 $errorType = 'FATAL';
89 } else if (false !== strpos($currentLine, 'PHP Parse error')) {
90 $currentLine = str_replace('PHP Parse error:', '', $currentLine);
91 $currentLine = trim($currentLine);
92 $errorType = 'SYNTAX';
93 } else if (false !== strpos($currentLine, 'PHP Exception')) {
94 $currentLine = str_replace('PHP Exception:', '', $currentLine);
95 $currentLine = trim($currentLine);
96 $errorType = 'EXCEPTION';
97 } else {
98 $errorType = 'UNKNOWN';
99 }
100
101 if (false !== strpos($currentLine, ' on line ')) {
102 $errorLine = explode(' on line ', $currentLine);
103 $errorLine = trim($errorLine[1]);
104 $currentLine = str_replace(' on line ' . $errorLine, '', $currentLine);
105 } else {
106 $errorLine = substr($currentLine, strrpos($currentLine, ':') + 1);
107 $currentLine = str_replace(':' . $errorLine, '', $currentLine);
108 }
109
110 $errorFile = explode(' in /', $currentLine, 2);
111 if (isset($errorFile[1])) {
112 $errorFile = '/' . trim($errorFile[1]);
113 $currentLine = str_replace(' in ' . $errorFile, '', $currentLine);
114 } else {
115 $errorFile = '';
116 }
117
118 // The message of the error
119 $errorMessage = trim($currentLine);
120
121 $parsedLogs[] = [
122 'id' => $id+1,
123 'dateTime' => $errorDateTime,
124 'type' => $errorType,
125 'file' => $errorFile,
126 'line' => (int)$errorLine,
127 'message' => $errorMessage,
128 'stackTrace' => []
129 ];
130 } // Stack trace beginning line
131 else if ('Stack trace:' === $currentLine) {
132 $parsedLogsLastKey = array_key_last($parsedLogs);
133 if (null === $parsedLogsLastKey) {
134 continue;
135 }
136
137 $stackTraceLineNumber = 0;
138 for ($trace_index = $id + 1, $trace_count = count($logFileHandle); $trace_index < $trace_count; $trace_index++) {
139 $trace_line = trim($logFileHandle[$trace_index]);
140 if ('' === $trace_line) {
141 continue;
142 }
143 if ('#' === $trace_line[0]) {
144 $prefix = '#' . $stackTraceLineNumber;
145 if (0 === strpos($trace_line, $prefix)) {
146 $trace_line = substr($trace_line, strlen($prefix));
147 }
148 $parsedLogs[$parsedLogsLastKey]['stackTrace'][] = trim($trace_line);
149 $stackTraceLineNumber++;
150 continue;
151 }
152 if (0 === strpos($trace_line, 'thrown in ')) {
153 $parsedLogs[$parsedLogsLastKey]['stackTrace'][] = $trace_line;
154 }
155 break;
156 }
157 }
158 }
159
160 return $parsedLogs;
161 }
162 }