if ( isset( $conf['readOnlyReason'] ) && is_string( $conf['readOnlyReason'] ) ) {
$this->readOnlyReason = $conf['readOnlyReason'];
}
- $this->chronProt = $this->newChronologyProtector();
- $this->trxProfiler = Profiler::instance()->getTransactionProfiler();
// Use APC/memcached style caching, but avoids loops with CACHE_DB (T141804)
$sCache = ObjectCache::getLocalServerInstance();
if ( $sCache->getQoS( $sCache::ATTR_EMULATION ) > $sCache::QOS_EMULATION_SQL ) {
} else {
$this->wanCache = WANObjectCache::newEmpty();
}
+ $this->trxProfiler = Profiler::instance()->getTransactionProfiler();
$this->trxLogger = LoggerFactory::getInstance( 'DBTransaction' );
$this->replLogger = LoggerFactory::getInstance( 'DBReplication' );
+ $this->chronProt = $this->newChronologyProtector();
$this->ticket = mt_rand();
}
],
$request->getFloat( 'cpPosTime', $request->getCookie( 'cpPosTime', '' ) )
);
+ $chronProt->setLogger( $this->replLogger );
if ( PHP_SAPI === 'cli' ) {
$chronProt->setEnabled( false );
} elseif ( $request->getHeader( 'ChronologyProtection' ) === 'false' ) {
'queryLogger' => LoggerFactory::getInstance( 'DBQuery' ),
'connLogger' => LoggerFactory::getInstance( 'DBConnection' ),
'replLogger' => LoggerFactory::getInstance( 'DBReplication' ),
- 'errorLogger' => [ MWExceptionHandler::class, 'logException' ]
+ 'errorLogger' => [ MWExceptionHandler::class, 'logException' ],
+ 'hostname' => wfHostname()
];
}
private $trxRecurringCallbacks = [];
/** @var string Local Wiki ID and default for selectDB() calls */
private $localDomain;
+ /** @var string Current server name */
+ private $host;
+
/** @var callable Exception logger */
private $errorLogger;
foreach ( [ 'replLogger', 'connLogger', 'queryLogger', 'perfLogger' ] as $key ) {
$this->$key = isset( $params[$key] ) ? $params[$key] : new \Psr\Log\NullLogger();
}
+
+ $this->host = isset( $params['hostname'] )
+ ? $params['hostname']
+ : ( gethostname() ?: 'unknown' );
}
/**
}
$serverName = $this->getServerName( $i );
$this->connLogger->debug(
- __METHOD__ . ": using server $serverName for group '$group'\n" );
+ __METHOD__ . ": using server $serverName for group '$group'" );
}
return $i;
$knownReachedPos = $this->srvCache->get( $key );
if ( $knownReachedPos && $knownReachedPos->hasReached( $this->mWaitForPos ) ) {
$this->replLogger->debug( __METHOD__ .
- ": replica DB $server known to be caught up (pos >= $knownReachedPos).\n" );
+ ": replica DB $server known to be caught up (pos >= $knownReachedPos)." );
return true;
}
$conn = $this->getAnyOpenConnection( $index );
if ( !$conn ) {
if ( !$open ) {
- $this->replLogger->debug( __METHOD__ . ": no connection open for $server\n" );
+ $this->replLogger->debug( __METHOD__ . ": no connection open for $server" );
return false;
} else {
$conn = $this->openConnection( $index, '' );
if ( !$conn ) {
- $this->replLogger->warning( __METHOD__ . ": failed to connect to $server\n" );
+ $this->replLogger->warning( __METHOD__ . ": failed to connect to $server" );
return false;
}
}
}
- $this->replLogger->info( __METHOD__ . ": Waiting for replica DB $server to catch up...\n" );
+ $this->replLogger->info( __METHOD__ . ": Waiting for replica DB $server to catch up..." );
$timeout = $timeout ?: $this->mWaitTimeout;
$result = $conn->masterPosWait( $this->mWaitForPos, $timeout );
if ( $result == -1 || is_null( $result ) ) {
// Timed out waiting for replica DB, use master instead
$msg = __METHOD__ . ": Timed out waiting on $server pos {$this->mWaitForPos}";
- $this->replLogger->warning( "$msg\n" );
- $this->perfLogger->warning( "$msg:\n" . wfBacktrace( true ) );
+ $this->replLogger->warning( "$msg" );
$ok = false;
} else {
- $this->replLogger->info( __METHOD__ . ": Done\n" );
+ $this->replLogger->info( __METHOD__ . ": Done" );
$ok = true;
// Remember that the DB reached this point
$this->srvCache->set( $key, $this->mWaitForPos, BagOStuff::TTL_DAY );
if ( $refCount <= 0 ) {
$this->mConns['foreignFree'][$serverIndex][$wiki] = $conn;
unset( $this->mConns['foreignUsed'][$serverIndex][$wiki] );
- wfDebug( __METHOD__ . ": freed connection $serverIndex/$wiki\n" );
+ $this->connLogger->debug( __METHOD__ . ": freed connection $serverIndex/$wiki" );
} else {
- wfDebug( __METHOD__ . ": reference count for $serverIndex/$wiki reduced to $refCount\n" );
+ $this->connLogger->debug( __METHOD__ .
+ ": reference count for $serverIndex/$wiki reduced to $refCount" );
}
}
if ( isset( $this->mConns['foreignUsed'][$i][$wiki] ) ) {
// Reuse an already-used connection
$conn = $this->mConns['foreignUsed'][$i][$wiki];
- wfDebug( __METHOD__ . ": reusing connection $i/$wiki\n" );
+ $this->connLogger->debug( __METHOD__ . ": reusing connection $i/$wiki" );
} elseif ( isset( $this->mConns['foreignFree'][$i][$wiki] ) ) {
// Reuse a free connection for the same wiki
$conn = $this->mConns['foreignFree'][$i][$wiki];
unset( $this->mConns['foreignFree'][$i][$wiki] );
$this->mConns['foreignUsed'][$i][$wiki] = $conn;
- wfDebug( __METHOD__ . ": reusing free connection $i/$wiki\n" );
+ $this->connLogger->debug( __METHOD__ . ": reusing free connection $i/$wiki" );
} elseif ( !empty( $this->mConns['foreignFree'][$i] ) ) {
// Reuse a connection from another wiki
$conn = reset( $this->mConns['foreignFree'][$i] );
// DatabaseMysqlBase::open() already handle this on connection.
if ( $dbName !== '' && !$conn->selectDB( $dbName ) ) {
$this->mLastError = "Error selecting database $dbName on server " .
- $conn->getServer() . " from client host " . wfHostname() . "\n";
+ $conn->getServer() . " from client host {$this->host}";
$this->mErrorConnection = $conn;
$conn = false;
} else {
$conn->tablePrefix( $prefix );
unset( $this->mConns['foreignFree'][$i][$oldWiki] );
$this->mConns['foreignUsed'][$i][$wiki] = $conn;
- wfDebug( __METHOD__ . ": reusing free connection from $oldWiki for $wiki\n" );
+ $this->connLogger->debug( __METHOD__ .
+ ": reusing free connection from $oldWiki for $wiki" );
}
} else {
// Open a new connection
$server['foreign'] = true;
$conn = $this->reallyOpenConnection( $server, $dbName );
if ( !$conn->isOpen() ) {
- wfDebug( __METHOD__ . ": error opening connection for $i/$wiki\n" );
+ $this->connLogger->warning( __METHOD__ . ": connection error for $i/$wiki" );
$this->mErrorConnection = $conn;
$conn = false;
} else {
$conn->tablePrefix( $prefix );
$this->mConns['foreignUsed'][$i][$wiki] = $conn;
- wfDebug( __METHOD__ . ": opened new connection for $i/$wiki\n" );
+ $this->connLogger->debug( __METHOD__ . ": opened new connection for $i/$wiki" );
}
}
*
* @param array $server
* @param bool $dbNameOverride
- * @throws MWException
* @return DatabaseBase
+ * @throws DBAccessError
+ * @throws MWException
*/
protected function reallyOpenConnection( $server, $dbNameOverride = false ) {
if ( $this->disabled ) {
// Log when many connection are made on requests
if ( ++$this->connsOpened >= self::CONN_HELD_WARN_THRESHOLD ) {
$this->perfLogger->warning( __METHOD__ . ": " .
- "{$this->connsOpened}+ connections made (master=$masterName)\n" .
- wfBacktrace( true ) );
+ "{$this->connsOpened}+ connections made (master=$masterName)" );
}
// Set loggers
if ( !is_object( $conn ) ) {
// No last connection, probably due to all servers being too busy
- wfLogDBError(
+ $this->connLogger->error(
"LB failure with no last connection. Connection error: {last_error}",
$context
);
throw new DBConnectionError( null, $this->mLastError );
} else {
$context['db_server'] = $conn->getProperty( 'mServer' );
- wfLogDBError(
+ $this->connLogger->warning(
"Connection error: {last_error} ({db_server})",
$context
);
if ( $limit > 0 && $time > $limit ) {
throw new DBTransactionError(
$conn,
+ "Transaction spent $time second(s) in writes, exceeding the $limit limit.",
wfMessage( 'transaction-duration-limit-exceeded', $time, $limit )->text()
);
}
// This happens if onTransactionIdle() callbacks leave callbacks on *another* DB
// (which finished its callbacks already). Warn and recover in this case. Let the
// callbacks run in the final commitMasterChanges() in LBFactory::shutdown().
- wfWarn( __METHOD__ . ": did not expect writes/callbacks pending." );
+ $this->queryLogger->error( __METHOD__ . ": found writes/callbacks pending." );
return;
} elseif ( $conn->trxLevel() ) {
// This happens for single-DB setups where DB_REPLICA uses the master DB,
$result = $conn->masterPosWait( $pos, $timeout );
if ( $result == -1 || is_null( $result ) ) {
$msg = __METHOD__ . ": Timed out waiting on {$conn->getServer()} pos {$pos}";
- $this->replLogger->warning( "$msg\n" );
- $this->perfLogger->warning( "$msg:\n" . wfBacktrace( true ) );
+ $this->replLogger->warning( "$msg" );
$ok = false;
} else {
- $this->replLogger->info( __METHOD__ . ": Done\n" );
+ $this->replLogger->info( __METHOD__ . ": Done" );
$ok = true;
}