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?

1 Like

Yes it is

So that it can be human readable

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

1 Like

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. ^.^

1 Like

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:


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
  # for more information on OTP Applications
  @moduledoc false

  use Application

  def start(_type, _args) do
      [:my_app, :repo, :query],
defmodule MyApp.Telemetry do
  require Logger

  def handle_event([:my_app, :repo, :query], measurements, metadata, _config) do ->
      to_iodata(measurements, metadata)

  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 =, &decode_value/1)

      time("db", query_time, true),
      time("decode", decode_time, false),
      time("queue", queue_time, false),
      inspect(params, charlists: false)

  defp decode_value(value) when is_list(value) do, &decode_value/1)

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

  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]

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.

1 Like