Разработка на Phoenix Framework, мощном стеке для создания высокопроизводительных веб-приложений на Elixir, — это удовольствие. Однако даже в самой элегантной системе могут возникать ошибки. Умение эффективно отлаживать код — ключевой навык разработчика. В этой статье мы рассмотрим практические методы отладки приложений Phoenix, от базовых до продвинутых, сопровождая каждый шаг конкретными примерами кода.
Начнем с фундамента. Встроенный в Elixir макрос `IO.inspect/2` — ваш первый и самый верный друг. Его красота в неинвазивности: он выводит значение любой структуры данных в консоль и возвращает это же значение, не нарушая поток выполнения. Представьте, что у вас есть функция в контексте `Accounts`, которая не возвращает ожидаемого пользователя.
```elixir
def get_user_by_email(email) do
User
|> where(email: ^email)
|> Repo.one()
|> IO.inspect(label: "User from DB") # Отладка здесь
end
```
В консоли вы увидите четкую метку и полную структуру `%User{}` или `nil`. Для сложных структур, таких как вложенные ассоциации Ecto, используйте опции `limit: :infinity` и `pretty: true`.
Когда `IO.inspect` недостаточно, на помощь приходит `IEx` (интерактивная оболочка Elixir). Запустите сервер Phoenix в интерактивном режиме командой `iex -S mix phx.server`. Теперь вы можете останавливать выполнение кода с помощью `require IEx; IEx.pry`. Допустим, у вас странное поведение в обработчике LiveView.
```elixir
def handle_event("add_item", %{"item" => item_params}, socket) do
require IEx; IEx.pry() # Выполнение остановится здесь
# ... ваша логика
end
```
Когда событие сработает, сессия IEx заблокирует процесс, и вы сможете инспектировать все переменные в текущей области видимости: `socket.assigns`, `item_params`, вызвать вспомогательные функции. Это невероятно мощный инструмент для исследования состояния системы в реальном времени.
Для отладки проблем, связанных с производительностью или параллельным выполнением, ключевым является логирование. Phoenix и Logger уже настроены. Используйте разные уровни логирования.
```elixir
Logger.debug("Starting transaction for user ID: #{user_id}")
Logger.info("Order #{order_id} processed successfully")
Logger.warn("Failed to send email to #{email}, queueing retry")
```
Чтобы логировать полные структуры, используйте `inspect/1` внутри логов: `Logger.debug(inspect(changeset.errors))`. Настройте уровень логирования в `config/dev.exs` для вывода отладочной информации.
Отладка Ecto-запросов — отдельная важная тема. Включите логирование всех SQL-запросов в консоль, добавив в `config/dev.exs`:
```elixir
config :my_app, MyApp.Repo,
loggers: [Ecto.LogEntry]
```
Теперь каждый запрос будет виден в терминале. Для сложных запросов используйте `Ecto.Adapters.SQL.explain/3`, чтобы получить план выполнения и найти "узкие" места.
Работа с Phoenix LiveView требует особого подхода. Помимо `IEx.pry` в обработчиках событий, используйте встроенные инструменты отладки. В `assets/js/app.js` можно добавить логирование жизненного цикла LiveView.
```javascript
let liveSocket = new LiveSocket("/live", Socket, {
params: {_csrf_token: csrfToken},
dom: {
onBeforeElUpdated(from, to) {
console.log("DOM will update", from, to);
}
}
});
```
Для визуальной отладки присваиваний и обработанных событий в LiveView есть специальный хук. Добавьте в ваш `app.js`:
```javascript
import {liveSocketDebug} from "./live_socket_debug"
let liveSocket = new LiveSocket("/live", Socket, {
...,
hooks: {Debug: liveSocketDebug}
});
```
И создайте файл `assets/js/live_socket_debug.js` с логированием. Теперь в консоли браузера вы будете видеть все внутренние сообщения LiveView.
Когда ошибка неуловима и воспроизводится только в определенных условиях, используйте трассировку процессов. В IEx выполните `:observer.start()` — откроется графический инструмент, показывающий дерево процессов, их состояние, нагрузку на память и CPU. Это незаменимо для поиска утечек памяти или "зависших" процессов.
Для отладки асинхронных задач, например, отправленных через Oban, логируйте контекст задачи и используйте веб-панель Oban. При возникновении ошибки задача будет прозрачно показана с трейсбэком.
Наконец, создавайте контекстные тесты. Часто лучшая отладка — это превентивная отладка. Написание модульных и интеграционных тестов с помощью ExUnit позволяет не только ловить ошибки, но и документировать поведение системы. Используйте `assert`, `refute` и особенно `assert_raise` для проверки ошибочных сценариев.
```elixir
test "get_user_by_email returns nil for non-existent email" do
assert nil == Accounts.get_user_by_email("ghost@example.com")
end
```
Комбинируя эти методы — от простого `IO.inspect` до мощного `:observer` и продуманного тестирования — вы превратите отладку из рутины в систематический и даже увлекательный процесс исследования вашего Phoenix-приложения. Помните, что цель — не просто исправить ошибку, но и понять глубинные причины ее возникновения, укрепляя архитектуру и свою экспертизу.
Отладка Phoenix Framework: Практическое руководство с примерами кода
Подробное практическое руководство по отладке приложений на Phoenix Framework. Статья охватывает использование IO.inspect, интерактивной отладки с IEx.pry, логирования, анализа Ecto-запросов, специальных инструментов для LiveView, наблюдения за процессами и важности тестирования. Каждый метод сопровождается конкретными примерами кода для немедленного применения в разработке.
25
1
Комментарии (11)