laravel-debugbar icon indicating copy to clipboard operation
laravel-debugbar copied to clipboard

Ability to add a custom stacktrace parsing method

Open OzanKurt opened this issue 11 months ago • 14 comments

Hello there,

I use https://github.com/yajra/laravel-datatables package in almost all of my projects.

I currently have a problem of seeing the source of the queries inside my DataTable classes.

For example:

I have a query builder setup inside my UsersDataTable.

    public function query()
    {
        return User::query();
    }

Since this function only starts to bulid the query it doesn't show up in debug_backtrace().

For this I've added a solution which allows me to check the "query sender" object and modify how the $frame was filled.

I've added simple static method to add my custom callables to QueryCollector, in there I can modify and return the $frame as I wish in case the $trace['object'] is matching my first parameter $objectType.

Here is an example DataTable::class query tracer.

QueryCollector::addCustomFrameParser(DataTable::class, function (object $frame, array $trace) {
    // Remove the 'App\' prefix from the namespace
    $relativeNamespace = str_replace('App\\', '', $trace['object']::class);

    // Convert namespace to a directory path
    $directoryPath = str_replace('\\', DIRECTORY_SEPARATOR, $relativeNamespace);
    $filePath = app_path($directoryPath) . '.php';

    // Get the file path inside the project from the class object
    $frame->file = $filePath;

    return $frame;
});

After I add this to my AppServiceProvider, I can simply see the change inside my "Query" tab.

Before: image

After: image

This way I can simply tell where I built the query and continue debugging/development.

OzanKurt avatar Mar 22 '24 16:03 OzanKurt

Did you try adding PATH_TO_FILE/DataTablesController.php to options.db.backtrace_exclude_paths? I have a bridge query builder, and I had a similar problem, I added the file_path to the backtrace_exclude_paths and I already got the correct file

https://github.com/barryvdh/laravel-debugbar/blob/03448e59739181179697dd996f581404db4ce7c5/config/debugbar.php#L213

parallels999 avatar Mar 22 '24 18:03 parallels999

Yes I tried, but since the query is NOT actually sent from the UsersDataTable PHP's debug_backtrace() only detects the call from: DataTablesController.php

Also here is how mine looks like usually:

'backtrace_exclude_paths' => [
    '/vendor/yajra/laravel-datatables',
    '/vendor/staudenmeir',
],

OzanKurt avatar Mar 22 '24 18:03 OzanKurt

Post Before\After with backtrace image Maybe there could be a simpler way

PaolaRuby avatar Mar 22 '24 20:03 PaolaRuby

Before: image

After: image

OzanKurt avatar Mar 22 '24 20:03 OzanKurt

extends UsersDataTable some yajra class?? or uses some yajra trait?

PaolaRuby avatar Mar 22 '24 20:03 PaolaRuby

It extends the DataTable class from the package.

OzanKurt avatar Mar 22 '24 20:03 OzanKurt

I think it could be made more native, maybe some "demo minimal app" to find another approach?

PaolaRuby avatar Mar 22 '24 20:03 PaolaRuby

I can make a demo next week, the change is actually very minimal anyway.

OzanKurt avatar Mar 22 '24 20:03 OzanKurt

I actually already pushed a demo to GitHub.

https://github.com/OzanKurt/debugbar-demo

You can simply pull and run with php artisan serve.

After you install the app you can simply open these two pages:

http://127.0.0.1:8000/?custom_parsing=true http://127.0.0.1:8000/?custom_parsing=false

replace the contents of QueryCollector and check it out.

OzanKurt avatar Mar 22 '24 21:03 OzanKurt

This removes a step from the trace, I'm going to try another approach Try #1588

erikn69 avatar Mar 22 '24 22:03 erikn69

So you suggest adding an extra source to the trace instead of modifying its file...

I'm fine with that approach as well.

One thing to add maybe would be the custom source parsing:

So instead of

if (($trace['class'] ?? null) == 'Yajra\DataTables\Services\DataTable') {

looping through an array of customs would be nicer

foreach (static::$customSourceParsers as $objectType => $customSourceParser) {
    if (isset($trace['object']) && is_a($trace['object'], $objectType)) {

OzanKurt avatar Mar 22 '24 22:03 OzanKurt

QueryCollector::addCustomFrameParser(DataTable::class, function (object $frame, array $trace) { // Remove the 'App' prefix from the namespace $relativeNamespace = str_replace('App\', '', $trace['object']::class);

I try to avoid that, not everyone has the knowledge to do that customization, and not all cases can be solved in that way the way I add it would be ready to use but @barryvdh decides

erikn69 avatar Mar 22 '24 23:03 erikn69

Why not add both, so people with the knowledge to customize can do it without needing a PR process.

OzanKurt avatar Mar 22 '24 23:03 OzanKurt

I'm not really sure about this, not seeing this in my own datatables. Don't want to complicate the backtrace too much.

barryvdh avatar Apr 01 '24 16:04 barryvdh