PluginProbe
Search Atlas SEO – OTTO AI SEO Automation for WordPress / trunk
Search Atlas SEO – OTTO AI SEO Automation for WordPress vtrunk
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
← All changes | includes/class-metasync-errorlogs.php +74 -24 2.6.22 → trunk View file →
@@ -12,26 +12,64 @@
12 12 }
13 13
14 14 public function getParsedLogFile() {
15 15 $parsedLogs = [];
16 - $logFileHandle = explode("\n", file_get_contents($this->logFilePath));
16 + $logFilePath = $this->logFilePath;
17 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 +
18 51 foreach ($logFileHandle as $id => $currentLine) {
19 52 // Normal error log line starts with the date & time in []
20 - if ('[' === @$currentLine[0]) {
53 + if ('[' === ($currentLine[0] ?? '')) {
21 54 // if (10000 === \count($parsedLogs)) {
22 55 // return $parsedLogs;
23 56 // }
24 57
25 - // Get the datetime when the error occurred and convert it to berlin timezone
58 + // Get the datetime when the error occurred and convert it to
59 + // the site's timezone.
26 60 try {
27 61 $dateArr = [];
28 62 preg_match('~^\[(.*?)\]~', $currentLine, $dateArr);
29 - $currentLine = str_replace($dateArr[0], '', $currentLine);
30 - $currentLine = trim($currentLine);
31 - $errorDateTime = new DateTime($dateArr[1]);
32 - $errorDateTime->setTimezone(new DateTimeZone('Europe/Berlin'));
33 - $errorDateTime = $errorDateTime->format('Y-m-d H:i:s');
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 + }
34 72 } catch (\Exception $e) {
35 73 $errorDateTime = '';
36 74 }
37 75
@@ -68,11 +106,15 @@
68 106 $errorLine = substr($currentLine, strrpos($currentLine, ':') + 1);
69 107 $currentLine = str_replace(':' . $errorLine, '', $currentLine);
70 108 }
71 109
72 - $errorFile = explode(' in /', $currentLine);
73 - $errorFile = '/' . trim($errorFile[1]);
74 - $currentLine = str_replace(' in ' . $errorFile, '', $currentLine);
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 + }
75 117
76 118 // The message of the error
77 119 $errorMessage = trim($currentLine);
78 120
@@ -86,24 +128,32 @@
86 128 'stackTrace' => []
87 129 ];
88 130 } // Stack trace beginning line
89 131 else if ('Stack trace:' === $currentLine) {
132 + $parsedLogsLastKey = array_key_last($parsedLogs);
133 + if (null === $parsedLogsLastKey) {
134 + continue;
135 + }
136 +
90 137 $stackTraceLineNumber = 0;
91 -
92 - foreach ($logFileHandle as $line) {
93 - $currentLine = str_replace(PHP_EOL, '', $line);
94 -
95 - // If the current line is a stack trace line
96 - if ('#' === $currentLine[0]) {
97 - $parsedLogsLastKey = key($parsedLogs);
98 - $currentLine = str_replace('#' . $stackTraceLineNumber, '', $currentLine);
99 - $parsedLogs[$parsedLogsLastKey]['stackTrace'][] = trim($currentLine);
100 -
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);
101 149 $stackTraceLineNumber++;
102 - } // If the current line is the last stack trace ('thrown in...')
103 - else {
104 - break;
150 + continue;
105 151 }
152 + if (0 === strpos($trace_line, 'thrown in ')) {
153 + $parsedLogs[$parsedLogsLastKey]['stackTrace'][] = $trace_line;
154 + }
155 + break;
106 156 }
107 157 }
108 158 }
109 159