Chris@0: Chris@0: * Chris@0: * For the full copyright and license information, please view the LICENSE Chris@0: * file that was distributed with this source code. Chris@0: */ Chris@0: Chris@0: namespace Symfony\Component\HttpKernel\DataCollector; Chris@0: Chris@0: use Symfony\Component\Debug\Exception\SilencedErrorContext; Chris@0: use Symfony\Component\HttpFoundation\Request; Chris@0: use Symfony\Component\HttpFoundation\Response; Chris@0: use Symfony\Component\HttpKernel\Log\DebugLoggerInterface; Chris@0: Chris@0: /** Chris@0: * LogDataCollector. Chris@0: * Chris@0: * @author Fabien Potencier Chris@0: */ Chris@0: class LoggerDataCollector extends DataCollector implements LateDataCollectorInterface Chris@0: { Chris@0: private $logger; Chris@0: Chris@0: public function __construct($logger = null) Chris@0: { Chris@0: if (null !== $logger && $logger instanceof DebugLoggerInterface) { Chris@0: $this->logger = $logger; Chris@0: } Chris@0: } Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: public function collect(Request $request, Response $response, \Exception $exception = null) Chris@0: { Chris@0: // everything is done as late as possible Chris@0: } Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: public function lateCollect() Chris@0: { Chris@0: if (null !== $this->logger) { Chris@0: $this->data = $this->computeErrorsCount(); Chris@0: $this->data['logs'] = $this->sanitizeLogs($this->logger->getLogs()); Chris@0: } Chris@0: } Chris@0: Chris@0: /** Chris@0: * Gets the logs. Chris@0: * Chris@0: * @return array An array of logs Chris@0: */ Chris@0: public function getLogs() Chris@0: { Chris@0: return isset($this->data['logs']) ? $this->data['logs'] : array(); Chris@0: } Chris@0: Chris@0: public function getPriorities() Chris@0: { Chris@0: return isset($this->data['priorities']) ? $this->data['priorities'] : array(); Chris@0: } Chris@0: Chris@0: public function countErrors() Chris@0: { Chris@0: return isset($this->data['error_count']) ? $this->data['error_count'] : 0; Chris@0: } Chris@0: Chris@0: public function countDeprecations() Chris@0: { Chris@0: return isset($this->data['deprecation_count']) ? $this->data['deprecation_count'] : 0; Chris@0: } Chris@0: Chris@0: public function countWarnings() Chris@0: { Chris@0: return isset($this->data['warning_count']) ? $this->data['warning_count'] : 0; Chris@0: } Chris@0: Chris@0: public function countScreams() Chris@0: { Chris@0: return isset($this->data['scream_count']) ? $this->data['scream_count'] : 0; Chris@0: } Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: public function getName() Chris@0: { Chris@0: return 'logger'; Chris@0: } Chris@0: Chris@0: private function sanitizeLogs($logs) Chris@0: { Chris@0: $sanitizedLogs = array(); Chris@0: Chris@0: foreach ($logs as $log) { Chris@0: if (!$this->isSilencedOrDeprecationErrorLog($log)) { Chris@0: $log['context'] = $log['context'] ? $this->cloneVar($log['context']) : $log['context']; Chris@0: $sanitizedLogs[] = $log; Chris@0: Chris@0: continue; Chris@0: } Chris@0: Chris@0: $exception = $log['context']['exception']; Chris@0: $errorId = md5("{$exception->getSeverity()}/{$exception->getLine()}/{$exception->getFile()}".($exception instanceof \Exception ? "\0".$exception->getMessage() : ''), true); Chris@0: Chris@0: if (isset($sanitizedLogs[$errorId])) { Chris@0: ++$sanitizedLogs[$errorId]['errorCount']; Chris@0: } else { Chris@0: $log['context'] = $log['context'] ? $this->cloneVar($log['context']) : $log['context']; Chris@0: Chris@0: $log += array( Chris@0: 'errorCount' => 1, Chris@0: 'scream' => $exception instanceof SilencedErrorContext, Chris@0: ); Chris@0: Chris@0: $sanitizedLogs[$errorId] = $log; Chris@0: } Chris@0: } Chris@0: Chris@0: return array_values($sanitizedLogs); Chris@0: } Chris@0: Chris@0: private function isSilencedOrDeprecationErrorLog(array $log) Chris@0: { Chris@0: if (!isset($log['context']['exception'])) { Chris@0: return false; Chris@0: } Chris@0: Chris@0: $exception = $log['context']['exception']; Chris@0: Chris@0: if ($exception instanceof SilencedErrorContext) { Chris@0: return true; Chris@0: } Chris@0: Chris@0: if ($exception instanceof \ErrorException && in_array($exception->getSeverity(), array(E_DEPRECATED, E_USER_DEPRECATED), true)) { Chris@0: return true; Chris@0: } Chris@0: Chris@0: return false; Chris@0: } Chris@0: Chris@0: private function computeErrorsCount() Chris@0: { Chris@0: $count = array( Chris@0: 'error_count' => $this->logger->countErrors(), Chris@0: 'deprecation_count' => 0, Chris@0: 'warning_count' => 0, Chris@0: 'scream_count' => 0, Chris@0: 'priorities' => array(), Chris@0: ); Chris@0: Chris@0: foreach ($this->logger->getLogs() as $log) { Chris@0: if (isset($count['priorities'][$log['priority']])) { Chris@0: ++$count['priorities'][$log['priority']]['count']; Chris@0: } else { Chris@0: $count['priorities'][$log['priority']] = array( Chris@0: 'count' => 1, Chris@0: 'name' => $log['priorityName'], Chris@0: ); Chris@0: } Chris@0: if ('WARNING' === $log['priorityName']) { Chris@0: ++$count['warning_count']; Chris@0: } Chris@0: Chris@0: if ($this->isSilencedOrDeprecationErrorLog($log)) { Chris@0: if ($log['context']['exception'] instanceof SilencedErrorContext) { Chris@0: ++$count['scream_count']; Chris@0: } else { Chris@0: ++$count['deprecation_count']; Chris@0: } Chris@0: } Chris@0: } Chris@0: Chris@0: ksort($count['priorities']); Chris@0: Chris@0: return $count; Chris@0: } Chris@0: }