Spec-Zone.ru › Elixir 1.18

Source Отладка

Существует несколько способов отладки кода на Elixir. В этой главе мы рассмотрим некоторые из наиболее распространенных способов.

IO.inspect/2

То, что делает IO.inspect(item, opts \\ []) по-настоящему полезным при отладке, заключается в том, что оно возвращает переданный ему item аргумент без изменения поведения исходного кода. Давайте посмотрим пример.

(1..10)
|> IO.inspect()
|> Enum.map(fn x -> x * 2 end)
|> IO.inspect()
|> Enum.sum()
|> IO.inspect()

Выводит:

1..10
[2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
110

Как видите, IO.inspect/2 позволяет «просматривать» значения практически в любом месте вашего кода без изменения результата, что очень полезно внутри конвейера, как в вышеприведённом случае.

IO.inspect/2 также предоставляет возможность оформления вывода с помощью label параметра. Метка будет выводиться перед просматриваемым item:

[1, 2, 3]
|> IO.inspect(label: "before")
|> Enum.map(&(&1 * 2))
|> IO.inspect(label: "after")
|> Enum.sum

Выводит:

before: [1, 2, 3]
after: [2, 4, 6]

Также очень часто используется IO.inspect/2 с binding/0, которая возвращает все имена переменных и их значения:

def some_fun(a, b, c) do
  IO.inspect(binding())
  ...
end

Когда some_fun/3 вызывается с :foo, "bar", :baz, оно выводит:

[a: :foo, b: "bar", c: :baz]

См. IO.inspect/2 и Inspect.Opts соответственно, чтобы узнать больше о функции и прочитать обо всех поддерживаемых параметрах.

dbg/2

В Elixir v1.14 была представлена dbg/2. dbg похожа на IO.inspect/2, но специально предназначена для отладки. Она выводит значение, переданное ей, и возвращает его (как и IO.inspect/2), но также выводит код и местоположение.

# In my_file.exs
feature = %{name: :dbg, inspiration: "Rust"}
dbg(feature)
dbg(Map.put(feature, :in_version, "1.14.0"))

Вышеприведенный код выводит следующее:

[my_file.exs:2: (file)]
feature #=> %{inspiration: "Rust", name: :dbg}
[my_file.exs:3: (file)]
Map.put(feature, :in_version, "1.14.0") #=> %{in_version: "1.14.0", inspiration: "Rust", name: :dbg}

Когда речь идёт о IO.inspect/2, мы упомянули о её полезности, когда её помещают между шагами |> конвейеров. dbg делает это лучше: она понимает код Elixir, поэтому выводит значения на каждом шаге конвейера.

# In dbg_pipes.exs
__ENV__.file
|> String.split("/", trim: true)
|> List.last()
|> File.exists?()
|> dbg()

Этот код выводит:

[dbg_pipes.exs:5: (file)]
__ENV__.file #=> "/home/myuser/dbg_pipes.exs"
|> String.split("/", trim: true) #=> ["home", "myuser", "dbg_pipes.exs"]
|> List.last() #=> "dbg_pipes.exs"
|> File.exists?() #=> true

Хотя dbg предоставляет удобства для работы со структурами Elixir, вам потребуется IEx, если вы хотите выполнить код и установить точки останова во время отладки.

Pry

При использовании IEx, вы можете передать --dbg pry в качестве параметра, чтобы «остановить» выполнение кода там, где находится вызов dbg:

$ iex --dbg pry

Или для отладки внутри проекта:

$ iex --dbg pry -S mix

Теперь любой вызов dbg спросит, хотите ли вы использовать pry для текущего кода. Если вы согласитесь, вы сможете получить доступ ко всем переменным, а также импортам и псевдонимам из кода напрямую из IEx. Это называется «prying». Пока сессия pry активна, выполнение кода останавливается, пока не будет вызвано continue (или c) или next (или n). Помните, что вы всегда можете запустить iex в контексте проекта с помощью iex -S mix TASK.

Точки останова

dbg вызовы требуют от нас изменения кода, который мы хотим отлаживать, и обладают ограниченными возможностями по шаговому выполнению. К счастью, IEx также предоставляет функцию IEx.break!/2, которая позволяет устанавливать и управлять точками останова в любом коде Elixir без изменения его исходного кода:

Аналогично dbg, как только достигается точка останова, выполнение кода останавливается до тех пор, пока не будут вызваны continue (или c), или next (или n). Точки останова по умолчанию могут перемещаться по строкам, однако они не имеют доступа к псевдонимам и импортам, когда точки останова установлены на скомпилированных модулях.

Задача mix test обеспечивает прямую интеграцию с точками останова через флаг -b/--breakpoints. Когда используется флаг, точка останова устанавливается в начале каждого выполняемого теста:

Вот некоторые команды, которые можно использовать на практике:

# Debug all failed tests
$ iex -S mix test --breakpoints --failed
# Debug the test at the given file:line
$ iex -S mix test -b path/to/file:line

Наблюдатель

Для отладки сложных систем перепрыгивание по коду недостаточно. Необходимо понимать всю виртуальную машину, процессы, приложения, а также настроить механизмы отслеживания. К счастью, это можно сделать в Erlang с помощью :observer. В вашем приложении:

$ iex
iex> :observer.start()

Отсутствующие зависимости

При запуске iex внутри проекта с iex -S mix, observer не будет доступен как зависимость. Для этого необходимо вызвать следующие функции перед запуском:

iex> Mix.ensure_application!(:wx)             # Not necessary on Erlang/OTP 27+
iex> Mix.ensure_application!(:runtime_tools)  # Not necessary on Erlang/OTP 27+
iex> Mix.ensure_application!(:observer)
iex> :observer.start()

Если какой-либо из вызовов выше потерпит неудачу, вот что могло произойти: некоторые менеджеры пакетов по умолчанию устанавливают минимальную версию Erlang без привязок WX для поддержки графического интерфейса. В некоторых менеджерах пакетов вы можете заменить безголовый Erlang более полной версией (ищите пакеты с названиями erlang против erlang-nox на Debian/Ubuntu/Arch). В других менеджерах может потребоваться установка отдельного пакета erlang-wx (или аналогичного названия).

Вышеуказанное откроет другой графический интерфейс, который предоставляет множество окон для полного понимания и навигации по среде выполнения и вашему проекту.

Мы рассматриваем Наблюдатель в контексте реального проекта в главе «Динамический супервайзор» руководства Mix & OTP. Это один из методов отладки, которые использовал фреймворк Phoenix для достижения 2 миллионов подключений на одном компьютере.

Если вы используете веб-фреймворк Phoenix, он поставляется с Phoenix LiveDashboard, веб-панелью для узлов в производстве, которая предоставляет аналогичные возможности Наблюдателю.

Наконец, вы также можете получить краткий обзор информации о среде выполнения, вызвав runtime_info/0 непосредственно в IEx.

Другие инструменты и сообщество

Мы только коснулись того, что может предложить виртуальная машина Erlang, например:

  • Наряду с приложением наблюдателя, Erlang также включает :crashdump_viewer для просмотра дампов сбоев

  • Интеграция с трассировщиками на уровне операционной системы, такими как Linux Trace Toolkit, DTRACE, и SystemTap

  • Микросостояние бухгалтерии измеряет, сколько времени среда выполнения тратит на несколько задач низкого уровня в короткий промежуток времени

  • Mix поставляется со многими задачами в пространстве имён profile, таких как mix profile.cprof и mix profile.fprof

  • Для более сложных случаев мы рекомендуем отличную книгу Erlang in Anger, которая доступна в виде бесплатной электронной книги

Счастливой отладки!

← Предыдущая страница Библиотеки Erlang
Следующая страница → Справочник по Enum

Скачать версию ePub

Создано с помощью ExDoc (v0.36.1) для языка программирования Elixir

© 2012-2024 The Elixir Team
Licensed under the Apache License, Version 2.0.
https://hexdocs.pm/elixir/1.18.1/debugging.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API