Share on Twitter
Share on Facebook
Share on HackerNews
Share on LinkedIn

Improved GraphQL Support in Sentry

Beautiful syntax-highlighted GraphQL errors are coming — get ‘em while they’re fresh! Not that we encourage you to add more errors of any kind to your code. But if you do, they’ll now look so much better in Sentry.

Wait, GraphQL?

At the time of writing, GraphQL has technically been around for more than 10 years. That’s quite some time in software terms, so you might have heard of it. But if you’re anything like me a couple of months ago [1], you could never quite put the finger on what GraphQL actually was. Maybe you’ve heard that it has its own query language. That it was this new shiny thing that would replace REST. That it’d be the definitive tool for building Star Wars APIs [2]. Some of that is true.

The basic idea is that instead of creating different endpoints, each with its own purpose and tied to a specific resource or set of resources, there is only a single /graphql endpoint that you talk to via a special query language. So instead of having to request 2+ endpoints to, say, execute your usual daily task of retrieving Luke’s midi-chlorian count and the color of his first robot, you tell the server to fetch you exactly what you need in one query. All the resolving happens on the server and you get a single response back. This has the advantage of saving your app multiple HTTP request-response round trips and preventing both over and underfetching of resources.

Another difference to your usual REST API is that GraphQL servers typically respond with HTTP status 200 OK even in case of errors, which is one of the reasons why some Sentry SDKs weren’t capturing them using the same mechanism we have in place for web framework errors. It required a solution tailored for GraphQL.

Sentry + GraphQL = <3

That is something Sentry engineers have been working on this year: to bring you better out-of-the-box visibility into your GraphQL codebases across different languages and platforms, like Android, Java, .NET, Python, and others. On the Python side of things, for instance [3], we now support the three most popular GraphQL server libraries (Graphene, Ariadne, and Strawberry — shoutout to the creator Patrick Arminio for helping us port and extend the existing Strawberry Sentry extension) as well as the biggest client library (GQL).

A minimal server example in Python

To demonstrate, let’s set up a small example using the Strawberry GraphQL library.

First, we install everything we need:

pip install sentry-sdk
pip install 'strawberry-graphql[debug-server]'
pip install fastapi
# save as schema.py

import strawberry
import sentry_sdk
from sentry_sdk.integrations.strawberry import StrawberryIntegration

sentry_sdk.init(
    dsn="<YOUR_DSN_GOES_HERE>",
    traces_sample_rate=1.0,
    integrations=[
        StrawberryIntegration(async_execution=True),
    ],
)

async def resolve_hello(root) -> str:
    1 / 0
    return "Hello world!"

@strawberry.type
class Query:
    hello: str = strawberry.field(resolver=resolve_hello)

schema = strawberry.Schema(Query)

Since we’ve explicitly installed a version of Strawberry that comes with a debug server, we can now run:

strawberry server schema

Navigate to http://127.0.0.1:8000/graphql in your browser. You should see the GraphiQL graphical interface, waiting for your input. Type query HelloQuery { hello } into the query input field then press the “Execute query” button. Your web server will be queried, which will result in an exception due to the ZeroDivisionError we’ve snuck into the resolve_hello resolver. You should see the (beautiful, syntax highlighted!) error in Sentry after a few moments: error

Note that by default, the Python SDK will not capture the request and response body to ensure no sensitive data is captured. This behavior can be configured.

But wait, there’s more

If available for your platform/framework/library, Sentry will show you the breadcrumb trail of GraphQL events leading to the event. This will include the different steps in the lifecycle of a query (parsing, validation, resolving, etc.) with varying granularity (platform and library dependent). Here’s an example of the breadcrumbs gathered for a GraphQL subscription error in the Java GraphQL integration: breadcrumbs

Additionally, Sentry will extract the variables used in the query (or mutation or subscription) and include them sanitized: subscription variables

Some integrations come with performance monitoring baked in, allowing you to see what parts of the query execution process take the longest time to complete: graphql spans

Questions? Comments?

We’d love to hear what you think — as always, let us know over at the Sentry Discord. In the meantime, we’ll continue working on improving our GraphQL support on more platforms.

Footnotes

[1] I’ve been a web dev for some time now and I’ve built my share of APIs. Nothing actually properly RESTful, mind you; mostly hand-crafted single-purpose JSON endpoints for very specific use cases. Bonus points if an endpoint was generic enough to be used from two different places! Peak engineering. (I might be exaggerating, but not that much.)

[2] Something we’ve all been waiting for!

[3] Did I mention that I work on Sentry’s Python SDK? You might know me from such smash hits as Update README.md or Fix mypy errors! (As you can tell, I was uniquely qualified to work on this.)

Your code is broken. Let's Fix it.
Get Started

More from the Sentry blog

ChangelogCodecovDashboardsDiscoverDogfooding ChroniclesEcosystemError MonitoringEventsGuest PostsMobileOpen SourcePerformance MonitoringRelease HealthResourceSDK UpdatesSentry
© 2024 • Sentry is a registered Trademark
of Functional Software, Inc.