【问题标题】:PHP: log stack trace for FATAL errors in productionPHP:记录生产中致命错误的堆栈跟踪
【发布时间】:2012-01-24 17:01:40
【问题描述】:

我想记录每个致命错误,甚至是超时和其他 E_ERRORS 错误。我使用 set_error_handler 和 shutdown 功能,但使用最后一个我无法获得堆栈跟踪。有什么办法吗?

我想在生产服务器上记录致命错误,以帮助解决仅在生产中出现的错误。我知道,开发服务器上的 xdebug 必须足够,但事实并非如此。也许我们可以使用激活最少选项的 xdebug,或者使用它的剥离版本来将堆栈跟踪添加到错误日志?

如果出现一个错误,即使是超时,此代码也会打印错误信息。

<?php
function shutdown()
{
    $a=error_get_last();
    if($a!==null) print_r($a);  
}
register_shutdown_function('shutdown');

【问题讨论】:

    标签: php error-handling


    【解决方案1】:

    您不会获得有关致命错误的堆栈跟踪,因为“致命”意味着脚本执行立即停止,即无法通过通常的渠道生成跟踪。因此,如果您设置了自定义错误处理程序来引发异常,则不会根据PHP manual 对致命错误进行调用:

    以下错误类型无法用用户定义的方式处理 功能:E_ERROR、E_PARSE、E_CORE_ERROR、E_CORE_WARNING、 E_COMPILE_ERROR、E_COMPILE_WARNING 和大部分 E_STRICT 在 调用 set_error_handler() 的文件。

    获取有关致命错误中发生的信息的最简单方法(没有打开display_errors,这在生产环境中不是一个选项)是在关闭处理程序中手动构建错误信息。另外,我不会在生产服务器上使用 xdebug ...它用于调试您的开发环境,并且会在生产环境中增加不必要的开销。

    因此,修改您的关闭处理程序,您可以执行以下操作:

    function shutdown()
    {
      if ( ! $err = error_get_last()) {
        return;
      }
    
      $fatals = array(
        E_USER_ERROR      => 'Fatal Error',
        E_ERROR           => 'Fatal Error',
        E_PARSE           => 'Parse Error', 
        E_CORE_ERROR      => 'Core Error',
        E_CORE_WARNING    => 'Core Warning',
        E_COMPILE_ERROR   => 'Compile Error',
        E_COMPILE_WARNING => 'Compile Warning'
      );
    
      if (isset($fatals[$err['type']])) {
        $msg = $fatals[$err['type']] . ': ' . $err['message'] . ' in ';
        $msg.= $err['file'] . ' on line ' . $err['line'];
        error_log($msg);
      }
    }
    

    【讨论】:

    • 请注意,我在 $fatals 数组中放入了 E_USER_ERROR,但实际上可以通过自定义错误处理程序成功处理。
    • 好的,我在想一个 PHP 模块,它可以捕获堆栈跟踪中的致命错误,比如 xdebug,但更轻。我的任务是如何获得有关生产中致命错误的更多信息以帮助纠正它们。
    • @CédricGirard 啊,我明白了。我认为绝大多数致命错误属于可以在开发阶段清除的类型……其余的都是特殊情况(例如内存不足,在请求中用棍子砸毁服务器等)。在这些情况下,我总是发现上述方法为日志记录提供了足够的信息。我尚未测试它是否适用于致命错误(我认为应该),但您可以尝试在关闭处理程序中添加对 debug_print_backtrace 的调用以获取跟踪信息
    • 我试了一下,但它总是空的,因为关闭处理程序是在执行错误代码之后运行的(而不是作为异常)。在我的公司,我们有大量遗留应用程序,并非所有应用程序都采用良好实践,因此我寻找其他方法来提高生产质量。
    【解决方案2】:

    如果你使用 HHVM 你可以设置

    hhvm.error_handling.call_user_handler_on_fatals = 1
    

    在您的php.ini 中,让它在致命错误时调用错误处理程序(带有堆栈跟踪)。 (more info)

    使用分析器也可能是一种选择 - 例如在致命处理程序中使用XHProf 并调用xhprof_disable() 可能会为您提供类似于堆栈跟踪的远程信息。 (不知道这是否真的有效。)

    【讨论】:

    • HHVM 选项和链接正是我想要的。
    【解决方案3】:

    要捕获最大执行超时,您可以使用 php-fpm 并设置 slowlog + request_slowlog_timeout 这将记录完整的堆栈跟踪。

    【讨论】:

      猜你喜欢
      • 2011-08-25
      • 1970-01-01
      • 2010-12-29
      • 2014-11-01
      • 1970-01-01
      • 2018-09-19
      • 1970-01-01
      • 2018-11-09
      相关资源
      最近更新 更多