== Motivation Mute a log channel, for which the Logger object is injected by service wiring, for a service that is overridden by default, such as 'DBLoadBalancerFactory'. For that, calling setLogger() mid-test would be too late. == Changes * Add a test-only method to LegacyLogger that makes it possible to change its `minimumLevel` attribute, thus making it turn itself into a NullLogger if raised to infinity. This is the same principle we use already for disabled log channels when using MediaWiki normally (see LegacyLogger::__construct). * Previously, the developer's LocalSettings.php was loaded which includes the Spi configuration. This meant other Spi's could be configured which means we might not be dealing with a LegacyLogger object. Similar to what we do with ObjectCache and JobQueue already, make the default Spi in tests the same as the normal MW default. * Add setNullLogger() which makes use of these two. Bug: T248195 Change-Id: Ieade3585812de47342259afa765e230fff06f526
103 lines
2.4 KiB
PHP
103 lines
2.4 KiB
PHP
<?php
|
|
|
|
namespace MediaWiki\Logger;
|
|
|
|
use Psr\Log\AbstractLogger;
|
|
use Psr\Log\LoggerInterface;
|
|
|
|
/**
|
|
* Wraps another spi to capture all logs generated. This can be
|
|
* used, for example, to collect all logs generated during a
|
|
* unit test and report them when the test fails.
|
|
*/
|
|
class LogCapturingSpi implements Spi {
|
|
/** @var LoggerInterface[] */
|
|
private $singletons;
|
|
/** @var Spi */
|
|
private $inner;
|
|
/** @var array */
|
|
private $logs = [];
|
|
|
|
public function __construct( Spi $inner ) {
|
|
$this->inner = $inner;
|
|
}
|
|
|
|
/**
|
|
* @return array
|
|
*/
|
|
public function getLogs() {
|
|
return $this->logs;
|
|
}
|
|
|
|
/**
|
|
* @param string $channel
|
|
* @return LoggerInterface
|
|
*/
|
|
public function getLogger( $channel ) {
|
|
if ( !isset( $this->singletons[$channel] ) ) {
|
|
$this->singletons[$channel] = $this->createLogger( $channel );
|
|
}
|
|
return $this->singletons[$channel];
|
|
}
|
|
|
|
/**
|
|
* @param array $log
|
|
*/
|
|
public function capture( $log ) {
|
|
$this->logs[] = $log;
|
|
}
|
|
|
|
/**
|
|
* @param string $channel
|
|
* @return LoggerInterface
|
|
*/
|
|
private function createLogger( $channel ) {
|
|
$inner = $this->inner->getLogger( $channel );
|
|
return new class( $channel, $inner, $this ) extends AbstractLogger {
|
|
/** @var string */
|
|
private $channel;
|
|
/** @var LoggerInterface */
|
|
private $logger;
|
|
/** @var LogCapturingSpi */
|
|
private $parent;
|
|
|
|
// phpcs:ignore MediaWiki.Usage.NestedFunctions.NestedFunction
|
|
public function __construct( $channel, LoggerInterface $logger, LogCapturingSpi $parent ) {
|
|
$this->channel = $channel;
|
|
$this->logger = $logger;
|
|
$this->parent = $parent;
|
|
}
|
|
|
|
// phpcs:ignore MediaWiki.Usage.NestedFunctions.NestedFunction
|
|
public function log( $level, $message, array $context = [] ) {
|
|
$this->parent->capture( [
|
|
'channel' => $this->channel,
|
|
'level' => $level,
|
|
'message' => $message,
|
|
'context' => $context
|
|
] );
|
|
$this->logger->log( $level, $message, $context );
|
|
}
|
|
};
|
|
}
|
|
|
|
/**
|
|
* @internal For use by MediaWikiIntegrationTestCase
|
|
* @return Spi
|
|
*/
|
|
public function getInnerSpi() : Spi {
|
|
return $this->inner;
|
|
}
|
|
|
|
/**
|
|
* @internal For use by MediaWikiIntegrationTestCase
|
|
* @param string $channel
|
|
* @param LoggerInterface|null $logger
|
|
* @return LoggerInterface|null
|
|
*/
|
|
public function setLoggerForTest( $channel, LoggerInterface $logger = null ) {
|
|
$ret = $this->singletons[$channel] ?? null;
|
|
$this->singletons[$channel] = $logger;
|
|
return $ret;
|
|
}
|
|
}
|