public static function trace(array $options = [])
    {
        $self = Debugger::getInstance();
        $defaults = [
            'depth' => 999,
            'format' => $self->outputFormat,
            'args' => false,
            'start' => 0,
            'scope' => null,
            'exclude' => ['call_user_func_array', 'trigger_error']
        ];
        $options = Hash::merge($defaults, $options);
        $backtrace = debug_backtrace();
        $count = count($backtrace);
        $back = [];
        $_trace = [
            'line' => '??',
            'file' => '[internal]',
            'class' => null,
            'function' => '[main]'
        ];
        for ($i = $options['start']; $i < $count && $i < $options['depth']; $i++) {
            $trace = $backtrace[$i] + ['file' => '[internal]', 'line' => '??'];
            $signature = $reference = '[main]';

            if (isset($backtrace[$i + 1])) {
                $next = $backtrace[$i + 1] + $_trace;
                $signature = $reference = $next['function'];

                if (!empty($next['class'])) {
                    $signature = $next['class'] . '::' . $next['function'];
                    $reference = $signature . '(';

                    if ($options['args'] && isset($next['args'])) {
                        $args = [];

                        foreach ($next['args'] as $arg) {
                            $args[] = Debugger::exportVar($arg);
                        }

                        $reference .= implode(', ', $args);
                    }

                    $reference .= ')';
                }
            }

            if (in_array($signature, $options['exclude'])) {
                continue;
            }

            if ($options['format'] === 'points' && $trace['file'] !== '[internal]') {
                $back[] = ['file' => $trace['file'], 'line' => $trace['line']];
            } else {
                $back[] = $trace;
            }
        }

        if ($options['format'] === 'array' || $options['format'] === 'points') {
            return $back;
        }

        return implode("\n", $back);
    }