diff --git a/extension.json b/extension.json index 560bee1099..aec3f33c96 100644 --- a/extension.json +++ b/extension.json @@ -416,6 +416,10 @@ "description": "String. The main part of subdomains, e.g. wiki.example.org, example.org is the main part.", "value": "" }, + "CreateWikiTrackDatabaseListMetrics": { + "description": "Boolean. Whether to track metrics related to the (re)generation of database lists.", + "value": false + }, "CreateWikiUseClosedWikis": { "description": "Boolean. Whether to implement front end logic for closing wikis.", "value": false diff --git a/includes/ConfigNames.php b/includes/ConfigNames.php index 48370c99d5..7b7f57711a 100644 --- a/includes/ConfigNames.php +++ b/includes/ConfigNames.php @@ -35,6 +35,8 @@ class ConfigNames { public const EmailNotifications = 'CreateWikiEmailNotifications'; + public const TrackDatabaseListMetrics = 'CreateWikiTrackDatabaseListMetrics'; + public const EnableManageInactiveWikis = 'CreateWikiEnableManageInactiveWikis'; public const EnableRESTAPI = 'CreateWikiEnableRESTAPI'; diff --git a/includes/Helpers/RemoteWiki.php b/includes/Helpers/RemoteWiki.php index 6e983ffdac..7468e9dad6 100644 --- a/includes/Helpers/RemoteWiki.php +++ b/includes/Helpers/RemoteWiki.php @@ -470,7 +470,7 @@ public function commit(): void { } if ( $this->resetDatabaseLists ) { - $this->dataStore->resetDatabaseLists( isNewChanges: true ); + $this->dataStore->resetDatabaseLists( isNewChanges: true, caller: __METHOD__ ); } $this->hookRunner->onCreateWikiRemoteWikiCommit( $this->dbname ); diff --git a/includes/ServiceWiring.php b/includes/ServiceWiring.php index c75c98eef4..98595bdb13 100644 --- a/includes/ServiceWiring.php +++ b/includes/ServiceWiring.php @@ -34,6 +34,7 @@ 'CreateWikiDataStore' => static function ( MediaWikiServices $services ): CreateWikiDataStore { return new CreateWikiDataStore( $services->getObjectCacheFactory(), + $services->getStatsFactory(), $services->get( 'CreateWikiDatabaseUtils' ), $services->get( 'CreateWikiHookRunner' ), new ServiceOptions( diff --git a/includes/Services/CreateWikiDataStore.php b/includes/Services/CreateWikiDataStore.php index 283f8981d8..a518ba30cc 100644 --- a/includes/Services/CreateWikiDataStore.php +++ b/includes/Services/CreateWikiDataStore.php @@ -12,6 +12,7 @@ use Wikimedia\ObjectCache\BagOStuff; use Wikimedia\Rdbms\IReadableDatabase; use Wikimedia\StaticArrayWriter; +use Wikimedia\Stats\StatsFactory; use function array_keys; use function file_put_contents; use function function_exists; @@ -28,6 +29,7 @@ class CreateWikiDataStore { public const CONSTRUCTOR_OPTIONS = [ ConfigNames::CacheDirectory, ConfigNames::CacheType, + ConfigNames::TrackDatabaseListMetrics, MainConfigNames::CacheDirectory, MainConfigNames::LocalDatabases, ]; @@ -41,9 +43,11 @@ class CreateWikiDataStore { private readonly string $cacheDir; private int $timestamp; private int $localServerTimestamp; + private readonly bool $trackDatabaseListMetrics; public function __construct( ObjectCacheFactory $objectCacheFactory, + private readonly StatsFactory $statsFactory, private readonly CreateWikiDatabaseUtils $databaseUtils, private readonly CreateWikiHookRunner $hookRunner, private readonly ServiceOptions $options @@ -64,6 +68,8 @@ public function __construct( $this->localServerTimestamp = (int)$this->localServerCache->get( $this->localServerCache->makeGlobalKey( self::CACHE_KEY, 'databases-local' ) ); + + $this->trackDatabaseListMetrics = $this->options->get( ConfigNames::TrackDatabaseListMetrics ); } /** @@ -73,7 +79,7 @@ public function __construct( */ public function syncCache(): void { if ( !$this->timestamp ) { - $this->resetDatabaseLists( isNewChanges: true ); + $this->resetDatabaseLists( isNewChanges: true, caller: __METHOD__ ); return; } @@ -86,7 +92,7 @@ public function syncCache(): void { // Only regenerate if localServerTimestamp is smaller than timestamp so multiple processes on the // same server don't try regenerating the dblists at the same time. if ( ( $mtime === 0 || $mtime < $this->timestamp ) && $this->localServerTimestamp < $this->timestamp ) { - $this->resetDatabaseLists( isNewChanges: false ); + $this->resetDatabaseLists( isNewChanges: false, caller: __METHOD__ ); } } @@ -105,7 +111,20 @@ public function getAllDatabases(): array { * the updated list to a PHP file within the cache directory. It also updates the * modification time (mtime) and stores it in the cache for future reference. */ - public function resetDatabaseLists( bool $isNewChanges ): void { + // @phan-suppress-next-line PhanDisallowedOptionalMethodParameter + public function resetDatabaseLists( bool $isNewChanges, ?string $caller = null ): void { + $timer = null; + if ( $this->trackDatabaseListMetrics ) { + /** @phan-suppress-next-line PhanPossiblyUndeclaredMethod */ + $this->statsFactory->getCounter( 'createwiki_dblist_generation_total' ) + ->setLabel( 'cause', $caller ?? 'unknown' ) + ->setLabel( 'new_changes', $isNewChanges ? 'Yes' : 'No' ) + ->increment(); + + $timer = $this->statsFactory->getTiming( 'createwiki_dblist_generation_seconds' ) + ->start(); + } + $mtime = time(); $this->localServerCache->set( $this->localServerCache->makeGlobalKey( self::CACHE_KEY, 'databases-local' ), @@ -132,6 +151,7 @@ public function resetDatabaseLists( bool $isNewChanges ): void { $this->writeToFile( $name, $list ); } + $timer?->stop(); return; } @@ -171,6 +191,7 @@ public function resetDatabaseLists( bool $isNewChanges ): void { ]; $this->writeToFile( 'databases', $list ); + $timer?->stop(); } /** diff --git a/includes/Services/WikiManagerFactory.php b/includes/Services/WikiManagerFactory.php index f8c96d7a46..228352c777 100644 --- a/includes/Services/WikiManagerFactory.php +++ b/includes/Services/WikiManagerFactory.php @@ -266,9 +266,10 @@ private function doAfterCreate( $this->hookRunner->onCreateWikiCreation( $this->dbname, $private ); + $method = __METHOD__; DeferredUpdates::addCallableUpdate( - function () use ( $requester, $extra ) { - $this->dataStore->resetDatabaseLists( isNewChanges: true ); + function () use ( $requester, $extra, $method ) { + $this->dataStore->resetDatabaseLists( isNewChanges: true, caller: $method ); $limits = [ 'memory' => 0, 'filesize' => 0, 'time' => 0, 'walltime' => 0 ]; Shell::makeScriptCommand( @@ -383,7 +384,7 @@ public function delete( bool $force ): ?string { ->execute(); } - $this->dataStore->resetDatabaseLists( isNewChanges: true ); + $this->dataStore->resetDatabaseLists( isNewChanges: true, caller: __METHOD__ ); $this->hookRunner->onCreateWikiDeletion( $this->cwdb, $this->dbname ); return null; @@ -417,7 +418,7 @@ public function rename( string $newDatabaseName ): ?string { ->execute(); } - $this->dataStore->resetDatabaseLists( isNewChanges: true ); + $this->dataStore->resetDatabaseLists( isNewChanges: true, caller: __METHOD__ ); $this->hookRunner->onCreateWikiRename( $this->cwdb, $this->dbname, $newDatabaseName ); return null; diff --git a/maintenance/ManageInactiveWikis.php b/maintenance/ManageInactiveWikis.php index 5b596620d3..35e3dd139e 100644 --- a/maintenance/ManageInactiveWikis.php +++ b/maintenance/ManageInactiveWikis.php @@ -77,7 +77,7 @@ public function execute(): void { } } - $this->dataStore->resetDatabaseLists( isNewChanges: true ); + $this->dataStore->resetDatabaseLists( isNewChanges: true, caller: __METHOD__ ); } private function checkLastActivity(