spatie / ray

Debug with Ray to fix problems faster
https://myray.app
MIT License
555 stars 101 forks source link

Uncaught ErrorException: var_export does not handle circular references #832

Closed genesiscz closed 6 months ago

genesiscz commented 10 months ago

Describe the bug When there's a circular reference in an object, I am getting a PHP Warning: Uncaught ErrorException: var_export does not handle circular references in /.../vendor/spatie/ray/src/Payloads/LogPayload.php:64 even though I am on 1.37.3 version which has try try/catch

        try {
            return var_export($value, true);
        } catch (Exception $ex) {
            return '';
        }

It is quite weird because I thought that ErrorException is a children of Exception. It is even more weird that I am getting out of memory exception in the Ray itself on the same line. image image

Versions

bartbrinkman commented 10 months ago

Downgrading to 1.37.2 worked for me.

timvandijck commented 10 months ago

@genesiscz @bartbrinkman I added an extra check for recursiveness before doing the var_export. Could you give 1.37.5 a try?

crynobone commented 10 months ago

@timvandijck Still broken with 1.37.5

CleanShot 2023-09-07 at 08 30 26

genesiscz commented 10 months ago

@genesiscz @bartbrinkman I added an extra check for recursiveness before doing the var_export. Could you give 1.37.5 a try?

Can you help me understand what the clipboard means? And isn't doing this check just resulting in Ray not receiving what it should?

genesiscz commented 10 months ago

In my case, this fix doesn't help, because I have magic __debugInfo() in my BaseModel which is being checked for recursiveness but results in false negative because I am redacting some of the key-values because of other dumpings (including ray). My print_r looks like this:

App\Lead\Manager\LeadHandlerUtils\CascadeOfferItemsGrouper Object
(
    [lastDistributionType:App\Lead\Manager\LeadHandlerUtils\CascadeOfferItemsGrouper:private] => exclusive
    [cascadeOfferItemGroups] => Illuminate\Support\Collection Object
        (
            [items:protected] => Array
                (
                    [0] => App\Collections\CascadeOfferItemsCollection Object
                        (
                            [items:protected] => Array
                                (
                                    [0] => App\Models\CascadeOfferItem Object
                                        (
                                            [guarded:protected] => Array
                                                (
                                                )

                                            [fillable:protected] => Array
                                                (
                                                )

                                            [original:protected] => retracted
                                            [netteRow:protected] => retracted
                                            [notDbValues] => retracted
                                            [notApiValues:protected] => Array
                                                (
                                                )

                                        )

                                )

                            [escapeWhenCastingToString:protected] => 
                        )

                    [1] => App\Collections\CascadeOfferItemsCollection Object
                        (
                            [items:protected] => Array
                                (
                                    [0] => App\Models\CascadeOfferItem Object
                                        (
                                            [guarded:protected] => Array
                                                (
                                                )

                                            [fillable:protected] => Array
                                                (
                                                )

                                            [original:protected] => retracted
                                            [netteRow:protected] => retracted
                                            [notDbValues] => retracted
                                            [notApiValues:protected] => Array
                                                (
                                                )

                                        )

                                )

                            [escapeWhenCastingToString:protected] => 
                        )

                    [2] => App\Collections\CascadeOfferItemsCollection Object
                        (
                            [items:protected] => Array
                                (
                                    [0] => App\Models\CascadeOfferItem Object
                                        (
                                            [guarded:protected] => Array
                                                (
                                                )

                                            [fillable:protected] => Array
                                                (
                                                )

                                            [original:protected] => retracted
                                            [netteRow:protected] => retracted
                                            [notDbValues] => retracted
                                            [notApiValues:protected] => Array
                                                (
                                                )

                                        )

                                    [1] => App\Models\CascadeOfferItem Object
                                        (
                                            [guarded:protected] => Array
                                                (
                                                )

                                            [fillable:protected] => Array
                                                (
                                                )

                                            [original:protected] => retracted
                                            [netteRow:protected] => retracted
                                            [notDbValues] => retracted
                                            [notApiValues:protected] => Array
                                                (
                                                )

                                        )

                                )

                            [escapeWhenCastingToString:protected] => 
                        )

                    [3] => App\Collections\CascadeOfferItemsCollection Object
                        (
                            [items:protected] => Array
                                (
                                    [0] => App\Models\CascadeOfferItem Object
                                        (
                                            [guarded:protected] => Array
                                                (
                                                )

                                            [fillable:protected] => Array
                                                (
                                                )

                                            [original:protected] => retracted
                                            [netteRow:protected] => retracted
                                            [notDbValues] => retracted
                                            [notApiValues:protected] => Array
                                                (
                                                )

                                        )

                                )

                            [escapeWhenCastingToString:protected] => 
                        )

                )

            [escapeWhenCastingToString:protected] => 
        )

)

Unfortunatelly even after commenting these methods, it won't start working. Even worse, the print_r is now resulting in memory error:

PHP Fatal error: Allowed memory size of 1073741824 bytes exhausted (tried to allocate 803213312 bytes) in /.../vendor/spatie/ray/src/Payloads/LogPayload.php on line 84

Maybe it's a bug in PHP not being able to detect the RECURSION because I have some weird recursion there? To be honest, I can't even find a documented *RECURSION* detection in the print_r itself: https://www.php.net/manual/en/function.print-r.php

timvandijck commented 10 months ago

@genesiscz @bartbrinkman I added an extra check for recursiveness before doing the var_export. Could you give 1.37.5 a try?

Can you help me understand what the clipboard means? And isn't doing this check just resulting in Ray not receiving what it should?

It was added to support the new copy button that allows you to copy the output in the Ray app. We need to send it in a different way (var_export) to make it usefull.

The copy button will not be shown if we detect a circular reference because it's hard to output that in a string format and var_export doesn't even support it. Most of the time these aren't the variables you would want to copy anyway.

Anyway: thank you for the input, I'm going to try and replicate it and see how we can resolve this.

crynobone commented 10 months ago

Shouldn't we revert this nice to have feature so that the core feature of Ray can be used?

It's better to re-submit the feature again in the future with better tests etc.

genesiscz commented 10 months ago

Just to elaborate on what happens:

I understand this could be even fixed on my side, but since the recursion is in a library and a property I use in BaseModel, there's no way to fix this on my side.

Anyway, I think it would be a good idea to even have the ability to switch off this feature as I can imagine the print_r itself on top of var_export can be memory and time consuming and sometimes older version of ray itself slow down the tests a lot if I have ray open (and pausing unfortunatelly doesn't work - I have to close ray for it to be fast again)

timvandijck commented 10 months ago

I was able to replicate scenario's that triggered the problems that were mentioned. I now added a more robust implementation to log variables.

As far as my own test scenario's go this seems to resolve all issues. It has been added to release 1.37.6.

In the future we might add some extra options to skip exporting these variables for when you want things to be faster like in tests.

genesiscz commented 10 months ago

I can confirm this resolved the issue. Thank you! Although, is there a way to force the depth to be deeper? Because

I kinda like the clipboard feature, but hitting depth 5 is pretty easy a lot of times:

App\Lead\Manager\LeadHandlerUtils\CascadeOfferItemsGrouper#1
(
    [App\Lead\Manager\LeadHandlerUtils\CascadeOfferItemsGrouper:lastDistributionType] => 'exclusive'
    [cascadeOfferItemGroups] => Illuminate\Support\Collection#2
    (
        [*:items] => [        
            0 => App\Collections\CascadeOfferItemsCollection#3
            (
                [*:items] => [                
                    0 => App\Models\CascadeOfferItem(...),
                ]
                [*:escapeWhenCastingToString] => false
            ),
            1 => App\Collections\CascadeOfferItemsCollection#4
            (
                [*:items] => [                
                    0 => App\Models\CascadeOfferItem(...),
                ]
                [*:escapeWhenCastingToString] => false
            ),
            2 => App\Collections\CascadeOfferItemsCollection#5
            (
                [*:items] => [                
                    0 => App\Models\CascadeOfferItem(...),
                    1 => App\Models\CascadeOfferItem(...),
                ]
                [*:escapeWhenCastingToString] => false
            ),
            3 => App\Collections\CascadeOfferItemsCollection#6
            (
                [*:items] => [                
                    0 => App\Models\CascadeOfferItem(...),
                ]
                [*:escapeWhenCastingToString] => false
            ),
        ]
        [*:escapeWhenCastingToString] => false
    )
)

Ray image

ZebTheWizard commented 10 months ago

have the same problem on 1.32, all I did was throw an exception, and log the exception with ray.

Edit: when I set always_send_raw_values => true I was able to get rid of the memory error

genesiscz commented 10 months ago

I am on 1.33.0 on laravel-ray and 1.37.7 on ray itself. Still happens on that version?

spatie-bot commented 6 months ago

Dear contributor,

because this issue seems to be inactive for quite some time now, I've automatically closed it. If you feel this issue deserves some attention from my human colleagues feel free to reopen it.