An alternative logger for Ecto queries.
It inlines bindings into the query, so it is easy to copy-paste logged SQL and run it in any IDE for debugging without manual transformation of common elixir terms to string representation (binary UUID, DateTime, Decimal, json, etc). Also, it highlights db time to make slow queries noticeable. Source table and inlined bindings are highlighted as well.
The package can be installed by adding ecto_dev_logger
to your list of dependencies in mix.exs
:
def deps do
[
{:ecto_dev_logger, "~> 0.14"}
]
end
Then disable default logger for your repo in config file for dev mode:
if config_env() == :dev do
config :my_app, MyApp.Repo, log: false
end
And install telemetry handler in MyApp.Application
:
Ecto.DevLogger.install(MyApp.Repo)
Telemetry handler will be installed only if log
configuration value is set to false
.
That's it.
The docs can be found at https://hexdocs.pm/ecto_dev_logger.
If you turn off repo logging for any reason in production, you can configure ecto_dev_logger
to only be available
in development. In your mix.exs
, restrict the installation to :dev
:
def deps do
[
{:ecto_dev_logger, "~> 0.10", only: :dev}
]
end
In MyApp.Application
, an additional function is required:
defmodule MyApp.Application do
@moduledoc "..."
def start(_type, _args) do
maybe_install_ecto_dev_logger()
# ...
end
if Code.ensure_loaded?(Ecto.DevLogger) do
defp maybe_install_ecto_dev_logger, do: Ecto.DevLogger.install(MyApp.Repo)
else
defp maybe_install_ecto_dev_logger, do: :ok
end
# ...
end
It is possible to format queries using a :before_inline_callback
option.
Here is an example of setup using pgFormatter as an external utility:
defmodule MyApp.Application do
def start(_type, _args) do
Ecto.DevLogger.install(MyApp.Repo, before_inline_callback: &__MODULE__.format_sql_query/1)
end
def format_sql_query(query) do
case System.shell("echo $SQL_QUERY | pg_format -", env: [{"SQL_QUERY", query}], stderr_to_stdout: true) do
{formatted_query, 0} -> String.trim_trailing(formatted_query)
_ -> query
end
end
end
You need to run a local postgres server for the tests to interact with. This is one way to do it:
~$ docker run -p5432:5432 --rm --name ecto_dev_logger_postgres -e POSTGRES_PASSWORD=postgres -d postgres