Отримання трасування стеку

Дата оновлення перекладу 2022-11-01

Отримання трасування стеку

При заяві про баг, окрім випадків неправильної поведінки в коді, дуже важливо, щоб ви надавали одне або декілька трасувань стеку. Щоб зрозуміти, навіщо, спочатку вам потрібно зрозуміти, що таке трасування стеку і чим воно може бути корисним вам як розробнику, а також менеджерам бібліотек.

Анатомія трасування стеку

Трасування стеку називається так, тому що воно дозволяє бачити слід функціональних викликів, які ведуть до точки коду з початку програми. Ця точка не обовʼязково буде виключенням. Наприклад, ви можете використати нативну функцію PHP debug_print_backtrace(), щоб отримати таке трасування. Для кожного трасування ви отримаєте файл та функцію або метод виклику, а також номер рядку цього виклику. Це часто дуже корисно для розуміння робочого процесу вашої програми і того, як вона може опинитися у найнеочікуваніших місцях, на кшталт рядків коду, де викликаються виключення.

Трасування стеку та виключення

В PHP, кожне виключення має власне трасування стеку, яке відображається за замовчуванням, якщо виключення не знайдено. При використанні Symfony, такі виключення проходять через користувацький обробник виключень, який покращує їх багатьма способами до відображення поточному серверу API (CLI або ні). Це означає зручніший спосіб отримання трасування стеку, коли вам не потрібно, щоб програма продовжувала викликати виключення, наступним чином: throw new \Exception();

Вкладені виключення

З мірою зростання додатків, їх складність часто обробляється шарами архитектури, які потрібно розділяти. Наприклад, якщо у вас є веб-додаток, який робить виклик до віддаленого API, при виконанні цього виклику може бути корисно огорнути виключення виключеннями, які мають особливий сенс у вашому домені, та створити відповідні HTTP виключення з них. Виключення можуть бути вкладені з використанням аргументу $previous,
який відображається у підпису класу Exception: public __construct ([ string $message = "" [, int $code = 0 [, Throwable $previous = NULL ]]] ) Це означає, що іноді, коли ви отримуєте виключення з додатку, насправді у вас їх може бути декілька.

Що шукати у трасуванні стеку

При використанні бібліотеки, ви будете викликати код, який ви не писали. При використанні фреймворку все навпаки: так як ви дотримуєтесь згод фреймворку, фреймворк знаходить ваш код і викликає його та робить якісь речі за вас, на кшталт маршрутизації або контролю доступу. Symfony є і фреймворком, і бібліотекою компонентів, тому викликає ваш код, а потім ваш код може викликати її. Це означає, що у вас завжди буде мінімум 2 частини, а часто і 3, у ваших трасуваннях стеку, при використанні Symfony: частина, яка починається в одній з точок входу фреймворку (в більшості випадків bin/console або public/index.php), та закінчується при досягненні вашого коду, в більшості випадків у команді або контролері, що знаходяться під src. Потім буде викликане виключення або у вашому коді, або у викликаних вами бібліотеках. Останнє вимагає третьої частини трасування стеку, з викликами у файлах під vendor. До того, як опинитися в цій бібліотеці, код проходить через багато процесів розгляду та конвеєров CI, що означає, що він з меншою вірогідністю стане джерелом проблеми, ніж код вашого додатку, так що вам важливо спочатку сфокусуватися на рядках, що починаються з src, і шукати все, що виглядає підозріло або неочікувано, на кшталт виклику методу, які не повинні відбуватися.

Далі ви можете подивитися, які пакети залучені. Файли під vendor систематизовані Composer в наступному порядку: vendor/acme/router, де acme - постачальник, router - бібліотека, а acme/router - пакет Composer. Якщо ви плануєте заявити про баг, переконайтеся, що заявляєте про нього в бібліотеці, яка викикає виключення. composer home acme/router повинен привести вас у правильне місце. Так як Symfony є моносховищем, використовуйте composer home symfony/symfony при заяві про баг у будь-якому компоненті.

Отримання трасування стеку в Symfony

Тепер, коли ми все це знаємо, давайте подивимося, як отримати трасування стеку в Symfony.

Трасування стеку у вашому веб-браузері

Необхідно памʼятати про декілька речей при виборі трасування стеку з вашого середовища розробки через веб-браузер:

  1. Виключень декілька? Якщо так, то найцікавішим частіше за все є 1/n, яке відображається останнім у прикладі нижче (воно зазначене як виключення [1/2]).
  2. У вкладці "Stack Traces", ви знайдете виключення, написані простим текстом, щоб ви могли легко ділитися ними, наприклад, у звітах про баги. Переконайтеся в тому, що ви видалили конфіденційну інформацію до того, як ділитися.
  3. Ви можете помітити, що існує також вкладка логів; ця вкладка не має нічого спільного з трасуванням стеку, а містить лише логи, вироблені у довільних місцях вашого додатку. Вони можуть відноситися до того виключення, яке ви отримуєте, або ні, але не є тим, що має на увазі термін "трасування стеку".

Так як трасування стеку можуть містити конфіденційні дані, вони не повинні бути розкриті у виробництві. Отримвання трасування стеку з вашого середовища виробництва, хоча і складніше, але все ж можливо з рішеннями, що включають в себе відправки на їх адресу електронної пошти за допомогою monolog.

Трасування стеку в CLI

Виключення можуть бути викликані під час виконання команди Symfony. За замовчуванням, відображається лише повідомлення, так як його зазвичай достатньо, щоб зрозуміти, що відбувається:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ php bin/console debug:exception


   Команда "debug:exception" не визначена.

   Ви мали на увазі щось з цього?
       debug:autowiring
       debug:config
       debug:container
       debug:event-dispatcher
       debug:form
       debug:router
       debug:translation
       debug:twig

Якщо це не той випадок, ви можете отримати трасування стеку, збільшивши уровень детальности за допомогою --verbose:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
$ php bin/console --verbose debug:exception

 In Application.php line 644:

   [Symfony\Component\Console\Exception\CommandNotFoundException]
   Command "debug:exception" is not defined.

   Ви мали на увазі щось з цього?
       debug:autowiring
       debug:config
       debug:container
       debug:event-dispatcher
       debug:form
       debug:router
       debug:translation
       debug:twig


 Трасування виключень:
   at /app/vendor/symfony/console/Application.php:644
  Symfony\Component\Console\Application->find() at /app/vendor/symfony/framework-bundle/Console/Application.php:116
  Symfony\Bundle\FrameworkBundle\Console\Application->find() at /app/vendor/symfony/console/Application.php:228
  Symfony\Component\Console\Application->doRun() at /app/vendor/symfony/framework-bundle/Console/Application.php:82
  Symfony\Bundle\FrameworkBundle\Console\Application->doRun() at /app/vendor/symfony/console/Application.php:140
  Symfony\Component\Console\Application->run() at /app/bin/console:42

Трасування стеку та виклики API

При отриманні виключення з API, ви можете не отримати трасування стеку, або воно може бути відображене у вигляді, неприйнятному для розповсюдження. На щастя, в середовищі розробки, ви можете отриамти трасування стеку у вигляді простого тексту, використовуючи профільувальник. Щоб знайти профіль, ви можете подивитися на заголовки відповідей X-Debug-Token-Link:

1
2
3
4
5
6
$ curl --head http://localhost:8000/api/posts/1
… більше заголовків
X-Debug-Token: 110e1e
X-Debug-Token-Link: http://localhost:8000/_profiler/110e1e
X-Robots-Tag: noindex
X-Previous-Debug-Token: 209101

Якщо ви перейдете за цим посиланням, ви потрапите на сторінку, дуже схожу на описану вище у Трасування стеку в вашому веб-браузері.