Monitoring Absinthe/GraphQL with PryIn

With the default installation, PryIn monitors your regular Phoenix controllers and channels.

If you are using Absinthe for GraphQL, you’re likely integrating it into your Phoenix application with the absinthe_plug library.

In this case, no metrics about your GraphQL queries and mutations will appear in PryIn by default, as they are not piped through a regular controller.

This is easily fixed with Custom Traces, though.

We simply create a small Plug:

defmodule MyApp.AbsinthePryInPlug do
  @behaviour Plug

  def init(opts), do: opts

  def call(conn = %{params: %{"operationName" => operation_name}}, _) do
    PryIn.CustomTrace.start(group: "Absinthe", key: operation_name)

    Plug.Conn.register_before_send(conn, fn conn ->
  def call(conn, _), do: conn

And add it to the router pipeline of the Absinthe Plug:

pipeline :graphql do
  plug MyApp.AbsinthePryInPlug

With those changes, your GraphQL queries and mutations will appear under the “Absinthe” custom trace group: Absinthe traces inside PryIn

Zooming into the “allProjects” query you get a graph showing the average and percentile execution time of all “allProject” requests and a list of those: Absinthe traces for the allProjects Query inside PryIn

After clicking on one of the traces in the table, you get a detailed breakdown of that request, including all database queries: Absinthe traces for the allProjects Query inside PryIn

One thing to note here: We’re using the operationName as key for the Custom Traces. This allows getting and comparing aggregate data for single operations, as you can see in the second screenshot:

“Did my allProjects query get slower on average compared to last week?” “What is the 95% percentile of all my newUser mutations?”

It also means that you need to set that in your queries. Queries and mutations with empty or missing operationName won’t end up on PryIn. But it’s a good idea to include an operation name anyway, so that was fine in our case.