diff options
author | Stephan Orbaugh <62374139+sorbaugh@users.noreply.github.com> | 2024-07-25 09:09:57 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-07-25 09:09:57 +0200 |
commit | 65941811b326a35bf828879fa0330029d9c75c05 (patch) | |
tree | b977e7d0a4a35823909e5050731bdba2dca9d77f /lib/private/DB | |
parent | d843d671d5dc3ae4023e80ae5e923f7f7b9cf946 (diff) | |
parent | 7fbb98187780ecf19a415366f9089c9b88f41362 (diff) | |
download | nextcloud-server-65941811b326a35bf828879fa0330029d9c75c05.tar.gz nextcloud-server-65941811b326a35bf828879fa0330029d9c75c05.zip |
Merge pull request #44788 from nextcloud/db-error-logging
feat: add additional logging for database errors
Diffstat (limited to 'lib/private/DB')
-rw-r--r-- | lib/private/DB/Connection.php | 51 | ||||
-rw-r--r-- | lib/private/DB/ConnectionAdapter.php | 4 | ||||
-rw-r--r-- | lib/private/DB/QueryBuilder/QueryBuilder.php | 1 |
3 files changed, 52 insertions, 4 deletions
diff --git a/lib/private/DB/Connection.php b/lib/private/DB/Connection.php index e584690f95d..3cdd5fd06c0 100644 --- a/lib/private/DB/Connection.php +++ b/lib/private/DB/Connection.php @@ -69,6 +69,9 @@ class Connection extends PrimaryReadReplicaConnection { /** @var array<string, int> */ protected $tableDirtyWrites = []; + protected bool $logDbException = false; + private ?array $transactionBacktrace = null; + protected bool $logRequestId; protected string $requestId; @@ -101,6 +104,7 @@ class Connection extends PrimaryReadReplicaConnection { $this->logger = Server::get(LoggerInterface::class); $this->logRequestId = $this->systemConfig->getValue('db.log_request_id', false); + $this->logDbException = $this->systemConfig->getValue('db.log_exceptions', false); $this->requestId = Server::get(IRequestId::class)->getId(); /** @var \OCP\Profiler\IProfiler */ @@ -304,7 +308,12 @@ class Connection extends PrimaryReadReplicaConnection { $sql = $this->finishQuery($sql); $this->queriesExecuted++; $this->logQueryToFile($sql); - return parent::executeQuery($sql, $params, $types, $qcp); + try { + return parent::executeQuery($sql, $params, $types, $qcp); + } catch (\Exception $e) { + $this->logDatabaseException($e); + throw $e; + } } /** @@ -346,7 +355,12 @@ class Connection extends PrimaryReadReplicaConnection { $sql = $this->finishQuery($sql); $this->queriesExecuted++; $this->logQueryToFile($sql); - return (int)parent::executeStatement($sql, $params, $types); + try { + return (int)parent::executeStatement($sql, $params, $types); + } catch (\Exception $e) { + $this->logDatabaseException($e); + throw $e; + } } protected function logQueryToFile(string $sql): void { @@ -419,11 +433,21 @@ class Connection extends PrimaryReadReplicaConnection { * @deprecated 15.0.0 - use unique index and "try { $db->insert() } catch (UniqueConstraintViolationException $e) {}" instead, because it is more reliable and does not have the risk for deadlocks - see https://github.com/nextcloud/server/pull/12371 */ public function insertIfNotExist($table, $input, ?array $compare = null) { - return $this->adapter->insertIfNotExist($table, $input, $compare); + try { + return $this->adapter->insertIfNotExist($table, $input, $compare); + } catch (\Exception $e) { + $this->logDatabaseException($e); + throw $e; + } } public function insertIgnoreConflict(string $table, array $values) : int { - return $this->adapter->insertIgnoreConflict($table, $values); + try { + return $this->adapter->insertIgnoreConflict($table, $values); + } catch (\Exception $e) { + $this->logDatabaseException($e); + throw $e; + } } private function getType($value) { @@ -682,6 +706,7 @@ class Connection extends PrimaryReadReplicaConnection { public function beginTransaction() { if (!$this->inTransaction()) { + $this->transactionBacktrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS); $this->transactionActiveSince = microtime(true); } return parent::beginTransaction(); @@ -691,6 +716,7 @@ class Connection extends PrimaryReadReplicaConnection { $result = parent::commit(); if ($this->getTransactionNestingLevel() === 0) { $timeTook = microtime(true) - $this->transactionActiveSince; + $this->transactionBacktrace = null; $this->transactionActiveSince = null; if ($timeTook > 1) { $this->logger->debug('Transaction took ' . $timeTook . 's', ['exception' => new \Exception('Transaction took ' . $timeTook . 's')]); @@ -703,6 +729,7 @@ class Connection extends PrimaryReadReplicaConnection { $result = parent::rollBack(); if ($this->getTransactionNestingLevel() === 0) { $timeTook = microtime(true) - $this->transactionActiveSince; + $this->transactionBacktrace = null; $this->transactionActiveSince = null; if ($timeTook > 1) { $this->logger->debug('Transaction rollback took longer than 1s: ' . $timeTook, ['exception' => new \Exception('Long running transaction rollback')]); @@ -759,4 +786,20 @@ class Connection extends PrimaryReadReplicaConnection { /** @var ServerInfoAwareConnection $this->_conn */ return $this->_conn->getServerVersion(); } + + /** + * Log a database exception if enabled + * + * @param \Exception $exception + * @return void + */ + public function logDatabaseException(\Exception $exception): void { + if ($this->logDbException) { + if ($exception instanceof Exception\UniqueConstraintViolationException) { + $this->logger->info($exception->getMessage(), ['exception' => $exception, 'transaction' => $this->transactionBacktrace]); + } else { + $this->logger->error($exception->getMessage(), ['exception' => $exception, 'transaction' => $this->transactionBacktrace]); + } + } + } } diff --git a/lib/private/DB/ConnectionAdapter.php b/lib/private/DB/ConnectionAdapter.php index b7225169e4c..88083711195 100644 --- a/lib/private/DB/ConnectionAdapter.php +++ b/lib/private/DB/ConnectionAdapter.php @@ -240,4 +240,8 @@ class ConnectionAdapter implements IDBConnection { public function getServerVersion(): string { return $this->inner->getServerVersion(); } + + public function logDatabaseException(\Exception $exception) { + $this->inner->logDatabaseException($exception); + } } diff --git a/lib/private/DB/QueryBuilder/QueryBuilder.php b/lib/private/DB/QueryBuilder/QueryBuilder.php index 0ea223cd89c..4c4786f02b6 100644 --- a/lib/private/DB/QueryBuilder/QueryBuilder.php +++ b/lib/private/DB/QueryBuilder/QueryBuilder.php @@ -253,6 +253,7 @@ class QueryBuilder implements IQueryBuilder { // `IQueryBuilder->execute` never wrapped the exception, but `executeQuery` and `executeStatement` do /** @var \Doctrine\DBAL\Exception $previous */ $previous = $e->getPrevious(); + throw $previous; } } |