Skip to content
Snippets Groups Projects
Verified Commit 970ff6e9 authored by Alex Pott's avatar Alex Pott
Browse files

Issue #3444060 by longwave, catch, mondrake: Implement failed database...

Issue #3444060 by longwave, catch, mondrake: Implement failed database statement events in performance test query logging
parent 1d6ca731
No related branches found
No related tags found
26 merge requests!11131[10.4.x-only-DO-NOT-MERGE]: Issue ##2842525 Ajax attached to Views exposed filter form does not trigger callbacks,!9470[10.3.x-only-DO-NOT-MERGE]: #3331771 Fix file_get_contents(): Passing null to parameter,!8540Issue #3457061: Bootstrap Modal dialog Not closing after 10.3.0 Update,!8528Issue #3456871 by Tim Bozeman: Support NULL services,!8373Issue #3427374 by danflanagan8, Vighneshh: taxonomy_tid ViewsArgumentDefault...,!3878Removed unused condition head title for views,!3818Issue #2140179: $entity->original gets stale between updates,!3742Issue #3328429: Create item list field formatter for displaying ordered and unordered lists,!3731Claro: role=button on status report items,!3651Issue #3347736: Create new SDC component for Olivero (header-search),!3531Issue #3336994: StringFormatter always displays links to entity even if the user in context does not have access,!3355Issue #3209129: Scrolling problems when adding a block via layout builder,!3154Fixes #2987987 - CSRF token validation broken on routes with optional parameters.,!3133core/modules/system/css/components/hidden.module.css,!2964Issue #2865710 : Dependencies from only one instance of a widget are used in display modes,!2812Issue #3312049: [Followup] Fix Drupal.Commenting.FunctionComment.MissingReturnType returns for NULL,!2378Issue #2875033: Optimize joins and table selection in SQL entity query implementation,!2062Issue #3246454: Add weekly granularity to views date sort,!1105Issue #3025039: New non translatable field on translatable content throws error,!1073issue #3191727: Focus states on mobile second level navigation items fixed,!10223132456: Fix issue where views instances are emptied before an ajax request is complete,!877Issue #2708101: Default value for link text is not saved,!617Issue #3043725: Provide a Entity Handler for user cancelation,!579Issue #2230909: Simple decimals fail to pass validation,!560Move callback classRemove outside of the loop,!555Issue #3202493
Pipeline #160732 canceled
Pipeline: drupal

#160736

    ...@@ -3,11 +3,10 @@ ...@@ -3,11 +3,10 @@
    namespace Drupal\performance_test; namespace Drupal\performance_test;
    use Drupal\Core\Database\Connection; use Drupal\Core\Database\Connection;
    use Drupal\Core\Database\Event\StatementEvent;
    use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\HttpKernel\HttpKernelInterface;
    use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
    use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Response;
    use Drupal\Core\Database\Event\StatementExecutionEndEvent;
    use Drupal\Core\Database\Event\StatementExecutionStartEvent;
    class DatabaseEventEnabler implements HttpKernelInterface { class DatabaseEventEnabler implements HttpKernelInterface {
    ...@@ -18,13 +17,7 @@ public function __construct(protected readonly HttpKernelInterface $httpKernel, ...@@ -18,13 +17,7 @@ public function __construct(protected readonly HttpKernelInterface $httpKernel,
    */ */
    public function handle(Request $request, $type = self::MAIN_REQUEST, $catch = TRUE): Response { public function handle(Request $request, $type = self::MAIN_REQUEST, $catch = TRUE): Response {
    if ($type === static::MAIN_REQUEST) { if ($type === static::MAIN_REQUEST) {
    $this->connection->enableEvents([ $this->connection->enableEvents(StatementEvent::all());
    // StatementExecutionStartEvent must be enabled in order for
    // StatementExecutionEndEvent to be fired, even though we only subscribe
    // to the latter event.
    StatementExecutionStartEvent::class,
    StatementExecutionEndEvent::class,
    ]);
    } }
    return $this->httpKernel->handle($request, $type, $catch); return $this->httpKernel->handle($request, $type, $catch);
    } }
    ......
    ...@@ -2,7 +2,9 @@ ...@@ -2,7 +2,9 @@
    namespace Drupal\performance_test; namespace Drupal\performance_test;
    use Drupal\Core\Database\Event\DatabaseEvent;
    use Drupal\Core\Database\Event\StatementExecutionEndEvent; use Drupal\Core\Database\Event\StatementExecutionEndEvent;
    use Drupal\Core\Database\Event\StatementExecutionFailureEvent;
    use Drupal\Core\DestructableInterface; use Drupal\Core\DestructableInterface;
    use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\EventDispatcher\EventSubscriberInterface;
    ...@@ -11,7 +13,7 @@ class PerformanceDataCollector implements EventSubscriberInterface, Destructable ...@@ -11,7 +13,7 @@ class PerformanceDataCollector implements EventSubscriberInterface, Destructable
    /** /**
    * Database events collected during the request. * Database events collected during the request.
    * *
    * @var Drupal\Core\Database\Event\StatementExecutionEndEvent[] * @var \Drupal\Core\Database\Event\DatabaseEvent[]
    */ */
    protected array $databaseEvents = []; protected array $databaseEvents = [];
    ...@@ -30,14 +32,15 @@ class PerformanceDataCollector implements EventSubscriberInterface, Destructable ...@@ -30,14 +32,15 @@ class PerformanceDataCollector implements EventSubscriberInterface, Destructable
    */ */
    public static function getSubscribedEvents(): array { public static function getSubscribedEvents(): array {
    return [ return [
    StatementExecutionEndEvent::class => 'onStatementExecutionEnd', StatementExecutionEndEvent::class => 'onDatabaseEvent',
    StatementExecutionFailureEvent::class => 'onDatabaseEvent',
    ]; ];
    } }
    /** /**
    * Logs database statements. * Logs database statements.
    */ */
    public function onStatementExecutionEnd(StatementExecutionEndEvent $event): void { public function onDatabaseEvent(DatabaseEvent $event): void {
    // Use the event object as a value object. // Use the event object as a value object.
    $this->databaseEvents[] = $event; $this->databaseEvents[] = $event;
    } }
    ......
    ...@@ -202,6 +202,7 @@ public function testLogin(): void { ...@@ -202,6 +202,7 @@ public function testLogin(): void {
    }, 'standardLogin'); }, 'standardLogin');
    $expected_queries = [ $expected_queries = [
    'SELECT "name", "value" FROM "key_value_expire" WHERE "expire" > "NOW" AND "name" IN ( "KEY" ) AND "collection" = "form"',
    'SELECT COUNT(*) AS "expression" FROM (SELECT 1 AS "expression" FROM "flood" "f" WHERE ("event" = "user.failed_login_ip") AND ("identifier" = "CLIENT_IP") AND ("timestamp" > "TIMESTAMP")) "subquery"', 'SELECT COUNT(*) AS "expression" FROM (SELECT 1 AS "expression" FROM "flood" "f" WHERE ("event" = "user.failed_login_ip") AND ("identifier" = "CLIENT_IP") AND ("timestamp" > "TIMESTAMP")) "subquery"',
    'SELECT "base_table"."uid" AS "uid", "base_table"."uid" AS "base_table_uid" FROM "users" "base_table" INNER JOIN "users_field_data" "users_field_data" ON "users_field_data"."uid" = "base_table"."uid" WHERE ("users_field_data"."name" IN ("ACCOUNT_NAME")) AND ("users_field_data"."default_langcode" IN (1))', 'SELECT "base_table"."uid" AS "uid", "base_table"."uid" AS "base_table_uid" FROM "users" "base_table" INNER JOIN "users_field_data" "users_field_data" ON "users_field_data"."uid" = "base_table"."uid" WHERE ("users_field_data"."name" IN ("ACCOUNT_NAME")) AND ("users_field_data"."default_langcode" IN (1))',
    'SELECT COUNT(*) AS "expression" FROM (SELECT 1 AS "expression" FROM "flood" "f" WHERE ("event" = "user.failed_login_user") AND ("identifier" = "CLIENT_IP") AND ("timestamp" > "TIMESTAMP")) "subquery"', 'SELECT COUNT(*) AS "expression" FROM (SELECT 1 AS "expression" FROM "flood" "f" WHERE ("event" = "user.failed_login_user") AND ("identifier" = "CLIENT_IP") AND ("timestamp" > "TIMESTAMP")) "subquery"',
    ...@@ -220,7 +221,7 @@ public function testLogin(): void { ...@@ -220,7 +221,7 @@ public function testLogin(): void {
    ]; ];
    $recorded_queries = $performance_data->getQueries(); $recorded_queries = $performance_data->getQueries();
    $this->assertSame($expected_queries, $recorded_queries); $this->assertSame($expected_queries, $recorded_queries);
    $this->assertSame(15, $performance_data->getQueryCount()); $this->assertSame(16, $performance_data->getQueryCount());
    $this->assertSame(60, $performance_data->getCacheGetCount()); $this->assertSame(60, $performance_data->getCacheGetCount());
    $this->assertSame(1, $performance_data->getCacheSetCount()); $this->assertSame(1, $performance_data->getCacheSetCount());
    $this->assertSame(1, $performance_data->getCacheDeleteCount()); $this->assertSame(1, $performance_data->getCacheDeleteCount());
    ...@@ -256,6 +257,7 @@ public function testLoginBlock(): void { ...@@ -256,6 +257,7 @@ public function testLoginBlock(): void {
    $expected_queries = [ $expected_queries = [
    'SELECT "name", "value" FROM "key_value" WHERE "name" IN ( "theme:stark" ) AND "collection" = "config.entity.key_store.block"', 'SELECT "name", "value" FROM "key_value" WHERE "name" IN ( "theme:stark" ) AND "collection" = "config.entity.key_store.block"',
    'SELECT "config"."name" AS "name" FROM "config" "config" WHERE ("collection" = "") AND ("name" LIKE "search.page.%" ESCAPE ' . "'\\\\'" . ') ORDER BY "collection" ASC, "name" ASC', 'SELECT "config"."name" AS "name" FROM "config" "config" WHERE ("collection" = "") AND ("name" LIKE "search.page.%" ESCAPE ' . "'\\\\'" . ') ORDER BY "collection" ASC, "name" ASC',
    'SELECT "name", "value" FROM "key_value_expire" WHERE "expire" > "NOW" AND "name" IN ( "KEY" ) AND "collection" = "form"',
    'SELECT COUNT(*) AS "expression" FROM (SELECT 1 AS "expression" FROM "flood" "f" WHERE ("event" = "user.failed_login_ip") AND ("identifier" = "CLIENT_IP") AND ("timestamp" > "TIMESTAMP")) "subquery"', 'SELECT COUNT(*) AS "expression" FROM (SELECT 1 AS "expression" FROM "flood" "f" WHERE ("event" = "user.failed_login_ip") AND ("identifier" = "CLIENT_IP") AND ("timestamp" > "TIMESTAMP")) "subquery"',
    'SELECT "base_table"."uid" AS "uid", "base_table"."uid" AS "base_table_uid" FROM "users" "base_table" INNER JOIN "users_field_data" "users_field_data" ON "users_field_data"."uid" = "base_table"."uid" WHERE ("users_field_data"."name" IN ("ACCOUNT_NAME")) AND ("users_field_data"."default_langcode" IN (1))', 'SELECT "base_table"."uid" AS "uid", "base_table"."uid" AS "base_table_uid" FROM "users" "base_table" INNER JOIN "users_field_data" "users_field_data" ON "users_field_data"."uid" = "base_table"."uid" WHERE ("users_field_data"."name" IN ("ACCOUNT_NAME")) AND ("users_field_data"."default_langcode" IN (1))',
    'SELECT "base"."uid" AS "uid", "base"."uuid" AS "uuid", "base"."langcode" AS "langcode" FROM "users" "base" WHERE "base"."uid" IN (2)', 'SELECT "base"."uid" AS "uid", "base"."uuid" AS "uuid", "base"."langcode" AS "langcode" FROM "users" "base" WHERE "base"."uid" IN (2)',
    ...@@ -274,7 +276,7 @@ public function testLoginBlock(): void { ...@@ -274,7 +276,7 @@ public function testLoginBlock(): void {
    ]; ];
    $recorded_queries = $performance_data->getQueries(); $recorded_queries = $performance_data->getQueries();
    $this->assertSame($expected_queries, $recorded_queries); $this->assertSame($expected_queries, $recorded_queries);
    $this->assertSame(17, $performance_data->getQueryCount()); $this->assertSame(18, $performance_data->getQueryCount());
    $this->assertSame(107, $performance_data->getCacheGetCount()); $this->assertSame(107, $performance_data->getCacheGetCount());
    $this->assertSame(1, $performance_data->getCacheSetCount()); $this->assertSame(1, $performance_data->getCacheSetCount());
    $this->assertSame(1, $performance_data->getCacheDeleteCount()); $this->assertSame(1, $performance_data->getCacheDeleteCount());
    ......
    ...@@ -243,6 +243,10 @@ protected static function logQuery(PerformanceData $performance_data, string $qu ...@@ -243,6 +243,10 @@ protected static function logQuery(PerformanceData $performance_data, string $qu
    $args[':db_condition_placeholder_1'] = 'CSS_FILE'; $args[':db_condition_placeholder_1'] = 'CSS_FILE';
    } }
    } }
    elseif (str_starts_with($query, 'SELECT "name", "value" FROM "key_value_expire" WHERE "expire" >')) {
    $args[':now'] = 'NOW';
    $args[':keys__0'] = 'KEY';
    }
    // Inline query arguments and log the query. // Inline query arguments and log the query.
    $query = str_replace(array_keys($args), array_values(static::quoteQueryArgs($args)), $query); $query = str_replace(array_keys($args), array_values(static::quoteQueryArgs($args)), $query);
    ......
    0% Loading or .
    You are about to add 0 people to the discussion. Proceed with caution.
    Please register or to comment