Comparing REST and GraphQL Monitoring Techniques

Maintaining an endpoint, especially a customer-facing one, requires constant log monitoring, whether using REST or GraphQL. As the industry has looked for solutions to build a more adaptive endpoint technology, it is also a must to monitor these endpoints. GraphQL and REST are two different technologies that allow user-facing clients to link to databases and platform logic. Both GraphQL and REST include monitoring techniques. Here, we will compare enterprise monitoring an endpoint using AWS API Gateway backed by a REST or GraphQL.

REST and GraphQL Monitoring Architecture

The architecture of a GraphQL versus a REST endpoint is fundamentally different. The architecture gives different locations available for monitoring your solution. Both RESTful and GraphQL systems are stateless, meaning the server and client do not need to know what state the other is in for interactions. Both RESTful and GraphQL systems also separate the client from the server. Either architecture can modify the server or client without affecting operations of the other as long as the format of the requests on the endpoint(s) remain consistent.  

GraphQL Monitoring and Server Architecture

GraphQL uses a single endpoint and allows users to select what portion of the available returned data is required, making it more flexible for developers to integrate and update. GraphQL endpoints include these components:

  1. A single HTTP endpoint
  2. A schema that defines data types
  3. An engine that uses the schema to route inputs to resolvers
  4. Resolvers process the inputs and interact with resources. 

Developers can place GraphQL Monitoring in any of several locations. Monitoring the HTTP endpoint itself will reveal all the traffic hitting the GraphQL server. Developers can monitor the GraphQL server where the server routes data from the endpoint to a specific resolver. Each resolver, query or mutation, can have monitoring implemented.  

REST Monitoring and Server Architecture

RESTful architecture is similar in components to GraphQL but requires a very different and more strict setup. REST is a paradigm for how to set up an endpoint following some relatively strict rules. Many endpoints exist claiming to be REST, but they do not precisely follow these rules. Endpoints that do not conform to the rules are better defined as HTTP APIs. REST is robust but inflexible in its capabilities since each endpoint requires its own design and building. It is up to the developers to design their endpoints as needed, but many believe only endpoints following these rules should be labeled as REST.

Designing a RESTful API includes defining the resources that will be made accessible using HTTP, identifying all resources with URLs (or resources), and mapping CRUD operations to standard HTTP methods. CRUD operations (create, retrieve, update, delete) are mapped to POST, GET, PUT, and DELETE methods, respectively.

Each RESTful URL expects to receive specific inputs and will return results based on those inputs. Inputs and outputs of each resource are set and known by both client and server to interact. 

Monitoring on RESTful APIs has some similarities to GraphQL. Developers can set up monitoring on the API endpoints directly. Monitoring may be averaged across all endpoints with the same base URL or broken up for each specific resource. When developers use compute functions between the database and the endpoint, developers can monitor these functions as well. If using AWS monitoring, it is common to use Lambda to power API endpoints. 

REST and GraphQL Error Monitoring

REST Error Format

RESTful APIs use well-defined HTTP status codes to signify errors. When a client makes a request, the server notifies the client if the request was successfully handled. A status code is returned with all request results, signifying what kind of error has occurred or what server response the client should expect. HTTP includes a few categories of status codes. These include 200 level (success), 400 level (client errors), and 500 level (server errors).

Errors can be caught in several places and monitored for RESTful endpoints. The API itself may be able to monitor the status codes and provide metrics for which codes are returned and how often. Logs from computing functions behind the endpoint can also be used to help troubleshoot error codes. Logs can be sent to third-party tools like Coralogix’s log analytics platform to help alert developers of systemic issues.

GraphQL Error Format

GraphQL monitoring looks at server responses to determine if an issue has arisen. Errors returned are categorized based on the error source. GraphQL’s model combines errors with data. So, when the server cannot retrieve some data, the server will return all available data and append an error when appropriate. The return format for GraphQL resolvers is shown below:

The Apollo server library allows developers to use internally generated syntax and validation errors that are applied automatically. Developers can also define custom error logic in resolvers so errors can be handled gracefully by the client.

A typical HTTP error can still be seen when there is an error in the API endpoint in front of a GraphQL server. For example, if the client was not authorized to interact with the GraphQL server, a 401 error is returned in the HTTP format. 

Monitoring errors in a GraphQL endpoint is more complex than Restful APIs. The status codes returned tend towards success (200) since any data that is found is returned. Error messages are secondary if only parts of the data needed are missing. Errors could instead be logged in the compute function behind the GraphQL server. If this is the case, CloudWatch log analytics would be helpful to track the errors. Custom metrics can be configured to differentiate errors. Developers can use third-party tools like Coralogix’s log analytics platform to analyze GraphQL logs and automatically find the causes of errors.

AWS API Gateway Monitoring

Developers could use many tools to host a cloud server. AWS, Azure, and many third-party companies accommodate API management tools that accommodate either RESTful or GraphQL architecture. Amazon’s API Gateway tool allows developers to build, manage, and maintain their endpoints.

API Gateway is backed by AWS’s monitoring tools, including but not limited to CloudWatch CloudTrail, and Kinesis. 

GraphQL Monitoring using CloudWatch API integration

The API Gateway Dashboard page includes some high-level graphs. These all allow developers to check how their APIs are currently functioning. Graphs include the number of API calls over time, both latency and integration latency over time, and different returned errors (both 4xx and 5xx errors over time). While these graphs are helpful to see the overall health of an endpoint, they do little else to help determine the actual issue and fix it. 

In CloudWatch, users can get a more clear picture of which APIs are failing using CloudWatch metrics. The same graphs in the API Dashboard shown above are available for each method (GET, POST, PUT, etc.) and each endpoint resource. Developers can use these metrics to understand which APIs are causing issues, so troubleshooting and optimization can be focussed on specific APIs. Metrics may be sent to other systems like Coralogix’s scalable metrics platform for alerting and analysis.

Since RESTful endpoints have different resources defined for each unique need, these separate graphs help find where problems are in the server. For example, if a single endpoint has high latency, it would bring up the average latency for the entire API. That endpoint can be isolated using the resource-specific graphs and fixed after checking other logs. With GraphQL endpoints, these resource-specific graphs are less valuable since GraphQL uses a single endpoint to access all endpoint data. So, while the graphs show an increased latency, users cannot know which resolvers are to blame for the problem.

Differences in Endpoint Traffic Monitoring

GraphQL and REST use fundamentally different techniques to get data for a client. Differences in how traffic is routed and handled highlight differences in how monitoring can be applied. 

Caching

Caching data allows for reducing the traffic requirements of your endpoint. The HTTP specification used by RESTful APIs has caching requirements. Different endpoints can set up caching based on which path semantics are used. Servers can cache GET requests according to HTTP. However, since GraphQL uses a single POST endpoint, these defined specifications do not apply to GraphQL. It is up to developers to implement caching for non-mutable (query) endpoints. It is also critical that developers implement their requirements to separate mutable (mutation) and non-mutable (query) functions on their GraphQL server. 

Resource Fetching 

REST APIs typically require data chaining to get a complete data set. Clients first retrieve data about a user, then can retrieve other vital data subsequently using different calls. By design, REST endpoints are generally split to get data separately and point to different, single resources or databases. GraphQL, on the other hand, was designed to have a single endpoint that can point at many resources. So, clients can retrieve more data with a single query. GraphQL endpoints tend to require less traffic. This fundamental difference emphasizes the importance of traffic monitoring on REST endpoints over that need in GraphQL servers.

Summary

GraphQL uses a single HTTP endpoint for all functions and allows different requests to route to the appropriate location in the GraphQL server. Monitoring these endpoints can be more difficult since only a single endpoint is used. Log analytics plays a vital role in troubleshooting GraphQL endpoints because GraphQL monitoring is a uniquely tricky challenge.

RESTful endpoints use HTTP endpoints for each available request. Each request will return an appropriate status code and message based on whether the request was successful or not. Status codes can be used to monitor the health of the system and logs used to troubleshoot when functionality is not as expected. 

Third-party metrics tools can be used to monitor and alert on RESTful endpoints using status codes. Log analytics tools will help developers isolate and repair issues in both GraphQL and RESTful endpoints. 

A GraphQL Introduction: Benefits and Tips for Using This API Technology

GraphQL is an open-source query and manipulation language to use for APIs. It contains server-side functionality and a query language for maintaining data interfaces. It was first created in 2012 by Facebook and publicly released in 2015. Since 2018, the GraphQL project has been hosted by the Linux Foundation and run by the GraphQL Foundation.

In this GraphQL introduction, we will discuss what is unique about GraphQL APIs, show how to set up a simple schema and resolvers, and introduce some tools that will be useful as you develop your own API.

What is Different About GraphQL?

There are critical aspects to GraphQL that make it unique from other web services. GraphQL allows users to build APIs with a single HTTP endpoint that fetches and alters data from multiple backend data sources. The format of the query is directly related to the structure of the returned data.

This connection between the request format and returned data allows the client to control the GraphQL API returned data. Since your API defines the data formats in the GraphQL schema, the API can be made self-documenting and may relate directly to data stored in multiple sources if needed.

While using GraphQL, there is no requirement for using a specific database configuration. Instead, GraphQL uses code to interface with whichever data structure you want to support. GraphQL bases its framework on the definition of types that are user-constructed to meet the data requirements. The types define what is sent from the server-side environment to the web (or other) service. The service defines what data it wants to receive based on the type definition.

Setting up a Schema: GraphQL Data Models

The GraphQL language uses definitions of so-called schemas to set up its API model. It uses an object-like notation called the GraphQL schema language, which defines what data is available in queries and mutations. Schemas allow users to define basic object types that describe the information sent to and received from the GraphQL interface.

Schema Creation Tips and Examples

In each case, a field may be made required or optional. Setting a field as optional allows flexibility to limit the amount of data used in the interface to only what is needed. A call to the same mutation or query may occur in multiple ways, with different pieces of the result being requested and returned. Also, developers may change schemas without releasing a new version of the API, a significant difference from classic REST APIs.

Let’s walk through a simple example to show how the description above might work.

We may have a set of queries and mutations that show a listing of bands and their works. Below is a simple example of a schema that could convey this information. The server-side function defines the schema containing all the fields available to the client.

There are some essential subtitles in this example to note:

  • You can define a strict object that the API will return. In this case, Music is the intended returned data model.
  • Use an exclamation mark (!) to define any required data. In the example below the client must request bandName when the client requests Music to be returned, and the backend code must provide a non-null value for it.
  • GraphQL includes scalar types out of the box, including Int, Float, String, Boolean, and ID. Depending on the implementation of GraphQL, you may be able to define custom scalar types like Date.
  • You can extend the schema with new root fields or object types like Album, used inside the Music return data.
  • You can specify that a field holds an array of objects in the response. In this example, the albums definition in Music or the members definition in Album are both defined as arrays.
  • You can define enumerations to restrict what values of a parameter are allowed, such as Genre.
const typeDefs = `

    type Music {

        bandName: String!

        numberOfAlbums: Int

        albums: [Album]

    }




    type Album {

        albumName: String!

        members: [Musician]

        genre: Genre

    }




    type Musician {

        firstName: String!

        lastName: String!

    }




    enum Genre {

        classicRock

        country

        jazz

        pop

        punk

    }

`

Defining Resolvers: Functions Behind the GraphQL Server

In GraphQL, resolvers are either a query that returns specific data objects to the client or a mutation that changes the data on the backend somehow. Queries and mutations have similar structures but should be separated logically.

Components and Formats of Queries and Mutations

Fields are attributes that the client may request from the backend. The client can expect to receive data in the same format in which it requests it. The following example shows the client requesting Music information. The query itself only requests some of the available data (omitting the available albums field). 

{

  music {

    bandName

    numberOfAlbums

  }

Here are the results of that request: 

{

  "data": {

    "music": [

      {

        "bandName": "The Beatles",

        "numberOfAlbums": 12

      },

      {

        "bandName": "U2",

        "numberOfAlbums": 14

      }

    ]

  }

}

The results include only fields that were requested and are in the format of the request. If some data was not available and the field is not required, the GraphQL service automatically sets that returned data to null.

Resolvers also allow for definitions of arguments. In GraphQL, users can define input arguments for the resolver in the schema with a new type called input, or each field may also be sent with an argument.

In the example below, an input is defined and used in the getBandDetails query. This input allows the client to request a specific band or even request details for all bands that put out a certain number of albums. The response will be an array of band details formatted as type Music defined in the first example above.

Setting inputs in this way allows us to use the same query filtering on different input details. If you want to require an input, add an ! after a field in the input. Doing this will cause GraphQL to throw an error if that value is missing from the input.

const typeDefs = `

    input getBand {

        bandName: String

        numberOfAlbums: Int

    }




    type Query {

        music(getBand): [Music]

    }

`

Schema Stitching for More Complex APIs

Once the schema is defined, you can code in the logic of the resolvers. Schema stitching allows you to add many resolvers and develop them as microservices. This is not a requirement to use GraphQL, but if you will be doing anything more than 2 or 3 resolvers, you will want to consider splitting it up logically for easy maintainability of code.

If you are using Javascript, a library called graphql-tools can be used to combine the separately coded resolvers into a central schema file to use in your GraphQL API. 

Languages

GraphQL is available in many different programming languages. These include JavaScript, Python, Flutter, C/C++, and Swift. Some of the support for the less-popular languages is not ideal. For example, the library for the C/C++ GraphQL parser was last updated in October 2017. However, popular languages like JavaScript and Python are updated much more frequently.

For a complete list of language support, see the GraphQL code page.

Apollo

Apollo is an open-source library built to support GraphQL clients and servers. It also includes tools to support your graphical interface. There may be a charge included depending on how you want to collaborate with your team using Apollo. However, you can easily use the open-source frameworks available to build your APIs.

Apollo Client

The Apollo Client is a state management library for JavaScript that allows users to manage data from GraphQL. Apollo will allow web services to get, cache, and modify server-side data with GraphQL with limited web service setup. The client is available for React, iOS, or Android.

Apollo Server

The Apollo server is a community-maintained library for the GraphQL server which runs on any Node.js HTTP server framework. It can be used as a stand-alone GraphQL server (including serverless), as an add-on to Node.js middleware (like Express), or as a gateway for a federated data graph.

The Apollo server code is used to link your backend data sources with the HTTP interface. It allows users to define GraphQL schema and create mutations and queries which are used by GraphQL. Integrations that would use the Apollo server include Express, Amazon Lambda, Azure Functions, and more.

Typically integrations will have their own Apollo libraries for installation. For example, you can use the apollo-server-lambda npm package when you want to run the GraphQL server on a Lambda function.

Support Tools

Automatic Documentation

Since GraphQL is based on a schema, documentation can be generated by simply pointing a tool at your HTTP Endpoint. Many tools have been built that allow for automatic documentation. The following is a shortlist of currently-maintained options.

GraphiQL

GraphiQL is a GUI allowing users to edit and test their resolvers as well as being an interface to auto-generated documentation. It will show you all possible queries, mutations, and types. It also remains updated as you change your code so you always have the latest version displayed.

DocQL

DocQL is in an open beta testing phase and beta testers will get discounted prices for ongoing use. This service will monitor your API in real-time and update documentation according to the available schema. 

graphdoc

graphDoc is an open-source library that will generate a static page for documenting your GraphQL schema.

Postman and Insomnia: API Endpoint Testing Tools

When you are testing your backend software, you can use Postman to test your resolvers before having a client web service or app ready. Postman includes a GraphQL type in its available Body options. Using a POST, set the URL to either the deployed API Gateway or a local host running your GraphQL schema. Set the query to appear as the Fields example.

If you use a mutation instead, you must include the keyword mutation in the resolver input as shown below. The result should be an object matching the request input.

postman testing resolvers

Insomnia is another tool that you can use to test your GraphQL endpoint. It has more-or-less the same features as Postman making it a good alternative. That said, if you are going to put custom authorization into your HTTP endpoint, Insomnia is not able to handle the setup requirements as easily as Postman. It does have a rich interface and is very simple to use, allowing users to create workspaces and share files and projects with other developers very easily.

Summary

In this GraphQL introduction, we’ve seen how GraphQL is a powerful API language and framework that allows developers to define exactly what data is available. It enables developers to get around some of the common headaches associated with REST APIs like maintaining multiple endpoints and keeping previous versions alive after revisions.

This GraphQL introduction showed the simplicity of the code needed to set up your first GraphQL API and introduced some tools to help you develop and debug the code as you go.