Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Built-in profiler #30823

Merged
merged 1 commit into from
Apr 4, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions apps/dav/composer/composer/autoload_classmap.php
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,7 @@
'OCA\\DAV\\Migration\\Version1016Date20201109085907' => $baseDir . '/../lib/Migration/Version1016Date20201109085907.php',
'OCA\\DAV\\Migration\\Version1017Date20210216083742' => $baseDir . '/../lib/Migration/Version1017Date20210216083742.php',
'OCA\\DAV\\Migration\\Version1018Date20210312100735' => $baseDir . '/../lib/Migration/Version1018Date20210312100735.php',
'OCA\\DAV\\Profiler\\ProfilerPlugin' => $baseDir . '/../lib/Profiler/ProfilerPlugin.php',
'OCA\\DAV\\Provisioning\\Apple\\AppleProvisioningNode' => $baseDir . '/../lib/Provisioning/Apple/AppleProvisioningNode.php',
'OCA\\DAV\\Provisioning\\Apple\\AppleProvisioningPlugin' => $baseDir . '/../lib/Provisioning/Apple/AppleProvisioningPlugin.php',
'OCA\\DAV\\RootCollection' => $baseDir . '/../lib/RootCollection.php',
Expand Down
1 change: 1 addition & 0 deletions apps/dav/composer/composer/autoload_static.php
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,7 @@ class ComposerStaticInitDAV
'OCA\\DAV\\Migration\\Version1016Date20201109085907' => __DIR__ . '/..' . '/../lib/Migration/Version1016Date20201109085907.php',
'OCA\\DAV\\Migration\\Version1017Date20210216083742' => __DIR__ . '/..' . '/../lib/Migration/Version1017Date20210216083742.php',
'OCA\\DAV\\Migration\\Version1018Date20210312100735' => __DIR__ . '/..' . '/../lib/Migration/Version1018Date20210312100735.php',
'OCA\\DAV\\Profiler\\ProfilerPlugin' => __DIR__ . '/..' . '/../lib/Profiler/ProfilerPlugin.php',
'OCA\\DAV\\Provisioning\\Apple\\AppleProvisioningNode' => __DIR__ . '/..' . '/../lib/Provisioning/Apple/AppleProvisioningNode.php',
'OCA\\DAV\\Provisioning\\Apple\\AppleProvisioningPlugin' => __DIR__ . '/..' . '/../lib/Provisioning/Apple/AppleProvisioningPlugin.php',
'OCA\\DAV\\RootCollection' => __DIR__ . '/..' . '/../lib/RootCollection.php',
Expand Down
47 changes: 47 additions & 0 deletions apps/dav/lib/Profiler/ProfilerPlugin.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<?php declare(strict_types = 1);
/**
* @copyright 2021 Carl Schwan <carl@carlschwan.eu>
*
* @author Carl Schwan <carl@carlschwan.eu>
*
* @license AGPL-3.0-or-later
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

namespace OCA\DAV\Profiler;

use OCP\IRequest;
use Sabre\DAV\Server;
use Sabre\HTTP\RequestInterface;
use Sabre\HTTP\ResponseInterface;

class ProfilerPlugin extends \Sabre\DAV\ServerPlugin {
private IRequest $request;

public function __construct(IRequest $request) {
$this->request = $request;
come-nc marked this conversation as resolved.
Show resolved Hide resolved
}

/** @return void */
public function initialize(Server $server) {
$server->on('afterMethod:*', [$this, 'afterMethod']);
}

/** @return void */
public function afterMethod(RequestInterface $request, ResponseInterface $response) {
$response->addHeader('X-Debug-Token', $this->request->getId());
}
}
31 changes: 21 additions & 10 deletions apps/dav/lib/Server.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@

use OCA\DAV\Connector\Sabre\RequestIdHeaderPlugin;
use OCP\Diagnostics\IEventLogger;
use OCP\Profiler\IProfiler;
use OCA\DAV\Profiler\ProfilerPlugin;
use OCP\AppFramework\Http\Response;
use Psr\Log\LoggerInterface;
use OCA\DAV\AppInfo\PluginManager;
use OCA\DAV\CalDAV\BirthdayService;
Expand Down Expand Up @@ -78,17 +81,19 @@
use SearchDAV\DAV\SearchPlugin;

class Server {
private IRequest $request;
private string $baseUri;
public Connector\Sabre\Server $server;
private IProfiler $profiler;

public function __construct(IRequest $request, string $baseUri) {
$this->profiler = \OC::$server->get(IProfiler::class);
if ($this->profiler->isEnabled()) {
/** @var IEventLogger $eventLogger */
$eventLogger = \OC::$server->get(IEventLogger::class);
$eventLogger->start('runtime', 'DAV Runtime');
}

/** @var IRequest */
private $request;

/** @var string */
private $baseUri;

/** @var Connector\Sabre\Server */
public $server;

public function __construct(IRequest $request, $baseUri) {
$this->request = $request;
$this->baseUri = $baseUri;
$logger = \OC::$server->getLogger();
Expand All @@ -115,6 +120,7 @@ public function __construct(IRequest $request, $baseUri) {
$this->server->httpRequest->setUrl($this->request->getRequestUri());
$this->server->setBaseUri($this->baseUri);

$this->server->addPlugin(new ProfilerPlugin($this->request));
$this->server->addPlugin(new BlockLegacyClientPlugin(\OC::$server->getConfig()));
$this->server->addPlugin(new AnonymousOptionsPlugin());
$authPlugin = new Plugin();
Expand Down Expand Up @@ -343,6 +349,11 @@ public function exec() {
$eventLogger->start('dav_server_exec', '');
$this->server->exec();
$eventLogger->end('dav_server_exec');
if ($this->profiler->isEnabled()) {
$eventLogger->end('runtime');
$profile = $this->profiler->collect(\OC::$server->get(IRequest::class), new Response());
$this->profiler->saveProfile($profile);
}
}

private function requestIsForSubtree(array $subTrees): bool {
Expand Down
1 change: 1 addition & 0 deletions apps/user_ldap/composer/composer/autoload_classmap.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
'OCA\\User_LDAP\\ConnectionFactory' => $baseDir . '/../lib/ConnectionFactory.php',
'OCA\\User_LDAP\\Controller\\ConfigAPIController' => $baseDir . '/../lib/Controller/ConfigAPIController.php',
'OCA\\User_LDAP\\Controller\\RenewPasswordController' => $baseDir . '/../lib/Controller/RenewPasswordController.php',
'OCA\\User_LDAP\\DataCollector\\LdapDataCollector' => $baseDir . '/../lib/DataCollector/LdapDataCollector.php',
'OCA\\User_LDAP\\Events\\GroupBackendRegistered' => $baseDir . '/../lib/Events/GroupBackendRegistered.php',
'OCA\\User_LDAP\\Events\\UserBackendRegistered' => $baseDir . '/../lib/Events/UserBackendRegistered.php',
'OCA\\User_LDAP\\Exceptions\\AttributeNotSet' => $baseDir . '/../lib/Exceptions/AttributeNotSet.php',
Expand Down
1 change: 1 addition & 0 deletions apps/user_ldap/composer/composer/autoload_static.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ class ComposerStaticInitUser_LDAP
'OCA\\User_LDAP\\ConnectionFactory' => __DIR__ . '/..' . '/../lib/ConnectionFactory.php',
'OCA\\User_LDAP\\Controller\\ConfigAPIController' => __DIR__ . '/..' . '/../lib/Controller/ConfigAPIController.php',
'OCA\\User_LDAP\\Controller\\RenewPasswordController' => __DIR__ . '/..' . '/../lib/Controller/RenewPasswordController.php',
'OCA\\User_LDAP\\DataCollector\\LdapDataCollector' => __DIR__ . '/..' . '/../lib/DataCollector/LdapDataCollector.php',
'OCA\\User_LDAP\\Events\\GroupBackendRegistered' => __DIR__ . '/..' . '/../lib/Events/GroupBackendRegistered.php',
'OCA\\User_LDAP\\Events\\UserBackendRegistered' => __DIR__ . '/..' . '/../lib/Events/UserBackendRegistered.php',
'OCA\\User_LDAP\\Exceptions\\AttributeNotSet' => __DIR__ . '/..' . '/../lib/Exceptions/AttributeNotSet.php',
Expand Down
50 changes: 50 additions & 0 deletions apps/user_ldap/lib/DataCollector/LdapDataCollector.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php declare(strict_types = 1);
/**
* @copyright 2022 Carl Schwan <carl@carlschwan.eu>
*
* @author Carl Schwan <carl@carlschwan.eu>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

namespace OCA\User_LDAP\DataCollector;

use OC\AppFramework\Http\Request;
use OCP\AppFramework\Http\Response;
use OCP\DataCollector\AbstractDataCollector;

class LdapDataCollector extends AbstractDataCollector {
public function startLdapRequest(string $query, array $args): void {
$this->data[] = [
'start' => microtime(true),
'query' => $query,
'args' => $args,
'end' => microtime(true),
];
}

public function stopLastLdapRequest(): void {
$this->data[count($this->data) - 1]['end'] = microtime(true);
}

public function getName(): string {
return 'ldap';
}

public function collect(Request $request, Response $response, \Throwable $exception = null): void {
}
}
32 changes: 23 additions & 9 deletions apps/user_ldap/lib/LDAP.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
* @author Robin McCorkell <robin@mccorkell.me.uk>
* @author Roeland Jago Douma <roeland@famdouma.nl>
* @author Roger Szabo <roger.szabo@web.de>
* @author Carl Schwan <carl@carlschwan.eu>
*
* @license AGPL-3.0
*
Expand All @@ -32,7 +33,9 @@
*/
namespace OCA\User_LDAP;

use OCP\Profiler\IProfiler;
use OC\ServerNotAvailableException;
use OCA\User_LDAP\DataCollector\LdapDataCollector;
use OCA\User_LDAP\Exceptions\ConstraintViolationException;
use OCA\User_LDAP\PagedResults\IAdapter;
use OCA\User_LDAP\PagedResults\Php73;
Expand All @@ -45,9 +48,18 @@ class LDAP implements ILDAPWrapper {
/** @var IAdapter */
protected $pagedResultsAdapter;

private ?LdapDataCollector $dataCollector = null;

public function __construct(string $logFile = '') {
$this->pagedResultsAdapter = new Php73();
$this->logFile = $logFile;

/** @var IProfiler $profiler */
$profiler = \OC::$server->get(IProfiler::class);
if ($profiler->isEnabled()) {
$this->dataCollector = new LdapDataCollector();
$profiler->add($this->dataCollector);
}
}

/**
Expand Down Expand Up @@ -295,24 +307,26 @@ protected function invokeLDAPMethod() {
if ($this->isResultFalse($result)) {
$this->postFunctionCall();
}
if ($this->dataCollector !== null) {
$this->dataCollector->stopLastLdapRequest();
}
return $result;
}
return null;
}

/**
* @param string $functionName
* @param array $args
*/
private function preFunctionCall($functionName, $args) {
private function preFunctionCall(string $functionName, array $args): void {
$this->curFunc = $functionName;
$this->curArgs = $args;

if ($this->dataCollector !== null) {
$args = array_map(fn ($item) => (!$this->isResource($item) ? $item : '(resource)'), $this->curArgs);

$this->dataCollector->startLdapRequest($this->curFunc, $args);
}

if ($this->logFile !== '' && is_writable(dirname($this->logFile)) && (!file_exists($this->logFile) || is_writable($this->logFile))) {
$args = array_reduce($this->curArgs, static function (array $carry, $item): array {
$carry[] = !is_resource($item) ? $item : '(resource)';
return $carry;
}, []);
$args = array_map(fn ($item) => (!$this->isResource($item) ? $item : '(resource)'), $this->curArgs);
file_put_contents(
$this->logFile,
$this->curFunc . '::' . json_encode($args) . "\n",
Expand Down
6 changes: 0 additions & 6 deletions build/psalm-baseline.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1023,7 +1023,6 @@
</RedundantCondition>
<TypeDoesNotContainType occurrences="2">
<code>get_class($res) === 'OpenSSLAsymmetricKey'</code>
<code>is_object($res)</code>
</TypeDoesNotContainType>
</file>
<file src="apps/encryption/lib/Crypto/EncryptAll.php">
Expand Down Expand Up @@ -2638,11 +2637,6 @@
<code>$default</code>
</MoreSpecificImplementedParamType>
</file>
<file src="lib/private/AppFramework/Utility/SimpleContainer.php">
<UndefinedMethod occurrences="1">
<code>getName</code>
</UndefinedMethod>
</file>
<file src="lib/private/Archive/TAR.php">
<UndefinedDocblockClass occurrences="1">
<code>$this-&gt;tar-&gt;extractInString($path)</code>
Expand Down
8 changes: 8 additions & 0 deletions config/config.sample.php
Original file line number Diff line number Diff line change
Expand Up @@ -962,6 +962,14 @@
*/
'log_rotate_size' => 100 * 1024 * 1024,

/**
* Enable built-in profiler. Helpful when trying to debug performance
* issues.
*
* Note that this has a performance impact and shouldn't be enabled
* on production.
*/
'profiler' => false,
CarlSchwan marked this conversation as resolved.
Show resolved Hide resolved

/**
* Alternate Code Locations
Expand Down
2 changes: 1 addition & 1 deletion core/templates/layout.user.php
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,6 @@
<div id="content" class="app-<?php p($_['appid']) ?>" role="main">
<?php print_unescaped($_['content']); ?>
</div>

<div id="profiler-toolbar"></div>
</body>
</html>
5 changes: 3 additions & 2 deletions lib/autoloader.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@

use \OCP\AutoloadNotAllowedException;
use OCP\ILogger;
use OCP\ICache;

class Autoloader {
/** @var bool */
Expand Down Expand Up @@ -182,9 +183,9 @@ public function load(string $class): bool {
/**
* Sets the optional low-latency cache for class to path mapping.
*
* @param \OC\Memcache\Cache $memoryCache Instance of memory cache.
* @param ICache $memoryCache Instance of memory cache.
*/
public function setMemoryCache(\OC\Memcache\Cache $memoryCache = null): void {
public function setMemoryCache(ICache $memoryCache = null): void {
$this->memoryCache = $memoryCache;
}
}
1 change: 1 addition & 0 deletions lib/base.php
Original file line number Diff line number Diff line change
Expand Up @@ -608,6 +608,7 @@ public static function init() {
$eventLogger->end('request');
});
$eventLogger->start('boot', 'Initialize');
$eventLogger->start('runtime', 'Runtime (total - autoloader)');

// Override php.ini and log everything if we're troubleshooting
if (self::$config->getValue('loglevel') === ILogger::DEBUG) {
Expand Down
12 changes: 12 additions & 0 deletions lib/composer/composer/autoload_classmap.php
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,8 @@
'OCP\\Dashboard\\RegisterWidgetEvent' => $baseDir . '/lib/public/Dashboard/RegisterWidgetEvent.php',
'OCP\\Dashboard\\Service\\IEventsService' => $baseDir . '/lib/public/Dashboard/Service/IEventsService.php',
'OCP\\Dashboard\\Service\\IWidgetsService' => $baseDir . '/lib/public/Dashboard/Service/IWidgetsService.php',
'OCP\\DataCollector\\AbstractDataCollector' => $baseDir . '/lib/public/DataCollector/AbstractDataCollector.php',
'OCP\\DataCollector\\IDataCollector' => $baseDir . '/lib/public/DataCollector/IDataCollector.php',
'OCP\\Defaults' => $baseDir . '/lib/public/Defaults.php',
'OCP\\Diagnostics\\IEvent' => $baseDir . '/lib/public/Diagnostics/IEvent.php',
'OCP\\Diagnostics\\IEventLogger' => $baseDir . '/lib/public/Diagnostics/IEventLogger.php',
Expand Down Expand Up @@ -467,6 +469,8 @@
'OCP\\Preview\\IVersionedPreviewFile' => $baseDir . '/lib/public/Preview/IVersionedPreviewFile.php',
'OCP\\Profile\\ILinkAction' => $baseDir . '/lib/public/Profile/ILinkAction.php',
'OCP\\Profile\\ParameterDoesNotExistException' => $baseDir . '/lib/public/Profile/ParameterDoesNotExistException.php',
'OCP\\Profiler\\IProfile' => $baseDir . '/lib/public/Profiler/IProfile.php',
'OCP\\Profiler\\IProfiler' => $baseDir . '/lib/public/Profiler/IProfiler.php',
'OCP\\Remote\\Api\\IApiCollection' => $baseDir . '/lib/public/Remote/Api/IApiCollection.php',
'OCP\\Remote\\Api\\IApiFactory' => $baseDir . '/lib/public/Remote/Api/IApiFactory.php',
'OCP\\Remote\\Api\\ICapabilitiesApi' => $baseDir . '/lib/public/Remote/Api/ICapabilitiesApi.php',
Expand Down Expand Up @@ -1025,6 +1029,7 @@
'OC\\DB\\Connection' => $baseDir . '/lib/private/DB/Connection.php',
'OC\\DB\\ConnectionAdapter' => $baseDir . '/lib/private/DB/ConnectionAdapter.php',
'OC\\DB\\ConnectionFactory' => $baseDir . '/lib/private/DB/ConnectionFactory.php',
'OC\\DB\\DbDataCollector' => $baseDir . '/lib/private/DB/DbDataCollector.php',
'OC\\DB\\Exceptions\\DbalException' => $baseDir . '/lib/private/DB/Exceptions/DbalException.php',
'OC\\DB\\MigrationException' => $baseDir . '/lib/private/DB/MigrationException.php',
'OC\\DB\\MigrationService' => $baseDir . '/lib/private/DB/MigrationService.php',
Expand All @@ -1035,6 +1040,7 @@
'OC\\DB\\MySQLMigrator' => $baseDir . '/lib/private/DB/MySQLMigrator.php',
'OC\\DB\\MySqlTools' => $baseDir . '/lib/private/DB/MySqlTools.php',
'OC\\DB\\OCSqlitePlatform' => $baseDir . '/lib/private/DB/OCSqlitePlatform.php',
'OC\\DB\\ObjectParameter' => $baseDir . '/lib/private/DB/ObjectParameter.php',
'OC\\DB\\OracleConnection' => $baseDir . '/lib/private/DB/OracleConnection.php',
'OC\\DB\\OracleMigrator' => $baseDir . '/lib/private/DB/OracleMigrator.php',
'OC\\DB\\PgSqlTools' => $baseDir . '/lib/private/DB/PgSqlTools.php',
Expand Down Expand Up @@ -1279,8 +1285,10 @@
'OC\\Memcache\\CASTrait' => $baseDir . '/lib/private/Memcache/CASTrait.php',
'OC\\Memcache\\Cache' => $baseDir . '/lib/private/Memcache/Cache.php',
'OC\\Memcache\\Factory' => $baseDir . '/lib/private/Memcache/Factory.php',
'OC\\Memcache\\LoggerWrapperCache' => $baseDir . '/lib/private/Memcache/LoggerWrapperCache.php',
'OC\\Memcache\\Memcached' => $baseDir . '/lib/private/Memcache/Memcached.php',
'OC\\Memcache\\NullCache' => $baseDir . '/lib/private/Memcache/NullCache.php',
'OC\\Memcache\\ProfilerWrapperCache' => $baseDir . '/lib/private/Memcache/ProfilerWrapperCache.php',
'OC\\Memcache\\Redis' => $baseDir . '/lib/private/Memcache/Redis.php',
'OC\\MemoryInfo' => $baseDir . '/lib/private/MemoryInfo.php',
'OC\\Migration\\BackgroundRepair' => $baseDir . '/lib/private/Migration/BackgroundRepair.php',
Expand Down Expand Up @@ -1347,6 +1355,10 @@
'OC\\Profile\\Actions\\WebsiteAction' => $baseDir . '/lib/private/Profile/Actions/WebsiteAction.php',
'OC\\Profile\\ProfileManager' => $baseDir . '/lib/private/Profile/ProfileManager.php',
'OC\\Profile\\TProfileHelper' => $baseDir . '/lib/private/Profile/TProfileHelper.php',
'OC\\Profiler\\FileProfilerStorage' => $baseDir . '/lib/private/Profiler/FileProfilerStorage.php',
'OC\\Profiler\\Profile' => $baseDir . '/lib/private/Profiler/Profile.php',
'OC\\Profiler\\Profiler' => $baseDir . '/lib/private/Profiler/Profiler.php',
'OC\\Profiler\\RoutingDataCollector' => $baseDir . '/lib/private/Profiler/RoutingDataCollector.php',
'OC\\RedisFactory' => $baseDir . '/lib/private/RedisFactory.php',
'OC\\Remote\\Api\\ApiBase' => $baseDir . '/lib/private/Remote/Api/ApiBase.php',
'OC\\Remote\\Api\\ApiCollection' => $baseDir . '/lib/private/Remote/Api/ApiCollection.php',
Expand Down
Loading