firefox-devtools / ux

Firefox DevTools UX Community
Mozilla Public License 2.0
103 stars 21 forks source link

See GraphQL operationName in Network tab list #112

Open peteruithoven opened 4 years ago

peteruithoven commented 4 years ago

Currently when working with GraphQL all the request look the same and there are no columns I could add to help me differentiate them. Screenshot from 2020-02-13 17-15-27@2x

Ideally I can see the Operation name that can be defined per GraphQL request:

Operation name: For debugging and server-side logging reasons, it’s useful to give your queries meaningful names. That way, when you see something wrong going on either in your network logs or your GraphQL server (for example in a tool like Apollo Optics), you can easily find that query in your codebase by name instead of trying to decipher the contents. Think of it like a function name in your favorite programming language.

From: https://blog.apollographql.com/the-anatomy-of-a-graphql-query-6dffa9e9e747

This usually is added to a request as is a property of json params: Screenshot from 2020-02-13 17-23-55@2x

There are GraphQL specific tools, but ideally this information can be seen where I also see other network communication related information.

violasong commented 4 years ago

Hi! CCing @janodvarko to weigh in on this :)

janodvarko commented 4 years ago

@peteruithoven can you please point me to a page I could load on my machine and see live how the GraphQL HTTP requests look like in the Network panel? (to see what you see)

Honza

peteruithoven commented 4 years ago

Yes! :) One of the great examples is probably the github Graphql explorer. Just login and press the execute (play icon) button. https://developer.github.com/v4/explorer/

Some simple query examples:

query repositories {
  viewer {
    repositories (last:5) {
      nodes {
        name
        createdAt
      }
    }
  }
}
query gists {
  viewer {
    gists(last:5){
      nodes {
        name
        createdAt
        url
      }
    }
  }
}

Another fun example: https://launchpad-star-wars.glitch.me/ With an operationName:

query heroAndFriends{
  hero(episode:JEDI) {
    name
    appearsIn
    friends {
      name
    }
  }
}

Short GraphQL intro's: https://hackernoon.com/3-minute-introduction-to-graphql-2c4e28ed528 https://medium.com/@chathuranga94/introduction-to-graphql-3e0142879aba

General GraphQL tutorial: https://www.howtographql.com/

janodvarko commented 4 years ago

Thanks!

So the operationName is added into the POST (JSON) data as a field:

Example:

{
  "query": "<the-query-string>",
  "variables": null,
  "operationName": "repositories"
}

Is there any other way how to pass the operationName to the server (e.g. through a URL query param?)

So, we could potentially introduce a new custom column that is showing a field from POST data. Either form data fields or from JSON structure if the request payload (POST data) is JSON.

Something similar what we have for Response headers

image

But, not sure how the UI would look like. How the user would specify what exact field should be rendered in that column.

@digitarald @bomsy @fvsch WDYT?

Honza

peteruithoven commented 4 years ago

Is there any other way how to pass the operationName to the server (e.g. through a URL query param?)

This is tricky because most users will be using existing libraries like the Apollo client which handles this part. (GraphQL requests in general are a bit more "formalized" / "standardized" than other REST requests)

janodvarko commented 4 years ago

This is tricky because most users will be using existing libraries like the Apollo client which handles this part. (GraphQL requests in general are a bit more "formalized" / "standardized" than other REST requests)

So, if I understand correctly, it's usually (or only?) sent through the request payload (POST data) as JSON? The Apollo client does that? (I can't load the link you provided)

peteruithoven commented 4 years ago

So, if I understand correctly, it's usually (or only?) sent through the request payload (POST data) as JSON?

Yes this is definitely the most common approach.

Exceptions are optimizations that are Apollo specific, which as far as I understand it expand on the GraphQL specification. For example by sending multiple queries in a batched request or sending queries as a get request. More info: https://www.apollographql.com/docs/apollo-server/v1/requests/

The Apollo client does that? (I can't load the link you provided)

Yes you mostly give those queries like I shared earlier to that client and the Apollo client will send out the right requests. (It won't if the data is available in it's cache) I corrected the link.

fvsch commented 4 years ago

If we want to hardcode basic GraphQL support in Netmonitor, I'm seeing a couple options:

  1. Create an optional (off by default) "GraphQL" column that can be toggled on and would show some basic info from the query.
  2. Maybe create a "GraphQL" tab for the details view, that would appear only on relevant requests, like we do for the "Messages" (websockets) tab?

One issue with (1) is that it doesn't help discoverability. Ideally developpers debugging a page using GraphQL should see some info directly without having to know that DevTools can do more for them if they right-click the headers and activate some setting.

We could perhaps overload the "File" column to show GraphQL info. Currently it will show:

graphql

and we could show:

graphql [operationName]

Would that be helpful?

Note that the /graphql endpoint is a convention and not per-spec.

fvsch commented 4 years ago

A GraphQL tab could show an accordion with a few sections:

  1. Variables (an object, parsed from JSON)
  2. The query (a string, prettified if possible)
  3. The resulting data
  4. Errors maybe?

(Not sure about the order.)

But maybe that's not super useful when we already have the Params and Response tabs, and there are extensions like Apollo DevTools around too.

peteruithoven commented 4 years ago

A GraphQL specific tab wouldn't add that much I think.

But I love the graphql [operationName] idea because that doesn't require checking the available columns. But (also) having it as a dedicated column makes sense I think.

Both would also enable expansion towards the future in how you determine the operation name. You could for example later on add support for those GET requests.

digitarald commented 4 years ago

Thank you @peteruithoven for all the details. I have seen GraphQL come up as a pain point. Maybe @wesbos has ideas here as well.

Seems like there are 2 main problems:

1. How to extract & display the query data from the POST params

🐞 Bug 1618732

Probably similar to how we treat messages in WebSocket inspector.

2. Show the operationName as column

Create an optional (off by default) "GraphQL" column that can be toggled on and would show some basic info from the query.

I feel like that what has to happen, or it would somehow get dropped into an existing column (path?). Maybe the UI can be shown heuristics-based.

Related:

Chrome has a column + UI that allows showing headers in columns, and users can add their own headers. Custom params might be solved a similar fashion (cc @violasong):

image image

Related idea: Sidepanel extension API to provide GraphQL details

@fvsch list of things that we could show for a request, similar to how GraphQL/Apollo extensions break down the data.

digitarald commented 4 years ago

So far I filed Bug 1618733 - [meta] Improve GraphQL support in DevTools to track the work for Bug 1618732 - Format GraphQL requests for operationName/query/variables.

janodvarko commented 4 years ago

Chrome has a column + UI that allows showing headers in columns, and users can add their own headers.

I like the idea to use similar UI for adding a custom column that would show data from any part of an HTTP request (response body, request body, query string, etc.). We could have just one UI that allows to specify the data source (request, response, etc.) as well as the data point within the source (e.g. operationName within request body).

We could use the HAR format to specify the entire data path. (e.g. log/entries/request/postData/params/operationName)

This could help to debug any REST based service.

Honza

digitarald commented 4 years ago

We could use the HAR format to specify the entire data path. (e.g. log/entries/request/postData/params/operationName)

Even when the operationName is in a JSON object in the params payload?

janodvarko commented 4 years ago

Even when the operationName is in a JSON object in the params payload?

Yes. What I have in mind is to use HAR path to specify the data source (e.g. params) and additional path to specify data point in the source.

Perhaps my example could improved:

Instead of log/entries/request/postData/params/operationName It could be log/entries/request/postData/params#operationName (to be more like real URL)

Honza