image


При разработке приложений часто приходится сталкиваться с необходимостью просмотра вывода exception stack trace (в логах или при debug-инге). Хотелось бы иметь возможность автоматически попадать в необходимое место кода, прямо кликом по строке в выводе stack trace в браузере или в терминале.


Если вы являетесь пользователем одного из последних продуктов компании JetBrains (в частности PhpStorm), вы можете использовать для этих целей внутреннее REST API (для навигации из браузера) и command line launcher (для навигации в терминале).


Навигация в браузере


Частичное описание методов REST API IDE от JetBrains можно посмотреть здесь:


» http://develar.org/idea-rest-api/


Одним из методов этого API является возможность открыть файл проекта и переместиться на произвольную позицию в этом файле внутри самой IDE.


Обращения к вызовам методов API осуществляется через вызов по адресу http://localhost:63342/


Пример вызова API для открытия файла выглядит как:


http://localhost:63342/api/file?file=src/path/to/file.php&line=100&column=34


где:


file — относительный или абсолютный путь файла
line — строка в файле, куда нужно переместить курсор
column — позиция на указанной строке


alert


Для того чтобы убрать сообщение, которое каждый раз появляется при вызове API в IDE, можно в настройках: Build, Execution, Deployment > Debugger поставить галочку "Allow unsigned request" (либо каждый раз придется в диалоге кликать на кнопку Ok).


Settings


Пример обработки вывода стандартного getTraceAsString() в php


Ниже показан Regexp, обрабатывающий стандартный вывод stack trace у Exception через getTraceAsString()


try {
    // some code
}(\Exception $e){
    $traceAsString = preg_replace('/#(\d+) (.+?\.php)\((\d+)\):/', '#$1 <a href="#" onclick="_goToEditorCodeLine(\'$2\', \'$3\'); return false;">$2($3):</a>', $e->getTraceAsString() );
    // some code
}

Каждая строка в Exception становится ссылкой, клик на которую открывает в IDE файл на нужной строке.


Также необходимо подключить JS функцию, которая будет непосредственно "дергать" метод API.


function _goToEditorCodeLine(file, line){?    
    var xmlhttp = new XMLHttpRequest();?    
    xmlhttp.open("GET", "http://localhost:63342/api/file?file=" + file + "&line=" + line, true);
    xmlhttp.send();?
}

Пример реализации на примере обработки Exception в Symfony 3


Поскольку в настоящий момент я работаю с Symfony, я на конкретном примере покажу как модифицировать страницу со стандартным Exception чтобы реализовать открытие в IDE файла.


Для того, чтобы переопределить кусочек шаблона, который отвечает за вывод страницы Exception необходимо в папке app/Resources/TwigBundle/views/Exception/ создать два файла


  • exception.html.twig
  • trace.html.twig

В файле exception.html.twig добавить простейшую функцию _goToEditorCodeLine(), код которой описан выше.


В файле trace.html.twig найдем место вывода строки и добавим в конец стрелку, нажатие на которую будет осуществлять открытие файла в IDE.


    in {{ trace.file|format_file(trace.line) }} <a href="#" onclick="_goToEditorCodeLine('{{ trace.file }}', '{{ trace.line }}'); return false;">&rarr;</a>&nbsp;

После этого в строке stack trace появлется стрелка, нажатие на которую открывает в IDE файл и перемещает курсор на нужную позицию.


Symfony Exception


Итоговый вариант двух файлов для Symfony 3 можно посмотреть здесь.


Интеграция с командной строкой в iTerm2


Если вы работаете в MacOS и используете iTerm2, можно провести интеграцию iTerm2 и Command Line Launcher соответствующей IDE, что позволит открывать файлы в IDE прямо из терминала.


Для установки launcher-а необходимо в IDE вызвать меню Tool > Create Command-line Launcher... и в диалоговом окне подтвердить путь, куда launcher будет установлен. В моем случае это /usr/local/bin/phpstorm (или /usr/local/bin/pstorm для более ранних версий) для IntelliJ IDEA это /usr/local/bin/idea.


Данный launcher позволяет, при вызове из командной строки, открывать файл и переходить на нужную строку в нем.


Пример вызова:


/usr/local/bin/phpstorm --line 40 /path/to/file


или


/usr/local/bin/phpstorm /path/to/file:40


В обоих случаях будет открыт файл /path/to/file на 40 строке.


Теперь сделаем интеграцию command line launcher и iTerm2. Идем в Edit Session > Advanced.


iTerm


В секции Semantic History, из выпадающего списка, выбираем run command... и вводим:


/usr/local/bin/phpstorm --line \2 \1


Теперь если нажать Cmd и навести стрелку курсора на какой либо файл в терминале — он станет ссылкой и клик по нему осуществит его открытие в IDE.


Если у вас логи имеют вид /path/to/file/:40, т.е. номер строки указан через двоеточие после файла — тогда IDE будет открывать файл прямо на этой строке.


Проблема c логами php-exception в том, что вывод имеет вид /path/to/file/(40), т.е. строка в файле стоит в скобках. В результате этого файл открывается, но на нужную строку не переходит.


Для решения этой проблемы можно преобразовать вывод лога в нужный нам формат, используя потоковый редактор sed.


sed -E 's/#([0-9]+) (.+\.php)\(([0-9]+)\):/#\1 \2:\3/g'


Пример обработки вывода функции tail


tail test.log | sed -E 's/#([0-9]+) (.+\.php)\(([0-9]+)\):/#\1 \2:\3/g'


В заключении еще раз хотел бы подчеркнуть, что данная схема работает практически с любым языком и любой IDE от JetBrains.

Поделиться с друзьями
-->

Комментарии (10)


  1. Dreyk
    28.11.2016 12:49
    +1

    Интересно, а если у меня запущено несколько IDE от JetBrains, как быть


    Вот сейчас у меня запущен RubyMine и WebStorm, на 63342-м порту мне отвечает RubyMine


  1. DVLev
    28.11.2016 13:07
    +2

    В одной из IDE переопределяете порт по которому слушает Debugger

    Preferences ->Debugger->Port и соответствующим образом меняете js функцию.


  1. SamDark
    28.11.2016 17:04
    +2

    Опа. А описан ли где-то этот REST-сервер на официальных ресурсах JetBrains? А то мы с регистрацией своего протокола мучались совсем недавно, а тут вон оно что...


  1. sidristij
    29.11.2016 12:05

    В R# все делается автоматически, через вставку из буфера обмена стектрейса.


  1. popstas
    29.11.2016 21:43
    +1

    Эту открывалку прикрутить бы к браузеру, чтобы открывал css/js в IDE.


  1. mnv
    30.11.2016 01:03
    +1

    Попробовал, отлично работает. Сделал аналогично для Laravel.


  1. ruFog
    30.11.2016 07:51
    +2

    1. mnv
      30.11.2016 09:21

      Очень похоже на то, но не совсем то. Чтобы работало так


      ide: 'phpstorm://open?file=%%f&line=%%l'

      надо видимо устанавливать это.


      Если написать так


      ide: 'http://localhost:63342/api/file?file=%%f&line=%%l'

      то работает, но при клике на ссылку в браузере, браузер тоже открывает эту страницу и там остается "белая страница".


  1. Tab10id
    01.12.2016 11:43
    +1

    Про rest не знал, пользуюсь вот этим:

    https://www.jetbrains.com/help/phpstorm/2016.2/working-with-phpstorm-features-from-command-line.html
    https://www.jetbrains.com/help/ruby/2016.2/working-with-rubymine-features-from-command-line.html
    etc

    Для перехода по клику пользуюсь обработкой txmt протокола аналогично этому:
    https://gist.github.com/gregd/1305906/c57a21e210aafd72102360cd3bdffb7ab195ed39

    Ссылки с протоколом txmt в моем случае генерят сторонние библиотеки (ruby: better_errors, rails-footnotes)

    Могу предположить, что возможности API соответствуют описанному механизму.


  1. akaSStalkALEX
    02.12.2016 23:24

    Для Yii2 никто не делал?