Как отлаживать ошибки "Symfony \ Component \ Debug \ Exception \ FatalErrorException" в PHP (Laravel)?

Я получаю отчеты о множестве ошибок, с которыми сталкиваются клиенты

Symfony\Component\Debug\Exception\FatalErrorException

Maximum execution time of 30 seconds exceeded

Я сам не могу реплицировать его ни на локальном компьютере, ни на рабочем сервере. URL-адреса для этого есть по всему сайту, поэтому, я думаю, это что-то глобальное, например, промежуточное ПО, которое вызывает это.

Я использую Sentry.io для сбора данных, но трассировка исключения имеет только 1 запись, которая указывает на определенный код в базовом коде Symfony, чаще всего:

vendor/symfony/finder/Iterator/ExcludeDirectoryFilterIterator.php at line 73

vendor/symfony/finder/Iterator/DateRangeFilterIterator.php at line 45

vendor/symfony/finder/Iterator/RecursiveDirectoryIterator.php at line 69

Очевидно, что есть что-то связанное с файловой системой, но из-за отсутствия следов я не вижу, где искать ошибку в коде сайта. Я бы предположил, что это какой-то бесконечный цикл или утечка, но нет никаких следов, чтобы посмотреть на это, и нет последовательного способа воспроизвести проблему.

Как мне искать проблему и отлаживать ее?

Могу ли я установить какие-либо настройки или инструменты, которые я могу использовать / включить?

Когда вы говорите, I, myself, cannot replicate it on my local machine nor on the production server вы пробовали это, используя учетную запись клиента, у которой возникли проблемы. Многие из них выглядят как итерации каталога файлов, если вы разрешите им загружать или создавать файлы, у них может быть слишком много файлов, и, имея учетную запись без них, вы не сможете воспроизвести проблему. Просто мысль.

ArtisticPhoenix 09.08.2018 17:35

У вас есть доступ к командной строке? Если да, вы можете попробовать strace tecmint.com/…

Adrian Hernandez-Lopez 09.08.2018 17:36

@ArtisticPhoenix Да, я пробовал использовать различные переменные сеанса (не вошли в систему, вошли в систему как разные пользователи). В системе нет загрузки / генерации файлов, и ошибки возникают случайным образом, когда пользователь пытается открыть даже простейшую страницу, которая извлекает некоторые базовые данные.

Giedrius 09.08.2018 17:44

@ AdrianHernandez-Lopez Я попробую, спасибо.

Giedrius 09.08.2018 17:44

Сообщения об ошибках обычно имеют обратную связь с основным фрагментом кода, который вызывал всю строку функций / классов, найдите место, где возникла ошибка, она почти наверняка будет в коде, который вы / кто-то написал, а не в базе кода Symfony

RiggsFolly 09.08.2018 18:45

@RiggsFolly Как я уже упоминал, стек трассировки включает только эту последнюю часть.

Giedrius 09.08.2018 18:46

Вы смотрели журнал ошибок в var/logs

RiggsFolly 09.08.2018 18:49

@RiggsFolly Да, исключения такие же, как они собраны в Sentry, и содержат одну и ту же трассировку только с 1 элементом.

Giedrius 09.08.2018 19:08

Ваша файловая система - локальная или сетевая?

alariva 09.08.2018 23:28

@alariva Это местное

Giedrius 10.08.2018 00:20

Таким образом, проблема возникает у вашего клиента только на производстве. Правильно? У вас есть или вы можете собрать точную информацию о том, когда это произойдет? Какие действия он совершал? Отметки времени? Журналы? Частота появления?

alariva 10.08.2018 00:23

@alariva Да, у меня есть точные журналы этого события, но я не могу воспроизвести его самостоятельно, поэтому он такой случайный и сложный для отладки. У меня есть более 1000 записей о том, когда и какие URL запрашиваются. Однако я делаю тот же запрос через производственный сервер с помощью различных комбинаций переменных сеанса и получаю ошибку только один раз из тысяч запросов.

Giedrius 10.08.2018 00:26

Таким образом, сужение может потребовать методической записи каждого вхождения (как ошибки, так и успеха) одного и того же действия триггера, а затем сравнения условий контекста. Если это файловая система, знаете ли вы, работает ли ваш хост на hdd или sdd? Есть ли вероятность сбоя HW или раздела?

alariva 10.08.2018 00:37

@alariva Я попытался сделать быстрый сценарий, который отправлял бы x запросов на URL, но это не оказалось эффективным (все запросы прошли). Он размещен на серверах AWS, поэтому я бы подумал, что у них будут проверки отказов жесткого диска. Я проверю приборную панель на предмет чего-нибудь в этом переулке, но это очень долгий путь: /

Giedrius 10.08.2018 00:40

Я вижу. Можете ли вы предоставить какую-либо справочную информацию о том, что делает приложение и какие операции выполняет пользователь при возникновении проблемы?

alariva 10.08.2018 00:51

@alariva Приложение представляет собой чрезвычайно простой сайт электронной коммерции, где люди выбирают продукт и платят за него. Это сложная вещь, проблема возникает по всем видам запросов, включая простое открытие домашней страницы, получение информации об их заказе и даже некоторые запросы AJAX (для получения корзины и т. д.).

Giedrius 10.08.2018 00:55

Похоже на проблему ввода-вывода, которая может возникнуть при попытке доступа к кешу или любому другому ресурсу на диске. Я также считаю, что это странно на aws, но на данный момент мы не можем отказаться от этого. Вы можете опубликовать свой .env? (Сначала удалите все токены и учетные данные) и composer.json?

alariva 10.08.2018 01:43

Позвольте нам продолжить обсуждение в чате.

Giedrius 10.08.2018 01:55

Я думаю, вы делаете какой-то вызов API, который вызывает проблему.

Ammar Ali 16.08.2018 04:39

@Giedrius Есть новости по этой проблеме? Также, пожалуйста, укажите в вопросе ваш полный стек разработчика.

Mysteryos 16.08.2018 08:13

Привет, сейчас я работаю над той же проблемой. Удалось ли как-нибудь решить это случайно? Если да, не могли бы вы поделиться? Если нет, может, мы сможем сотрудничать и вместе найти ответы?

vvmul 13.03.2019 10:07

@dardvas Привет, на самом деле я не нашел четкого решения для этого, мне просто пришлось отлаживать код по крупицам, чтобы найти, где была проблема, я думаю, что в моем случае это была утечка памяти.

Giedrius 13.03.2019 17:08

@Giedrius мне кажется, что в файловой системе хранится слишком много файлов кеша. Перенос их в Redis, как сказал IlGala, решил проблему. Что ж, ваш вопрос и ответы на него составляют хороший контрольный список для всех, кто сталкивается с этой проблемой :)

vvmul 14.03.2019 10:02

@dardvas Это хорошо, спасибо! Я отмечу этот ответ, так как я также считаю, что это более вероятная причина и наиболее полезный ответ.

Giedrius 15.03.2019 17:42
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
12
24
4 275
11
Перейти к ответу Данный вопрос помечен как решенный

Ответы 11

Если вы не уверены в причине исключения, вы можете обработать его двумя способами.

1 увеличить время ожидания запроса ini_set ('max_execution_time', 60); // 60 секунд = 1 минута

2 оберните свой код в try catch

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

1. Я думаю, что увеличение тайм-аута может быть временным решением, но не устранит основную причину. 2. Вы хотите обернуть все приложение (в index.php или bootstrap.php)? Если это так, то это не приводит к другим результатам, одно и то же исключение просто обрабатывается вручную.

Giedrius 10.08.2018 00:23

Я не думаю, что вам стоит пока увеличивать тайм-аут. если вы сделаете «попытаться поймать», вы сможете понять основную проблему. Если нет, проверьте операции / функции, выполняемые в конкретном методе или классе. Есть вероятность, что вы запрашиваете огромную таблицу и, возможно, пытаетесь использовать информацию.

если ты это сделаешь

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

это даст вам представление о том, сколько запросов выполняется для операции

Невозможно отловить это с помощью try catch, поскольку на самом деле это ошибка PHP, а не исключение.

Чтобы отладить это, у вас есть несколько вариантов:

  1. Добавьте несколько журналов в код, чтобы определить, где истекает время ожидания
  2. Вы можете использовать Пакет сервера дампа Laravel для выгрузки логов. На самом деле он будет поставляться с Laravel 5.7, но вы всегда можете добавить пакет сейчас.

Я установил laravel-debugbar, думаю, вам это поможет.

композитору требуется barryvdh / laravel-debugbar Затем откройте config / app.php и внутри массива «поставщиков» добавьте:

Barryvdh\Debugbar\ServiceProvider::class,

в классе массива псевдонимов:

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

и вы можете просмотреть

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

// Сделай что-нибудь… });

Можете ли вы зарегистрировать функцию выключения? Функция выключения вызывается даже при истечении времени ожидания. С его помощью вы можете распечатать или сохранить то, что хотите, в файл журнала. Я не уверен, есть ли лучший способ получить обратную трассировку в laravel, но я бы, вероятно, сделал это в чистом php (вызовите 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

Не знал об этом, обязательно попробую. Спасибо!

Giedrius 19.08.2018 17:49
Ответ принят как подходящий

Прочитав вашу беседу в чате, я увидел, что вы используете эту конфигурацию .env:

CACHE_DRIVER=file 
SESSION_DRIVER=file 

Думаю, в этом проблема ... Объясняюсь немного лучше.

Когда вы используете драйвер file для кеша или сеанса, Laravel создаст тонны файлов, в которых хранятся данные сеанса пользователей или данные кеша приложений ...

Если ваша электронная коммерция растет и генерирует большой трафик, возможно, что производительность снижается из-за большого количества файлов, которые необходимо сканировать фреймворком.

Я думаю, это может быть два возможных решения:

  • Ваша производственная среда должна быть обновлена ​​(я не знаю спецификации вашего производственного сервера и достаточно ли у вас ресурсов).
  • Файловый драйвер становится слишком медленным для требований вашего приложения.

Я обычно использую Redis в качестве драйвера кэша и сеанса, он быстрее и с хорошей стратегией «умного кэширования» это отличный инструмент.

Я думаю, вам стоит попробовать использовать и его, если возможно. Memcached тоже может быть хорошим решением.

В этом есть большой смысл. Я постараюсь решить свою проблему, используя ваши ответы и ответы @elitepc (register_shudown_function), и посмотрю, к чему это меня приведет, спасибо!

Giedrius 19.08.2018 17:49

вопрос: «Как отлаживать ошибки тайм-аута в PHP (Laravel)?», приложение должно работать с этой конфигурацией CACHE_DRIVER = file SESSION_DRIVER = file, конечно, лучше использовать redis, но вопрос не в этом ...

fico7489 25.10.2019 08:16

Честно говоря, вам лучше всего установить xdebug и просто отладить его по старинке, пройти весь запрос, чтобы найти узкое место, и попытаться выяснить, откуда оно взялось. Laravel, как и другие фреймворки, был разработан для максимально плавной работы. Если вы столкнулись с подобными ошибками, это означает, что вы просто что-то неправильно запрограммировали.

Также сложно дать вам конкретный совет без дополнительной информации. Я бы предложил воссоздать спецификации среды (вы можете использовать Docker или Vagrant или что-то еще, что придет вам в голову, что будет работать), с которым сталкивается ваше приложение Laravel, а затем запустить с xdebug, чтобы найти, в чем проблема.

Вы не можете поймать ошибку тайм-аута php. Эта ошибка возникает, когда интерпретатор php прекращает выполнение. Вы можете только увеличить ограничение по времени, например, ini_set ('max_execution_time', 300), или преобразовать длительную работу по выполнению в задание cron, например, расписание задач laravel.

Я не привык к Laravel, но у меня была эта проблема, и я решил ее с помощью PHP-функции register_shutdown_function.

Я обнаружил, что это очень полезно для отслеживания случайных ошибок. Вот как я это делаю в своем коде. Вы можете поместить это где-нибудь в общий файл, который будет выполняться на каждой странице, index.php будет для вас хорошим вариантом, поскольку все маршруты Laravel проходят через него (мое предположение).

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
    }
}

Похоже, PHP ждет какого-то ресурса, например. файловый доступ, база данных, почтовый сервер (думаю файл).

  • Вы пробовали использовать свое приложение на многих вкладках за один сеанс?
  • Вы пробовали войти в одну и ту же учетную запись на многих машинах?
  • Может быть, какая-то часть скрипта открывает файл, а не закрывает его?
  • Вы отслеживали действия пользователей при открытии сайта, чтобы получить эту ошибку?
  • Проверьте свою производственную базу данных - может быть, очень маленький лимит подключений?

РЕДАКТИРОВАТЬ

Я вижу, что вы используете библиотеку dannyvankooten/vat.php, которая делает некоторые запросы к внешним сервисам. Это может быть источником ваших проблем. Эта библиотека делает запросы с помощью curl. Автор устанавливает CURLOPT_CONNECTTIMEOUT, но CURLOPT_TIMEOUT не установлен, и ваш сценарий иногда может ждать дольше, чем это ограничено настройкой max_execution_time.

Новая версия часовой предоставит вам правильную трассировку стека.

Вы должны использовать версию "getsentry / sentry-php"> = "2.0"

Другие вопросы по теме