MediaWiki  master
MonologSpi.php
Go to the documentation of this file.
1 <?php
21 namespace MediaWiki\Logger;
22 
24 use Monolog\Handler\NullHandler;
25 use Monolog\Handler\StreamHandler;
26 use Monolog\Logger;
27 use Wikimedia\ObjectFactory;
28 
117 class MonologSpi implements Spi {
118 
122  protected $singletons;
123 
128  protected $config;
129 
133  public function __construct( array $config ) {
134  $this->config = [];
135  $this->mergeConfig( $config );
136  }
137 
144  public function mergeConfig( array $config ) {
145  foreach ( $config as $key => $value ) {
146  if ( isset( $this->config[$key] ) ) {
147  $this->config[$key] = array_merge( $this->config[$key], $value );
148  } else {
149  $this->config[$key] = $value;
150  }
151  }
152  if ( !isset( $this->config['loggers']['@default'] ) ) {
153  $this->config['loggers']['@default'] = [
154  'handlers' => [ '@default' ],
155  ];
156  if ( !isset( $this->config['handlers']['@default'] ) ) {
157  $this->config['handlers']['@default'] = [
158  'class' => StreamHandler::class,
159  'args' => [ 'php://stderr', Logger::ERROR ],
160  ];
161  }
162  }
163  $this->reset();
164  }
165 
172  public function reset() {
173  $this->singletons = [
174  'loggers' => [],
175  'handlers' => [],
176  'formatters' => [],
177  'processors' => [],
178  ];
179  }
180 
191  public function getLogger( $channel ) {
192  if ( !isset( $this->singletons['loggers'][$channel] ) ) {
193  // Fallback to using the '@default' configuration if an explict
194  // configuration for the requested channel isn't found.
195  $spec = $this->config['loggers'][$channel] ?? $this->config['loggers']['@default'];
196 
197  $monolog = $this->createLogger( $channel, $spec );
198  $this->singletons['loggers'][$channel] = $monolog;
199  }
200 
201  return $this->singletons['loggers'][$channel];
202  }
203 
210  protected function createLogger( $channel, $spec ) {
211  $obj = new Logger( $channel );
212 
213  if ( isset( $spec['calls'] ) ) {
214  foreach ( $spec['calls'] as $method => $margs ) {
215  $obj->$method( ...$margs );
216  }
217  }
218 
219  if ( isset( $spec['processors'] ) ) {
220  foreach ( $spec['processors'] as $processor ) {
221  $obj->pushProcessor( $this->getProcessor( $processor ) );
222  }
223  }
224 
225  if ( isset( $spec['handlers'] ) && $spec['handlers'] ) {
226  foreach ( $spec['handlers'] as $handler ) {
227  $obj->pushHandler( $this->getHandler( $handler ) );
228  }
229  } else {
230  // When no handlers are registered Monolog 1.x sends logs to stderr,
231  // which could be not expected: avoid this behaviour
232  $obj->pushHandler( new NullHandler() );
233  }
234  return $obj;
235  }
236 
242  public function getProcessor( $name ) {
243  if ( !isset( $this->singletons['processors'][$name] ) ) {
244  $spec = $this->config['processors'][$name];
245  $processor = ObjectFactory::getObjectFromSpec( $spec );
246  $this->singletons['processors'][$name] = $processor;
247  }
248  return $this->singletons['processors'][$name];
249  }
250 
256  public function getHandler( $name ) {
257  if ( !isset( $this->singletons['handlers'][$name] ) ) {
258  $spec = $this->config['handlers'][$name];
259  $handler = ObjectFactory::getObjectFromSpec( $spec );
260  if (
261  isset( $spec['formatter'] ) &&
262  is_subclass_of( $handler, 'Monolog\Handler\FormattableHandlerInterface' )
263  ) {
264  $handler->setFormatter(
265  $this->getFormatter( $spec['formatter'] )
266  );
267  }
268  if ( isset( $spec['buffer'] ) && $spec['buffer'] ) {
269  $handler = new BufferHandler( $handler );
270  }
271  $this->singletons['handlers'][$name] = $handler;
272  }
273  return $this->singletons['handlers'][$name];
274  }
275 
281  public function getFormatter( $name ) {
282  if ( !isset( $this->singletons['formatters'][$name] ) ) {
283  $spec = $this->config['formatters'][$name];
284  $formatter = ObjectFactory::getObjectFromSpec( $spec );
285  $this->singletons['formatters'][$name] = $formatter;
286  }
287  return $this->singletons['formatters'][$name];
288  }
289 }
MediaWiki\Logger\MonologSpi\getFormatter
getFormatter( $name)
Create or return cached formatter.
Definition: MonologSpi.php:281
MediaWiki\Logger\MonologSpi
LoggerFactory service provider that creates loggers implemented by Monolog.
Definition: MonologSpi.php:117
MediaWiki\Logger\MonologSpi\$config
array[][] $config
Configuration for creating new loggers.
Definition: MonologSpi.php:128
MediaWiki\Logger\MonologSpi\$singletons
array $singletons
Definition: MonologSpi.php:122
MediaWiki\Logger\MonologSpi\getProcessor
getProcessor( $name)
Create or return cached processor.
Definition: MonologSpi.php:242
MediaWiki\Logger
Definition: ConsoleLogger.php:3
MediaWiki\Logger\MonologSpi\__construct
__construct(array $config)
Definition: MonologSpi.php:133
MediaWiki\Logger\MonologSpi\getLogger
getLogger( $channel)
Get a logger instance.
Definition: MonologSpi.php:191
MediaWiki\Logger\MonologSpi\getHandler
getHandler( $name)
Create or return cached handler.
Definition: MonologSpi.php:256
MediaWiki\Logger\MonologSpi\reset
reset()
Reset internal caches.
Definition: MonologSpi.php:172
MediaWiki\Logger\Monolog\BufferHandler
Updates \Monolog\Handler\BufferHandler to use DeferredUpdates rather than register_shutdown_function.
Definition: BufferHandler.php:35
MediaWiki\Logger\Spi
Service provider interface for \Psr\Log\LoggerInterface implementation libraries.
Definition: Spi.php:38
MediaWiki\Logger\MonologSpi\mergeConfig
mergeConfig(array $config)
Merge additional configuration data into the configuration.
Definition: MonologSpi.php:144
MediaWiki\Logger\MonologSpi\createLogger
createLogger( $channel, $spec)
Create a logger.
Definition: MonologSpi.php:210