Problem/Motivation
Contrib/custom database drivers are not in the Drupal\Core\Database
namespace, and in this case Log::findCaller
will not report the caller correctly, but just the first function/method coming after the first call to the database connection, or worse after a vendor namespaced method if the driver implements methods there.
Incurred into this while experimenting a db driver https://github.com/mondrake/drudbal in conjuction with #2605284: Testing framework does not work with contributed database drivers, and getting failure for the LoggingTest.
See the trace below: in this case the identified 'caller' is always 'query' since it's the first method coming after either not namespaced or not into Drupal\Core\Database namespace.
[0] => Drupal\Core\Database\Log -> findCaller
[1] => Drupal\Core\Database\Log -> log
[2] => Drupal\Core\Database\Statement -> execute
[3] => Doctrine\DBAL\Statement -> execute
[4] => Drupal\Driver\Database\dbal\Connection -> query
[5] => -> db_query
[6] => Drupal\drudbal\Tests\LoggingTest -> testEnableLogging
[7] => Drupal\simpletest\TestBase -> run
[8] => -> _simpletest_batch_operation
[9] => -> _batch_process
[10] => -> _batch_do
[11] => -> _batch_page
[12] => Drupal\system\Controller\BatchController -> batchPage
[13] => -> call_user_func_array
[14] => Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber -> Drupal\Core\EventSubscriber\{closure}
[15] => Drupal\Core\Render\Renderer -> executeInRenderContext
[16] => Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber -> wrapControllerExecutionInRenderContext
[17] => Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber -> Drupal\Core\EventSubscriber\{closure}
[18] => -> call_user_func_array
[19] => Symfony\Component\HttpKernel\HttpKernel -> handleRaw
[20] => Symfony\Component\HttpKernel\HttpKernel -> handle
[21] => Drupal\Core\StackMiddleware\Session -> handle
[22] => Drupal\Core\StackMiddleware\KernelPreHandle -> handle
[23] => Drupal\page_cache\StackMiddleware\PageCache -> pass
[24] => Drupal\page_cache\StackMiddleware\PageCache -> handle
[25] => Drupal\Core\StackMiddleware\ReverseProxyMiddleware -> handle
[26] => Drupal\Core\StackMiddleware\NegotiationMiddleware -> handle
[27] => Stack\StackedHttpKernel -> handle
[28] => Drupal\Core\DrupalKernel -> handle
Proposed resolution
I think we can safely assume in D8 any logged query will always pass by the Connection object. Get its class name, and drop any stack entry with classes that are not the same as the connection class, drop any entry of the connection class, and then process the remaining stack trace as before. Will get to:
[0] => -> db_query
[1] => Drupal\drudbal\Tests\LoggingTest -> testEnableLogging
[2] => Drupal\simpletest\TestBase -> run
[3] => -> _simpletest_batch_operation
[4] => -> _batch_process
[5] => -> _batch_do
[6] => -> _batch_page
[7] => Drupal\system\Controller\BatchController -> batchPage
[8] => -> call_user_func_array
[9] => Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber -> Drupal\Core\EventSubscriber\{closure}
[10] => Drupal\Core\Render\Renderer -> executeInRenderContext
[11] => Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber -> wrapControllerExecutionInRenderContext
[12] => Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber -> Drupal\Core\EventSubscriber\{closure}
[13] => -> call_user_func_array
[14] => Symfony\Component\HttpKernel\HttpKernel -> handleRaw
[15] => Symfony\Component\HttpKernel\HttpKernel -> handle
[16] => Drupal\Core\StackMiddleware\Session -> handle
[17] => Drupal\Core\StackMiddleware\KernelPreHandle -> handle
[18] => Drupal\page_cache\StackMiddleware\PageCache -> pass
[19] => Drupal\page_cache\StackMiddleware\PageCache -> handle
[20] => Drupal\Core\StackMiddleware\ReverseProxyMiddleware -> handle
[21] => Drupal\Core\StackMiddleware\NegotiationMiddleware -> handle
[22] => Stack\StackedHttpKernel -> handle
[23] => Drupal\Core\DrupalKernel -> handle
Remaining tasks
Review patch.
User interface changes
None
API changes
None
Data model changes
None