src/Base/Logger/Debugger.php
public static function backTrace($withArgs = false, $traceShift = 0, $useEcho = false)
    {
        $trace = debug_backtrace();
        if ($traceShift > 0) {
            $trace = array_slice($trace, $traceShift);
        }
        $called = array_shift($trace);
        $trace = static::reduceBacktrace($trace);
        $functions = [];
        $padLn = 12;
        $traceNum = 0;
        foreach ($trace as $row) {
            $function = $row['function'];
            $functionStr = isset($row['class'])
                ? $row['class'] . $row['type'] . $function
                : $function;
            $functionStr = Console::ansiFormat($functionStr, [Console::FG_GREEN, Console::BOLD]);
            if ($withArgs) {
                /** @var \Throwable[] $exceptionArgs */
                $exceptionArgs = [];
                list($argsSimple, $argsFull, $argsStrLength) = static::getArgumentsFromTrace($row, true);
                $argsFullExt = $argsStrLength > 100;
                $argsFullMaxLn = 0;
                $functionStr .= '(' . implode(', ', $argsSimple) . ')';
                if ($argsFullExt) {
                    foreach ($argsFull as $argName => $argValue) {
                        $argLn = mb_strlen($argName);
                        $argsFullMaxLn = $argsFullMaxLn < $argLn ? $argLn : $argsFullMaxLn;
                    }
                }
                $argsFullOld = $argsFull;
                $argsFull = [];
                foreach ($argsFullOld as $argName => $argValue) {
                    $argName = str_pad($argName, $argsFullMaxLn, ' ', STR_PAD_RIGHT);
                    $argsFull[] = Console::ansiFormat($argName, [Console::FG_GREEN]) . ' ' . $argValue;
                }
                $argsFullSeparator = $argsFullExt ? "\n" . str_repeat(' ', $padLn) : ", ";
                $functionStr .= !empty($argsFull) ? "\n" . str_repeat(' ', $padLn) . implode($argsFullSeparator, $argsFull) : '';
                if (!empty($exceptionArgs)) {
                    foreach ($exceptionArgs as $exceptionArg) {
                        $functionStr .= "\n" . str_pad('', $padLn, ' ', STR_PAD_LEFT)
                            . Console::ansiFormat($exceptionArg->getMessage(), [Console::FG_RED]);
                    }
                }
            } else {
                $functionStr .= '()';
            }
            $positionStr = '';
            if (isset($row['file']) && $row['file'] !== "") {
                $positionStr .= "\n" . str_pad('', $padLn, ' ', STR_PAD_RIGHT)
                    . Console::ansiFormat($row['file'], [Console::FG_PURPLE]);
            } else {
                $positionStr .= "\n" . str_pad('', $padLn, ' ', STR_PAD_RIGHT)
                    . Console::ansiFormat('{no path}', [Console::FG_PURPLE]);
            }
            if (isset($row['line']) && $row['line'] !== "") {
                $positionStr .= ' ' . Console::ansiFormat('#' . $row['line'], [Console::FG_CYAN]);
            }
            $functionStr .= $positionStr;
            $functionStr = str_pad('[' . $traceNum . '] ', $padLn - 1, '-', STR_PAD_RIGHT) . ' ' . $functionStr;
            $functionStr = str_pad($functionStr, $padLn, ' ', STR_PAD_RIGHT);
            $functions[] = $functionStr;
            $traceNum++;
        }
        $str = "\n" . implode("\n", $functions) . "\n";
        $str .= Console::ansiFormat("Called from " . $called['file'] . ' #' . $called['line'], [Console::FG_YELLOW]) . "\n";
        if ($useEcho) {
            echo $str . "\n";
        } else {
            /** @var WritableStreamInterface $stream */
            $stream = \Reaction::create('stdoutWriteStream');
            $stream->write($str . "\n");
        }
    }
public static function backTrace($withArgs = false, $traceShift = 0, $useEcho = false)
    {
        $trace = debug_backtrace();
        if ($traceShift > 0) {
            $trace = array_slice($trace, $traceShift);
        }
        $called = array_shift($trace);
        $trace = static::reduceBacktrace($trace);
        $functions = [];
        $padLn = 12;
        $traceNum = 0;
        foreach ($trace as $row) {
            $function = $row['function'];
            $functionStr = isset($row['class'])
                ? $row['class'] . $row['type'] . $function
                : $function;
            $functionStr = Console::ansiFormat($functionStr, [Console::FG_GREEN, Console::BOLD]);
            if ($withArgs) {
                /** @var \Throwable[] $exceptionArgs */
                $exceptionArgs = [];
                list($argsSimple, $argsFull, $argsStrLength) = static::getArgumentsFromTrace($row, true);
                $argsFullExt = $argsStrLength > 100;
                $argsFullMaxLn = 0;
                $functionStr .= '(' . implode(', ', $argsSimple) . ')';
                if ($argsFullExt) {
                    foreach ($argsFull as $argName => $argValue) {
                        $argLn = mb_strlen($argName);
                        $argsFullMaxLn = $argsFullMaxLn < $argLn ? $argLn : $argsFullMaxLn;
                    }
                }
                $argsFullOld = $argsFull;
                $argsFull = [];
                foreach ($argsFullOld as $argName => $argValue) {
                    $argName = str_pad($argName, $argsFullMaxLn, ' ', STR_PAD_RIGHT);
                    $argsFull[] = Console::ansiFormat($argName, [Console::FG_GREEN]) . ' ' . $argValue;
                }
                $argsFullSeparator = $argsFullExt ? "\n" . str_repeat(' ', $padLn) : ", ";
                $functionStr .= !empty($argsFull) ? "\n" . str_repeat(' ', $padLn) . implode($argsFullSeparator, $argsFull) : '';
                if (!empty($exceptionArgs)) {
                    foreach ($exceptionArgs as $exceptionArg) {
                        $functionStr .= "\n" . str_pad('', $padLn, ' ', STR_PAD_LEFT)
                            . Console::ansiFormat($exceptionArg->getMessage(), [Console::FG_RED]);
                    }
                }
            } else {
                $functionStr .= '()';
            }
            $positionStr = '';
            if (isset($row['file']) && $row['file'] !== "") {
                $positionStr .= "\n" . str_pad('', $padLn, ' ', STR_PAD_RIGHT)
                    . Console::ansiFormat($row['file'], [Console::FG_PURPLE]);
            } else {
                $positionStr .= "\n" . str_pad('', $padLn, ' ', STR_PAD_RIGHT)
                    . Console::ansiFormat('{no path}', [Console::FG_PURPLE]);
            }
            if (isset($row['line']) && $row['line'] !== "") {
                $positionStr .= ' ' . Console::ansiFormat('#' . $row['line'], [Console::FG_CYAN]);
            }
            $functionStr .= $positionStr;
            $functionStr = str_pad('[' . $traceNum . '] ', $padLn - 1, '-', STR_PAD_RIGHT) . ' ' . $functionStr;
            $functionStr = str_pad($functionStr, $padLn, ' ', STR_PAD_RIGHT);
            $functions[] = $functionStr;
            $traceNum++;
        }
        $str = "\n" . implode("\n", $functions) . "\n";
        $str .= Console::ansiFormat("Called from " . $called['file'] . ' #' . $called['line'], [Console::FG_YELLOW]) . "\n";
        if ($useEcho) {
            echo $str . "\n";
        } else {
            /** @var WritableStreamInterface $stream */
            $stream = \Reaction::create('stdoutWriteStream');
            $stream->write($str . "\n");
        }
    }
Print backtrace to console
@param bool $withArgs Show arguments names and content
@param int  $traceShift Shift trace for number positions
@param bool $useEcho Use direct call to `echo` function instead of Stream::write()