annotate vendor/symfony/http-kernel/DataCollector/LoggerDataCollector.php @ 19:fa3358dc1485 tip

Add ndrum files
author Chris Cannam
date Wed, 28 Aug 2019 13:14:47 +0100
parents af1871eacc83
children
rev   line source
Chris@0 1 <?php
Chris@0 2
Chris@0 3 /*
Chris@0 4 * This file is part of the Symfony package.
Chris@0 5 *
Chris@0 6 * (c) Fabien Potencier <fabien@symfony.com>
Chris@0 7 *
Chris@0 8 * For the full copyright and license information, please view the LICENSE
Chris@0 9 * file that was distributed with this source code.
Chris@0 10 */
Chris@0 11
Chris@0 12 namespace Symfony\Component\HttpKernel\DataCollector;
Chris@0 13
Chris@0 14 use Symfony\Component\Debug\Exception\SilencedErrorContext;
Chris@0 15 use Symfony\Component\HttpFoundation\Request;
Chris@0 16 use Symfony\Component\HttpFoundation\Response;
Chris@0 17 use Symfony\Component\HttpKernel\Log\DebugLoggerInterface;
Chris@0 18
Chris@0 19 /**
Chris@0 20 * LogDataCollector.
Chris@0 21 *
Chris@0 22 * @author Fabien Potencier <fabien@symfony.com>
Chris@0 23 */
Chris@0 24 class LoggerDataCollector extends DataCollector implements LateDataCollectorInterface
Chris@0 25 {
Chris@0 26 private $logger;
Chris@14 27 private $containerPathPrefix;
Chris@0 28
Chris@14 29 public function __construct($logger = null, $containerPathPrefix = null)
Chris@0 30 {
Chris@0 31 if (null !== $logger && $logger instanceof DebugLoggerInterface) {
Chris@14 32 if (!method_exists($logger, 'clear')) {
Chris@14 33 @trigger_error(sprintf('Implementing "%s" without the "clear()" method is deprecated since Symfony 3.4 and will be unsupported in 4.0 for class "%s".', DebugLoggerInterface::class, \get_class($logger)), E_USER_DEPRECATED);
Chris@14 34 }
Chris@14 35
Chris@0 36 $this->logger = $logger;
Chris@0 37 }
Chris@14 38
Chris@14 39 $this->containerPathPrefix = $containerPathPrefix;
Chris@0 40 }
Chris@0 41
Chris@0 42 /**
Chris@0 43 * {@inheritdoc}
Chris@0 44 */
Chris@0 45 public function collect(Request $request, Response $response, \Exception $exception = null)
Chris@0 46 {
Chris@0 47 // everything is done as late as possible
Chris@0 48 }
Chris@0 49
Chris@0 50 /**
Chris@0 51 * {@inheritdoc}
Chris@0 52 */
Chris@14 53 public function reset()
Chris@14 54 {
Chris@14 55 if ($this->logger && method_exists($this->logger, 'clear')) {
Chris@14 56 $this->logger->clear();
Chris@14 57 }
Chris@17 58 $this->data = [];
Chris@14 59 }
Chris@14 60
Chris@14 61 /**
Chris@14 62 * {@inheritdoc}
Chris@14 63 */
Chris@0 64 public function lateCollect()
Chris@0 65 {
Chris@0 66 if (null !== $this->logger) {
Chris@14 67 $containerDeprecationLogs = $this->getContainerDeprecationLogs();
Chris@14 68 $this->data = $this->computeErrorsCount($containerDeprecationLogs);
Chris@14 69 $this->data['compiler_logs'] = $this->getContainerCompilerLogs();
Chris@14 70 $this->data['logs'] = $this->sanitizeLogs(array_merge($this->logger->getLogs(), $containerDeprecationLogs));
Chris@14 71 $this->data = $this->cloneVar($this->data);
Chris@0 72 }
Chris@0 73 }
Chris@0 74
Chris@0 75 /**
Chris@0 76 * Gets the logs.
Chris@0 77 *
Chris@0 78 * @return array An array of logs
Chris@0 79 */
Chris@0 80 public function getLogs()
Chris@0 81 {
Chris@17 82 return isset($this->data['logs']) ? $this->data['logs'] : [];
Chris@0 83 }
Chris@0 84
Chris@0 85 public function getPriorities()
Chris@0 86 {
Chris@17 87 return isset($this->data['priorities']) ? $this->data['priorities'] : [];
Chris@0 88 }
Chris@0 89
Chris@0 90 public function countErrors()
Chris@0 91 {
Chris@0 92 return isset($this->data['error_count']) ? $this->data['error_count'] : 0;
Chris@0 93 }
Chris@0 94
Chris@0 95 public function countDeprecations()
Chris@0 96 {
Chris@0 97 return isset($this->data['deprecation_count']) ? $this->data['deprecation_count'] : 0;
Chris@0 98 }
Chris@0 99
Chris@0 100 public function countWarnings()
Chris@0 101 {
Chris@0 102 return isset($this->data['warning_count']) ? $this->data['warning_count'] : 0;
Chris@0 103 }
Chris@0 104
Chris@0 105 public function countScreams()
Chris@0 106 {
Chris@0 107 return isset($this->data['scream_count']) ? $this->data['scream_count'] : 0;
Chris@0 108 }
Chris@0 109
Chris@14 110 public function getCompilerLogs()
Chris@14 111 {
Chris@17 112 return isset($this->data['compiler_logs']) ? $this->data['compiler_logs'] : [];
Chris@14 113 }
Chris@14 114
Chris@0 115 /**
Chris@0 116 * {@inheritdoc}
Chris@0 117 */
Chris@0 118 public function getName()
Chris@0 119 {
Chris@0 120 return 'logger';
Chris@0 121 }
Chris@0 122
Chris@14 123 private function getContainerDeprecationLogs()
Chris@14 124 {
Chris@14 125 if (null === $this->containerPathPrefix || !file_exists($file = $this->containerPathPrefix.'Deprecations.log')) {
Chris@17 126 return [];
Chris@14 127 }
Chris@14 128
Chris@18 129 if ('' === $logContent = trim(file_get_contents($file))) {
Chris@18 130 return [];
Chris@18 131 }
Chris@18 132
Chris@14 133 $bootTime = filemtime($file);
Chris@17 134 $logs = [];
Chris@18 135 foreach (unserialize($logContent) as $log) {
Chris@17 136 $log['context'] = ['exception' => new SilencedErrorContext($log['type'], $log['file'], $log['line'], $log['trace'], $log['count'])];
Chris@14 137 $log['timestamp'] = $bootTime;
Chris@14 138 $log['priority'] = 100;
Chris@14 139 $log['priorityName'] = 'DEBUG';
Chris@14 140 $log['channel'] = '-';
Chris@14 141 $log['scream'] = false;
Chris@14 142 unset($log['type'], $log['file'], $log['line'], $log['trace'], $log['trace'], $log['count']);
Chris@14 143 $logs[] = $log;
Chris@14 144 }
Chris@14 145
Chris@14 146 return $logs;
Chris@14 147 }
Chris@14 148
Chris@14 149 private function getContainerCompilerLogs()
Chris@14 150 {
Chris@14 151 if (null === $this->containerPathPrefix || !file_exists($file = $this->containerPathPrefix.'Compiler.log')) {
Chris@17 152 return [];
Chris@14 153 }
Chris@14 154
Chris@17 155 $logs = [];
Chris@14 156 foreach (file($file, FILE_IGNORE_NEW_LINES) as $log) {
Chris@14 157 $log = explode(': ', $log, 2);
Chris@14 158 if (!isset($log[1]) || !preg_match('/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+(?:\\\\[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+)++$/', $log[0])) {
Chris@17 159 $log = ['Unknown Compiler Pass', implode(': ', $log)];
Chris@14 160 }
Chris@14 161
Chris@17 162 $logs[$log[0]][] = ['message' => $log[1]];
Chris@14 163 }
Chris@14 164
Chris@14 165 return $logs;
Chris@14 166 }
Chris@14 167
Chris@0 168 private function sanitizeLogs($logs)
Chris@0 169 {
Chris@17 170 $sanitizedLogs = [];
Chris@17 171 $silencedLogs = [];
Chris@0 172
Chris@0 173 foreach ($logs as $log) {
Chris@0 174 if (!$this->isSilencedOrDeprecationErrorLog($log)) {
Chris@0 175 $sanitizedLogs[] = $log;
Chris@0 176
Chris@0 177 continue;
Chris@0 178 }
Chris@0 179
Chris@14 180 $message = $log['message'];
Chris@0 181 $exception = $log['context']['exception'];
Chris@14 182
Chris@14 183 if ($exception instanceof SilencedErrorContext) {
Chris@14 184 if (isset($silencedLogs[$h = spl_object_hash($exception)])) {
Chris@14 185 continue;
Chris@14 186 }
Chris@14 187 $silencedLogs[$h] = true;
Chris@14 188
Chris@14 189 if (!isset($sanitizedLogs[$message])) {
Chris@17 190 $sanitizedLogs[$message] = $log + [
Chris@14 191 'errorCount' => 0,
Chris@14 192 'scream' => true,
Chris@17 193 ];
Chris@14 194 }
Chris@14 195 $sanitizedLogs[$message]['errorCount'] += $exception->count;
Chris@14 196
Chris@14 197 continue;
Chris@14 198 }
Chris@14 199
Chris@14 200 $errorId = md5("{$exception->getSeverity()}/{$exception->getLine()}/{$exception->getFile()}\0{$message}", true);
Chris@0 201
Chris@0 202 if (isset($sanitizedLogs[$errorId])) {
Chris@0 203 ++$sanitizedLogs[$errorId]['errorCount'];
Chris@0 204 } else {
Chris@17 205 $log += [
Chris@0 206 'errorCount' => 1,
Chris@14 207 'scream' => false,
Chris@17 208 ];
Chris@0 209
Chris@0 210 $sanitizedLogs[$errorId] = $log;
Chris@0 211 }
Chris@0 212 }
Chris@0 213
Chris@0 214 return array_values($sanitizedLogs);
Chris@0 215 }
Chris@0 216
Chris@0 217 private function isSilencedOrDeprecationErrorLog(array $log)
Chris@0 218 {
Chris@0 219 if (!isset($log['context']['exception'])) {
Chris@0 220 return false;
Chris@0 221 }
Chris@0 222
Chris@0 223 $exception = $log['context']['exception'];
Chris@0 224
Chris@0 225 if ($exception instanceof SilencedErrorContext) {
Chris@0 226 return true;
Chris@0 227 }
Chris@0 228
Chris@17 229 if ($exception instanceof \ErrorException && \in_array($exception->getSeverity(), [E_DEPRECATED, E_USER_DEPRECATED], true)) {
Chris@0 230 return true;
Chris@0 231 }
Chris@0 232
Chris@0 233 return false;
Chris@0 234 }
Chris@0 235
Chris@14 236 private function computeErrorsCount(array $containerDeprecationLogs)
Chris@0 237 {
Chris@17 238 $silencedLogs = [];
Chris@17 239 $count = [
Chris@0 240 'error_count' => $this->logger->countErrors(),
Chris@0 241 'deprecation_count' => 0,
Chris@0 242 'warning_count' => 0,
Chris@0 243 'scream_count' => 0,
Chris@17 244 'priorities' => [],
Chris@17 245 ];
Chris@0 246
Chris@0 247 foreach ($this->logger->getLogs() as $log) {
Chris@0 248 if (isset($count['priorities'][$log['priority']])) {
Chris@0 249 ++$count['priorities'][$log['priority']]['count'];
Chris@0 250 } else {
Chris@17 251 $count['priorities'][$log['priority']] = [
Chris@0 252 'count' => 1,
Chris@0 253 'name' => $log['priorityName'],
Chris@17 254 ];
Chris@0 255 }
Chris@0 256 if ('WARNING' === $log['priorityName']) {
Chris@0 257 ++$count['warning_count'];
Chris@0 258 }
Chris@0 259
Chris@0 260 if ($this->isSilencedOrDeprecationErrorLog($log)) {
Chris@14 261 $exception = $log['context']['exception'];
Chris@14 262 if ($exception instanceof SilencedErrorContext) {
Chris@14 263 if (isset($silencedLogs[$h = spl_object_hash($exception)])) {
Chris@14 264 continue;
Chris@14 265 }
Chris@14 266 $silencedLogs[$h] = true;
Chris@14 267 $count['scream_count'] += $exception->count;
Chris@0 268 } else {
Chris@0 269 ++$count['deprecation_count'];
Chris@0 270 }
Chris@0 271 }
Chris@0 272 }
Chris@0 273
Chris@14 274 foreach ($containerDeprecationLogs as $deprecationLog) {
Chris@14 275 $count['deprecation_count'] += $deprecationLog['context']['exception']->count;
Chris@14 276 }
Chris@14 277
Chris@0 278 ksort($count['priorities']);
Chris@0 279
Chris@0 280 return $count;
Chris@0 281 }
Chris@0 282 }