2010-08-28 14:23:21 +01:00
< ? php
/*
2011-01-15 13:29:43 +00:00
* This file is part of the Symfony package .
2010-08-28 14:23:21 +01:00
*
2011-03-06 11:40:06 +00:00
* ( c ) Fabien Potencier < fabien @ symfony . com >
2010-08-28 14:23:21 +01:00
*
2011-01-15 13:29:43 +00:00
* For the full copyright and license information , please view the LICENSE
* file that was distributed with this source code .
2010-08-28 14:23:21 +01:00
*/
2011-01-15 13:29:43 +00:00
namespace Symfony\Component\HttpKernel\DataCollector ;
2016-08-08 14:40:30 +01:00
use Symfony\Component\Debug\Exception\SilencedErrorContext ;
2011-01-15 13:29:43 +00:00
use Symfony\Component\HttpFoundation\Request ;
use Symfony\Component\HttpFoundation\Response ;
2011-05-31 06:59:30 +01:00
use Symfony\Component\HttpKernel\Log\DebugLoggerInterface ;
2011-01-15 13:29:43 +00:00
2010-08-28 14:23:21 +01:00
/**
* LogDataCollector .
*
2011-03-06 11:40:06 +00:00
* @ author Fabien Potencier < fabien @ symfony . com >
2010-08-28 14:23:21 +01:00
*/
2013-09-30 16:49:53 +01:00
class LoggerDataCollector extends DataCollector implements LateDataCollectorInterface
2010-08-28 14:23:21 +01:00
{
2011-03-23 18:47:16 +00:00
private $logger ;
2017-04-11 22:22:30 +01:00
private $containerPathPrefix ;
2010-08-28 14:23:21 +01:00
2017-04-11 22:22:30 +01:00
public function __construct ( $logger = null , $containerPathPrefix = null )
2010-08-28 14:23:21 +01:00
{
2011-05-31 06:59:30 +01:00
if ( null !== $logger && $logger instanceof DebugLoggerInterface ) {
2017-10-05 10:48:08 +01:00
if ( ! method_exists ( $logger , 'clear' )) {
2017-12-31 06:25:36 +00:00
@ 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 );
2017-10-05 10:48:08 +01:00
}
2011-05-31 06:59:30 +01:00
$this -> logger = $logger ;
2010-08-28 14:23:21 +01:00
}
2017-04-11 22:22:30 +01:00
$this -> containerPathPrefix = $containerPathPrefix ;
2010-08-28 14:23:21 +01:00
}
2013-09-30 06:59:16 +01:00
/**
* { @ inheritdoc }
*/
public function collect ( Request $request , Response $response , \Exception $exception = null )
{
// everything is done as late as possible
}
2017-10-05 10:48:08 +01:00
/**
* { @ inheritdoc }
*/
public function reset ()
{
if ( $this -> logger && method_exists ( $this -> logger , 'clear' )) {
$this -> logger -> clear ();
}
$this -> data = array ();
}
2010-08-28 14:23:21 +01:00
/**
* { @ inheritdoc }
*/
2013-09-30 16:49:53 +01:00
public function lateCollect ()
2010-08-28 14:23:21 +01:00
{
if ( null !== $this -> logger ) {
2017-04-11 22:22:30 +01:00
$containerDeprecationLogs = $this -> getContainerDeprecationLogs ();
2017-06-01 10:17:30 +01:00
$this -> data = $this -> computeErrorsCount ( $containerDeprecationLogs );
2017-04-11 22:22:30 +01:00
$this -> data [ 'compiler_logs' ] = $this -> getContainerCompilerLogs ();
$this -> data [ 'logs' ] = $this -> sanitizeLogs ( array_merge ( $this -> logger -> getLogs (), $containerDeprecationLogs ));
2017-02-15 10:50:57 +00:00
$this -> data = $this -> cloneVar ( $this -> data );
2010-08-28 14:23:21 +01:00
}
}
/**
* Gets the logs .
*
* @ return array An array of logs
*/
public function getLogs ()
{
return isset ( $this -> data [ 'logs' ]) ? $this -> data [ 'logs' ] : array ();
}
2014-03-17 17:25:25 +00:00
public function getPriorities ()
{
return isset ( $this -> data [ 'priorities' ]) ? $this -> data [ 'priorities' ] : array ();
}
2016-08-18 13:31:26 +01:00
public function countErrors ()
{
return isset ( $this -> data [ 'error_count' ]) ? $this -> data [ 'error_count' ] : 0 ;
}
2012-12-01 11:25:00 +00:00
public function countDeprecations ()
{
return isset ( $this -> data [ 'deprecation_count' ]) ? $this -> data [ 'deprecation_count' ] : 0 ;
}
2016-08-17 14:29:33 +01:00
public function countWarnings ()
{
return isset ( $this -> data [ 'warning_count' ]) ? $this -> data [ 'warning_count' ] : 0 ;
}
2014-02-04 20:08:27 +00:00
public function countScreams ()
{
return isset ( $this -> data [ 'scream_count' ]) ? $this -> data [ 'scream_count' ] : 0 ;
}
2017-04-11 22:22:30 +01:00
public function getCompilerLogs ()
{
return isset ( $this -> data [ 'compiler_logs' ]) ? $this -> data [ 'compiler_logs' ] : array ();
}
2010-08-28 14:23:21 +01:00
/**
* { @ inheritdoc }
*/
public function getName ()
{
return 'logger' ;
}
2011-06-19 11:18:50 +01:00
2017-04-11 22:22:30 +01:00
private function getContainerDeprecationLogs ()
{
if ( null === $this -> containerPathPrefix || ! file_exists ( $file = $this -> containerPathPrefix . 'Deprecations.log' )) {
return array ();
}
$bootTime = filemtime ( $file );
$logs = array ();
foreach ( unserialize ( file_get_contents ( $file )) as $log ) {
2017-06-01 10:17:30 +01:00
$log [ 'context' ] = array ( 'exception' => new SilencedErrorContext ( $log [ 'type' ], $log [ 'file' ], $log [ 'line' ], $log [ 'trace' ], $log [ 'count' ]));
2017-04-11 22:22:30 +01:00
$log [ 'timestamp' ] = $bootTime ;
$log [ 'priority' ] = 100 ;
$log [ 'priorityName' ] = 'DEBUG' ;
$log [ 'channel' ] = '-' ;
$log [ 'scream' ] = false ;
2017-07-05 13:26:31 +01:00
unset ( $log [ 'type' ], $log [ 'file' ], $log [ 'line' ], $log [ 'trace' ], $log [ 'trace' ], $log [ 'count' ]);
2017-04-11 22:22:30 +01:00
$logs [] = $log ;
}
return $logs ;
}
private function getContainerCompilerLogs ()
{
if ( null === $this -> containerPathPrefix || ! file_exists ( $file = $this -> containerPathPrefix . 'Compiler.log' )) {
return array ();
}
$logs = array ();
foreach ( file ( $file , FILE_IGNORE_NEW_LINES ) as $log ) {
$log = explode ( ': ' , $log , 2 );
2017-05-30 14:00:50 +01:00
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 ])) {
$log = array ( 'Unknown Compiler Pass' , implode ( ': ' , $log ));
}
2017-04-11 22:22:30 +01:00
$logs [ $log [ 0 ]][] = array ( 'message' => $log [ 1 ]);
}
return $logs ;
}
2011-06-19 11:18:50 +01:00
private function sanitizeLogs ( $logs )
{
2015-08-30 13:16:23 +01:00
$sanitizedLogs = array ();
2017-11-07 12:04:37 +00:00
$silencedLogs = array ();
2015-08-30 13:16:23 +01:00
foreach ( $logs as $log ) {
2016-08-08 14:40:30 +01:00
if ( ! $this -> isSilencedOrDeprecationErrorLog ( $log )) {
$sanitizedLogs [] = $log ;
2015-08-30 13:16:23 +01:00
2016-08-08 14:40:30 +01:00
continue ;
}
2015-08-30 13:16:23 +01:00
2017-06-01 10:17:30 +01:00
$message = $log [ 'message' ];
2016-08-08 14:40:30 +01:00
$exception = $log [ 'context' ][ 'exception' ];
2017-06-01 10:17:30 +01:00
if ( $exception instanceof SilencedErrorContext ) {
if ( isset ( $silencedLogs [ $h = spl_object_hash ( $exception )])) {
continue ;
}
$silencedLogs [ $h ] = true ;
if ( ! isset ( $sanitizedLogs [ $message ])) {
$sanitizedLogs [ $message ] = $log + array (
'errorCount' => 0 ,
'scream' => true ,
);
}
$sanitizedLogs [ $message ][ 'errorCount' ] += $exception -> count ;
continue ;
}
$errorId = md5 ( " { $exception -> getSeverity () } / { $exception -> getLine () } / { $exception -> getFile () } \0 { $message } " , true );
2015-08-30 13:16:23 +01:00
2016-08-17 14:29:33 +01:00
if ( isset ( $sanitizedLogs [ $errorId ])) {
++ $sanitizedLogs [ $errorId ][ 'errorCount' ];
} else {
$log += array (
'errorCount' => 1 ,
2017-06-01 10:17:30 +01:00
'scream' => false ,
2016-08-17 14:29:33 +01:00
);
2016-08-08 14:40:30 +01:00
2016-08-17 14:29:33 +01:00
$sanitizedLogs [ $errorId ] = $log ;
2014-05-26 11:29:25 +01:00
}
2011-06-19 11:18:50 +01:00
}
2016-08-08 14:40:30 +01:00
return array_values ( $sanitizedLogs );
}
private function isSilencedOrDeprecationErrorLog ( array $log )
{
if ( ! isset ( $log [ 'context' ][ 'exception' ])) {
return false ;
}
$exception = $log [ 'context' ][ 'exception' ];
if ( $exception instanceof SilencedErrorContext ) {
return true ;
}
if ( $exception instanceof \ErrorException && in_array ( $exception -> getSeverity (), array ( E_DEPRECATED , E_USER_DEPRECATED ), true )) {
return true ;
}
return false ;
2011-06-19 11:18:50 +01:00
}
2017-06-01 10:17:30 +01:00
private function computeErrorsCount ( array $containerDeprecationLogs )
2012-12-01 11:25:00 +00:00
{
2017-06-01 10:17:30 +01:00
$silencedLogs = array ();
2014-02-04 20:08:27 +00:00
$count = array (
'error_count' => $this -> logger -> countErrors (),
'deprecation_count' => 0 ,
2016-08-17 14:29:33 +01:00
'warning_count' => 0 ,
2014-02-04 20:08:27 +00:00
'scream_count' => 0 ,
2014-03-17 17:25:25 +00:00
'priorities' => array (),
2014-02-04 20:08:27 +00:00
);
2012-12-01 11:25:00 +00:00
foreach ( $this -> logger -> getLogs () as $log ) {
2014-03-17 17:25:25 +00:00
if ( isset ( $count [ 'priorities' ][ $log [ 'priority' ]])) {
++ $count [ 'priorities' ][ $log [ 'priority' ]][ 'count' ];
} else {
$count [ 'priorities' ][ $log [ 'priority' ]] = array (
'count' => 1 ,
'name' => $log [ 'priorityName' ],
);
}
2016-08-17 14:29:33 +01:00
if ( 'WARNING' === $log [ 'priorityName' ]) {
++ $count [ 'warning_count' ];
}
2014-03-17 17:25:25 +00:00
2016-08-08 14:40:30 +01:00
if ( $this -> isSilencedOrDeprecationErrorLog ( $log )) {
2017-06-01 10:17:30 +01:00
$exception = $log [ 'context' ][ 'exception' ];
if ( $exception instanceof SilencedErrorContext ) {
if ( isset ( $silencedLogs [ $h = spl_object_hash ( $exception )])) {
continue ;
}
$silencedLogs [ $h ] = true ;
$count [ 'scream_count' ] += $exception -> count ;
2016-08-08 14:40:30 +01:00
} else {
++ $count [ 'deprecation_count' ];
2014-02-04 20:08:27 +00:00
}
2012-12-01 11:25:00 +00:00
}
}
2017-06-01 10:17:30 +01:00
foreach ( $containerDeprecationLogs as $deprecationLog ) {
2017-07-05 13:26:31 +01:00
$count [ 'deprecation_count' ] += $deprecationLog [ 'context' ][ 'exception' ] -> count ;
2017-06-01 10:17:30 +01:00
}
2014-03-17 17:25:25 +00:00
ksort ( $count [ 'priorities' ]);
2012-12-01 11:25:00 +00:00
return $count ;
}
2010-08-28 14:23:21 +01:00
}