Ecto debug sql in uuid

I am using postgres on ecto
Is that possible that for displaying the uuid field to string on the default debug message?

i.e. <<245, 252, 79, 136, 69, 93, 65, 2, 183, 229, 195, 202, 100, 239, 131, 74>>

Many thanks

SELECT s0."id", s0."description", s0."parent_story_id", s0."position", s0."project_id", s0."stage_id", s0."tags", s0."title", s0."type", s0."created_by", s0."updated_by", s0."created_at", s0."updated_at" FROM "stories" AS s0 WHERE (s0."parent_story_id" = ANY($1)) AND (s0."type" = $2) [[<<245, 252, 79, 136, 69, 93, 65, 2, 183, 229, 195, 202, 100, 239, 131, 74>>], "team_story"]

I’m not really sure what you are asking? A UUID is a binary field of 16 bytes, it is not string representable, although displaying it as HEX with some dashes is pretty common, are you referencing that?

Yes it is

So that it can be human readable

i.e. eee9a6e7-03f6-4e3e-aeff-5f4f2863dfca

Hmm, unsure how postgrex is setup here, but it might not know what it is to be able to do that, it might just see a binary blob… Need someone who knows postgrex internals to answer here. ^.^

I was working on a PR that would help with that but then ecto switched to telemetry logging and I never finished it because it doesn’t really make sense in Ecto anymore. But I had code around Ecto.UUID.cast/1:

iex(12)> Ecto.UUID.cast(<<245, 252, 79, 136, 69, 93, 65, 2, 183, 229, 195, 202, 100, 239, 131, 74>>)
{:ok, "f5fc4f88-455d-4102-b7e5-c3ca64ef834a"}

Here’s the commit if you want to try it out: Log uuid's as readable strings instead of raw binaries · axelson/ecto@58f0fce · GitHub

Thank you for your help

After I turn off the default debug message and set my own telemetry event receiver, it works now.

defmodule MyApp.Application do
  # See https://hexdocs.pm/elixir/Application.html
  # for more information on OTP Applications
  @moduledoc false

  use Application

  def start(_type, _args) do
    :telemetry.attach(
      "my-app-handler",
      [:my_app, :repo, :query],
      &MyApp.Telemetry.handle_event/4,
      %{}
    )
    .
    .
defmodule MyApp.Telemetry do
  require Logger

  def handle_event([:my_app, :repo, :query], measurements, metadata, _config) do
    Logger.info(fn ->
      to_iodata(measurements, metadata)
    end)
  end

  def to_iodata(measurements, metadata) do
    %{
      query_time: query_time,
      decode_time: decode_time,
      queue_time: queue_time
    } = measurements

    %{
      params: params,
      query: query,
      result: result,
      source: source
    } = metadata

    params = Enum.map(params, &decode_value/1)

    [
      "QUERY",
      ?\s,
      ok_error(result),
      ok_source(source),
      time("db", query_time, true),
      time("decode", decode_time, false),
      time("queue", queue_time, false),
      ?\n,
      query,
      ?\s,
      inspect(params, charlists: false)
    ]
  end

  defp decode_value(value) when is_list(value) do
    Enum.map(value, &decode_value/1)
  end

  defp decode_value(binary) when is_binary(binary) do
    case Ecto.UUID.cast(binary) do
      {:ok, uuid} -> uuid
      :error -> binary
    end
  end

  defp decode_value(%Ecto.Query.Tagged{value: value}), do: value

  defp decode_value(value), do: value

  ## Helpers

  defp ok_error({:ok, _}), do: "OK"
  defp ok_error({:error, _}), do: "ERROR"

  defp ok_source(nil), do: ""
  defp ok_source(source), do: " source=#{inspect(source)}"

  defp time(_label, nil, _force), do: []

  defp time(label, time, force) do
    us = System.convert_time_unit(time, :native, :microsecond)
    ms = div(us, 100) / 10

    if force or ms > 0 do
      [?\s, label, ?=, :io_lib_format.fwrite_g(ms), ?m, ?s]
    else
      []
    end
  end
end

And this is the result

SELECT t0."id", t0."completed_at", t0."description", t0."gitlab_project_id", t0."is_completed", t0."mr_id", t0."position", t0."stage_id", t0."story_id", t0."tags", t0."title", t0."created_by", t0."updated_by", t0."created_at", t0."updated_at" FROM "tasks" AS t0 WHERE (t0."story_id" = ANY($1)) [["0738f062-fdbc-45b1-a25f-7955a6496996", "2b15858a-2344-4a58-9066-cfc3a0a00edc"]]

Nice! Thanks for sharing the resulting code! Maybe I’ll try to integrate it into my codebase. Would be nice to have human-readable logs.