Setting logger metadata in absinthe middleware

I have an app getting a lot of timeouts while resolving GraphQL queries, and I’m trying to identify the culprit query or queries. My logs don’t have much context right now, so I’m looking to add the current object and field identifiers to the logger metadata.

My best idea so far is to have a middleware put/delete the appropriate metadata. Here’s what I have so far:

defmodule MyAppWeb.GraphQL.Schema do
  use Absinthe.Schema
  alias MyAppWeb.GraphQL.Middleware.LoggerMetadata

  ...

  def middleware(middleware, field, object) do
    Enum.flat_map(middleware, fn
      current_middleware = {{Absinthe.Resolution, :call}, _resolver} ->
        [
          {{LoggerMetadata, :put}, {object.identifier, field.identifier}},
          current_middleware,
          {{LoggerMetadata, :delete}, nil}
        ]

      current_middleware ->
        current_middleware
    end)
  end
end
defmodule MyAppWeb.GraphQL.Middleware.LoggerMetadata do
  @spec put(Absinthe.Resolution.t(), {atom(), atom()}) :: Absinthe.Resolution.t()
  def put(resolution, {object_id, field_id}) do
    Logger.metadata(graphql_object: object_id, graphql_field: field_id)

    resolution
  end

  @spec delete(Absinthe.Resolution.t(), none()) :: Absinthe.Resolution.t()
  def delete(resolution, _) do
    Logger.metadata(graphql_object: nil, graphql_field: nil)

    resolution
  end
end

This works, but the Enum.flat_map/2 solution seems brittle to me: if the behavior of the resolve macro ever changed, this would no longer work.

Is there a better way about this? I’d love to just be able to change the behavior of the resolve macro to return all three middlewares, but I’m assuming that’s not possible (the source code has been hard to follow). I don’t want to create a custom resolve macro; it seems like too much of a chore to enforce its use over the regular resolve macro.

Hey @brettbeatty. This seems like a great time to use Telemetry: https://hexdocs.pm/absinthe/1.5.0-rc.5/telemetry.html#content