* The following libraries are now required:
** psr/log
This library provides the interfaces set by the PSR-3 standard (http://www.php-fig.org/psr/psr-3/)
- which are used by MediaWiki internally via the MWLoggerFactory class.
+ which are used by MediaWiki internally via the
+ MediaWiki\Logger\LoggerFactory class.
See the structured logging RfC (https://www.mediawiki.org/wiki/Requests_for_comment/Structured_logging)
for more background information.
** cssjanus/cssjanus
* @file
*/
+use MediaWiki\Logger\LegacyLogger;
+
// So extensions (and other code) can check whether they're running in API mode
define( 'MW_API', true );
} else {
$items[] = "failed in ApiBeforeMain";
}
- MWLoggerLegacyLogger::emit( implode( ',', $items ) . "\n", $wgAPIRequestLog );
+ LegacyLogger::emit( implode( ',', $items ) . "\n", $wgAPIRequestLog );
wfDebug( "Logged API request to $wgAPIRequestLog\n" );
}
'MWFunction' => __DIR__ . '/includes/utils/MWFunction.php',
'MWHookException' => __DIR__ . '/includes/Hooks.php',
'MWHttpRequest' => __DIR__ . '/includes/HttpFunctions.php',
- 'MWLogger' => __DIR__ . '/includes/debug/logger/Logger.php',
- 'MWLoggerFactory' => __DIR__ . '/includes/debug/logger/Factory.php',
- 'MWLoggerLegacyLogger' => __DIR__ . '/includes/debug/logger/legacy/Logger.php',
- 'MWLoggerLegacySpi' => __DIR__ . '/includes/debug/logger/legacy/Spi.php',
- 'MWLoggerMonologHandler' => __DIR__ . '/includes/debug/logger/monolog/Handler.php',
- 'MWLoggerMonologLegacyFormatter' => __DIR__ . '/includes/debug/logger/monolog/LegacyFormatter.php',
- 'MWLoggerMonologProcessor' => __DIR__ . '/includes/debug/logger/monolog/Processor.php',
- 'MWLoggerMonologSpi' => __DIR__ . '/includes/debug/logger/monolog/Spi.php',
- 'MWLoggerMonologSyslogHandler' => __DIR__ . '/includes/debug/logger/monolog/SyslogHandler.php',
- 'MWLoggerNullSpi' => __DIR__ . '/includes/debug/logger/NullSpi.php',
- 'MWLoggerSpi' => __DIR__ . '/includes/debug/logger/Spi.php',
+ 'MWLogger' => __DIR__ . '/includes/debug/logger/Shims.php',
+ 'MWLoggerFactory' => __DIR__ . '/includes/debug/logger/Shims.php',
+ 'MWLoggerLegacyLogger' => __DIR__ . '/includes/debug/logger/Shims.php',
+ 'MWLoggerLegacySpi' => __DIR__ . '/includes/debug/logger/Shims.php',
+ 'MWLoggerMonologHandler' => __DIR__ . '/includes/debug/logger/Shims.php',
+ 'MWLoggerMonologLegacyFormatter' => __DIR__ . '/includes/debug/logger/Shims.php',
+ 'MWLoggerMonologProcessor' => __DIR__ . '/includes/debug/logger/Shims.php',
+ 'MWLoggerMonologSpi' => __DIR__ . '/includes/debug/logger/Shims.php',
+ 'MWLoggerMonologSyslogHandler' => __DIR__ . '/includes/debug/logger/Shims.php',
+ 'MWLoggerNullSpi' => __DIR__ . '/includes/debug/logger/Shims.php',
+ 'MWLoggerSpi' => __DIR__ . '/includes/debug/logger/Shims.php',
'MWMemcached' => __DIR__ . '/includes/objectcache/MemcachedClient.php',
'MWMessagePack' => __DIR__ . '/includes/libs/MWMessagePack.php',
'MWNamespace' => __DIR__ . '/includes/MWNamespace.php',
'MediaWikiSite' => __DIR__ . '/includes/site/MediaWikiSite.php',
'MediaWikiTitleCodec' => __DIR__ . '/includes/title/MediaWikiTitleCodec.php',
'MediaWikiVersionFetcher' => __DIR__ . '/includes/MediaWikiVersionFetcher.php',
+ 'MediaWiki\\Logger\\LegacyLogger' => __DIR__ . '/includes/debug/logger/LegacyLogger.php',
+ 'MediaWiki\\Logger\\LegacySpi' => __DIR__ . '/includes/debug/logger/LegacySpi.php',
+ 'MediaWiki\\Logger\\LoggerFactory' => __DIR__ . '/includes/debug/logger/LoggerFactory.php',
+ 'MediaWiki\\Logger\\MonologSpi' => __DIR__ . '/includes/debug/logger/MonologSpi.php',
+ 'MediaWiki\\Logger\\Monolog\\LegacyFormatter' => __DIR__ . '/includes/debug/logger/monolog/LegacyFormatter.php',
+ 'MediaWiki\\Logger\\Monolog\\LegacyHandler' => __DIR__ . '/includes/debug/logger/monolog/LegacyHandler.php',
+ 'MediaWiki\\Logger\\Monolog\\SyslogHandler' => __DIR__ . '/includes/debug/logger/monolog/SyslogHandler.php',
+ 'MediaWiki\\Logger\\Monolog\\WikiProcessor' => __DIR__ . '/includes/debug/logger/monolog/WikiProcessor.php',
+ 'MediaWiki\\Logger\\NullSpi' => __DIR__ . '/includes/debug/logger/NullSpi.php',
+ 'MediaWiki\\Logger\\Spi' => __DIR__ . '/includes/debug/logger/Spi.php',
'MemCachedClientforWiki' => __DIR__ . '/includes/objectcache/MemcachedClient.php',
'MemcLockManager' => __DIR__ . '/includes/filebackend/lockmanager/MemcLockManager.php',
'MemcachedBagOStuff' => __DIR__ . '/includes/objectcache/MemcachedBagOStuff.php',
--- /dev/null
+MediaWiki\Logger\LoggerFactory implements a PSR-3 [0] compatible message
+logging system.
+
+Named Psr\Log\LoggerInterface instances can be obtained from the
+MediaWiki\Logger\LoggerFactory::getInstance() static method.
+MediaWiki\Logger\LoggerFactory expects a class implementing the
+MediaWiki\Logger\Spi interface to act as a factory for new
+Psr\Log\LoggerInterface instances.
+
+The "Spi" in MediaWiki\Logger\Spi stands for "service provider interface". An
+SPI is an API intended to be implemented or extended by a third party. This
+software design pattern is intended to enable framework extension and
+replaceable components. It is specifically used in the
+MediaWiki\Logger\LoggerFactory service to allow alternate PSR-3 logging
+implementations to be easily integrated with MediaWiki.
+
+The service provider interface allows the backend logging library to be
+implemented in multiple ways. The $wgMWLoggerDefaultSpi global provides the
+classname of the default MediaWiki\Logger\Spi implementation to be loaded at
+runtime. This can either be the name of a class implementing the
+MediaWiki\Logger\Spi with a zero argument constructor or a callable that will
+return an MediaWiki\Logger\Spi instance. Alternately the
+MediaWiki\Logger\LoggerFactory::registerProvider() static method can be called
+to inject an MediaWiki\Logger\Spi instance into the LoggerFactory and bypass
+the use of the default configuration variable.
+
+The MediaWiki\Logger\LegacySpi class implements a service provider to generate
+MediaWiki\Logger\LegacyLogger instances. The MediaWiki\Logger\LegacyLogger
+class implements the PSR-3 logger interface and provides output and
+configuration equivalent to the historic logging output of wfDebug,
+wfDebugLog, wfLogDBError and wfErrorLog. The MediaWiki\Logger\LegacySpi class
+is the default service provider configured in DefaultSettings.php. It's usage
+should be transparent for users who are not ready or do not wish to switch to
+a alternate logging platform.
+
+The MediaWiki\Logger\MonologSpi class implements a service provider to
+generate Psr\Log\LoggerInterface instances that use the Monolog [1] logging
+library. See the PHP docs (or source) for MediaWiki\Logger\MonologSpi for
+details on the configuration of this provider. The default configuration
+installs a null handler that will silently discard all logging events. The
+documentation provided by the class describes a more feature rich logging
+configuration.
+
+== Classes ==
+; MediaWiki\Logger\LoggerFactory
+: Factory for Psr\Log\LoggerInterface loggers
+; MediaWiki\Logger\Spi
+: Service provider interface for MediaWiki\Logger\LoggerFactory
+; MediaWiki\Logger\NullSpi
+: MediaWiki\Logger\Spi for creating instances that discard all log events
+; MediaWiki\Logger\LegacySpi
+: Service provider for creating MediaWiki\Logger\LegacyLogger instances
+; MediaWiki\Logger\LegacyLogger
+: PSR-3 logger that mimics the historical output and configuration of wfDebug,
+ wfErrorLog and other global logging functions.
+; MediaWiki\Logger\MonologSpi
+: MediaWiki\Logger\Spi for creating instances backed by the monolog logging library
+; MediaWiki\Logger\Monolog\LegacyHandler
+: Monolog handler that replicates the udp2log and file logging
+ functionality of wfErrorLog()
+; MediaWiki\Logger\Monolog\WikiProcessor
+: Monolog log processer that adds host: wfHostname() and wiki: wfWikiID()
+ to all records
+
+== Globals ==
+; $wgMWLoggerDefaultSpi
+: Specification for creating the default service provider interface to use
+ with MediaWiki\Logger\LoggerFactory
+
+[0]: https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md
+[1]: https://github.com/Seldaek/monolog
+++ /dev/null
-MWLoggerFactory implements a PSR-3 [0] compatible message logging system.
-
-Named Psr\Log\LoggerInterface instances can be obtained from the
-MWLoggerFactory::getInstance() static method. MWLoggerFactory expects a class
-implementing the MWLoggerSpi interface to act as a factory for new
-Psr\Log\LoggerInterface instances.
-
-The "Spi" in MWLoggerSpi stands for "service provider interface". A SPI is
-an API intended to be implemented or extended by a third party. This software
-design pattern is intended to enable framework extension and replaceable
-components. It is specifically used in the MWLoggerFactory service to allow
-alternate PSR-3 logging implementations to be easily integrated with
-MediaWiki.
-
-The MWLoggerFactory::getInstance() static method is the means by which most
-code acquires a Psr\Log\LoggerInterface instance. This in turn delegates
-creation of Psr\Log\LoggerInterface instances to a class implementing the
-MWLoggerSpi service provider interface.
-
-The service provider interface allows the backend logging library to be
-implemented in multiple ways. The $wgMWLoggerDefaultSpi global provides the
-classname of the default MWLoggerSpi implementation to be loaded at runtime.
-This can either be the name of a class implementing the MWLoggerSpi with
-a zero argument constructor or a callable that will return an MWLoggerSpi
-instance. Alternately the MWLoggerFactory::registerProvider method can be
-called to inject an MWLoggerSpi instance into MWLoggerFactory and bypass the
-use of this configuration variable.
-
-The MWLoggerLegacySpi class implements a service provider to generate
-MWLoggerLegacyLogger instances. The MWLoggerLegacyLogger class implements the
-PSR-3 logger interface and provides output and configuration equivalent to the
-historic logging output of wfDebug, wfDebugLog, wfLogDBError and wfErrorLog.
-The MWLoggerLegacySpi class is the default service provider configured in
-DefaultSettings.php. It's usage should be transparent for users who are not
-ready or do not wish to switch to a alternate logging platform.
-
-The MWLoggerMonologSpi class implements a service provider to generate
-Psr\Log\LoggerInterface instances that use the Monolog [1] logging library.
-See the PHP docs (or source) for MWLoggerMonologSpi for details on the
-configuration of this provider. The default configuration installs a null
-handler that will silently discard all logging events. The documentation
-provided by the class describes a more feature rich logging configuration.
-
-== Classes ==
-; MWLoggerFactory
-: Factory for Psr\Log\LoggerInterface loggers
-; MWLoggerSpi
-: Service provider interface for MWLoggerFactory
-; MWLoggerNullSpi
-: MWLoggerSpi for creating instances that discard all log events
-; MWLoggerLegacySpi
-: Service provider for creating MWLoggerLegacyLogger instances
-; MWLoggerLegacyLogger
-: PSR-3 logger that mimics the historical output and configuration of wfDebug,
- wfErrorLog and other global logging functions.
-; MWLoggerMonologSpi
-: MWLoggerSpi for creating instances backed by the monolog logging library
-; MwLoggerMonologHandler
-: Monolog handler that replicates the udp2log and file logging
- functionality of wfErrorLog()
-; MwLoggerMonologProcessor
-: Monolog log processer that adds host: wfHostname() and wiki: wfWikiID()
- to all records
-
-== Globals ==
-; $wgMWLoggerDefaultSpi
-: Specification for creating the default service provider interface to use
- with MWLoggerFactory
-
-[0]: https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md
-[1]: https://github.com/Seldaek/monolog
*
* The value should be an array suitable for use with
* ObjectFactory::getObjectFromSpec(). The created object is expected to
- * implement the MWLoggerSpi interface. See ObjectFactory for additional
+ * implement the MediaWiki\Logger\Spi interface. See ObjectFactory for additional
* details.
*
- * Alternately the MWLoggerFactory::registerProvider method can be called to
- * inject an MWLoggerSpi instance into MWLoggerFactory and bypass the use of
- * this configuration variable entirely.
+ * Alternately the MediaWiki\Logger\LoggerFactory::registerProvider method can
+ * be called to inject an MediaWiki\Logger\Spi instance into the LoggerFactory
+ * and bypass the use of this configuration variable entirely.
*
* @par To completely disable logging:
* @code
- * $wgMWLoggerDefaultSpi = array( 'class' => 'MWLoggerNullSpi' );
+ * $wgMWLoggerDefaultSpi = array( 'class' => '\\MediaWiki\\Logger\\NullSpi' );
* @endcode
*
* @since 1.25
* @see MwLogger
*/
$wgMWLoggerDefaultSpi = array(
- 'class' => 'MWLoggerLegacySpi',
+ 'class' => '\\MediaWiki\\Logger\\LegacySpi',
);
/**
use Liuggio\StatsdClient\StatsdClient;
use Liuggio\StatsdClient\Sender\SocketSender;
+use MediaWiki\Logger\LoggerFactory;
// Hide compatibility functions from Doxygen
/// @cond
$context['prefix'] = $wgDebugLogPrefix;
}
- $logger = MWLoggerFactory::getInstance( 'wfDebug' );
+ $logger = LoggerFactory::getInstance( 'wfDebug' );
$logger->debug( $text, $context );
}
$text = trim( $text );
- $logger = MWLoggerFactory::getInstance( $logGroup );
+ $logger = LoggerFactory::getInstance( $logGroup );
$context['private'] = ( $dest === 'private' );
$logger->info( $text, $context );
}
* @param array $context Additional logging context data
*/
function wfLogDBError( $text, array $context = array() ) {
- $logger = MWLoggerFactory::getInstance( 'wfLogDBError' );
+ $logger = LoggerFactory::getInstance( 'wfLogDBError' );
$logger->error( trim( $text ), $context );
}
* @param string $file Filename
* @param array $context Additional logging context data
* @throws MWException
- * @deprecated since 1.25 Use MWLoggerLegacyLogger::emit or UDPTransport
+ * @deprecated since 1.25 Use MediaWiki\Logger\LegacyLogger::emit or UDPTransport
*/
function wfErrorLog( $text, $file, array $context = array() ) {
wfDeprecated( __METHOD__, '1.25' );
- $logger = MWLoggerFactory::getInstance( 'wfErrorLog' );
+ $logger = LoggerFactory::getInstance( 'wfErrorLog' );
$context['destination'] = $file;
$logger->info( trim( $text ), $context );
}
$ctx['output'] = $profiler->getOutput();
- $log = MWLoggerFactory::getInstance( 'profileoutput' );
+ $log = LoggerFactory::getInstance( 'profileoutput' );
$log->info( "Elapsed: {elapsed}; URL: <{url}>\n{output}", $ctx );
}
* @file
*/
+use MediaWiki\Logger\LoggerFactory;
+
/**
* The MediaWiki class is the helper class for the index.php entry point.
*/
$wgTitle = $title;
$trxProfiler = Profiler::instance()->getTransactionProfiler();
- $trxProfiler->setLogger( MWLoggerFactory::getInstance( 'DBPerformance' ) );
+ $trxProfiler->setLogger( LoggerFactory::getInstance( 'DBPerformance' ) );
// Aside from rollback, master queries should not happen on GET requests.
// Periodic or "in passing" updates on GET should use the job queue.
$n = intval( $jobRunRate );
}
- $runJobsLogger = MWLoggerFactory::getInstance( 'runJobs' );
+ $runJobsLogger = LoggerFactory::getInstance( 'runJobs' );
if ( !$this->config->get( 'RunJobsAsync' ) ) {
// Fall back to running the job here while the user waits
+++ /dev/null
-<?php
-/**
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- */
-
-
-/**
- * PSR-3 logger instance factory.
- *
- * Creation of \Psr\Log\LoggerInterface instances is managed via the
- * MWLoggerFactory::getInstance() static method which in turn delegates to the
- * currently registered service provider.
- *
- * A service provider is any class implementing the MWLoggerSpi interface.
- * There are two possible methods of registering a service provider. The
- * MWLoggerFactory::registerProvider() static method can be called at any time
- * to change the service provider. If MWLoggerFactory::getInstance() is called
- * before any service provider has been registered, it will attempt to use the
- * $wgMWLoggerDefaultSpi global to bootstrap MWLoggerSpi registration.
- * $wgMWLoggerDefaultSpi is expected to be an array usable by
- * ObjectFactory::getObjectFromSpec() to create a class.
- *
- * @see MWLoggerSpi
- * @since 1.25
- * @author Bryan Davis <bd808@wikimedia.org>
- * @copyright © 2014 Bryan Davis and Wikimedia Foundation.
- */
-class MWLoggerFactory {
-
- /**
- * Service provider.
- * @var MWLoggerSpi $spi
- */
- private static $spi;
-
-
- /**
- * Register a service provider to create new \Psr\Log\LoggerInterface
- * instances.
- *
- * @param MWLoggerSpi $provider Provider to register
- */
- public static function registerProvider( MWLoggerSpi $provider ) {
- self::$spi = $provider;
- }
-
-
- /**
- * Get the registered service provider.
- *
- * If called before any service provider has been registered, it will
- * attempt to use the $wgMWLoggerDefaultSpi global to bootstrap
- * MWLoggerSpi registration. $wgMWLoggerDefaultSpi is expected to be an
- * array usable by ObjectFactory::getObjectFromSpec() to create a class.
- *
- * @return MWLoggerSpi
- * @see registerProvider()
- * @see ObjectFactory::getObjectFromSpec()
- */
- public static function getProvider() {
- if ( self::$spi === null ) {
- global $wgMWLoggerDefaultSpi;
- $provider = ObjectFactory::getObjectFromSpec(
- $wgMWLoggerDefaultSpi
- );
- self::registerProvider( $provider );
- }
- return self::$spi;
- }
-
-
- /**
- * Get a named logger instance from the currently configured logger factory.
- *
- * @param string $channel Logger channel (name)
- * @return \Psr\Log\LoggerInterface
- */
- public static function getInstance( $channel ) {
- if ( !interface_exists( '\Psr\Log\LoggerInterface' ) ) {
- $message = <<<TXT
-MediaWiki requires the <a href="https://github.com/php-fig/log">PSR-3 logging library</a> to be present. This library is not embedded directly in MediaWiki's git repository and must be installed separately by the end user.
-
-Please see <a href="https://www.mediawiki.org/wiki/Download_from_Git#Fetch_external_libraries">mediawiki.org</a> for help on installing the required components.
-TXT;
- echo $message;
- trigger_error( $message, E_USER_ERROR );
- die( 1 );
- }
-
- return self::getProvider()->getLogger( $channel );
- }
-
-
- /**
- * Construction of utility class is not allowed.
- */
- private function __construct() {
- // no-op
- }
-}
--- /dev/null
+<?php
+/**
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ */
+
+namespace MediaWiki\Logger;
+
+use MWDebug;
+use Psr\Log\AbstractLogger;
+use Psr\Log\LogLevel;
+use UDPTransport;
+
+/**
+ * PSR-3 logger that mimics the historic implementation of MediaWiki's
+ * wfErrorLog logging implementation.
+ *
+ * This logger is configured by the following global configuration variables:
+ * - `$wgDebugLogFile`
+ * - `$wgDebugLogGroups`
+ * - `$wgDBerrorLog`
+ * - `$wgDBerrorLogTZ`
+ *
+ * See documentation in DefaultSettings.php for detailed explanations of each
+ * variable.
+ *
+ * @see \MediaWiki\Logger\LoggerFactory
+ * @since 1.25
+ * @author Bryan Davis <bd808@wikimedia.org>
+ * @copyright © 2014 Bryan Davis and Wikimedia Foundation.
+ */
+class LegacyLogger extends AbstractLogger {
+
+ /**
+ * @var string $channel
+ */
+ protected $channel;
+
+ /**
+ * Convert Psr\Log\LogLevel constants into int for sane comparisons
+ * These are the same values that Monlog uses
+ *
+ * @var array
+ */
+ protected static $levelMapping = array(
+ LogLevel::DEBUG => 100,
+ LogLevel::INFO => 200,
+ LogLevel::NOTICE => 250,
+ LogLevel::WARNING => 300,
+ LogLevel::ERROR => 400,
+ LogLevel::CRITICAL => 500,
+ LogLevel::ALERT => 550,
+ LogLevel::EMERGENCY => 600,
+ );
+
+
+ /**
+ * @param string $channel
+ */
+ public function __construct( $channel ) {
+ $this->channel = $channel;
+ }
+
+ /**
+ * Logs with an arbitrary level.
+ *
+ * @param string|int $level
+ * @param string $message
+ * @param array $context
+ */
+ public function log( $level, $message, array $context = array() ) {
+ if ( self::shouldEmit( $this->channel, $message, $level, $context ) ) {
+ $text = self::format( $this->channel, $message, $context );
+ $destination = self::destination( $this->channel, $message, $context );
+ self::emit( $text, $destination );
+ }
+ // Add to debug toolbar
+ MWDebug::debugMsg( $message, array( 'channel' => $this->channel ) + $context );
+ }
+
+
+ /**
+ * Determine if the given message should be emitted or not.
+ *
+ * @param string $channel
+ * @param string $message
+ * @param string|int $level Psr\Log\LogEvent constant or Monlog level int
+ * @param array $context
+ * @return bool True if message should be sent to disk/network, false
+ * otherwise
+ */
+ public static function shouldEmit( $channel, $message, $level, $context ) {
+ global $wgDebugLogFile, $wgDBerrorLog, $wgDebugLogGroups;
+
+ if ( $channel === 'wfLogDBError' ) {
+ // wfLogDBError messages are emitted if a database log location is
+ // specfied.
+ $shouldEmit = (bool)$wgDBerrorLog;
+
+ } elseif ( $channel === 'wfErrorLog' ) {
+ // All messages on the wfErrorLog channel should be emitted.
+ $shouldEmit = true;
+
+ } elseif ( isset( $wgDebugLogGroups[$channel] ) ) {
+ $logConfig = $wgDebugLogGroups[$channel];
+
+ if ( is_array( $logConfig ) ) {
+ $shouldEmit = true;
+ if ( isset( $logConfig['sample'] ) ) {
+ // Emit randomly with a 1 in 'sample' chance for each message.
+ $shouldEmit = mt_rand( 1, $logConfig['sample'] ) === 1;
+ }
+
+ if ( isset( $logConfig['level'] ) ) {
+ if ( is_string( $level ) ) {
+ $level = self::$levelMapping[$level];
+ }
+ $shouldEmit = $level >= self::$levelMapping[$logConfig['level']];
+ }
+ } else {
+ // Emit unless the config value is explictly false.
+ $shouldEmit = $logConfig !== false;
+ }
+
+ } elseif ( isset( $context['private'] ) && $context['private'] ) {
+ // Don't emit if the message didn't match previous checks based on
+ // the channel and the event is marked as private. This check
+ // discards messages sent via wfDebugLog() with dest == 'private'
+ // and no explicit wgDebugLogGroups configuration.
+ $shouldEmit = false;
+ } else {
+ // Default return value is the same as the historic wfDebug
+ // method: emit if $wgDebugLogFile has been set.
+ $shouldEmit = $wgDebugLogFile != '';
+ }
+
+ return $shouldEmit;
+ }
+
+
+ /**
+ * Format a message.
+ *
+ * Messages to the 'wfDebug', 'wfLogDBError' and 'wfErrorLog' channels
+ * receive special fomatting to mimic the historic output of the functions
+ * of the same name. All other channel values are formatted based on the
+ * historic output of the `wfDebugLog()` global function.
+ *
+ * @param string $channel
+ * @param string $message
+ * @param array $context
+ * @return string
+ */
+ public static function format( $channel, $message, $context ) {
+ global $wgDebugLogGroups;
+
+ if ( $channel === 'wfDebug' ) {
+ $text = self::formatAsWfDebug( $channel, $message, $context );
+
+ } elseif ( $channel === 'wfLogDBError' ) {
+ $text = self::formatAsWfLogDBError( $channel, $message, $context );
+
+ } elseif ( $channel === 'wfErrorLog' ) {
+ $text = "{$message}\n";
+
+ } elseif ( $channel === 'profileoutput' ) {
+ // Legacy wfLogProfilingData formatitng
+ $forward = '';
+ if ( isset( $context['forwarded_for'] )) {
+ $forward = " forwarded for {$context['forwarded_for']}";
+ }
+ if ( isset( $context['client_ip'] ) ) {
+ $forward .= " client IP {$context['client_ip']}";
+ }
+ if ( isset( $context['from'] ) ) {
+ $forward .= " from {$context['from']}";
+ }
+ if ( $forward ) {
+ $forward = "\t(proxied via {$context['proxy']}{$forward})";
+ }
+ if ( $context['anon'] ) {
+ $forward .= ' anon';
+ }
+ if ( !isset( $context['url'] ) ) {
+ $context['url'] = 'n/a';
+ }
+
+ $log = sprintf( "%s\t%04.3f\t%s%s\n",
+ gmdate( 'YmdHis' ), $context['elapsed'], $context['url'], $forward );
+
+ $text = self::formatAsWfDebugLog(
+ $channel, $log . $context['output'], $context );
+
+ } elseif ( !isset( $wgDebugLogGroups[$channel] ) ) {
+ $text = self::formatAsWfDebug(
+ $channel, "[{$channel}] {$message}", $context );
+
+ } else {
+ // Default formatting is wfDebugLog's historic style
+ $text = self::formatAsWfDebugLog( $channel, $message, $context );
+ }
+
+ return self::interpolate( $text, $context );
+ }
+
+
+ /**
+ * Format a message as `wfDebug()` would have formatted it.
+ *
+ * @param string $channel
+ * @param string $message
+ * @param array $context
+ * @return string
+ */
+ protected static function formatAsWfDebug( $channel, $message, $context ) {
+ $text = preg_replace( '![\x00-\x08\x0b\x0c\x0e-\x1f]!', ' ', $message );
+ if ( isset( $context['seconds_elapsed'] ) ) {
+ // Prepend elapsed request time and real memory usage with two
+ // trailing spaces.
+ $text = "{$context['seconds_elapsed']} {$context['memory_used']} {$text}";
+ }
+ if ( isset( $context['prefix'] ) ) {
+ $text = "{$context['prefix']}{$text}";
+ }
+ return "{$text}\n";
+ }
+
+
+ /**
+ * Format a message as `wfLogDBError()` would have formatted it.
+ *
+ * @param string $channel
+ * @param string $message
+ * @param array $context
+ * @return string
+ */
+ protected static function formatAsWfLogDBError( $channel, $message, $context ) {
+ global $wgDBerrorLogTZ;
+ static $cachedTimezone = null;
+
+ if ( $wgDBerrorLogTZ && !$cachedTimezone ) {
+ $cachedTimezone = new DateTimeZone( $wgDBerrorLogTZ );
+ }
+
+ // Workaround for https://bugs.php.net/bug.php?id=52063
+ // Can be removed when min PHP > 5.3.6
+ if ( $cachedTimezone === null ) {
+ $d = date_create( 'now' );
+ } else {
+ $d = date_create( 'now', $cachedTimezone );
+ }
+ $date = $d->format( 'D M j G:i:s T Y' );
+
+ $host = wfHostname();
+ $wiki = wfWikiID();
+
+ $text = "{$date}\t{$host}\t{$wiki}\t{$message}\n";
+ return $text;
+ }
+
+
+ /**
+ * Format a message as `wfDebugLog() would have formatted it.
+ *
+ * @param string $channel
+ * @param string $message
+ * @param array $context
+ */
+ protected static function formatAsWfDebugLog( $channel, $message, $context ) {
+ $time = wfTimestamp( TS_DB );
+ $wiki = wfWikiID();
+ $host = wfHostname();
+ $text = "{$time} {$host} {$wiki}: {$message}\n";
+ return $text;
+ }
+
+
+ /**
+ * Interpolate placeholders in logging message.
+ *
+ * @param string $message
+ * @param array $context
+ * @return string Interpolated message
+ */
+ public static function interpolate( $message, array $context ) {
+ if ( strpos( $message, '{' ) !== false ) {
+ $replace = array();
+ foreach ( $context as $key => $val ) {
+ $replace['{' . $key . '}'] = $val;
+ }
+ $message = strtr( $message, $replace );
+ }
+ return $message;
+ }
+
+
+ /**
+ * Select the appropriate log output destination for the given log event.
+ *
+ * If the event context contains 'destination'
+ *
+ * @param string $channel
+ * @param string $message
+ * @param array $context
+ * @return string
+ */
+ protected static function destination( $channel, $message, $context ) {
+ global $wgDebugLogFile, $wgDBerrorLog, $wgDebugLogGroups;
+
+ // Default destination is the debug log file as historically used by
+ // the wfDebug function.
+ $destination = $wgDebugLogFile;
+
+ if ( isset( $context['destination'] ) ) {
+ // Use destination explicitly provided in context
+ $destination = $context['destination'];
+
+ } elseif ( $channel === 'wfDebug' ) {
+ $destination = $wgDebugLogFile;
+
+ } elseif ( $channel === 'wfLogDBError' ) {
+ $destination = $wgDBerrorLog;
+
+ } elseif ( isset( $wgDebugLogGroups[$channel] ) ) {
+ $logConfig = $wgDebugLogGroups[$channel];
+
+ if ( is_array( $logConfig ) ) {
+ $destination = $logConfig['destination'];
+ } else {
+ $destination = strval( $logConfig );
+ }
+ }
+
+ return $destination;
+ }
+
+
+ /**
+ * Log to a file without getting "file size exceeded" signals.
+ *
+ * Can also log to UDP with the syntax udp://host:port/prefix. This will send
+ * lines to the specified port, prefixed by the specified prefix and a space.
+ *
+ * @param string $text
+ * @param string $file Filename
+ * @throws MWException
+ */
+ public static function emit( $text, $file ) {
+ if ( substr( $file, 0, 4 ) == 'udp:' ) {
+ $transport = UDPTransport::newFromString( $file );
+ $transport->emit( $text );
+ } else {
+ wfSuppressWarnings();
+ $exists = file_exists( $file );
+ $size = $exists ? filesize( $file ) : false;
+ if ( !$exists ||
+ ( $size !== false && $size + strlen( $text ) < 0x7fffffff )
+ ) {
+ file_put_contents( $file, $text, FILE_APPEND );
+ }
+ wfRestoreWarnings();
+ }
+ }
+
+}
--- /dev/null
+<?php
+/**
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ */
+
+namespace MediaWiki\Logger;
+
+/**
+ * LoggerFactory service provider that creates LegacyLogger instances.
+ *
+ * Usage:
+ * @code
+ * $wgMWLoggerDefaultSpi = array(
+ * 'class' => '\\MediaWiki\\Logger\\LegacySpi',
+ * );
+ * @endcode
+ *
+ * @see \MediaWiki\Logger\LoggerFactory
+ * @since 1.25
+ * @author Bryan Davis <bd808@wikimedia.org>
+ * @copyright © 2014 Bryan Davis and Wikimedia Foundation.
+ */
+class LegacySpi implements Spi {
+
+ /**
+ * @var array $singletons
+ */
+ protected $singletons = array();
+
+
+ /**
+ * Get a logger instance.
+ *
+ * @param string $channel Logging channel
+ * @return \Psr\Log\LoggerInterface Logger instance
+ */
+ public function getLogger( $channel ) {
+ if ( !isset( $this->singletons[$channel] ) ) {
+ $this->singletons[$channel] = new LegacyLogger( $channel );
+ }
+ return $this->singletons[$channel];
+ }
+
+}
+++ /dev/null
-<?php
-/**
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- */
-
-
-/**
- * Backwards compatibility stub for usage from before the introduction of
- * MWLoggerFactory.
- *
- * @deprecated since 1.25 Use MWLoggerFactory
- * @todo This class should be removed before the 1.25 final release.
- */
-class MWLogger {
-
- /**
- * Register a service provider to create new \Psr\Log\LoggerInterface
- * instances.
- *
- * @param MWLoggerSpi $provider Provider to register
- * @deprecated since 1.25 Use MWLoggerFactory::registerProvider()
- */
- public static function registerProvider( MWLoggerSpi $provider ) {
- MWLoggerFactory::registerProvider( $provider );
- }
-
-
- /**
- * Get the registered service provider.
- *
- * If called before any service provider has been registered, it will
- * attempt to use the $wgMWLoggerDefaultSpi global to bootstrap
- * MWLoggerSpi registration. $wgMWLoggerDefaultSpi is expected to be an
- * array usable by ObjectFactory::getObjectFromSpec() to create a class.
- *
- * @return MWLoggerSpi
- * @see registerProvider()
- * @see ObjectFactory::getObjectFromSpec()
- * @deprecated since 1.25 Use MWLoggerFactory::getProvider()
- */
- public static function getProvider() {
- return MWLoggerFactory::getProvider();
- }
-
-
- /**
- * Get a named logger instance from the currently configured logger factory.
- *
- * @param string $channel Logger channel (name)
- * @return \Psr\Log\LoggerInterface
- * @deprecated since 1.25 Use MWLoggerFactory::getInstance()
- */
- public static function getInstance( $channel ) {
- return MWLoggerFactory::getInstance( $channel );
- }
-
-}
--- /dev/null
+<?php
+/**
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ */
+
+namespace MediaWiki\Logger;
+
+use ObjectFactory;
+
+/**
+ * PSR-3 logger instance factory.
+ *
+ * Creation of \Psr\Log\LoggerInterface instances is managed via the
+ * LoggerFactory::getInstance() static method which in turn delegates to the
+ * currently registered service provider.
+ *
+ * A service provider is any class implementing the Spi interface.
+ * There are two possible methods of registering a service provider. The
+ * LoggerFactory::registerProvider() static method can be called at any time
+ * to change the service provider. If LoggerFactory::getInstance() is called
+ * before any service provider has been registered, it will attempt to use the
+ * $wgMWLoggerDefaultSpi global to bootstrap Spi registration.
+ * $wgMWLoggerDefaultSpi is expected to be an array usable by
+ * ObjectFactory::getObjectFromSpec() to create a class.
+ *
+ * @see \MediaWiki\Logger\Spi
+ * @since 1.25
+ * @author Bryan Davis <bd808@wikimedia.org>
+ * @copyright © 2014 Bryan Davis and Wikimedia Foundation.
+ */
+class LoggerFactory {
+
+ /**
+ * Service provider.
+ * @var Spi $spi
+ */
+ private static $spi;
+
+
+ /**
+ * Register a service provider to create new \Psr\Log\LoggerInterface
+ * instances.
+ *
+ * @param Spi $provider Provider to register
+ */
+ public static function registerProvider( Spi $provider ) {
+ self::$spi = $provider;
+ }
+
+
+ /**
+ * Get the registered service provider.
+ *
+ * If called before any service provider has been registered, it will
+ * attempt to use the $wgMWLoggerDefaultSpi global to bootstrap
+ * Spi registration. $wgMWLoggerDefaultSpi is expected to be an
+ * array usable by ObjectFactory::getObjectFromSpec() to create a class.
+ *
+ * @return Spi
+ * @see registerProvider()
+ * @see ObjectFactory::getObjectFromSpec()
+ */
+ public static function getProvider() {
+ if ( self::$spi === null ) {
+ global $wgMWLoggerDefaultSpi;
+ $provider = ObjectFactory::getObjectFromSpec(
+ $wgMWLoggerDefaultSpi
+ );
+ self::registerProvider( $provider );
+ }
+ return self::$spi;
+ }
+
+
+ /**
+ * Get a named logger instance from the currently configured logger factory.
+ *
+ * @param string $channel Logger channel (name)
+ * @return \Psr\Log\LoggerInterface
+ */
+ public static function getInstance( $channel ) {
+ if ( !interface_exists( '\Psr\Log\LoggerInterface' ) ) {
+ $message = (
+ 'MediaWiki requires the <a href="https://github.com/php-fig/log">PSR-3 logging ' .
+ "library</a> to be present. This library is not embedded directly in MediaWiki's " .
+ "git repository and must be installed separately by the end user.\n\n" .
+ 'Please see <a href="https://www.mediawiki.org/wiki/Download_from_Git' .
+ '#Fetch_external_libraries">mediawiki.org</a> for help on installing ' .
+ 'the required components.'
+ );
+ echo $message;
+ trigger_error( $message, E_USER_ERROR );
+ die( 1 );
+ }
+
+ return self::getProvider()->getLogger( $channel );
+ }
+
+
+ /**
+ * Construction of utility class is not allowed.
+ */
+ private function __construct() {
+ // no-op
+ }
+}
--- /dev/null
+<?php
+/**
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ */
+
+namespace MediaWiki\Logger;
+
+use Monolog\Logger;
+use ObjectFactory;
+
+/**
+ * LoggerFactory service provider that creates loggers implemented by
+ * Monolog.
+ *
+ * Configured using an array of configuration data with the keys 'loggers',
+ * 'processors', 'handlers' and 'formatters'.
+ *
+ * The ['loggers']['@default'] configuration will be used to create loggers
+ * for any channel that isn't explicitly named in the 'loggers' configuration
+ * section.
+ *
+ * Configuration will most typically be provided in the $wgMWLoggerDefaultSpi
+ * global configuration variable used by LoggerFactory to construct its
+ * default SPI provider:
+ * @code
+ * $wgMWLoggerDefaultSpi = array(
+ * 'class' => '\\MediaWiki\\Logger\\MonologSpi',
+ * 'args' => array( array(
+ * 'loggers' => array(
+ * '@default' => array(
+ * 'processors' => array( 'wiki', 'psr', 'pid', 'uid', 'web' ),
+ * 'handlers' => array( 'stream' ),
+ * ),
+ * 'runJobs' => array(
+ * 'processors' => array( 'wiki', 'psr', 'pid' ),
+ * 'handlers' => array( 'stream' ),
+ * )
+ * ),
+ * 'processors' => array(
+ * 'wiki' => array(
+ * 'class' => '\\MediaWiki\\Logger\\Monolog\\WikiProcessor',
+ * ),
+ * 'psr' => array(
+ * 'class' => '\\Monolog\\Processor\\PsrLogMessageProcessor',
+ * ),
+ * 'pid' => array(
+ * 'class' => '\\Monolog\\Processor\\ProcessIdProcessor',
+ * ),
+ * 'uid' => array(
+ * 'class' => '\\Monolog\\Processor\\UidProcessor',
+ * ),
+ * 'web' => array(
+ * 'class' => '\\Monolog\\Processor\\WebProcessor',
+ * ),
+ * ),
+ * 'handlers' => array(
+ * 'stream' => array(
+ * 'class' => '\\Monolog\\Handler\\StreamHandler',
+ * 'args' => array( 'path/to/your.log' ),
+ * 'formatter' => 'line',
+ * ),
+ * 'redis' => array(
+ * 'class' => '\\Monolog\\Handler\\RedisHandler',
+ * 'args' => array( function() {
+ * $redis = new Redis();
+ * $redis->connect( '127.0.0.1', 6379 );
+ * return $redis;
+ * },
+ * 'logstash'
+ * ),
+ * 'formatter' => 'logstash',
+ * ),
+ * 'udp2log' => array(
+ * 'class' => '\\MediaWiki\\Logger\\Monolog\\LegacyHandler',
+ * 'args' => array(
+ * 'udp://127.0.0.1:8420/mediawiki
+ * ),
+ * 'formatter' => 'line',
+ * ),
+ * ),
+ * 'formatters' => array(
+ * 'line' => array(
+ * 'class' => '\\Monolog\\Formatter\\LineFormatter',
+ * ),
+ * 'logstash' => array(
+ * 'class' => '\\Monolog\\Formatter\\LogstashFormatter',
+ * 'args' => array( 'mediawiki', php_uname( 'n' ), null, '', 1 ),
+ * ),
+ * ),
+ * ) ),
+ * );
+ * @endcode
+ *
+ * @see https://github.com/Seldaek/monolog
+ * @since 1.25
+ * @author Bryan Davis <bd808@wikimedia.org>
+ * @copyright © 2014 Bryan Davis and Wikimedia Foundation.
+ */
+class MonologSpi implements Spi {
+
+ /**
+ * @var array $singletons
+ */
+ protected $singletons;
+
+ /**
+ * Configuration for creating new loggers.
+ * @var array $config
+ */
+ protected $config;
+
+
+ /**
+ * @param array $config Configuration data.
+ */
+ public function __construct( array $config ) {
+ $this->config = $config;
+ $this->reset();
+ }
+
+
+ /**
+ * Reset internal caches.
+ *
+ * This is public for use in unit tests. Under normal operation there should
+ * be no need to flush the caches.
+ */
+ public function reset() {
+ $this->singletons = array(
+ 'loggers' => array(),
+ 'handlers' => array(),
+ 'formatters' => array(),
+ 'processors' => array(),
+ );
+ }
+
+
+ /**
+ * Get a logger instance.
+ *
+ * Creates and caches a logger instance based on configuration found in the
+ * $wgMWLoggerMonologSpiConfig global. Subsequent request for the same channel
+ * name will return the cached instance.
+ *
+ * @param string $channel Logging channel
+ * @return \Psr\Log\LoggerInterface Logger instance
+ */
+ public function getLogger( $channel ) {
+ if ( !isset( $this->singletons['loggers'][$channel] ) ) {
+ // Fallback to using the '@default' configuration if an explict
+ // configuration for the requested channel isn't found.
+ $spec = isset( $this->config['loggers'][$channel] ) ?
+ $this->config['loggers'][$channel] :
+ $this->config['loggers']['@default'];
+
+ $monolog = $this->createLogger( $channel, $spec );
+ $this->singletons['loggers'][$channel] = $monolog;
+ }
+
+ return $this->singletons['loggers'][$channel];
+ }
+
+
+ /**
+ * Create a logger.
+ * @param string $channel Logger channel
+ * @param array $spec Configuration
+ * @return \Monolog\Logger
+ */
+ protected function createLogger( $channel, $spec ) {
+ $obj = new Logger( $channel );
+
+ if ( isset( $spec['processors'] ) ) {
+ foreach ( $spec['processors'] as $processor ) {
+ $obj->pushProcessor( $this->getProcessor( $processor ) );
+ }
+ }
+
+ if ( isset( $spec['handlers'] ) ) {
+ foreach ( $spec['handlers'] as $handler ) {
+ $obj->pushHandler( $this->getHandler( $handler ) );
+ }
+ }
+ return $obj;
+ }
+
+
+ /**
+ * Create or return cached processor.
+ * @param string $name Processor name
+ * @return callable
+ */
+ public function getProcessor( $name ) {
+ if ( !isset( $this->singletons['processors'][$name] ) ) {
+ $spec = $this->config['processors'][$name];
+ $processor = ObjectFactory::getObjectFromSpec( $spec );
+ $this->singletons['processors'][$name] = $processor;
+ }
+ return $this->singletons['processors'][$name];
+ }
+
+
+ /**
+ * Create or return cached handler.
+ * @param string $name Processor name
+ * @return \Monolog\Handler\HandlerInterface
+ */
+ public function getHandler( $name ) {
+ if ( !isset( $this->singletons['handlers'][$name] ) ) {
+ $spec = $this->config['handlers'][$name];
+ $handler = ObjectFactory::getObjectFromSpec( $spec );
+ if ( isset( $spec['formatter'] ) ) {
+ $handler->setFormatter(
+ $this->getFormatter( $spec['formatter'] )
+ );
+ }
+ $this->singletons['handlers'][$name] = $handler;
+ }
+ return $this->singletons['handlers'][$name];
+ }
+
+
+ /**
+ * Create or return cached formatter.
+ * @param string $name Formatter name
+ * @return \Monolog\Formatter\FormatterInterface
+ */
+ public function getFormatter( $name ) {
+ if ( !isset( $this->singletons['formatters'][$name] ) ) {
+ $spec = $this->config['formatters'][$name];
+ $formatter = ObjectFactory::getObjectFromSpec( $spec );
+ $this->singletons['formatters'][$name] = $formatter;
+ }
+ return $this->singletons['formatters'][$name];
+ }
+}
* @file
*/
+namespace MediaWiki\Logger;
+
+use Psr\Log\NullLogger;
/**
- * MWLoggerFactory service provider that creates \Psr\Log\NullLogger
+ * LoggerFactory service provider that creates \Psr\Log\NullLogger
* instances. A NullLogger silently discards all log events sent to it.
*
* Usage:
* @code
* $wgMWLoggerDefaultSpi = array(
- * 'class' => 'MWLoggerNullSpi',
+ * 'class' => '\\MediaWiki\\Logger\\NullSpi',
* );
* @endcode
*
- * @see MWLoggerFactory
+ * @see \MediaWiki\Logger\LoggerFactory
* @since 1.25
* @author Bryan Davis <bd808@wikimedia.org>
* @copyright © 2014 Bryan Davis and Wikimedia Foundation.
*/
-class MWLoggerNullSpi implements MWLoggerSpi {
+class NullSpi implements Spi {
/**
* @var \Psr\Log\NullLogger $singleton
public function __construct() {
- $this->singleton = new \Psr\Log\NullLogger();
+ $this->singleton = new NullLogger();
}
--- /dev/null
+<?php
+/**
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ */
+
+/**
+ * Backwards compatibility stub for usage from before the introduction of
+ * MediaWiki\Logger\LoggerFactory.
+ *
+ * @deprecated since 1.25 Use \MediaWiki\Logger\LoggerFactory
+ * @todo This class should be removed before the 1.25 final release.
+ */
+class MWLogger {
+
+ /**
+ * Register a service provider to create new \Psr\Log\LoggerInterface
+ * instances.
+ *
+ * @param \MediaWiki\Logger\Spi $provider Provider to register
+ * @deprecated since 1.25 Use MediaWiki\Logger\LoggerFactory::registerProvider()
+ */
+ public static function registerProvider( \MediaWiki\Logger\Spi $provider ) {
+ \MediaWiki\Logger\LoggerFactory::registerProvider( $provider );
+ }
+
+
+ /**
+ * Get the registered service provider.
+ *
+ * If called before any service provider has been registered, it will
+ * attempt to use the $wgMWLoggerDefaultSpi global to bootstrap
+ * MWLoggerSpi registration. $wgMWLoggerDefaultSpi is expected to be an
+ * array usable by ObjectFactory::getObjectFromSpec() to create a class.
+ *
+ * @return \MediaWiki\Logger\Spi
+ * @see registerProvider()
+ * @see ObjectFactory::getObjectFromSpec()
+ * @deprecated since 1.25 Use MediaWiki\Logger\LoggerFactory::getProvider()
+ */
+ public static function getProvider() {
+ return \MediaWiki\Logger\LoggerFactory::getProvider();
+ }
+
+
+ /**
+ * Get a named logger instance from the currently configured logger factory.
+ *
+ * @param string $channel Logger channel (name)
+ * @return \Psr\Log\LoggerInterface
+ * @deprecated since 1.25 Use MediaWiki\Logger\LoggerFactory::getInstance()
+ */
+ public static function getInstance( $channel ) {
+ return \MediaWiki\Logger\LoggerFactory::getInstance( $channel );
+ }
+
+}
+
+/**
+ * Backwards compatibility stub for usage from before the introduction of
+ * the MediaWiki\Logger namespace.
+ *
+ * @deprecated since 1.25 Use \MediaWiki\Logger\LoggerFactory
+ * @todo This class should be removed before the 1.25 final release.
+ */
+class MWLoggerFactory extends \MediaWiki\Logger\LoggerFactory {
+}
+
+/**
+ * Backwards compatibility stub for usage from before the introduction of
+ * the MediaWiki\Logger namespace.
+ *
+ * @deprecated since 1.25 Use \MediaWiki\Logger\LegacyLogger
+ * @todo This class should be removed before the 1.25 final release.
+ */
+class MWLoggerLegacyLogger extends \MediaWiki\Logger\LegacyLogger {
+}
+
+/**
+ * Backwards compatibility stub for usage from before the introduction of
+ * the MediaWiki\Logger namespace.
+ *
+ * @deprecated since 1.25 Use \MediaWiki\Logger\LegacySpi
+ * @todo This class should be removed before the 1.25 final release.
+ */
+class MWLoggerLegacySpi extends \MediaWiki\Logger\LegacySpi {
+}
+
+/**
+ * Backwards compatibility stub for usage from before the introduction of
+ * the MediaWiki\Logger namespace.
+ *
+ * @deprecated since 1.25 Use \MediaWiki\Logger\Monolog\LegacyHandler
+ * @todo This class should be removed before the 1.25 final release.
+ */
+class MWLoggerMonologHandler extends \MediaWiki\Logger\Monolog\LegacyHandler {
+}
+
+/**
+ * Backwards compatibility stub for usage from before the introduction of
+ * the MediaWiki\Logger namespace.
+ *
+ * @deprecated since 1.25 Use \MediaWiki\Logger\Monolog\LegacyFormatter
+ * @todo This class should be removed before the 1.25 final release.
+ */
+class MWLoggerMonologLegacyFormatter extends \MediaWiki\Logger\Monolog\LegacyFormatter {
+}
+
+/**
+ * Backwards compatibility stub for usage from before the introduction of
+ * the MediaWiki\Logger namespace.
+ *
+ * @deprecated since 1.25 Use \MediaWiki\Logger\Monolog\WikiProcessor
+ * @todo This class should be removed before the 1.25 final release.
+ */
+class MWLoggerMonologProcessor extends \MediaWiki\Logger\Monolog\WikiProcessor {
+}
+
+/**
+ * Backwards compatibility stub for usage from before the introduction of
+ * the MediaWiki\Logger namespace.
+ *
+ * @deprecated since 1.25 Use \MediaWiki\Logger\MonologSpi
+ * @todo This class should be removed before the 1.25 final release.
+ */
+class MWLoggerMonologSpi extends \MediaWiki\Logger\MonologSpi {
+}
+
+/**
+ * Backwards compatibility stub for usage from before the introduction of
+ * the MediaWiki\Logger namespace.
+ *
+ * @deprecated since 1.25 Use \MediaWiki\Logger\Monolog\SyslogHandler
+ * @todo This class should be removed before the 1.25 final release.
+ */
+class MWLoggerMonologSyslogHandler extends \MediaWiki\Logger\Monolog\SyslogHandler {
+}
+
+/**
+ * Backwards compatibility stub for usage from before the introduction of
+ * the MediaWiki\Logger namespace.
+ *
+ * @deprecated since 1.25 Use \MediaWiki\Logger\NullSpi
+ * @todo This class should be removed before the 1.25 final release.
+ */
+class MWLoggerNullSpi extends \MediaWiki\Logger\NullSpi {
+}
+
+/**
+ * Backwards compatibility stub for usage from before the introduction of
+ * the MediaWiki\Logger namespace.
+ *
+ * @deprecated since 1.25 Use \MediaWiki\Logger\Spi
+ * @todo This class should be removed before the 1.25 final release.
+ */
+interface MWLoggerSpi extends \MediaWiki\Logger\Spi {
+}
* @file
*/
+namespace MediaWiki\Logger;
+
/**
* Service provider interface for \Psr\Log\LoggerInterface implementation
* libraries.
* MediaWiki can be configured to use a class implementing this interface to
* create new \Psr\Log\LoggerInterface instances via either the
* $wgMWLoggerDefaultSpi global variable or code that constructs an instance
- * and registers it via the MWLoggerFactory::registerProvider() static method.
+ * and registers it via the LoggerFactory::registerProvider() static method.
*
- * @see MWLoggerFactory
+ * @see \MediaWiki\Logger\LoggerFactory
* @since 1.25
* @author Bryan Davis <bd808@wikimedia.org>
* @copyright © 2014 Bryan Davis and Wikimedia Foundation.
*/
-interface MWLoggerSpi {
+interface Spi {
/**
* Get a logger instance.
+++ /dev/null
-<?php
-/**
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- */
-
-/**
- * PSR-3 logger that mimics the historic implementation of MediaWiki's
- * wfErrorLog logging implementation.
- *
- * This logger is configured by the following global configuration variables:
- * - `$wgDebugLogFile`
- * - `$wgDebugLogGroups`
- * - `$wgDBerrorLog`
- * - `$wgDBerrorLogTZ`
- *
- * See documentation in DefaultSettings.php for detailed explanations of each
- * variable.
- *
- * @see MWLoggerFactory
- * @since 1.25
- * @author Bryan Davis <bd808@wikimedia.org>
- * @copyright © 2014 Bryan Davis and Wikimedia Foundation.
- */
-use Psr\Log\AbstractLogger;
-use Psr\Log\LogLevel;
-
-class MWLoggerLegacyLogger extends AbstractLogger {
-
- /**
- * @var string $channel
- */
- protected $channel;
-
- /**
- * Convert Psr\Log\LogLevel constants into int for sane comparisons
- * These are the same values that Monlog uses
- *
- * @var array
- */
- protected static $levelMapping = array(
- LogLevel::DEBUG => 100,
- LogLevel::INFO => 200,
- LogLevel::NOTICE => 250,
- LogLevel::WARNING => 300,
- LogLevel::ERROR => 400,
- LogLevel::CRITICAL => 500,
- LogLevel::ALERT => 550,
- LogLevel::EMERGENCY => 600,
- );
-
-
- /**
- * @param string $channel
- */
- public function __construct( $channel ) {
- $this->channel = $channel;
- }
-
- /**
- * Logs with an arbitrary level.
- *
- * @param string|int $level
- * @param string $message
- * @param array $context
- */
- public function log( $level, $message, array $context = array() ) {
- if ( self::shouldEmit( $this->channel, $message, $level, $context ) ) {
- $text = self::format( $this->channel, $message, $context );
- $destination = self::destination( $this->channel, $message, $context );
- self::emit( $text, $destination );
- }
- // Add to debug toolbar
- MWDebug::debugMsg( $message, array( 'channel' => $this->channel ) + $context );
- }
-
-
- /**
- * Determine if the given message should be emitted or not.
- *
- * @param string $channel
- * @param string $message
- * @param string|int $level Psr\Log\LogEvent constant or Monlog level int
- * @param array $context
- * @return bool True if message should be sent to disk/network, false
- * otherwise
- */
- public static function shouldEmit( $channel, $message, $level, $context ) {
- global $wgDebugLogFile, $wgDBerrorLog, $wgDebugLogGroups;
-
- if ( $channel === 'wfLogDBError' ) {
- // wfLogDBError messages are emitted if a database log location is
- // specfied.
- $shouldEmit = (bool)$wgDBerrorLog;
-
- } elseif ( $channel === 'wfErrorLog' ) {
- // All messages on the wfErrorLog channel should be emitted.
- $shouldEmit = true;
-
- } elseif ( isset( $wgDebugLogGroups[$channel] ) ) {
- $logConfig = $wgDebugLogGroups[$channel];
-
- if ( is_array( $logConfig ) ) {
- $shouldEmit = true;
- if ( isset( $logConfig['sample'] ) ) {
- // Emit randomly with a 1 in 'sample' chance for each message.
- $shouldEmit = mt_rand( 1, $logConfig['sample'] ) === 1;
- }
-
- if ( isset( $logConfig['level'] ) ) {
- if ( is_string( $level ) ) {
- $level = self::$levelMapping[$level];
- }
- $shouldEmit = $level >= self::$levelMapping[$logConfig['level']];
- }
- } else {
- // Emit unless the config value is explictly false.
- $shouldEmit = $logConfig !== false;
- }
-
- } elseif ( isset( $context['private'] ) && $context['private'] ) {
- // Don't emit if the message didn't match previous checks based on
- // the channel and the event is marked as private. This check
- // discards messages sent via wfDebugLog() with dest == 'private'
- // and no explicit wgDebugLogGroups configuration.
- $shouldEmit = false;
- } else {
- // Default return value is the same as the historic wfDebug
- // method: emit if $wgDebugLogFile has been set.
- $shouldEmit = $wgDebugLogFile != '';
- }
-
- return $shouldEmit;
- }
-
-
- /**
- * Format a message.
- *
- * Messages to the 'wfDebug', 'wfLogDBError' and 'wfErrorLog' channels
- * receive special fomatting to mimic the historic output of the functions
- * of the same name. All other channel values are formatted based on the
- * historic output of the `wfDebugLog()` global function.
- *
- * @param string $channel
- * @param string $message
- * @param array $context
- * @return string
- */
- public static function format( $channel, $message, $context ) {
- global $wgDebugLogGroups;
-
- if ( $channel === 'wfDebug' ) {
- $text = self::formatAsWfDebug( $channel, $message, $context );
-
- } elseif ( $channel === 'wfLogDBError' ) {
- $text = self::formatAsWfLogDBError( $channel, $message, $context );
-
- } elseif ( $channel === 'wfErrorLog' ) {
- $text = "{$message}\n";
-
- } elseif ( $channel === 'profileoutput' ) {
- // Legacy wfLogProfilingData formatitng
- $forward = '';
- if ( isset( $context['forwarded_for'] )) {
- $forward = " forwarded for {$context['forwarded_for']}";
- }
- if ( isset( $context['client_ip'] ) ) {
- $forward .= " client IP {$context['client_ip']}";
- }
- if ( isset( $context['from'] ) ) {
- $forward .= " from {$context['from']}";
- }
- if ( $forward ) {
- $forward = "\t(proxied via {$context['proxy']}{$forward})";
- }
- if ( $context['anon'] ) {
- $forward .= ' anon';
- }
- if ( !isset( $context['url'] ) ) {
- $context['url'] = 'n/a';
- }
-
- $log = sprintf( "%s\t%04.3f\t%s%s\n",
- gmdate( 'YmdHis' ), $context['elapsed'], $context['url'], $forward );
-
- $text = self::formatAsWfDebugLog(
- $channel, $log . $context['output'], $context );
-
- } elseif ( !isset( $wgDebugLogGroups[$channel] ) ) {
- $text = self::formatAsWfDebug(
- $channel, "[{$channel}] {$message}", $context );
-
- } else {
- // Default formatting is wfDebugLog's historic style
- $text = self::formatAsWfDebugLog( $channel, $message, $context );
- }
-
- return self::interpolate( $text, $context );
- }
-
-
- /**
- * Format a message as `wfDebug()` would have formatted it.
- *
- * @param string $channel
- * @param string $message
- * @param array $context
- * @return string
- */
- protected static function formatAsWfDebug( $channel, $message, $context ) {
- $text = preg_replace( '![\x00-\x08\x0b\x0c\x0e-\x1f]!', ' ', $message );
- if ( isset( $context['seconds_elapsed'] ) ) {
- // Prepend elapsed request time and real memory usage with two
- // trailing spaces.
- $text = "{$context['seconds_elapsed']} {$context['memory_used']} {$text}";
- }
- if ( isset( $context['prefix'] ) ) {
- $text = "{$context['prefix']}{$text}";
- }
- return "{$text}\n";
- }
-
-
- /**
- * Format a message as `wfLogDBError()` would have formatted it.
- *
- * @param string $channel
- * @param string $message
- * @param array $context
- * @return string
- */
- protected static function formatAsWfLogDBError( $channel, $message, $context ) {
- global $wgDBerrorLogTZ;
- static $cachedTimezone = null;
-
- if ( $wgDBerrorLogTZ && !$cachedTimezone ) {
- $cachedTimezone = new DateTimeZone( $wgDBerrorLogTZ );
- }
-
- // Workaround for https://bugs.php.net/bug.php?id=52063
- // Can be removed when min PHP > 5.3.6
- if ( $cachedTimezone === null ) {
- $d = date_create( 'now' );
- } else {
- $d = date_create( 'now', $cachedTimezone );
- }
- $date = $d->format( 'D M j G:i:s T Y' );
-
- $host = wfHostname();
- $wiki = wfWikiID();
-
- $text = "{$date}\t{$host}\t{$wiki}\t{$message}\n";
- return $text;
- }
-
-
- /**
- * Format a message as `wfDebugLog() would have formatted it.
- *
- * @param string $channel
- * @param string $message
- * @param array $context
- */
- protected static function formatAsWfDebugLog( $channel, $message, $context ) {
- $time = wfTimestamp( TS_DB );
- $wiki = wfWikiID();
- $host = wfHostname();
- $text = "{$time} {$host} {$wiki}: {$message}\n";
- return $text;
- }
-
-
- /**
- * Interpolate placeholders in logging message.
- *
- * @param string $message
- * @param array $context
- * @return string Interpolated message
- */
- public static function interpolate( $message, array $context ) {
- if ( strpos( $message, '{' ) !== false ) {
- $replace = array();
- foreach ( $context as $key => $val ) {
- $replace['{' . $key . '}'] = $val;
- }
- $message = strtr( $message, $replace );
- }
- return $message;
- }
-
-
- /**
- * Select the appropriate log output destination for the given log event.
- *
- * If the event context contains 'destination'
- *
- * @param string $channel
- * @param string $message
- * @param array $context
- * @return string
- */
- protected static function destination( $channel, $message, $context ) {
- global $wgDebugLogFile, $wgDBerrorLog, $wgDebugLogGroups;
-
- // Default destination is the debug log file as historically used by
- // the wfDebug function.
- $destination = $wgDebugLogFile;
-
- if ( isset( $context['destination'] ) ) {
- // Use destination explicitly provided in context
- $destination = $context['destination'];
-
- } elseif ( $channel === 'wfDebug' ) {
- $destination = $wgDebugLogFile;
-
- } elseif ( $channel === 'wfLogDBError' ) {
- $destination = $wgDBerrorLog;
-
- } elseif ( isset( $wgDebugLogGroups[$channel] ) ) {
- $logConfig = $wgDebugLogGroups[$channel];
-
- if ( is_array( $logConfig ) ) {
- $destination = $logConfig['destination'];
- } else {
- $destination = strval( $logConfig );
- }
- }
-
- return $destination;
- }
-
-
- /**
- * Log to a file without getting "file size exceeded" signals.
- *
- * Can also log to UDP with the syntax udp://host:port/prefix. This will send
- * lines to the specified port, prefixed by the specified prefix and a space.
- *
- * @param string $text
- * @param string $file Filename
- * @throws MWException
- */
- public static function emit( $text, $file ) {
- if ( substr( $file, 0, 4 ) == 'udp:' ) {
- $transport = UDPTransport::newFromString( $file );
- $transport->emit( $text );
- } else {
- wfSuppressWarnings();
- $exists = file_exists( $file );
- $size = $exists ? filesize( $file ) : false;
- if ( !$exists ||
- ( $size !== false && $size + strlen( $text ) < 0x7fffffff )
- ) {
- file_put_contents( $file, $text, FILE_APPEND );
- }
- wfRestoreWarnings();
- }
- }
-
-}
+++ /dev/null
-<?php
-/**
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- */
-
-/**
- * MWLoggerFactory service provider that creates MWLoggerLegacyLogger
- * instances.
- *
- * Usage:
- * @code
- * $wgMWLoggerDefaultSpi = array(
- * 'class' => 'MWLoggerLegacySpi',
- * );
- * @endcode
- *
- * @see MWLoggerFactory
- * @since 1.25
- * @author Bryan Davis <bd808@wikimedia.org>
- * @copyright © 2014 Bryan Davis and Wikimedia Foundation.
- */
-class MWLoggerLegacySpi implements MWLoggerSpi {
-
- /**
- * @var array $singletons
- */
- protected $singletons = array();
-
-
- /**
- * Get a logger instance.
- *
- * @param string $channel Logging channel
- * @return \Psr\Log\LoggerInterface Logger instance
- */
- public function getLogger( $channel ) {
- if ( !isset( $this->singletons[$channel] ) ) {
- $this->singletons[$channel] = new MWLoggerLegacyLogger( $channel );
- }
- return $this->singletons[$channel];
- }
-
-}
+++ /dev/null
-<?php
-/**
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- */
-
-
-/**
- * Log handler that replicates the behavior of MediaWiki's wfErrorLog()
- * logging service. Log output can be directed to a local file, a PHP stream,
- * or a udp2log server.
- *
- * For udp2log output, the stream specification must have the form:
- * "udp://HOST:PORT[/PREFIX]"
- * where:
- * - HOST: IPv4, IPv6 or hostname
- * - PORT: server port
- * - PREFIX: optional (but recommended) prefix telling udp2log how to route
- * the log event. The special prefix "{channel}" will use the log event's
- * channel as the prefix value.
- *
- * When not targeting a udp2log stream this class will act as a drop-in
- * replacement for Monolog's StreamHandler.
- *
- * @since 1.25
- * @author Bryan Davis <bd808@wikimedia.org>
- * @copyright © 2013 Bryan Davis and Wikimedia Foundation.
- */
-class MWLoggerMonologHandler extends \Monolog\Handler\AbstractProcessingHandler {
-
- /**
- * Log sink descriptor
- * @var string $uri
- */
- protected $uri;
-
- /**
- * Filter log events using legacy rules
- * @var bool $useLegacyFilter
- */
- protected $useLegacyFilter;
-
- /**
- * Log sink
- * @var resource $sink
- */
- protected $sink;
-
- /**
- * @var string $error
- */
- protected $error;
-
- /**
- * @var string $host
- */
- protected $host;
-
- /**
- * @var int $port
- */
- protected $port;
-
- /**
- * @var string $prefix
- */
- protected $prefix;
-
-
- /**
- * @param string $stream Stream URI
- * @param bool $useLegacyFilter Filter log events using legacy rules
- * @param int $level Minimum logging level that will trigger handler
- * @param bool $bubble Can handled meesages bubble up the handler stack?
- */
- public function __construct(
- $stream,
- $useLegacyFilter = false,
- $level = \Monolog\Logger::DEBUG,
- $bubble = true
- ) {
- parent::__construct( $level, $bubble );
- $this->uri = $stream;
- $this->useLegacyFilter = $useLegacyFilter;
- }
-
- /**
- * Open the log sink described by our stream URI.
- */
- protected function openSink() {
- if ( !$this->uri ) {
- throw new LogicException(
- 'Missing stream uri, the stream can not be opened.' );
- }
- $this->error = null;
- set_error_handler( array( $this, 'errorTrap' ) );
-
- if ( substr( $this->uri, 0, 4 ) == 'udp:' ) {
- $parsed = parse_url( $this->uri );
- if ( !isset( $parsed['host'] ) ) {
- throw new UnexpectedValueException( sprintf(
- 'Udp transport "%s" must specify a host', $this->uri
- ) );
- }
- if ( !isset( $parsed['port'] ) ) {
- throw new UnexpectedValueException( sprintf(
- 'Udp transport "%s" must specify a port', $this->uri
- ) );
- }
-
- $this->host = $parsed['host'];
- $this->port = $parsed['port'];
- $this->prefix = '';
-
- if ( isset( $parsed['path'] ) ) {
- $this->prefix = ltrim( $parsed['path'], '/' );
- }
-
- if ( filter_var( $this->host, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6 ) ) {
- $domain = AF_INET6;
-
- } else {
- $domain = AF_INET;
- }
-
- $this->sink = socket_create( $domain, SOCK_DGRAM, SOL_UDP );
-
- } else {
- $this->sink = fopen( $this->uri, 'a' );
- }
- restore_error_handler();
-
- if ( !is_resource( $this->sink ) ) {
- $this->sink = null;
- throw new UnexpectedValueException( sprintf(
- 'The stream or file "%s" could not be opened: %s',
- $this->uri, $this->error
- ) );
- }
- }
-
-
- /**
- * Custom error handler.
- * @param int $code Error number
- * @param string $msg Error message
- */
- protected function errorTrap( $code, $msg ) {
- $this->error = $msg;
- }
-
-
- /**
- * Should we use UDP to send messages to the sink?
- * @return bool
- */
- protected function useUdp() {
- return $this->host !== null;
- }
-
-
- protected function write( array $record ) {
- if ( $this->useLegacyFilter &&
- !MWLoggerLegacyLogger::shouldEmit(
- $record['channel'], $record['message'],
- $record['level'], $record
- ) ) {
- // Do not write record if we are enforcing legacy rules and they
- // do not pass this message. This used to be done in isHandling(),
- // but Monolog 1.12.0 made a breaking change that removed access
- // to the needed channel and context information.
- return;
- }
-
- if ( $this->sink === null ) {
- $this->openSink();
- }
-
- $text = (string)$record['formatted'];
- if ( $this->useUdp() ) {
-
- // Clean it up for the multiplexer
- if ( $this->prefix !== '' ) {
- $leader = ( $this->prefix === '{channel}' ) ?
- $record['channel'] : $this->prefix;
- $text = preg_replace( '/^/m', "{$leader} ", $text );
-
- // Limit to 64KB
- if ( strlen( $text ) > 65506 ) {
- $text = substr( $text, 0, 65506 );
- }
-
- if ( substr( $text, -1 ) != "\n" ) {
- $text .= "\n";
- }
-
- } elseif ( strlen( $text ) > 65507 ) {
- $text = substr( $text, 0, 65507 );
- }
-
- socket_sendto(
- $this->sink, $text, strlen( $text ), 0, $this->host, $this->port );
-
- } else {
- fwrite( $this->sink, $text );
- }
- }
-
-
- public function close() {
- if ( is_resource( $this->sink ) ) {
- if ( $this->useUdp() ) {
- socket_close( $this->sink );
-
- } else {
- fclose( $this->sink );
- }
- }
- $this->sink = null;
- }
-
-}
* @file
*/
+namespace MediaWiki\Logger\Monolog;
+
+use MediaWiki\Logger\LegacyLogger;
+use Monolog\Formatter\NormalizerFormatter;
+
/**
* Log message formatter that mimics the legacy log message formatting of
* `wfDebug`, `wfDebugLog`, `wfLogDBError` and `wfErrorLog` global functions by
- * delegating the formatting to MWLoggerLegacyLogger.
+ * delegating the formatting to \MediaWiki\Logger\LegacyLogger.
*
* @since 1.25
* @author Bryan Davis <bd808@wikimedia.org>
* @copyright © 2013 Bryan Davis and Wikimedia Foundation.
- * @see MWLoggerLegacyLogger
+ * @see \MediaWiki\Logger\LegacyLogger
*/
-class MWLoggerMonologLegacyFormatter extends \Monolog\Formatter\NormalizerFormatter {
+class LegacyFormatter extends NormalizerFormatter {
public function __construct() {
parent::__construct( 'c' );
public function format( array $record ) {
$normalized = parent::format( $record );
- return MWLoggerLegacyLogger::format(
+ return LegacyLogger::format(
$normalized['channel'], $normalized['message'], $normalized
);
}
--- /dev/null
+<?php
+/**
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ */
+
+namespace MediaWiki\Logger\Monolog;
+
+use LogicException;
+use MediaWiki\Logger\LegacyLogger;
+use Monolog\Handler\AbstractProcessingHandler;
+use Monolog\Logger;
+use UnexpectedValueException;
+
+/**
+ * Log handler that replicates the behavior of MediaWiki's wfErrorLog()
+ * logging service. Log output can be directed to a local file, a PHP stream,
+ * or a udp2log server.
+ *
+ * For udp2log output, the stream specification must have the form:
+ * "udp://HOST:PORT[/PREFIX]"
+ * where:
+ * - HOST: IPv4, IPv6 or hostname
+ * - PORT: server port
+ * - PREFIX: optional (but recommended) prefix telling udp2log how to route
+ * the log event. The special prefix "{channel}" will use the log event's
+ * channel as the prefix value.
+ *
+ * When not targeting a udp2log stream this class will act as a drop-in
+ * replacement for Monolog's StreamHandler.
+ *
+ * @since 1.25
+ * @author Bryan Davis <bd808@wikimedia.org>
+ * @copyright © 2013 Bryan Davis and Wikimedia Foundation.
+ */
+class LegacyHandler extends AbstractProcessingHandler {
+
+ /**
+ * Log sink descriptor
+ * @var string $uri
+ */
+ protected $uri;
+
+ /**
+ * Filter log events using legacy rules
+ * @var bool $useLegacyFilter
+ */
+ protected $useLegacyFilter;
+
+ /**
+ * Log sink
+ * @var resource $sink
+ */
+ protected $sink;
+
+ /**
+ * @var string $error
+ */
+ protected $error;
+
+ /**
+ * @var string $host
+ */
+ protected $host;
+
+ /**
+ * @var int $port
+ */
+ protected $port;
+
+ /**
+ * @var string $prefix
+ */
+ protected $prefix;
+
+
+ /**
+ * @param string $stream Stream URI
+ * @param bool $useLegacyFilter Filter log events using legacy rules
+ * @param int $level Minimum logging level that will trigger handler
+ * @param bool $bubble Can handled meesages bubble up the handler stack?
+ */
+ public function __construct(
+ $stream,
+ $useLegacyFilter = false,
+ $level = Logger::DEBUG,
+ $bubble = true
+ ) {
+ parent::__construct( $level, $bubble );
+ $this->uri = $stream;
+ $this->useLegacyFilter = $useLegacyFilter;
+ }
+
+ /**
+ * Open the log sink described by our stream URI.
+ */
+ protected function openSink() {
+ if ( !$this->uri ) {
+ throw new LogicException(
+ 'Missing stream uri, the stream can not be opened.' );
+ }
+ $this->error = null;
+ set_error_handler( array( $this, 'errorTrap' ) );
+
+ if ( substr( $this->uri, 0, 4 ) == 'udp:' ) {
+ $parsed = parse_url( $this->uri );
+ if ( !isset( $parsed['host'] ) ) {
+ throw new UnexpectedValueException( sprintf(
+ 'Udp transport "%s" must specify a host', $this->uri
+ ) );
+ }
+ if ( !isset( $parsed['port'] ) ) {
+ throw new UnexpectedValueException( sprintf(
+ 'Udp transport "%s" must specify a port', $this->uri
+ ) );
+ }
+
+ $this->host = $parsed['host'];
+ $this->port = $parsed['port'];
+ $this->prefix = '';
+
+ if ( isset( $parsed['path'] ) ) {
+ $this->prefix = ltrim( $parsed['path'], '/' );
+ }
+
+ if ( filter_var( $this->host, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6 ) ) {
+ $domain = AF_INET6;
+
+ } else {
+ $domain = AF_INET;
+ }
+
+ $this->sink = socket_create( $domain, SOCK_DGRAM, SOL_UDP );
+
+ } else {
+ $this->sink = fopen( $this->uri, 'a' );
+ }
+ restore_error_handler();
+
+ if ( !is_resource( $this->sink ) ) {
+ $this->sink = null;
+ throw new UnexpectedValueException( sprintf(
+ 'The stream or file "%s" could not be opened: %s',
+ $this->uri, $this->error
+ ) );
+ }
+ }
+
+
+ /**
+ * Custom error handler.
+ * @param int $code Error number
+ * @param string $msg Error message
+ */
+ protected function errorTrap( $code, $msg ) {
+ $this->error = $msg;
+ }
+
+
+ /**
+ * Should we use UDP to send messages to the sink?
+ * @return bool
+ */
+ protected function useUdp() {
+ return $this->host !== null;
+ }
+
+
+ protected function write( array $record ) {
+ if ( $this->useLegacyFilter &&
+ !LegacyLogger::shouldEmit(
+ $record['channel'], $record['message'],
+ $record['level'], $record
+ ) ) {
+ // Do not write record if we are enforcing legacy rules and they
+ // do not pass this message. This used to be done in isHandling(),
+ // but Monolog 1.12.0 made a breaking change that removed access
+ // to the needed channel and context information.
+ return;
+ }
+
+ if ( $this->sink === null ) {
+ $this->openSink();
+ }
+
+ $text = (string)$record['formatted'];
+ if ( $this->useUdp() ) {
+
+ // Clean it up for the multiplexer
+ if ( $this->prefix !== '' ) {
+ $leader = ( $this->prefix === '{channel}' ) ?
+ $record['channel'] : $this->prefix;
+ $text = preg_replace( '/^/m', "{$leader} ", $text );
+
+ // Limit to 64KB
+ if ( strlen( $text ) > 65506 ) {
+ $text = substr( $text, 0, 65506 );
+ }
+
+ if ( substr( $text, -1 ) != "\n" ) {
+ $text .= "\n";
+ }
+
+ } elseif ( strlen( $text ) > 65507 ) {
+ $text = substr( $text, 0, 65507 );
+ }
+
+ socket_sendto(
+ $this->sink, $text, strlen( $text ), 0, $this->host, $this->port
+ );
+
+ } else {
+ fwrite( $this->sink, $text );
+ }
+ }
+
+
+ public function close() {
+ if ( is_resource( $this->sink ) ) {
+ if ( $this->useUdp() ) {
+ socket_close( $this->sink );
+
+ } else {
+ fclose( $this->sink );
+ }
+ }
+ $this->sink = null;
+ }
+}
+++ /dev/null
-<?php
-/**
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- */
-
-/**
- * Injects `wfHostname()` and `wfWikiID()` in all records.
- *
- * @since 1.25
- * @author Bryan Davis <bd808@wikimedia.org>
- * @copyright © 2013 Bryan Davis and Wikimedia Foundation.
- */
-class MWLoggerMonologProcessor {
-
- /**
- * @param array $record
- * @return array
- */
- public function __invoke( array $record ) {
- $record['extra'] = array_merge(
- $record['extra'],
- array(
- 'host' => wfHostname(),
- 'wiki' => wfWikiID(),
- )
- );
- return $record;
- }
-
-}
+++ /dev/null
-<?php
-/**
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- */
-
-/**
- * MWLoggerFactory service provider that creates loggers implemented by
- * Monolog.
- *
- * Configured using an array of configuration data with the keys 'loggers',
- * 'processors', 'handlers' and 'formatters'.
- *
- * The ['loggers']['@default'] configuration will be used to create loggers
- * for any channel that isn't explicitly named in the 'loggers' configuration
- * section.
- *
- * Configuration will most typically be provided in the $wgMWLoggerDefaultSpi
- * global configuration variable used by MWLoggerFactory to construct its
- * default SPI provider:
- * @code
- * $wgMWLoggerDefaultSpi = array(
- * 'class' => 'MWLoggerMonologSpi',
- * 'args' => array( array(
- * 'loggers' => array(
- * '@default' => array(
- * 'processors' => array( 'wiki', 'psr', 'pid', 'uid', 'web' ),
- * 'handlers' => array( 'stream' ),
- * ),
- * 'runJobs' => array(
- * 'processors' => array( 'wiki', 'psr', 'pid' ),
- * 'handlers' => array( 'stream' ),
- * )
- * ),
- * 'processors' => array(
- * 'wiki' => array(
- * 'class' => 'MWLoggerMonologProcessor',
- * ),
- * 'psr' => array(
- * 'class' => '\\Monolog\\Processor\\PsrLogMessageProcessor',
- * ),
- * 'pid' => array(
- * 'class' => '\\Monolog\\Processor\\ProcessIdProcessor',
- * ),
- * 'uid' => array(
- * 'class' => '\\Monolog\\Processor\\UidProcessor',
- * ),
- * 'web' => array(
- * 'class' => '\\Monolog\\Processor\\WebProcessor',
- * ),
- * ),
- * 'handlers' => array(
- * 'stream' => array(
- * 'class' => '\\Monolog\\Handler\\StreamHandler',
- * 'args' => array( 'path/to/your.log' ),
- * 'formatter' => 'line',
- * ),
- * 'redis' => array(
- * 'class' => '\\Monolog\\Handler\\RedisHandler',
- * 'args' => array( function() {
- * $redis = new Redis();
- * $redis->connect( '127.0.0.1', 6379 );
- * return $redis;
- * },
- * 'logstash'
- * ),
- * 'formatter' => 'logstash',
- * ),
- * 'udp2log' => array(
- * 'class' => 'MWLoggerMonologHandler',
- * 'args' => array(
- * 'udp://127.0.0.1:8420/mediawiki
- * ),
- * 'formatter' => 'line',
- * ),
- * ),
- * 'formatters' => array(
- * 'line' => array(
- * 'class' => '\\Monolog\\Formatter\\LineFormatter',
- * ),
- * 'logstash' => array(
- * 'class' => '\\Monolog\\Formatter\\LogstashFormatter',
- * 'args' => array( 'mediawiki', php_uname( 'n' ), null, '', 1 ),
- * ),
- * ),
- * ) ),
- * );
- * @endcode
- *
- * @see https://github.com/Seldaek/monolog
- * @since 1.25
- * @author Bryan Davis <bd808@wikimedia.org>
- * @copyright © 2014 Bryan Davis and Wikimedia Foundation.
- */
-class MWLoggerMonologSpi implements MWLoggerSpi {
-
- /**
- * @var array $singletons
- */
- protected $singletons;
-
- /**
- * Configuration for creating new loggers.
- * @var array $config
- */
- protected $config;
-
-
- /**
- * @param array $config Configuration data.
- */
- public function __construct( array $config ) {
- $this->config = $config;
- $this->reset();
- }
-
-
- /**
- * Reset internal caches.
- *
- * This is public for use in unit tests. Under normal operation there should
- * be no need to flush the caches.
- */
- public function reset() {
- $this->singletons = array(
- 'loggers' => array(),
- 'handlers' => array(),
- 'formatters' => array(),
- 'processors' => array(),
- );
- }
-
-
- /**
- * Get a logger instance.
- *
- * Creates and caches a logger instance based on configuration found in the
- * $wgMWLoggerMonologSpiConfig global. Subsequent request for the same channel
- * name will return the cached instance.
- *
- * @param string $channel Logging channel
- * @return \Psr\Log\LoggerInterface Logger instance
- */
- public function getLogger( $channel ) {
- if ( !isset( $this->singletons['loggers'][$channel] ) ) {
- // Fallback to using the '@default' configuration if an explict
- // configuration for the requested channel isn't found.
- $spec = isset( $this->config['loggers'][$channel] ) ?
- $this->config['loggers'][$channel] :
- $this->config['loggers']['@default'];
-
- $monolog = $this->createLogger( $channel, $spec );
- $this->singletons['loggers'][$channel] = $monolog;
- }
-
- return $this->singletons['loggers'][$channel];
- }
-
-
- /**
- * Create a logger.
- * @param string $channel Logger channel
- * @param array $spec Configuration
- * @return \Monolog\Logger
- */
- protected function createLogger( $channel, $spec ) {
- $obj = new \Monolog\Logger( $channel );
-
- if ( isset( $spec['processors'] ) ) {
- foreach ( $spec['processors'] as $processor ) {
- $obj->pushProcessor( $this->getProcessor( $processor ) );
- }
- }
-
- if ( isset( $spec['handlers'] ) ) {
- foreach ( $spec['handlers'] as $handler ) {
- $obj->pushHandler( $this->getHandler( $handler ) );
- }
- }
- return $obj;
- }
-
-
- /**
- * Create or return cached processor.
- * @param string $name Processor name
- * @return callable
- */
- public function getProcessor( $name ) {
- if ( !isset( $this->singletons['processors'][$name] ) ) {
- $spec = $this->config['processors'][$name];
- $processor = ObjectFactory::getObjectFromSpec( $spec );
- $this->singletons['processors'][$name] = $processor;
- }
- return $this->singletons['processors'][$name];
- }
-
-
- /**
- * Create or return cached handler.
- * @param string $name Processor name
- * @return \Monolog\Handler\HandlerInterface
- */
- public function getHandler( $name ) {
- if ( !isset( $this->singletons['handlers'][$name] ) ) {
- $spec = $this->config['handlers'][$name];
- $handler = ObjectFactory::getObjectFromSpec( $spec );
- if ( isset( $spec['formatter'] ) ) {
- $handler->setFormatter(
- $this->getFormatter( $spec['formatter'] )
- );
- }
- $this->singletons['handlers'][$name] = $handler;
- }
- return $this->singletons['handlers'][$name];
- }
-
-
- /**
- * Create or return cached formatter.
- * @param string $name Formatter name
- * @return \Monolog\Formatter\FormatterInterface
- */
- public function getFormatter( $name ) {
- if ( !isset( $this->singletons['formatters'][$name] ) ) {
- $spec = $this->config['formatters'][$name];
- $formatter = ObjectFactory::getObjectFromSpec( $spec );
- $this->singletons['formatters'][$name] = $formatter;
- }
- return $this->singletons['formatters'][$name];
- }
-}
* @file
*/
+namespace MediaWiki\Logger\Monolog;
+
use Monolog\Handler\SyslogUdpHandler;
use Monolog\Logger;
* @author Bryan Davis <bd808@wikimedia.org>
* @copyright © 2015 Bryan Davis and Wikimedia Foundation.
*/
-class MWLoggerMonologSyslogHandler extends SyslogUdpHandler {
+class SyslogHandler extends SyslogUdpHandler {
/**
* @var string $appname
--- /dev/null
+<?php
+/**
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ */
+
+namespace MediaWiki\Logger\Monolog;
+
+/**
+ * Injects `wfHostname()` and `wfWikiID()` in all records.
+ *
+ * @since 1.25
+ * @author Bryan Davis <bd808@wikimedia.org>
+ * @copyright © 2013 Bryan Davis and Wikimedia Foundation.
+ */
+class WikiProcessor {
+
+ /**
+ * @param array $record
+ * @return array
+ */
+ public function __invoke( array $record ) {
+ $record['extra'] = array_merge(
+ $record['extra'],
+ array(
+ 'host' => wfHostname(),
+ 'wiki' => wfWikiID(),
+ )
+ );
+ return $record;
+ }
+
+}
* @file
*/
+use MediaWiki\Logger\LoggerFactory;
+
/**
* Show an error that looks like an HTTP server error.
* Replacement for wfHttpError().
}
private function doLog() {
- $logger = MWLoggerFactory::getInstance( 'HttpError' );
+ $logger = LoggerFactory::getInstance( 'HttpError' );
$content = $this->content;
if ( $content instanceof Message ) {
* @ingroup JobQueue
*/
+use MediaWiki\Logger\LoggerFactory;
use Psr\Log\LoggerAwareInterface;
use Psr\Log\LoggerInterface;
*/
public function __construct( LoggerInterface $logger = null ) {
if ( $logger === null ) {
- $logger = MWLoggerFactory::getInstance( 'runJobs' );
+ $logger = LoggerFactory::getInstance( 'runJobs' );
}
$this->setLogger( $logger );
}
* @ingroup Cache
*/
+use MediaWiki\Logger\LoggerFactory;
+
/**
* Functions to get cache objects
*
*/
static function newFromParams( $params ) {
if ( isset( $params['loggroup'] ) ) {
- $params['logger'] = MWLoggerFactory::getInstance( $params['loggroup'] );
+ $params['logger'] = LoggerFactory::getInstance( $params['loggroup'] );
} else {
// For backwards-compatability with custom parameters, lets not
// have all logging suddenly disappear
- $params['logger'] = MWLoggerFactory::getInstance( 'objectcache' );
+ $params['logger'] = LoggerFactory::getInstance( 'objectcache' );
}
if ( isset( $params['factory'] ) ) {
return call_user_func( $params['factory'], $params );
* @author Aaron Schulz
*/
+use MediaWiki\Logger\LoggerFactory;
+
/**
* Special page designed for running background tasks (internal use only)
*
// Do all of the specified tasks...
if ( in_array( 'jobs', explode( '|', $params['tasks'] ) ) ) {
- $runner = new JobRunner( MWLoggerFactory::getInstance( 'runJobs' ) );
+ $runner = new JobRunner( LoggerFactory::getInstance( 'runJobs' ) );
$response = $runner->run( array(
'type' => $params['type'],
'maxJobs' => $params['maxjobs'] ? $params['maxjobs'] : 1,
require_once __DIR__ . '/Maintenance.php';
+use MediaWiki\Logger\LoggerFactory;
+
/**
* Maintenance script that runs pending jobs.
*
$json = ( $this->getOption( 'result' ) === 'json' );
- $runner = new JobRunner( MWLoggerFactory::getInstance( 'runJobs' ) );
+ $runner = new JobRunner( LoggerFactory::getInstance( 'runJobs' ) );
if ( !$json ) {
$runner->setDebugHandler( array( $this, 'debugInternal' ) );
}
* @ingroup Maintenance ExternalStorage
*/
+use MediaWiki\Logger\LegacyLogger;
+
$optionsWithArgs = RecompressTracked::getOptionsWithArgs();
require __DIR__ . '/../commandLine.inc';
$header .= "({$this->slaveId})";
}
$header .= ' ' . wfWikiID();
- MWLoggerLegacyLogger::emit( sprintf( "%-50s %s\n", $header, $msg ), $file );
+ LegacyLogger::emit( sprintf( "%-50s %s\n", $header, $msg ), $file );
}
/**
--- /dev/null
+<?php
+/**
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ */
+
+namespace MediaWiki\Logger;
+
+use MediaWikiTestCase;
+use Psr\Log\LogLevel;
+
+class LegacyLoggerTest extends MediaWikiTestCase {
+
+ /**
+ * @covers LegacyLogger::interpolate
+ * @dataProvider provideInterpolate
+ */
+ public function testInterpolate( $message, $context, $expect ) {
+ $this->assertEquals(
+ $expect, LegacyLogger::interpolate( $message, $context ) );
+ }
+
+ public function provideInterpolate() {
+ return array(
+ array(
+ 'no-op',
+ array(),
+ 'no-op',
+ ),
+ array(
+ 'Hello {world}!',
+ array(
+ 'world' => 'World',
+ ),
+ 'Hello World!',
+ ),
+ array(
+ '{greeting} {user}',
+ array(
+ 'greeting' => 'Goodnight',
+ 'user' => 'Moon',
+ ),
+ 'Goodnight Moon',
+ ),
+ array(
+ 'Oops {key_not_set}',
+ array(),
+ 'Oops {key_not_set}',
+ ),
+ array(
+ '{ not interpolated }',
+ array(
+ 'not interpolated' => 'This should NOT show up in the message',
+ ),
+ '{ not interpolated }',
+ ),
+ );
+ }
+
+ /**
+ * @covers LegacyLogger::shouldEmit
+ * @dataProvider provideShouldEmit
+ */
+ public function testShouldEmit( $level, $config, $expected ) {
+ $this->setMwGlobals( 'wgDebugLogGroups', array( 'fakechannel' => $config ) );
+ $this->assertEquals(
+ $expected,
+ LegacyLogger::shouldEmit( 'fakechannel', 'some message', $level, array() )
+ );
+ }
+
+ public static function provideShouldEmit() {
+ $dest = array( 'destination' => 'foobar' );
+ $tests = array(
+ array(
+ LogLevel::DEBUG,
+ $dest,
+ true
+ ),
+ array(
+ LogLevel::WARNING,
+ $dest + array( 'level' => LogLevel::INFO ),
+ true,
+ ),
+ array(
+ LogLevel::INFO,
+ $dest + array( 'level' => LogLevel::CRITICAL ),
+ false,
+ ),
+ );
+
+ if ( class_exists( '\Monolog\Logger' ) ) {
+ $tests[] = array(
+ \Monolog\Logger::INFO,
+ $dest + array( 'level' => LogLevel::INFO ),
+ true,
+ );
+ $tests[] = array(
+ \Monolog\Logger::WARNING,
+ $dest + array( 'level' => LogLevel::EMERGENCY ),
+ false,
+ );
+ }
+
+ return $tests;
+ }
+
+}
+++ /dev/null
-<?php
-/**
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- */
-use Psr\Log\LogLevel;
-
-class MWLoggerLegacyLoggerTest extends MediaWikiTestCase {
-
- /**
- * @covers MWLoggerLegacyLogger::interpolate
- * @dataProvider provideInterpolate
- */
- public function testInterpolate( $message, $context, $expect ) {
- $this->assertEquals(
- $expect, MWLoggerLegacyLogger::interpolate( $message, $context ) );
- }
-
- public function provideInterpolate() {
- return array(
- array(
- 'no-op',
- array(),
- 'no-op',
- ),
- array(
- 'Hello {world}!',
- array(
- 'world' => 'World',
- ),
- 'Hello World!',
- ),
- array(
- '{greeting} {user}',
- array(
- 'greeting' => 'Goodnight',
- 'user' => 'Moon',
- ),
- 'Goodnight Moon',
- ),
- array(
- 'Oops {key_not_set}',
- array(),
- 'Oops {key_not_set}',
- ),
- array(
- '{ not interpolated }',
- array(
- 'not interpolated' => 'This should NOT show up in the message',
- ),
- '{ not interpolated }',
- ),
- );
- }
-
- /**
- * @covers MWLoggerLegacyLogger::shouldEmit
- * @dataProvider provideShouldEmit
- */
- public function testShouldEmit( $level, $config, $expected ) {
- $this->setMwGlobals( 'wgDebugLogGroups', array( 'fakechannel' => $config ) );
- $this->assertEquals(
- $expected,
- MWLoggerLegacyLogger::shouldEmit( 'fakechannel', 'some message', $level, array() )
- );
- }
-
- public static function provideShouldEmit() {
- $dest = array( 'destination' => 'foobar' );
- $tests = array(
- array(
- LogLevel::DEBUG,
- $dest,
- true
- ),
- array(
- LogLevel::WARNING,
- $dest + array( 'level' => LogLevel::INFO ),
- true,
- ),
- array(
- LogLevel::INFO,
- $dest + array( 'level' => LogLevel::CRITICAL ),
- false,
- ),
- );
-
- if ( class_exists( '\Monolog\Logger' ) ) {
- $tests[] = array(
- \Monolog\Logger::INFO,
- $dest + array( 'level' => LogLevel::INFO ),
- true,
- );
- $tests[] = array(
- \Monolog\Logger::WARNING,
- $dest + array( 'level' => LogLevel::EMERGENCY ),
- false,
- );
- }
-
- return $tests;
- }
-
-}