*/
public function run() {
try {
+ $this->setDBProfilingAgent();
try {
$this->main();
} catch ( ErrorPageError $e ) {
$this->doPostOutputShutdown( 'normal' );
}
+ private function setDBProfilingAgent() {
+ $services = MediaWikiServices::getInstance();
+ // Add a comment for easy SHOW PROCESSLIST interpretation
+ $name = $this->context->getUser()->getName();
+ $services->getDBLoadBalancerFactory()->setAgentName(
+ mb_strlen( $name ) > 15 ? mb_substr( $name, 0, 15 ) . '...' : $name
+ );
+ }
+
/**
* @see MediaWiki::preOutputCommit()
* @param callable $postCommitWork [default: null]
protected $mDBname;
/** @var array[] $aliases Map of (table => (dbname, schema, prefix) map) */
protected $tableAliases = [];
- /** @var bool */
+ /** @var bool Whether this PHP instance is for a CLI script */
protected $cliMode;
+ /** @var string Agent name for query profiling */
+ protected $agent;
/** @var BagOStuff APC cache */
protected $srvCache;
$this->cliMode = isset( $params['cliMode'] )
? $params['cliMode']
: ( PHP_SAPI === 'cli' );
+ $this->agent = isset( $params['agent'] )
+ ? str_replace( '/', '-', $params['agent'] ) // escape for comment
+ : '';
$this->mFlags = $flags;
if ( $this->mFlags & DBO_DEFAULT ) {
* @throws InvalidArgumentException If the database driver or extension cannot be found
*/
final public static function factory( $dbType, $p = [] ) {
- global $wgCommandLineMode;
-
$canonicalDBTypes = [
'mysql' => [ 'mysqli', 'mysql' ],
'postgres' => [],
$p['schema'] = isset( $defaultSchemas[$dbType] ) ? $defaultSchemas[$dbType] : null;
}
$p['foreign'] = isset( $p['foreign'] ) ? $p['foreign'] : false;
- $p['cliMode'] = $wgCommandLineMode;
$conn = new $class( $p );
if ( isset( $p['connLogger'] ) ) {
if ( isset( $p['errorLogger'] ) ) {
$conn->errorLogger = $p['errorLogger'];
} else {
- $conn->errorLogger = [ MWExceptionHandler::class, 'logException' ];
+ $conn->errorLogger = function ( Exception $e ) {
+ trigger_error( get_class( $e ) . ': ' . $e->getMessage(), E_WARNING );
+ };
}
} else {
$conn = null;
}
public function query( $sql, $fname = __METHOD__, $tempIgnore = false ) {
- global $wgUser;
-
$priorWritesPending = $this->writesOrCallbacksPending();
$this->mLastQuery = $sql;
$this->mDoneWrites = microtime( true );
}
- # Add a comment for easy SHOW PROCESSLIST interpretation
- if ( is_object( $wgUser ) && $wgUser->isItemLoaded( 'name' ) ) {
- $userName = $wgUser->getName();
- if ( mb_strlen( $userName ) > 15 ) {
- $userName = mb_substr( $userName, 0, 15 ) . '...';
- }
- $userName = str_replace( '/', '', $userName );
- } else {
- $userName = '';
- }
-
// Add trace comment to the begin of the sql string, right after the operator.
// Or, for one-word queries (like "BEGIN" or COMMIT") add it to the end (bug 42598)
- $commentedSql = preg_replace( '/\s|$/', " /* $fname $userName */ ", $sql, 1 );
+ $commentedSql = preg_replace( '/\s|$/', " /* $fname {$this->agent} */ ", $sql, 1 );
# Start implicit transactions that wrap the request if DBO_TRX is enabled
if ( !$this->mTrxLevel && $this->getFlag( DBO_TRX )
* @TODO: inject objects via dependency framework
*/
public function __construct( array $conf ) {
+ global $wgCommandLineMode;
+
$defaults = [
'domain' => wfWikiID(),
'hostname' => wfHostname(),
$defaults['wanCache'] = $wCache;
}
+ $this->agent = isset( $params['agent'] ) ? $params['agent'] : '';
+ $this->cliMode = isset( $params['cliMode'] ) ? $params['cliMode'] : $wgCommandLineMode;
+
parent::__construct( $conf + $defaults );
}
/** @var callable[] */
protected $replicationWaitCallbacks = [];
+ /** @var bool Whether this PHP instance is for a CLI script */
+ protected $cliMode;
+ /** @var string Agent name for query profiling */
+ protected $agent;
+
const SHUTDOWN_NO_CHRONPROT = 0; // don't save DB positions at all
const SHUTDOWN_CHRONPROT_ASYNC = 1; // save DB positions, but don't wait on remote DCs
const SHUTDOWN_CHRONPROT_SYNC = 2; // save DB positions, waiting on all DCs
*/
public function __construct( array $conf ) {
$this->domain = isset( $conf['domain'] ) ? $conf['domain'] : '';
+
if ( isset( $conf['readOnlyReason'] ) && is_string( $conf['readOnlyReason'] ) ) {
$this->readOnlyReason = $conf['readOnlyReason'];
}
$this->errorLogger = isset( $conf['errorLogger'] )
? $conf['errorLogger']
: function ( Exception $e ) {
- trigger_error( E_WARNING, $e->getMessage() );
+ trigger_error( E_WARNING, get_class( $e ) . ': ' . $e->getMessage() );
};
$this->hostname = isset( $conf['hostname'] )
? $conf['hostname']
: new TransactionProfiler();
$this->ticket = mt_rand();
+ $this->cliMode = isset( $params['cliMode'] ) ? $params['cliMode'] : PHP_SAPI === 'cli';
+ $this->agent = isset( $params['agent'] ) ? $params['agent'] : '';
}
/**
isset( $_GET['cpPosTime'] ) ? $_GET['cpPosTime'] : null
);
$chronProt->setLogger( $this->replLogger );
- if ( PHP_SAPI === 'cli' ) {
+ if ( $this->cliMode ) {
$chronProt->setEnabled( false );
}
'connLogger' => $this->connLogger,
'replLogger' => $this->replLogger,
'errorLogger' => $this->errorLogger,
- 'hostname' => $this->hostname
+ 'hostname' => $this->hostname,
+ 'cliMode' => $this->cliMode,
+ 'agent' => $this->agent
];
}
public function closeAll() {
$this->forEachLBCallMethod( 'closeAll', [] );
}
+
+ /**
+ * @param string $agent Agent name for query profiling
+ * @since 1.28
+ */
+ public function setAgentName( $agent ) {
+ $this->agent = $agent;
+ }
}
private $localDomain;
/** @var string Current server name */
private $host;
+ /** @var bool Whether this PHP instance is for a CLI script */
+ protected $cliMode;
+ /** @var string Agent name for query profiling */
+ protected $agent;
/** @var callable Exception logger */
private $errorLogger;
$this->errorLogger = isset( $params['errorLogger'] )
? $params['errorLogger']
: function ( Exception $e ) {
- trigger_error( E_WARNING, $e->getMessage() );
+ trigger_error( get_class( $e ) . ': ' . $e->getMessage(), E_WARNING );
};
foreach ( [ 'replLogger', 'connLogger', 'queryLogger', 'perfLogger' ] as $key ) {
$this->host = isset( $params['hostname'] )
? $params['hostname']
: ( gethostname() ?: 'unknown' );
+ $this->cliMode = isset( $params['cliMode'] ) ? $params['cliMode'] : PHP_SAPI === 'cli';
+ $this->agent = isset( $params['agent'] ) ? $params['agent'] : '';
}
/**
$server['connLogger'] = $this->connLogger;
$server['queryLogger'] = $this->queryLogger;
$server['trxProfiler'] = $this->trxProfiler;
+ $server['cliMode'] = $this->cliMode;
+ $server['errorLogger'] = $this->errorLogger;
+ $server['agent'] = $this->agent;
// Create a live connection object
try {
* Set triggers like when to try to run deferred updates
* @since 1.28
*/
- public function setTriggers() {
+ public function setAgentAndTriggers() {
+ if ( function_exists( 'posix_getpwuid' ) ) {
+ $agent = posix_getpwuid( posix_geteuid() )['name'];
+ } else {
+ $agent = 'sysadmin';
+ }
+ $agent .= '@' . wfHostname();
+
$lbFactory = MediaWikiServices::getInstance()->getDBLoadBalancerFactory();
+ // Add a comment for easy SHOW PROCESSLIST interpretation
+ $lbFactory->setAgentName(
+ mb_strlen( $agent ) > 15 ? mb_substr( $agent, 0, 15 ) . '...' : $agent
+ );
self::setLBFactoryTriggers( $lbFactory );
}
// A good time when no DBs have writes pending is around lag checks.
// This avoids having long running scripts just OOM and lose all the updates.
-$maintenance->setTriggers();
+$maintenance->setAgentAndTriggers();
// Do the work
$maintenance->execute();