Как я могу получить полную строку PHP getTraceAsString()?

Я использую getTraceAsString() для получения трассировки стека, но по какой-то причине строка усекается.

Например, возникает исключение, и я регистрирую строку, используя:

catch (SoapFault $e) {
error_log( $e->getTraceAsString() )
}

Строка, которая выводится:

#0 C:\Somedirectory\Somedirectory\Somedirectory\Somedir\SomeScript.php(10): SoapClient->SoapClient('http://www.ex...')

Как я могу получить полную строку для печати?


person User    schedule 22.12.2009    source источник
comment
Привет. Давным-давно тебе здесь хорошо помогли. Не могли бы вы принять ответ или даже опубликовать свой собственный? Спасибо.   -  person Mawg says reinstate Monica    schedule 30.10.2020


Ответы (8)


Я создал эту функцию для возврата трассировки стека без усеченных строк:

function getExceptionTraceAsString($exception) {
    $rtn = "";
    $count = 0;
    foreach ($exception->getTrace() as $frame) {
        $args = "";
        if (isset($frame['args'])) {
            $args = array();
            foreach ($frame['args'] as $arg) {
                if (is_string($arg)) {
                    $args[] = "'" . $arg . "'";
                } elseif (is_array($arg)) {
                    $args[] = "Array";
                } elseif (is_null($arg)) {
                    $args[] = 'NULL';
                } elseif (is_bool($arg)) {
                    $args[] = ($arg) ? "true" : "false";
                } elseif (is_object($arg)) {
                    $args[] = get_class($arg);
                } elseif (is_resource($arg)) {
                    $args[] = get_resource_type($arg);
                } else {
                    $args[] = $arg;
                }   
            }   
            $args = join(", ", $args);
        }
        $rtn .= sprintf(
            "#%s %s(%s): %s%s%s(%s)\n",
            $count,
            $frame['file'],
            $frame['line'],
            isset($frame['class']) ? $frame['class'] : '',
            isset($frame['type']) ? $frame['type'] : '', // "->" or "::"
            $frame['function'],
            $args
        );
        $count++;
    }
    return $rtn;
}

В качестве альтернативы вы можете отредактировать исходный код php, где он усекает вывод: https://github.com/php/php-src/blob/master/Zend/zend_exceptions.c#L392

person Steve    schedule 20.05.2011
comment
Спасибо за эту функцию. Очень полезно. Усечение обратной трассировки в Exception беспокоило меня годами, но у меня никогда не было времени что-либо с этим поделать. Я добавил вашу функцию в свой основной класс Exception на lampcms.com. - person Dmitri; 03.07.2011
comment
Спасибо, Стив. Я добавил несколько интервалов для цветового кодирования, и мы в деле, например: $rtn .= sprintf( #%s ‹span style='color:green'›%s‹/span›‹span style='color :darkred'›(%s)‹/span›: ‹span style='color:blue’›%s(%s)‹/span›\n, - person Andrew; 11.06.2016
comment
Спасибо за это. Однако, когда я попробовал это, я получил два уведомления: Notice: Undefined index: file и Notice: Undefined index: line. - person Alexandre R. Janini; 22.06.2016
comment
Почему бы не использовать только json_encode() для массива трассировки исключений? - person Mehdi Rahimi; 08.05.2019
comment
Обратите внимание, что существует новая директива INI (zend.exception_ignore_args) для включения или исключения аргументов из трассировки стека, сгенерированной из исключений. Источник: php.net/manual/de/migration74.other-changes. php Обязательно установите для него значение 0, например. вот так: ini_set('zend.exception_ignore_args', 0); - person Alfred Bez; 21.01.2020

Это решение хорошее, но в моем случае оно выдало ошибку, потому что в моей трассировке есть внутренние функции. Я добавил несколько строк кода, чтобы проверить это, чтобы функции трассировки все еще работали.

function getExceptionTraceAsString($exception) {
    $rtn = "";
    $count = 0;
    foreach ($exception->getTrace() as $frame) {


        $args = "";
        if (isset($frame['args'])) {
            $args = array();
            foreach ($frame['args'] as $arg) {
                if (is_string($arg)) {
                    $args[] = "'" . $arg . "'";
                } elseif (is_array($arg)) {
                    $args[] = "Array";
                } elseif (is_null($arg)) {
                    $args[] = 'NULL';
                } elseif (is_bool($arg)) {
                    $args[] = ($arg) ? "true" : "false";
                } elseif (is_object($arg)) {
                    $args[] = get_class($arg);
                } elseif (is_resource($arg)) {
                    $args[] = get_resource_type($arg);
                } else {
                    $args[] = $arg;
                }
            }
            $args = join(", ", $args);
        }
        $current_file = "[internal function]";
        if(isset($frame['file']))
        {
            $current_file = $frame['file'];
        }
        $current_line = "";
        if(isset($frame['line']))
        {
            $current_line = $frame['line'];
        }
        $rtn .= sprintf( "#%s %s(%s): %s(%s)\n",
            $count,
            $current_file,
            $current_line,
            $frame['function'],
            $args );
        $count++;
    }
    return $rtn;
}
person Jason Gallavin    schedule 22.07.2015

Некоторая лучшая версия https://stackoverflow.com/a/6076667/194508 находится здесь https://gist.github.com/1437966 добавлен класс для вывода.

person Ladislav Prskavec    schedule 06.12.2011

Поможет ли изменение настройки php.ini log_errors_max_len?

Также обратите внимание, что сообщения обрезаются только во время вывода, вы все равно можете получить исходное сообщение об ошибке вызовом $exception->getMessage()

person Gordon    schedule 22.12.2009
comment
Перед созданием этого поста я увеличил значение log_errors_max_len с 1024 до 4096. Но разницы не было. - person User; 23.12.2009
comment
Что касается getMessage(), я использую как getMessage(), так и getTraceAsString(), но они печатают разные вещи, поэтому мне нужны они оба. - person User; 23.12.2009
comment
Этого недостаточно для полного getTraceAsString() вывода - person andras.tim; 03.03.2017
comment
Это просто решило проблему, с которой я столкнулся. Неперехваченные исключения регулируются этой настройкой (хотя строковое исключение не имеет этой проблемы). - person Christian; 16.07.2018

Существует также отличный jTraceEx рецепт Эрнеста Фогельзингера по адресу https://www.php.net/manual/exception.gettraceasstring.php#114980, который поддерживает цепочки исключений и отформатирован в стиле Java.

Вот сравнение, взятое непосредственно из его комментария на php.net:

Исключение::getTraceAsString :

#0 /var/htdocs/websites/sbdevel/public/index.php(70): seabird\test\C->exc()
#1 /var/htdocs/websites/sbdevel/public/index.php(85): seabird\test\C->doexc()
#2 /var/htdocs/websites/sbdevel/public/index.php(89): seabird\test\fail2()
#3 /var/htdocs/websites/sbdevel/public/index.php(93): seabird\test\fail1()
#4 {main}

jTraceEx:

Exception: Thrown from class C
 at seabird.test.C.exc(index.php:78)
 at seabird.test.C.doexc(index.php:70)
 at seabird.test.fail2(index.php:85)
 at seabird.test.fail1(index.php:89)
 at (main)(index.php:93)
Caused by: Exception: Thrown from class B
 at seabird.test.B.exc(index.php:64)
 at seabird.test.C.exc(index.php:75)
 ... 4 more
Caused by: Exception: Thrown from class A
 at seabird.test.A.exc(index.php:46)
 at seabird.test.B.exc(index.php:61)
 ... 5 more
person Lucas Cimon    schedule 05.01.2016

Вы можете распечатать обратную трассировку с помощью

debug_print_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);

Он не усекается.

Пример печати будет

#0  W3\\Sausage\\Mushroom->setCredentials() called at [/sausage/common/library/W3/Vzaar/Api.php:40]
#1  W3\\Sausage\\Mushroom->__construct() called at [/sausage/common/modules/video.mod.php:24]
#2  ModVideo->__construct() called at [/sausage/common/core/modules.core.php:133]
#3  Modules->__get() called at [/sausage/common/search/Classified/ESAdapter.php:399]
#4  Base\\Search\\Classified\\ESAdapter->getVideoInfo() called at [/sausage/common/search/Classified/ESAdapter.php:436]
#5  Base\\Search\\Classified\\ESAdapter->fillDataSet() called at [/sausage/common/search/Adapter.php:58]
person Oli Girling    schedule 31.05.2019

В случае повторной генерации исключений можно указать предыдущее исключение в качестве третьего аргумента. Таким образом можно связать трассировку исключения.

try  {
    f('123');
} catch(Throwable $e){
    var_dump($e);
}

function f($arg){
    if(is_string($arg)){
        try {
            g($arg);
        } catch(UnexpectedValueException $e) {
            // Supply a third argument to pass the previous Exception.
            throw new RuntimeException('Error in function g()', $e->getCode(), $e);
        } catch(Throwable $e) {
            // Supply a third argument to pass the previous Exception.
            throw new RuntimeException('Unkown Error in function g()', $e->getCode(), $e);
        }   
    }   
}

function g($string){
    if(strlen($string) < 6){
        try {
            h($string);
        } catch(UnexpectedValueException $e) {
            throw new UnexpectedValueException('String is smaller then 6', $e->getCode(), $e);
        }
    }
    return $string;
}

function h($string){
    if(strlen($string) < 4){
        throw new UnexpectedValueException('String is smaller then 4');
    }
    return $string;
}

ВЫХОД:

C:\wamp64\www\julian\index.php:21:
object(RuntimeException)[3]
  protected 'message' => string 'Error in function g()' (length=21)
  private 'string' (Exception) => string '' (length=0)
  protected 'code' => int 0
  protected 'file' => string 'C:\wamp64\www\julian\index.php' (length=30)
  protected 'line' => int 30
  private 'trace' (Exception) => 
    array (size=1)
      0 => 
        array (size=4)
          'file' => string 'C:\wamp64\www\julian\index.php' (length=30)
          'line' => int 19
          'function' => string 'f' (length=1)
          'args' => 
            array (size=1)
              0 => string '123' (length=3)
  private 'previous' (Exception) => 
    object(UnexpectedValueException)[2]
      protected 'message' => string 'String is smaller then 6' (length=24)
      private 'string' (Exception) => string '' (length=0)
      protected 'code' => int 0
      protected 'file' => string 'C:\wamp64\www\julian\index.php' (length=30)
      protected 'line' => int 43
      private 'trace' (Exception) => 
        array (size=2)
          0 => 
            array (size=4)
              'file' => string 'C:\wamp64\www\julian\index.php' (length=30)
              'line' => int 27
              'function' => string 'g' (length=1)
              'args' => 
                array (size=1)
                  0 => string '123' (length=3)
          1 => 
            array (size=4)
              'file' => string 'C:\wamp64\www\julian\index.php' (length=30)
              'line' => int 19
              'function' => string 'f' (length=1)
              'args' => 
                array (size=1)
                  0 => string '123' (length=3)
      private 'previous' (Exception) => 
        object(UnexpectedValueException)[1]
          protected 'message' => string 'String is smaller then 4' (length=24)
          private 'string' (Exception) => string '' (length=0)
          protected 'code' => int 0
          protected 'file' => string 'C:\wamp64\www\julian\index.php' (length=30)
          protected 'line' => int 51
          private 'trace' (Exception) => 
            array (size=3)
              0 => 
                array (size=4)
                  'file' => string 'C:\wamp64\www\julian\index.php' (length=30)
                  'line' => int 41
                  'function' => string 'h' (length=1)
                  'args' => 
                    array (size=1)
                      0 => string '123' (length=3)
              1 => 
                array (size=4)
                  'file' => string 'C:\wamp64\www\julian\index.php' (length=30)
                  'line' => int 27
                  'function' => string 'g' (length=1)
                  'args' => 
                    array (size=1)
                      0 => string '123' (length=3)
              2 => 
                array (size=4)
                  'file' => string 'C:\wamp64\www\julian\index.php' (length=30)
                  'line' => int 19
                  'function' => string 'f' (length=1)
                  'args' => 
                    array (size=1)
                      0 => string '123' (length=3)
          private 'previous' (Exception) => null
          public 'xdebug_message' => string '<tr><th align='left' bgcolor='#f57900' colspan="5"><span style='background-color: #cc0000; color: #fce94f; font-size: x-large;'>( ! )</span> UnexpectedValueException: String is smaller then 4 in C:\wamp64\www\julian\index.php on line <i>51</i></th></tr>
<tr><th align='left' bgcolor='#e9b96e' colspan='5'>Call Stack</th></tr>
<tr><th align='center' bgcolor='#eeeeec'>#</th><th align='left' bgcolor='#eeeeec'>Time</th><th align='left' bgcolor='#eeeeec'>Memory</th><th align='left' bgcolor='#eeeeec'>Function</th><th align='left' bgcolor='#eeeeec'>Location</th></tr>
<tr><td bgcolor='#eeeeec' align='center'>1</td><td bgcolor='#eeeeec' align='center'>0.0034</td><td bgcolor='#eeeeec' align='right'>361152</td><td bgcolor='#eeeeec'>{main}(  )</td><td title='C:\wamp64\www\julian\index.php' bgcolor='#eeeeec'>...\index.php<b>:</b>0</td></tr>
<tr><td bgcolor='#eeeeec' align='center'>2</td><td bgcolor='#eeeeec' align='center'>0.0034</td><td bgcolor='#eeeeec' align='right'>361528</td><td bgcolor='#eeeeec'>f(  )</td><td title='C'... (length=1645)
      public 'xdebug_message' => string '<tr><th align='left' bgcolor='#f57900' colspan="5"><span style='background-color: #cc0000; color: #fce94f; font-size: x-large;'>( ! )</span> UnexpectedValueException: String is smaller then 6 in C:\wamp64\www\julian\index.php on line <i>43</i></th></tr>
<tr><th align='left' bgcolor='#e9b96e' colspan='5'>Call Stack</th></tr>
<tr><th align='center' bgcolor='#eeeeec'>#</th><th align='left' bgcolor='#eeeeec'>Time</th><th align='left' bgcolor='#eeeeec'>Memory</th><th align='left' bgcolor='#eeeeec'>Function</th><th align='left' bgcolor='#eeeeec'>Location</th></tr>
<tr><td bgcolor='#eeeeec' align='center'>1</td><td bgcolor='#eeeeec' align='center'>0.0034</td><td bgcolor='#eeeeec' align='right'>361152</td><td bgcolor='#eeeeec'>{main}(  )</td><td title='C:\wamp64\www\julian\index.php' bgcolor='#eeeeec'>...\index.php<b>:</b>0</td></tr>
<tr><td bgcolor='#eeeeec' align='center'>2</td><td bgcolor='#eeeeec' align='center'>0.0034</td><td bgcolor='#eeeeec' align='right'>361528</td><td bgcolor='#eeeeec'>f(  )</td><td title='C'... (length=1376)
  public 'xdebug_message' => string '<tr><th align='left' bgcolor='#f57900' colspan="5"><span style='background-color: #cc0000; color: #fce94f; font-size: x-large;'>( ! )</span> RuntimeException: Error in function g() in C:\wamp64\www\julian\index.php on line <i>30</i></th></tr>
<tr><th align='left' bgcolor='#e9b96e' colspan='5'>Call Stack</th></tr>
<tr><th align='center' bgcolor='#eeeeec'>#</th><th align='left' bgcolor='#eeeeec'>Time</th><th align='left' bgcolor='#eeeeec'>Memory</th><th align='left' bgcolor='#eeeeec'>Function</th><th align='left' bgcolor='#eeeeec'>Location</th></tr>
<tr><td bgcolor='#eeeeec' align='center'>1</td><td bgcolor='#eeeeec' align='center'>0.0034</td><td bgcolor='#eeeeec' align='right'>361152</td><td bgcolor='#eeeeec'>{main}(  )</td><td title='C:\wamp64\www\julian\index.php' bgcolor='#eeeeec'>...\index.php<b>:</b>0</td></tr>
<tr><td bgcolor='#eeeeec' align='center'>2</td><td bgcolor='#eeeeec' align='center'>0.0034</td><td bgcolor='#eeeeec' align='right'>361528</td><td bgcolor='#eeeeec'>f(  )</td><td title='C:\wamp64\ww'... (length=1096)
person Julian    schedule 08.12.2020

Если вам сойдет с рук var_dump(), простое решение:

try {
   ...
} catch (Exception $e)
   var_dump($e->getTrace());
}

Украдено из этого замечательного ответа Андре

person Josh Johnson    schedule 20.01.2017
comment
Это просто выведет массив - person Xiao; 20.09.2017