vendor/symfony/http-kernel/DataCollector/LoggerDataCollector.php line 64

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