sikanhe / apollo-tracing-elixir

Apollo Tracing middleware for Absinthe
114 stars 8 forks source link

Socket example? #20

Open bjunc opened 6 years ago

bjunc commented 6 years ago

Any suggestions on setting up tracing for websocket?

athal7 commented 6 years ago

@bjunc this isn't something that we've figured out quite yet, mainly because existing use cases are push-based, so the resolution has been from a pre-formed data structure. Is your use case around subscriptions as well or are you issuing queries over websockets?

bjunc commented 6 years ago

My use-case is essentially a typical request/response of queries/mutations, but over socket. We use it for server-to-server communication, prior to page load. Our Phoenix GraphQL API is completely headless, and hosted on a different box than the presentation layer (built in Nuxt, which is SSR Vue.js). So when someone makes a page request to the Nuxt app, the Nodejs part of the app connects to the Phoenix app via socket, makes a few requests, renders the HTML, sends that to the browser, and then closes the socket connection. Future API calls from the browser are done via HTTP.

So, we're not using GraphQL for subscriptions / push.

athal7 commented 6 years ago

Got it, so in that case I think you should be able to follow the examples in the README for non-plug-based resolution.

bjunc commented 6 years ago

Are you referring to the custom_absinthe_runner? I'm not really sure how that'd slot in. The only areas we really tweak to allow GraphQL over socket, is in connect/2. For instance:

def connect(%{"token" => token} = _params, socket) do
  case FooApp.Auth.Guardian.decode_and_verify(token) do
    {:ok, claims} ->
      case FooApp.Auth.Guardian.resource_from_claims(claims) do
        {:ok, user} ->
          # Assign current_user to Absinthe socket context for use in resolve
          socket = Absinthe.Phoenix.Socket.put_opts(socket, context: %{current_user: user})
          {:ok, socket}

        {:error, _reason} ->
          :error
      end

    {:error, _reason} ->
      :error
  end
end

Do you maybe have a more complete example / description of how tracing can fit into a socket request/response? Is it something the Absinthe team would need to build into Absinthe.Phoenix.Socket?

athal7 commented 6 years ago

From what I can tell it looks like you can specify a pipeline when you include the Absinthe Phoenix Socket, e.g.

defmodule MyApp.Web.UserSocket do
  use Phoenix.Socket
  use Absinthe.Phoenix.Socket
    schema: MyApp.Web.Schema,
    pipeline: ApolloTracing.Pipeline

  transport :websocket, Phoenix.Transports.WebSocket

  def connect(params, socket) do
    socket = Absinthe.Phoenix.Socket.put_options(socket, [
      context: %{current_user: find_current_user(params)}
    ])
    {:ok, socket}
  end

  def id(_socket), do: nil
end

This doesn't seem to be documented well either on their side or on our side. Let me know if this works for you, and if so, we can add some documentation here.

bjunc commented 6 years ago

Thanks @athal7, I'll take a look and report back.