# In a pipe chain (doesn't break the chain)
data
|> step_one()
|> IO.inspect(label: "after step_one")
|> step_two()
# Inline
IO.inspect(variable, label: "my var")
# Inspect with options
IO.inspect(big_struct, label: "struct", limit: :infinity, pretty: true)
# At end of pipe: shows every step
data
|> step_one()
|> step_two()
|> dbg()
# Any expression
dbg(some_function(x, y))
dbg(socket.assigns)
dbg shows file:line, the expression text, and the value. The compiler warns about leftover dbg calls.
# Add to code (both parts required)
require IEx; IEx.pry()
# Must start server with IEx:
iex -S mix phx.server
# In the pry session:
variable_name # inspect any local variable
socket.assigns # access nested data
continue # resume execution
respawn # give up and restart the shell
Only works with iex -S mix. Freezes the paused process until you continue.
# Start console with app loaded
iex -S mix
# Start console with Phoenix server
iex -S mix phx.server
# Recompile after editing files (no restart needed)
recompile()
# Database queries
alias Speechwave.{Repo, Talks}
import Ecto.Query
Repo.all(Talks.Talk)
Repo.get_by(Talks.Talk, slug: "my-talk")
# ETS tables
:ets.tab2list(:rate_limiter)
:ets.info(:rate_limiter)
:ets.lookup(:rate_limiter, "session-id")
# Processes
Process.registered() # all named processes
Process.whereis(Speechwave.RateLimiter) # find a specific one
:sys.get_state(Speechwave.RateLimiter) # GenServer internal state
# Application config
Application.get_all_env(:speechwave)
| Need | Tool |
|---|---|
| Quick value check | IO.inspect(val, label: "x") |
| Pipe chain debugging | |> dbg() |
| Explore variables interactively | require IEx; IEx.pry() |
| DB queries / process inspection | iex -S mix |
| ETS / GenServer state | :ets.tab2list/1 / :sys.get_state/1 |
dbg triggers a compiler warning, caught by mix precommit. IO.inspect does not warn, so remove it manually before committing.