web-dev-qa-db-fra.com

Comment déboguer les erreurs de délai d'attente dans PHP (Laravel)?

Je reçois des rapports de nombreuses erreurs rencontrées par les clients

Symfony\Component\Debug\Exception\FatalErrorException

Temps d'exécution maximal de 30 secondes dépassé

Je ne peux moi-même pas le reproduire sur mon ordinateur local ni sur le serveur de production. Les URL pour cela sont partout sur le site, donc, je suppose que c'est quelque chose de global, comme un middleware qui en est la cause. 

J'utilise Sentry.io pour collecter les données, mais le suivi des exceptions ne comporte qu'une entrée pointant vers un certain code du code de base Symfony, le plus souvent:

vendor/symfony/Finder/Iterator/ExcludeDirectoryFilterIterator.php à la ligne 73

vendor/symfony/Finder/Iterator/DateRangeFilterIterator.php à la ligne 45

vendor/symfony/Finder/Iterator/RecursiveDirectoryIterator.php à la ligne 69

De toute évidence, il semble qu'il y ait quelque chose de lié au système de fichiers, mais, faute de trace, je ne vois pas où chercher l'erreur dans le code du site. J'imagine que c'est une sorte de boucle ou de fuite infinie, mais il n'y a aucune trace pour la regarder, et aucun moyen cohérent de reproduire le problème.

Comment devrais-je rechercher le problème et le déboguer? 

Y a-t-il des paramètres que je pourrais définir ou des outils que je pourrais utiliser/activer?

7
Giedrius

Il semble que PHP attend une ressource, par exemple. accès au fichier, base de données, serveur de messagerie (je pense fichier).

  • Avez-vous essayé d'utiliser votre application sur plusieurs onglets avec une session?
  • Avez-vous essayé de vous connecter au même compte à partir de nombreuses machines?
  • Peut-être qu'une partie du script ouvre un fichier et ne le ferme pas?
  • Avez-vous suivi les actions des utilisateurs de l’ouverture du site pour obtenir cette erreur?
  • Vérifiez votre base de données de production - peut-être avez-vous une très petite limite de connexions?

MODIFIER

Je vois que vous utilisez la bibliothèque dannyvankooten/vat.php qui envoie des requêtes à des services externes. Cela peut être une source de vos problèmes. Cette bibliothèque fait des demandes en utilisant curl. L'auteur définit CURLOPT_CONNECTTIMEOUT mais CURLOPT_TIMEOUT n'est pas défini et votre script peut parfois attendre plus longtemps que le paramètre max_execution_time ne le limite.

2
arczinosek

Je ne suis pas habitué à Laravel mais j'ai eu ce problème où je l'ai résolu en utilisant la fonction register_shutdown_function de PHP.

Je l’ai trouvé très utile pour le suivi des erreurs qui se produisent de manière aléatoire ..__ C'est ce que je fais dans mon code. Vous pouvez mettre cela quelque part dans un fichier commun qui s'exécutera sur chaque page, index.php serait une bonne option pour vous car toutes les routes Laravel le traversent (mon hypothèse).

register_shutdown_function( "check_for_fatal" );

function check_for_fatal(){
    $time = time(); //time when this error occurred

    $error = error_get_last();
    if (in_array($error["type"], [E_ERROR, E_CORE_ERROR, E_RECOVERABLE_ERROR])){
        $email_body = [];
        $email_body[] = 'Date: ' . date('m-d-Y H:i:s', $time);
        ob_start();
        var_dump($error);
        $email_body[] = ob_get_clean();
        //include any other data as needed
        //$body[] = "add data as appropriate";

        //You can email it to yourself, but if there are lots of errors you will be bombarded with emails
        mail('[email protected]', 'Subject', implode("\r\n", $email_body));
       //or you can save this to some log file
    }
}
2
Sheikh Azad

Après avoir lu votre conversation en ligne, j'ai constaté que vous utilisiez cette configuration .env:

CACHE_DRIVER=file 
SESSION_DRIVER=file 

Je pense que c'est le problème ... Je m'explique un peu mieux.

Lorsque vous utilisez le pilote file pour le cache ou la session, Laravel crée des tonnes de fichiers qui stockent les données de session des utilisateurs ou les données de cache d'application ... 

Si votre commerce électronique se développe et génère beaucoup de trafic, il est possible que les performances ralentissent à cause de cette multitude de fichiers qui doivent être analysés par le cadre.

Je pense que cela peut être deux solutions possibles:

  • Votre environnement de production doit être mis à niveau (je ne connais pas les spécifications de votre serveur de production ou si vous disposez de suffisamment de ressources).
  • Le pilote de fichier devient trop lent pour les besoins de votre application.

J'utilise habituellement redis en tant que cache et pilote de session, c'est plus rapide et avec une bonne stratégie de "mise en cache intelligente" c'est un excellent outil.

Je pense que vous devriez essayer de l'utiliser aussi bien si possible. Memcached peut être une bonne solution aussi. 

2
IlGala

Si vous n'êtes pas sûr de la raison de l'exception, vous pouvez la gérer de deux manières.

1 augmenter le délai de requête ini_set ('max_execution_time', 60); // 60 secondes = 1 minute

2 envelopper votre code dans try catch

try{
  //logic goes here
}catch(\Excaption $e){
 Log::error($e->getMessage().' '. $e->getFile().' '. $e->getLine());
 return back()->with('error',$e->getMessage() );
}
2
Afraz Ahmad

Pouvez-vous enregistrer une fonction d'arrêt? La fonction d'arrêt est appelée même en cas de dépassement du délai d'attente. Avec celui-ci, vous pouvez imprimer ou enregistrer ce que vous voulez dans un fichier journal ... Je ne sais pas s'il existe un meilleur moyen de récupérer la trace dans laravel, mais c'est ce que je ferais probablement en php pur (appeler debug_backtrace).

<?php

function timedOut() {
    //save to a log file instead of printing
    var_dump(debug_backtrace());
}

register_shutdown_function("timedOut");

http://php.net/manual/en/function.register-shutdown-function.php

http://php.net/manual/en/function.debug-backtrace.php

2
elitepc

J'ai installé laravel-debugbar.Je pense que cela vous aidera.

composer require barryvdh/laravel-debugbar Ouvrez ensuite config/app.php et dans le tableau ‘providers’, ajoutez:

Barryvdh\Debugbar\ServiceProvider::class,

dans la classe d'alias array:

'Debugbar' => Barryvdh\Debugbar\Facade::class,

et vous pouvez voir 

Debugbar::measure('My long operation', function() {

// Faire quelque chose…});

0
betovaz81

Il n'y a aucun moyen de détecter cela dans un test try, car il s'agit en réalité d'une erreur PHP plutôt que d'une exception.

Pour pouvoir déboguer ceci, vous avez deux options:

  1. Ajouter des journaux dans le code pour identifier où il expire
  2. Vous pouvez utiliser le package de serveur de vidage Laravel pour vider les journaux. Cela va effectivement être livré avec Laravel 5.7 mais vous pouvez toujours ajouter le paquet pour l'instant
0
Paras

Je ne pense pas que vous devriez augmenter le délai d'attente pour l'instant. Si vous faites l'essai, vous pourrez peut-être comprendre le problème sous-jacent. Sinon, vérifiez les opérations/fonctions effectuées dans la méthode ou la classe spécifique. Il est possible que vous interrogiez une grande table et essayiez peut-être d'utiliser les informations.

si tu fais 

\DB::listen(function ($sql) {
        var_dump($sql);
   });

cela vous donnera une indication du nombre de requêtes en cours d'exécution pour l'opération

0
Yoweli Kachala

Vous ne pouvez pas attraper l'erreur de délai d'attente php. Cette erreur se produit lorsque l'interpréteur php arrête l'exécution. Vous pouvez uniquement augmenter la limite de temps, par exemple, ini_set ('max_execution_time', 300) ou convertir un travail d'exécution longue en une tâche cron, par exemple, une planification de tâches.

0
Ismail Zafar