web-dev-qa-db-ja.com

PHP(Laravel)の "Symfony \ Component \ Debug \ Exception \ FatalErrorException"エラーをデバッグする方法は?

クライアントで発生した多くのエラーのレポートを取得しています

Symfony\Component\Debug\Exception\FatalErrorException

30秒の最大実行時間を超えました

私自身、ローカルマシンや本番サーバーに複製することはできません。このためのURLはすべてサイト全体にあるため、これはミドルウェアのようにグローバルなもので、これを引き起こしていると思います。

私は Sentry.io を使用してデータを収集していますが、例外トレースには、Symfony基本コードの特定のコードを指す1つのエントリしかありません。

73行目のvendor/symfony/Finder/Iterator/ExcludeDirectoryFilterIterator.php

45行目のvendor/symfony/Finder/Iterator/DateRangeFilterIterator.php

69行目のvendor/symfony/Finder/Iterator/RecursiveDirectoryIterator.php

明らかに、ファイルシステムに関連する何かがあるようですが、トレースがないため、サイトコードのどこに間違いがあるかを確認できません。それはある種の無限ループまたはリークだと思いますが、それを調べる痕跡はなく、問題を再現する一貫した方法もありません。

問題を探してこれをデバッグするにはどうすればよいですか?

設定できる設定、または使用/有効化できるツールはありますか?

12
Giedrius

チャットの会話を読んだ後、これを使用していることがわかりました.env設定:

CACHE_DRIVER=file 
SESSION_DRIVER=file 

これが問題だと思います...もう少し説明します。

fileドライバーをキャッシュまたはセッションに使用すると、Laravelはユーザーセッションデータまたはアプリケーションキャッシュデータを格納する大量のファイルを作成します...

Eコマースが成長して大量のトラフィックを生成している場合は、フレームワークでスキャンする必要があるこの大量のファイルが原因で、パフォーマンスが低下している可能性があります。

私はそれが2つの可能な解決策かもしれないと思います:

  • 実稼働環境をアップグレードする必要があります(実稼働サーバーの仕様、または十分なリソースがあるかどうかはわかりません)。
  • アプリケーションの要件に対して、ファイルドライバーが遅くなりすぎています。

私は通常、キャッシュとセッションのドライバーとして redis を使用します。これはより高速で、「スマートキャッシング」の優れた戦略を備えた優れたツールです。

可能であれば、ぜひ使ってみてください。 Memcached も良い解決策かもしれません。

5
IlGala

PHPは、ファイルアクセス、データベース、メールサーバー(ファイルだと思います)などのリソースを待機しています)のようです。

  • 1つのセッションで多くのタブでアプリを使用してみましたか?
  • 多くのマシンから同じアカウントにログインしてみましたか?
  • たぶんスクリプトの一部がファイルを開いて閉じていませんか?
  • このエラーを取得するために、サイトを開いてからのユーザーアクションを追跡しましたか?
  • 運用データベースを確認してください-おそらく接続の制限が非常に小さいですか?

[〜#〜]編集[〜#〜]

外部サービスにいくつかのリクエストを行うdannyvankooten/vat.phpライブラリを使用しているようです。これは問題の原因となる可能性があります。このライブラリはcurlを使用してリクエストを作成しています。作成者はCURLOPT_CONNECTTIMEOUTを設定していますが、CURLOPT_TIMEOUTが設定されておらず、スクリプトがmax_execution_time設定で制限されている時間より長く待機することがあります。

2
arczinosek

私はLaravelに慣れていませんが、PHPのregister_shutdown_functionを使用して解決したところ、この問題が発生しました。

ランダムに発生するエラーの追跡に非常に役立つことがわかりました。これは、コードでこれを行う方法です。すべてのページで実行される共通ファイルのどこかにこれを置くことができます。すべてのLaravelルートが通るので、index.phpは良いオプションです(私の仮定)。

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

例外の理由がわからない場合は、2つの方法で処理できます。

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() );
}
2
Afraz Ahmad

シャットダウン機能を登録できますか?タイムアウトが発生してもシャットダウン関数が呼び出されます。これを使用すると、ログファイルに必要なものを印刷または保存できます。 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

2
elitepc

新しいsentryバージョンは、適切なスタックトレースを提供します。

"getsentry/sentry-php"version> = "2.0"を使用する必要があります

0
fico7489

Laravel-debugbarをインストールしました。

composerはbarryvdh/laravel-debugbarを必要とします次に、config/app.phpを開き、「providers」配列内に以下を追加します。

Barryvdh\Debugbar\ServiceProvider::class,

エイリアス配列クラス:

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

そしてあなたは見ることができます

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

//何かをします…});

0
betovaz81

これは実際には例外ではなくPHPエラーであるため、try catchでこれをキャッチする方法はありません。

これをデバッグできるようにするには、いくつかのオプションがあります。

  1. コードにログを追加して、タイムアウトした場所を特定します
  2. Laravelダンプサーバーパッケージ を使用してログをダンプできます。これは実際にはLaravel 5.7で出荷されますが、今のところいつでもパッケージを追加できます
0
Paras

まだタイムアウトを増やすべきではないと思います。 「キャッチしよう」とすると、根本的な問題が理解できるかもしれません。そうでない場合は、特定のメソッドまたはクラスで実行される操作/機能を確認してください。巨大なテーブルをクエリしていて、その情報を使用しようとしている可能性があります。

もし、するなら

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

これにより、操作に対して実行されているクエリの数がわかります

0
Yoweli Kachala

PHPタイムアウトエラーをキャッチできません。このエラーは、phpインタープリターが実行を停止したときに発生します。時間制限を増やすことができるのは、たとえばini_set( 'max_execution_time'、300)か、長時間実行作業をcronジョブに変換することだけです。たとえば、laravelタスクスケジュール。

0
Ismail Zafar