Implement support for a minimum log level in $wgDebugLogGroups
authorKunal Mehta <legoktm@gmail.com>
Tue, 30 Dec 2014 01:42:48 +0000 (17:42 -0800)
committerBryanDavis <bdavis@wikimedia.org>
Wed, 31 Dec 2014 18:16:17 +0000 (18:16 +0000)
For some log groups, we only want to log them if they meet a certain
level of severity. An example of this is the current 'memcached-serious'
log group, which can be merged with the normal 'memcached' group
in the future, and report at a severity of ERROR.

This adds a 'level' parameter to the $wgDebugLogGroups, for example:
    $wgDebugLogGroups['memcached'] = array(
        'destination' => '/var/log/mw/memcached.log',
        'level' => \Psr\Log\LogLevel::ERROR,
    );

Bug: T85073
Change-Id: Ic53bc4c8e318ed188fe6f4e838e6789b3c3fd574

includes/DefaultSettings.php
includes/debug/logger/legacy/Logger.php
includes/debug/logger/monolog/Handler.php
tests/phpunit/includes/debug/logging/legacy/LoggerTest.php

index 4261c68..1884b5f 100644 (file)
@@ -5239,9 +5239,11 @@ $wgDebugDumpSqlLength = 500;
  * Log destinations may be one of the following:
  * - false to completely remove from the output, including from $wgDebugLogFile.
  * - string values specifying a filename or URI.
- * - associative array mapping 'destination' key to the desired filename or URI.
- *   The associative array may also contain a 'sample' key with an integer value,
- *   specifying a sampling factor.
+ * - associative array with keys:
+ *   - 'destination' desired filename or URI.
+ *   - 'sample' an integer value, specifying a sampling factor (optional)
+ *   - 'level' A \Psr\Log\LogLevel constant, indicating the minimum level
+ *             to log (optional, since 1.25)
  *
  * @par Example:
  * @code
@@ -5253,6 +5255,7 @@ $wgDebugDumpSqlLength = 500;
  * $wgDebugLogGroups['memcached'] = array(
  *     'destination' => '/var/log/mediawiki/memcached.log',
  *     'sample' => 1000,  // log 1 message out of every 1,000.
+ *     'level' => \Psr\Log\LogLevel::WARNING
  * );
  * @endcode
  */
index a682504..0737770 100644 (file)
  * @author Bryan Davis <bd808@wikimedia.org>
  * @copyright © 2014 Bryan Davis and Wikimedia Foundation.
  */
-class MWLoggerLegacyLogger extends \Psr\Log\AbstractLogger {
+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
@@ -59,7 +79,7 @@ class MWLoggerLegacyLogger extends \Psr\Log\AbstractLogger {
         * @param array $context
         */
        public function log( $level, $message, array $context = array() ) {
-               if ( self::shouldEmit( $this->channel, $message, $context ) ) {
+               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 );
@@ -72,11 +92,12 @@ class MWLoggerLegacyLogger extends \Psr\Log\AbstractLogger {
         *
         * @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, $context ) {
+       public static function shouldEmit( $channel, $message, $level, $context ) {
                global $wgDebugLogFile, $wgDBerrorLog, $wgDebugLogGroups;
 
                if ( $channel === 'wfLogDBError' ) {
@@ -91,10 +112,19 @@ class MWLoggerLegacyLogger extends \Psr\Log\AbstractLogger {
                } elseif ( isset( $wgDebugLogGroups[$channel] ) ) {
                        $logConfig = $wgDebugLogGroups[$channel];
 
-                       if ( is_array( $logConfig ) && isset( $logConfig['sample'] ) ) {
-                               // Emit randomly with a 1 in 'sample' chance for each message.
-                               $shouldEmit = mt_rand( 1, $logConfig['sample'] ) === 1;
-
+                       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;
index 42ab797..05ac64e 100644 (file)
@@ -101,7 +101,7 @@ class MWLoggerMonologHandler extends \Monolog\Handler\AbstractProcessingHandler
                $levelOk = parent::isHandling( $record );
                if ( $levelOk && $this->useLegacyFilter ) {
                        return MWLoggerLegacyLogger::shouldEmit(
-                               $record['channel'], $record['message'], $record
+                               $record['channel'], $record['message'], $record['level'], $record
                        );
                }
                return $levelOk;
index 22d3270..66e9be4 100644 (file)
@@ -17,6 +17,7 @@
  *
  * @file
  */
+use Psr\Log\LogLevel;
 
 class MWLoggerLegacyLoggerTest extends MediaWikiTestCase {
 
@@ -66,4 +67,52 @@ class MWLoggerLegacyLoggerTest extends MediaWikiTestCase {
                );
        }
 
+       /**
+        * @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;
+       }
+
 }