diff --git a/RELEASE-NOTES-1.27 b/RELEASE-NOTES-1.27 index ac19d39952f..915b93bc0e3 100644 --- a/RELEASE-NOTES-1.27 +++ b/RELEASE-NOTES-1.27 @@ -175,6 +175,12 @@ HHVM 3.1. be a good idea, but will log out all current sessions. * $wgEventRelayerConfig was added, for managing PubSub event relay configuration, specifically for reliable CDN url purges. +* Requests have unique IDs, equal to the UNIQUE_ID environment variable (when + MediaWiki is behind Apache+mod_unique_id or something similar) or a randomly- + generated 24-character string. This request ID is used to annotate log records + and error messages. It is available client-side via mw.config.get( 'wgRequestId' ). + The request ID supplants exception IDs. Accordingly, MWExceptionHandler::getLogId() + is deprecated. === External library changes in 1.27 === diff --git a/includes/OutputPage.php b/includes/OutputPage.php index 0c3d60929e1..3c0dc18b6c3 100644 --- a/includes/OutputPage.php +++ b/includes/OutputPage.php @@ -3210,6 +3210,7 @@ class OutputPage extends ContextSource { 'wgMonthNamesShort' => $lang->getMonthAbbreviationsArray(), 'wgRelevantPageName' => $relevantTitle->getPrefixedDBkey(), 'wgRelevantArticleId' => $relevantTitle->getArticleID(), + 'wgRequestId' => WebRequest::getRequestId(), ]; if ( $user->isLoggedIn() ) { diff --git a/includes/WebRequest.php b/includes/WebRequest.php index 812a320f91c..f4b4871ee95 100644 --- a/includes/WebRequest.php +++ b/includes/WebRequest.php @@ -246,6 +246,25 @@ class WebRequest { return microtime( true ) - $this->requestTime; } + /** + * Get the unique request ID. + * This is either the value of the UNIQUE_ID envvar (if present) or a + * randomly-generated 24-character string. + * + * @return string + * @since 1.27 + */ + public static function getRequestId() { + static $reqId; + + if ( !$reqId ) { + $reqId = isset( $_SERVER['UNIQUE_ID'] ) + ? $_SERVER['UNIQUE_ID'] : wfRandomString( 24 ); + } + + return $reqId; + } + /** * Get the current URL protocol (http or https) * @return string diff --git a/includes/api/ApiMain.php b/includes/api/ApiMain.php index 63b79ac3eb5..5566d317754 100644 --- a/includes/api/ApiMain.php +++ b/includes/api/ApiMain.php @@ -871,7 +871,7 @@ class ApiMain extends ApiBase { $errMessage = [ 'code' => 'internal_api_error_' . get_class( $e ), - 'info' => '[' . MWExceptionHandler::getLogId( $e ) . '] ' . $info, + 'info' => '[' . WebRequest::getRequestId() . '] ' . $info, ]; } return $errMessage; diff --git a/includes/debug/logger/monolog/WikiProcessor.php b/includes/debug/logger/monolog/WikiProcessor.php index 7f60f2e2e79..e3c048dae52 100644 --- a/includes/debug/logger/monolog/WikiProcessor.php +++ b/includes/debug/logger/monolog/WikiProcessor.php @@ -21,7 +21,8 @@ namespace MediaWiki\Logger\Monolog; /** - * Injects `wfHostname()`, `wfWikiID()` and `$wgVersion` in all records. + * Annotate log records with request-global metadata, such as the hostname, + * wiki / request ID, and MediaWiki version. * * @since 1.25 * @author Bryan Davis @@ -41,6 +42,7 @@ class WikiProcessor { 'host' => wfHostname(), 'wiki' => wfWikiID(), 'mwversion' => $wgVersion, + 'reqId' => WebRequest::getRequestId(), ] ); return $record; diff --git a/includes/exception/MWException.php b/includes/exception/MWException.php index e1d7e6cb4b8..bebd91580f5 100644 --- a/includes/exception/MWException.php +++ b/includes/exception/MWException.php @@ -141,7 +141,7 @@ class MWException extends Exception { nl2br( htmlspecialchars( MWExceptionHandler::getRedactedTraceAsString( $this ) ) ) . "

\n"; } else { - $logId = MWExceptionHandler::getLogId( $this ); + $logId = WebRequest::getRequestId(); $type = get_class( $this ); return "
" . '[' . $logId . '] ' . diff --git a/includes/exception/MWExceptionHandler.php b/includes/exception/MWExceptionHandler.php index b71f92c5999..63adc29bfdd 100644 --- a/includes/exception/MWExceptionHandler.php +++ b/includes/exception/MWExceptionHandler.php @@ -445,14 +445,13 @@ TXT; * $wgShowExceptionDetails is set to false), to the entry in the debug log. * * @since 1.22 + * @deprecated since 1.27: Exception IDs are synonymous with request IDs. * @param Exception|Throwable $e * @return string */ public static function getLogId( $e ) { - if ( !isset( $e->_mwLogId ) ) { - $e->_mwLogId = wfRandomString( 8 ); - } - return $e->_mwLogId; + wfDeprecated( __METHOD__, '1.27' ); + return WebRequest::getRequestId(); } /** @@ -478,7 +477,7 @@ TXT; * @return string */ public static function getLogMessage( $e ) { - $id = self::getLogId( $e ); + $id = WebRequest::getRequestId(); $type = get_class( $e ); $file = $e->getFile(); $line = $e->getLine(); @@ -489,9 +488,9 @@ TXT; } public static function getPublicLogMessage( Exception $e ) { - $logId = self::getLogId( $e ); + $reqId = WebRequest::getRequestId(); $type = get_class( $e ); - return '[' . $logId . '] ' + return '[' . $reqId . '] ' . gmdate( 'Y-m-d H:i:s' ) . ': ' . 'Fatal exception of type ' . $type; } @@ -509,7 +508,7 @@ TXT; public static function getLogContext( $e ) { return [ 'exception' => $e, - 'exception_id' => static::getLogId( $e ), + 'exception_id' => WebRequest::getRequestId(), ]; } @@ -527,7 +526,7 @@ TXT; public static function getStructuredExceptionData( $e ) { global $wgLogExceptionBacktrace; $data = [ - 'id' => self::getLogId( $e ), + 'id' => WebRequest::getRequestId(), 'type' => get_class( $e ), 'file' => $e->getFile(), 'line' => $e->getLine(),