亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

在處理另一個異常時,我應該如何處理記錄器拋出的異常?

在處理另一個異常時,我應該如何處理記錄器拋出的異常?

PHP
呼啦一陣風 2021-09-18 21:24:57
我正在處理一個 PHP 項目,在該項目中我使用 Monolog 捕獲異常并記錄錯誤并返回一個用戶友好的頁面作為響應。該項目目前處于初期階段,所以我只是StreamHandler在公眾無法訪問的應用程序目錄中使用 Monolog 的類將錯誤記錄到文件中,隨著我的進步,我意識到如果出現某種 IO 錯誤,這可能會失敗等等我還將登錄到數據庫(可能是 ElasticSearch)并通過電子郵件向管理員發送嚴重錯誤。當我使用 時StreamHandler,我可以看到它在無法打開文件時拋出異?!,F在,我應該如何處理這種異常情況,如果日志記錄機制本身失敗,我應該如何記錄它?我可以讓另一個記錄器處理異常,該記錄器在這種危急情況下發送電子郵件,但同樣,我如何處理郵件程序拋出的異常?我認為頁面會充滿太多的 try-catch 塊,并且記錄器散布在整個頁面中,這看起來非常難看。是否有一種優雅、干凈的解決方案,它不涉及在大型項目中使用的太多嵌套的 try-catch 塊?(也歡迎不受歡迎的意見)這里有一些代碼供參考:try{    $routes = require_once(__DIR__.'/Routes.php');    $router = new RouteFactory($routes, $request, \Skletter\View\ErrorPages::class);    $router->buildPaths('Skletter\Controller\\', 'Skletter\View\\');    $app = new Application($injector);    $app->run($request, $router);}catch (InjectionException | InvalidErrorPage | NoHandlerSpecifiedException $e){    $log = new Logger('Resolution');    try    {        $log->pushHandler(new StreamHandler(__DIR__ . '/../app/logs/error.log', Logger::CRITICAL));        $log->addCritical($e->getMessage(),            array(                'Stack Trace' => $e->getTraceAsString()            ));    }    catch (Exception $e)    {        echo "No access to log file: ". $e->getMessage();        // Should I handle this exception by pushing to db or emailing?        // Can possibly introduce another nested try-catch block     }    finally    {        /**         * @var \Skletter\View\ErrorPageView $errorPage         */        $errorPage = $injector->make(\Skletter\View\ErrorPages::class);        $errorPage->internalError($request)->send();    }}
查看完整描述

3 回答

?
有只小跳蛙

TA貢獻1824條經驗 獲得超8個贊

記錄異常和通知它們是整個項目必須全局解決的兩個任務。它們不應該用幫助try-catch塊來解決,因為通常try-catch應該使用幫助塊來嘗試解決產生異常的具體本地定位問題(例如,修改數據或嘗試重復執行)或執行操作以恢復應用狀態。關于異常的日志記錄和通知是應該使用全局異常處理程序解決的任務。PHP 有一個本地機制來配置一個帶有set_exception_handler函數的異常處理程序。例如:


function handle_exception(Exception $exception)

{

    //do something, for example, store an exception to log file

}


set_exception_handler('handle_exception');

配置處理程序后,所有拋出的異常都將使用handle_exception()函數進行處理。例如:


function handle_exception(Exception $exception)

{

    echo $exception->getMessage();

}


set_exception_handler('handle_exception');

// some code

throw Exception('Some error was happened');

此外,您始終可以使用幫助restore_exception_handler函數禁用當前異常處理程序。


在您的情況下,您可以創建一個簡單的異常處理程序類,該類將包含日志記錄方法和通知方法,并實現一種機制來處理將選擇必要方法的異常。例如:


class ExceptionHandler

{    

    /**

     * Store an exception into a log file         

     * @param Exception $exception the exception that'll be sent

     */

    protected function storeToLog(Exception $exception)

    {}


    /**

     * Send an exception to the email address

     * @param Exception $exception the exception that'll be sent

     */

    protected function sendToEmail(Exception $exception)

    {}


    /**

     * Do some other actions with an exception

     * @param Exception $exception the exception that'll be handled

     */

    protected function doSomething(Exception $exception)

    {}


    /**

     * Handle an exception

     * @param Exception $exception the exception that'll be handled

     */

    public function handle(Exception $exception)

    {

        try {

            // try to store the exception to log file

            $this->storeToLog($exception);

        } catch (Exception $exception) {

            try {

                // if the exception wasn't stored to log file 

                // then try to send the exception via email

                $this->sendToEmail($exception);

            } catch (Exception $exception) {

                // if the exception wasn't stored to log file 

                // and wasn't send via email 

                // then try to do something else

                $this->doSomething($exception);

            }

        }


    }

}

之后,您可以注冊此處理程序


$handler = new ExceptionHandler();

set_exception_handler([$handler, 'handle']);



$routes = require_once(__DIR__.'/Routes.php');


$router = new RouteFactory($routes, $request, \Skletter\View\ErrorPages::class);

$router->buildPaths('Skletter\Controller\\', 'Skletter\View\\');


$app = new Application($injector);

$app->run($request, $router);


查看完整回答
反對 回復 2021-09-18
?
UYOU

TA貢獻1878條經驗 獲得超4個贊

如果我是你,我會在“kernel.exception”事件中捕獲該異常,原因很簡單:你的記錄器無處不在。只需編寫一個監聽器,測試類似的東西


if ($e instanceof MONOLOG_SPECIFIC_EXCEPTION) {

   // handle exception here

}


如果您也使用命令,請對“console.exception”事件執行相同的操作。


查看完整回答
反對 回復 2021-09-18
?
喵喔喔

TA貢獻1735條經驗 獲得超5個贊

您可以嘗試一些解決方案。

  1. 您可以將記錄器包裝在您自己的另一個類中,處理那里的所有異常和可能的錯誤,并使用您的類進行日志記錄。

  2. 有時無法捕獲所有錯誤,異常未得到處理并且發生極少數情況(即 IO 錯誤),您可以決定接受它。在這種情況下,您可以使用您自己提出的解決方案。使用 ELK 包,您將能夠根據您感興趣的參數配置手表監視器。


查看完整回答
反對 回復 2021-09-18
  • 3 回答
  • 0 關注
  • 232 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號