%PDF- %PDF-
Mini Shell

Mini Shell

Direktori : /data/www_bck/varak.net_bck/havranipapuce.varak.net/includes/debug/logger/
Upload File :
Create Path :
Current File : //data/www_bck/varak.net_bck/havranipapuce.varak.net/includes/debug/logger/LegacyLogger.php

<?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 DateTimeZone;
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();
		}
	}

}

Zerion Mini Shell 1.0