/**
* Compatibility functions
*
- * We support PHP 5.3.2 and up.
+ * We support PHP 5.3.3 and up.
* Re-implementations of newer functions or functions in non-standard
* PHP extensions may be included here.
*/
* $wgDebugRawPage - if false, 'action=raw' hits will not result in debug output.
* $wgDebugComments - if on, some debug items may appear in comments in the HTML output.
*
+ * @since 1.25 support for additional context data
+ *
* @param string $text
* @param string|bool $dest Destination of the message:
* - 'all': both to the log and HTML (debug toolbar or HTML comments)
* For backward compatibility, it can also take a boolean:
* - true: same as 'all'
* - false: same as 'log'
+ * @param array $context Additional logging context data
*/
-function wfDebug( $text, $dest = 'all' ) {
+function wfDebug( $text, $dest = 'all', array $context = array() ) {
global $wgDebugRawPage, $wgDebugLogPrefix;
+ global $wgDebugTimestamps, $wgRequestTime;
if ( !$wgDebugRawPage && wfIsDebugRawPage() ) {
return;
$dest = 'log';
}
- $timer = wfDebugTimer();
- if ( $timer !== '' ) {
- // Prepend elapsed request time and real memory usage to each line
- $text = preg_replace( '/[^\n]/', $timer . '\0', $text, 1 );
+ $text = trim( $text );
+
+ // Inline logic from deprecated wfDebugTimer()
+ if ( $wgDebugTimestamps ) {
+ $context['seconds_elapsed'] = sprintf(
+ '%6.4f',
+ microtime( true ) - $wgRequestTime
+ );
+ $context['memory_used'] = sprintf(
+ '%5.1fM',
+ ( memory_get_usage( true ) / ( 1024 * 1024 ) )
+ );
}
if ( $dest === 'all' ) {
- MWDebug::debugMsg( $text );
+ $prefix = '';
+ if ( $wgDebugTimestamps ) {
+ // Prepend elapsed request time and real memory usage with two
+ // trailing spaces.
+ $prefix = "{$context['seconds_elapsed']} {$context['memory_used']} ";
+ }
+ MWDebug::debugMsg( "{$prefix}{$text}" );
}
- $ctx = array();
if ( $wgDebugLogPrefix !== '' ) {
- $ctx['prefix'] = $wgDebugLogPrefix;
+ $context['prefix'] = $wgDebugLogPrefix;
}
$logger = MWLogger::getInstance( 'wfDebug' );
- $logger->debug( rtrim( $text, "\n" ), $ctx );
+ $logger->debug( $text, $context );
}
/**
/**
* Get microsecond timestamps for debug logs
*
+ * @deprecated since 1.25
* @return string
*/
function wfDebugTimer() {
global $wgDebugTimestamps, $wgRequestTime;
+ wfDeprecated( __METHOD__, '1.25' );
+
if ( !$wgDebugTimestamps ) {
return '';
}
* a sampling factor.
*
* @since 1.23 support for sampling log messages via $wgDebugLogGroups.
+ * @since 1.25 support for additional context data
*
* @param string $logGroup
* @param string $text
* For backward compatibility, it can also take a boolean:
* - true: same as 'all'
* - false: same as 'private'
+ * @param array $context Additional logging context data
*/
-function wfDebugLog( $logGroup, $text, $dest = 'all' ) {
- global $wgDebugLogGroups;
-
+function wfDebugLog(
+ $logGroup, $text, $dest = 'all', array $context = array()
+) {
// Turn $dest into a string if it's a boolean (for b/c)
if ( $dest === true ) {
$dest = 'all';
}
$logger = MWLogger::getInstance( $logGroup );
- $logger->debug( $text, array(
- 'private' => ( $dest === 'private' ),
- ) );
+ $context['private'] = ( $dest === 'private' );
+ $logger->debug( $text, $context );
}
/**
* Log for database errors
*
+ * @since 1.25 support for additional context data
+ *
* @param string $text Database error message.
+ * @param array $context Additional logging context data
*/
-function wfLogDBError( $text ) {
+function wfLogDBError( $text, array $context = array() ) {
$logger = MWLogger::getInstance( 'wfLogDBError' );
- $logger->error( trim( $text ) );
+ $logger->error( trim( $text ), $context );
}
/**
*
* Can also log to TCP or UDP with the syntax udp://host:port/prefix. This will
* send lines to the specified port, prefixed by the specified prefix and a space.
+ * @since 1.25 support for additional context data
*
* @param string $text
* @param string $file Filename
+ * @param array $context Additional logging context data
* @throws MWException
*/
-function wfErrorLog( $text, $file ) {
+function wfErrorLog( $text, $file, array $context = array() ) {
$logger = MWLogger::getInstance( 'wfErrorLog' );
- $logger->info( trim( $text ), array(
- 'destination' => $file,
- ) );
+ $context['destination'] = $file;
+ $logger->info( trim( $text ), $context );
}
/**
* @todo document
*/
function wfLogProfilingData() {
- global $wgRequestTime, $wgDebugLogFile, $wgDebugLogGroups, $wgDebugRawPage;
+ global $wgRequestTime, $wgDebugLogGroups, $wgDebugRawPage;
global $wgProfileLimit, $wgUser, $wgRequest;
StatCounter::singleton()->flush();
$profiler->logData();
- // Check whether this should be logged in the debug file.
if ( isset( $wgDebugLogGroups['profileoutput'] )
&& $wgDebugLogGroups['profileoutput'] === false
) {
- // Explicitely disabled
- return;
- }
- if ( !isset( $wgDebugLogGroups['profileoutput'] ) && $wgDebugLogFile == '' ) {
- // Logging not enabled; no point going further
+ // Explicitly disabled
return;
}
if ( !$wgDebugRawPage && wfIsDebugRawPage() ) {
return;
}
- $forward = '';
+ $ctx = array( 'elapsed' => $elapsed );
if ( !empty( $_SERVER['HTTP_X_FORWARDED_FOR'] ) ) {
- $forward = ' forwarded for ' . $_SERVER['HTTP_X_FORWARDED_FOR'];
+ $ctx['forwarded_for'] = $_SERVER['HTTP_X_FORWARDED_FOR'];
}
if ( !empty( $_SERVER['HTTP_CLIENT_IP'] ) ) {
- $forward .= ' client IP ' . $_SERVER['HTTP_CLIENT_IP'];
+ $ctx['client_ip'] = $_SERVER['HTTP_CLIENT_IP'];
}
if ( !empty( $_SERVER['HTTP_FROM'] ) ) {
- $forward .= ' from ' . $_SERVER['HTTP_FROM'];
+ $ctx['from'] = $_SERVER['HTTP_FROM'];
}
- if ( $forward ) {
- $forward = "\t(proxied via {$_SERVER['REMOTE_ADDR']}{$forward})";
+ if ( isset( $ctx['forwarded_for'] ) ||
+ isset( $ctx['client_ip'] ) ||
+ isset( $ctx['from'] ) ) {
+ $ctx['proxy'] = $_SERVER['REMOTE_ADDR'];
}
+
// Don't load $wgUser at this late stage just for statistics purposes
- // @todo FIXME: We can detect some anons even if it is not loaded. See User::getId()
+ // @todo FIXME: We can detect some anons even if it is not loaded.
+ // See User::getId()
if ( $wgUser->isItemLoaded( 'id' ) && $wgUser->isAnon() ) {
- $forward .= ' anon';
+ $ctx['anon'] = true;
+ } else {
+ $ctx['anon'] = false;
}
// Command line script uses a FauxRequest object which does not have
// any knowledge about an URL and throw an exception instead.
try {
- $requestUrl = $wgRequest->getRequestURL();
- } catch ( MWException $e ) {
- $requestUrl = 'n/a';
+ $ctx['url'] = urldecode( $wgRequest->getRequestURL() );
+ } catch ( MWException $ignored ) {
+ // no-op
}
- $log = sprintf( "%s\t%04.3f\t%s\n",
- gmdate( 'YmdHis' ), $elapsed,
- urldecode( $requestUrl . $forward ) );
+ $ctx['output'] = $profiler->getOutput();
- wfDebugLog( 'profileoutput', $log . $profiler->getOutput() );
+ $log = MWLogger::getInstance( 'profileoutput' );
+ $log->info( "Elapsed: {elapsed}; URL: <{url}>\n{output}", $ctx );
}
/**
array_shift( $args );
array_shift( $args );
$options = (array)$options;
+ $validOptions = array( 'parse', 'parseinline', 'escape', 'escapenoentities', 'replaceafter',
+ 'parsemag', 'content' );
foreach ( $options as $arrayKey => $option ) {
if ( !preg_match( '/^[0-9]+|language$/', $arrayKey ) ) {
- # An unknown index, neither numeric nor "language"
+ // An unknown index, neither numeric nor "language"
wfWarn( "wfMsgExt called with incorrect parameter key $arrayKey", 1, E_USER_WARNING );
- } elseif ( preg_match( '/^[0-9]+$/', $arrayKey ) && !in_array( $option,
- array( 'parse', 'parseinline', 'escape', 'escapenoentities',
- 'replaceafter', 'parsemag', 'content' ) ) ) {
- # A numeric index with unknown value
+ } elseif ( preg_match( '/^[0-9]+$/', $arrayKey ) && !in_array( $option, $validOptions ) ) {
+ // A numeric index with unknown value
wfWarn( "wfMsgExt called with incorrect parameter $option", 1, E_USER_WARNING );
}
}
/**
* Get a debug backtrace as a string
*
+ * @param bool|null $raw If true, the return value is plain text. If false, HTML.
+ * Defaults to $wgCommandLineMode if unset.
* @return string
+ * @since 1.25 Supports $raw parameter.
*/
-function wfBacktrace() {
+function wfBacktrace( $raw = null ) {
global $wgCommandLineMode;
- if ( $wgCommandLineMode ) {
- $msg = '';
- } else {
- $msg = "<ul>\n";
+ if ( $raw === null ) {
+ $raw = $wgCommandLineMode;
}
- $backtrace = wfDebugBacktrace();
- foreach ( $backtrace as $call ) {
- if ( isset( $call['file'] ) ) {
- $f = explode( DIRECTORY_SEPARATOR, $call['file'] );
- $file = $f[count( $f ) - 1];
- } else {
- $file = '-';
- }
- if ( isset( $call['line'] ) ) {
- $line = $call['line'];
- } else {
- $line = '-';
- }
- if ( $wgCommandLineMode ) {
- $msg .= "$file line $line calls ";
- } else {
- $msg .= '<li>' . $file . ' line ' . $line . ' calls ';
- }
- if ( !empty( $call['class'] ) ) {
- $msg .= $call['class'] . $call['type'];
- }
- $msg .= $call['function'] . '()';
- if ( $wgCommandLineMode ) {
- $msg .= "\n";
- } else {
- $msg .= "</li>\n";
- }
- }
- if ( $wgCommandLineMode ) {
- $msg .= "\n";
+ if ( $raw ) {
+ $frameFormat = "%s line %s calls %s()\n";
+ $traceFormat = "%s";
} else {
- $msg .= "</ul>\n";
+ $frameFormat = "<li>%s line %s calls %s()</li>\n";
+ $traceFormat = "<ul>\n%s</ul>\n";
}
- return $msg;
+ $frames = array_map( function ( $frame ) use ( $frameFormat ) {
+ $file = !empty( $frame['file'] ) ? basename( $frame['file'] ) : '-';
+ $line = $frame['line'] ?: '-';
+ $call = $frame['function'];
+ if ( !empty( $frame['class'] ) ) {
+ $call = $frame['class'] . $frame['type'] . $call;
+ }
+ return sprintf( $frameFormat, $file, $line, $call );
+ }, wfDebugBacktrace() );
+
+ return sprintf( $traceFormat, implode( '', $frames ) );
}
/**
// Figure out which clusters need to be checked
$lbs = array();
if ( $cluster === '*' ) {
- wfGetLBFactory()->forEachLB( function( LoadBalancer $lb ) use ( &$lbs ) {
+ wfGetLBFactory()->forEachLB( function ( LoadBalancer $lb ) use ( &$lbs ) {
$lbs[] = $lb;
} );
} elseif ( $cluster !== false ) {
* @return bool
*/
function wfIsTrustedProxy( $ip ) {
+ wfDeprecated( __METHOD__, '1.24' );
return IP::isTrustedProxy( $ip );
}
* @since 1.23 Supports CIDR ranges in $wgSquidServersNoPurge
*/
function wfIsConfiguredProxy( $ip ) {
+ wfDeprecated( __METHOD__, '1.24' );
return IP::isConfiguredProxy( $ip );
}