At New Relic, we want to help you build code fast. We want to help you build observability into your workflows and processes. And we want to help you automate manual toil so you can focus on delivering value to your customers. So while we’ve been using GraphQL internally for a number of years, we’re now rolling out support for GraphQL—a strongly typed query language that lets a client fetch the data it needs from a service—across our portfolio, beginning with account data, New Relic Infrastructure, and the New Relic Query Language (NRQL).

More specifically, in New Relic, you can use the GraphQL API to:

In this post, I’ll walk through two examples using the GraphQL API to query information about New Relic Infrastructure cloud integrations—specifically those from Amazon Web Services (AWS)—and update their configuration values. But first a bit of history.

How we learned to love GraphQL

A few years ago, as New Relic faced an expanding technology landscape, an expanding product portfolio, and an expanding code base, our development teams realized the need to rethink our approach to APIs. We needed a solution that provides simplified authorization and a common API layer that we could rapidly iterate on as we build new capabilities within our platform.

That’s when we started using GraphQL. Originally created by developers at Facebook, and now an open-source project maintained by the GraphQL Foundation, GraphQL is being used in production at companies that operate at massive scale, such as Airbnb, Netflix, and The New York Times. Unlike typical REST APIs that often require loading from multiple endpoints, GraphQL provides a single endpoint that can manage complex queries so you can get the data your app needs from many services all in one request.

Using GraphQL in New Relic

GraphQL is strongly typed, which allows developers to explicitly declare what information is available via queries to the GraphQL service. This declaration is done via a GraphQL schema. Schemas give developers the flexibility they need to express information about the data they return. For example, each field has a description, which developers can use to indicate the proper usage of the data.

Schemas also provide the API blueprint developers need to build tools for properly constructing queries and guiding proper usage of any returned data. For example, developers can use the schema to indicate if a field has been deprecated so tools like IDEs can surface this fact and discourage use of that data.

And “schema stitching”—creating a single schema from several underlying GraphQL APIs—allows developers to deliver a unified access experience across all of their APIs, as we’ve done at New Relic:

The New Relic GraphQL implementation includes several underlying GraphQL APIs—including accounts, Infrastructure, and the New Relic database (for constructing NRQL queries).

For more information on GraphQL, the following examples of querying cloud integration configuration data use GraphQL queries and mutations:

  • Queries: GraphQL requests that only fetch data
  • Mutations: GraphQL requests that modify and fetch data

The New Relic GraphQL API has a single endpoint: https://api.newrelic.com/graphiql. This launches (after authenticating the user) the GraphiQL interface—an interactive, browser-based IDE for running GraphQL requests.

In GraphiQL, you build and run your query on the left, and the result is returned on the right.

You can click into fields to drill into their definitions. For example, if you drill into actor, you’ll see it contains fields for user and accounts:

{
  actor {
   user {
    name
    email
    }
   accounts {
    id
    name
   }
  }
}

The fields under actor expose data from different downstream services that are unified in the GrahQL schema delivered by the GraphQL server. When you issue a query, the GraphQL server pulls apart the query and invokes a resolver for each of the services. When the queries complete (or time out or encounter errors), the GraphQL server assembles the result and returns it to you. In the example above, we get information about the user and all the accounts that they have access to.

Unlike Typical REST APIs that often require loading from multiple endpoints, GraphQL provides a single endpoint that can manage complex queries so you can get all the data your app needs from many services in one request.

Tip: For complete query syntax, see the GraphQL queries documentation.

Let’s walk through our examples to show the full power of GraphQL’s data collection capabilities.

Example 1: Querying Infrastructure cloud integrations with GraphiQL

In my first example, I’ll use GraphiQL to query for various data about the AWS integrations that are running in my New Relic account. I’ll use the data I gather in this example to update some specific settings in the next section.

Tip: If you’re planning on following along, make sure you generate an API key that you can use with New Relic’s GraphQL API. In fact, you can generate one directly from GraphiQL.

Let’s start with a list of the AWS integrations I have available in New Relic Infrastructure:

AWS integrations installed in New Relic Infrastructure.

AWS integrations installed in New Relic Infrastructure.

Next, let’s retrieve some information about these AWS services via a GraphQL query. I’m going to query for the cloud provider (in this case, AWS) that’s linked to my account and the set of integrations from AWS that I’ve installed. To do this, I need to pass the ID of the account I want to query—this is the account(id: MY ACCOUNT ID) part of the query.

Notice that I’m “nesting” requests to get information about the cloud provider and the integrations I’m using. If I were using a REST API, this would require multiple calls, but with the GraphQL API, I can gather this information with just one query.

 

{
  actor {
    account(id: MY ACCOUNT ID) {
      cloud {
        linkedAccounts {
          id
          externalId
          name
          authLabel
          provider {
            id
            name
            slug
          }
          integrations {
            id
            name
            service {
              id
              slug
              name
              createdAt
              updatedAt
              provider {
                name
                id
              }
            }
          }
        }
      }
    }
  }
}

When the query completes, the GraphQL server assembles the results about the AWS integrations I’ve installed, as shown below (note that I’ve truncated the example):

{
  "data": {
    "actor": {
      "account": {
        "cloud": {
          "linkedAccounts": [
            {
              "authLabel": "arn:aws:iam::8xxxxxxx7:role/NewRelicInfrastructure-Integrations-Origami",
              "externalId": "8xxxxxxx7",
              "id": 3542,
              "integrations": [
                {
                  "id": 75540,
                  "name": "RDS",
                  "service": {
                    "createdAt": 1470991744,
                    "id": 3,
                    "name": "RDS",
                    "provider": {
                      "id": 1,
                      "name": "Amazon Web Services"
                 },
                  "slug": "rds",
                  "updatedAt": 1534242454
                }
               },
                             {
                  "id": 14233,
                  "name": "S3",
                  "service": {
                    "createdAt": 1470991745,
                    "id": 4,
                    "name": "S3",
                    "provider": {
                       "id": 1,
                       "name": "Amazon Web Services"
                    },
                    "slug": "s3",
                    "updatedAt": 1534242454
                }
               },
                             {
                  "id": 12223,
                  "name": "Lambda",
                  "service": {
                    "createdAt": 1477910055,
                    "id": 14,
                    "name": "Lambda",
                    "provider": {
                      "id": 1,
                      "name": "Amazon Web Services"
                    },
                    "slug": "lambda",
                    "updatedAt": 1534242454
                  }
                 },
                              {
                  "id": 172534,
                  "name": "DynamoDB",
                  "service": {
                    "createdAt": 1470991758,
                    "id": 13,
                    "name": "DynamoDB",
                    "provider": {
                      "id": 1,
                      "name": "Amazon Web Services"
                    },
                    "slug": "dynamodb",
                    "updatedAt": 1534242454
                  }
                },

             }
           }
         ]
        }
      }
    }
  }
}

But what if I want more specific information about one of the integrations? Specifically, I want to see what tags (user-defined metadata) I’ve applied to a particular integration as well as its metrics polling interval (how often New Relic polls the integration for data), and when these settings were last updated.

To do this, I’ll need to use one of the more nuanced features of GraphQL—interfaces, an abstract type that represents a collection of common fields that other object types can implement.

So in my original query, I’ll add two new clauses:

... on CloudDynamodbIntegration{
  metricsPollingInterval
  tagKey
  tagValue
  updatedAt
}
... on CloudRedshiftIntegration{
  metricsPollingInterval
  tagKey
  tagValue
  updatedAt
}

Now, if my query hits a result that is of type CloudDynamodbIntegration or CloudReshiftIntegration, it also return the fields metricsPollingInterval, tagKey, tagValue, and updatedAt.

Here’s what my (truncated) query will like now:

{
  actor {
    account(id: MY ACCOUNT ID) {
      cloud {
        linkedAccounts {
          id
          externalId
          name
          authLabel
          provider {
             ...
          }
          integrations {
             id
             name
             service {

             ...

                }
             }
             ... on CloudDynamodbIntegration{
               metricsPollingInterval
               tagKey
               tagValue
               updatedAt
             }
             ... on CloudRedshiftIntegration{
               metricsPollingInterval
               tagKey
               tagValue
               updatedAt
             }
           }
         }
       }
     }
   }
 }

In the result, notice that the DynamoDb and Redshift configuration information contain the extra fields that I specified in the query using their interfaces.

   {
               "id": 173397,
               "metricsPollingInterval": 900,
               "name": "Redshift",
               "service": {
                 "createdAt": 1497364366,
                 "id": 21,
                 "name": "Redshift",
                 "provider": {
                   "id": 1,
                   "name": "Amazon Web Services"
               },
               "slug": "redshift",
               "updatedAt": 1534242454
             },
            "tagKey": "mdw-test",
            "tagValue": null,
            "updatedAt": 1544435410
          },
          {
            "id": 112183,
            "metricsPollingInterval": 900,
            "name": "DynamoDB",
            "service": {
              "createdAt": 1470991758,
              "id": 13,
              "name": "DynamoDB",
              "provider": {
                "id": 1,
                "name": "Amazon Web Services"
              },
              "slug": "dynamodb",
              "updatedAt": 1534242454
             },
             "tagKey": "mdw-test",
             "tagValue": null,
             "updatedAt": 1549499902
           },

OK! I’ve successfully queried information about my AWS integrations in New Relic Infrastructure, and I’ve used an interface to get additional information about a specific integration. Now, I’ll use the GraphQL API to update the metrics data polling intervals in one of these integrations.

Example 2: Modifying integration configurations with the GraphiQL

In GraphQL, when you modify data with a write operation, it’s called a mutation.

In this example, I’ll build a mutation to update the polling intervals of an AWS integration. First, though, I’ll set a polling interval so that we’ll notice when I change it with GraphiQL.

Here are the configuration options for my AWS DynamoDB integration:

DynamoDB integration configuration options in New Relic Infrastructure.

As you can see, I’ve set the metrics data and inventory data polling intervals to every 5 minutes, and I’ve also toggled Collect tags to ON.

Now I’ll build the mutation query.

First, I’ll start with the keyword mutation, and like any GraphQL API request, enclose it in a pair of curly braces,{ }.

Next, I want to specify that I’m configuring a cloud integration; so I’ll add cloudConfigureIntegration, which takes two arguments: accountId and integrations. For accountId, I’ll use the same account id from the first example to get information about the Infrastructure-linked accounts. The second argument is the integrations that I want to update. Again, integrations are specified by cloud provider, so here I want to include aws. So far my mutation looks like this:

mutation{
  cloudConfigureIntegration(
    accountId:MY ACCOUNT ID
    integrations:{aws

I want to specify that I’m updating the configuration for DynamoDB, so I’ll pass in an object with dynamodb as the key and an array that contains objects with the values I want to to set. Remember, for our mutation, we want to update the metricsPollingInterval (valid values are 300, 900, 1800, and 3600 seconds) and add a tagKey (metadata about the function of the integration).

The final part of the mutation adds a set of fields to return if my request is successful and a set of fields to return if there are any errors.

Here’s the full query:

mutation{
   cloudConfigureIntegration(
     accountId:630060
     integrations:{aws:{
       dynamodb:[
         { linkedAccountId:4912
           metricsPollingInterval:1800
           tagKey:"mdw-test"
         }]
       }
    }
 )
{
   integrations{
     id
     name
     updatedAt
     ... on CloudDynamodbIntegration{
          metricsPollingInterval
          tagKey
          tagValue
          updatedAt
          }
     }
     errors{
      linkedAccountId
      message
      integrationSlug
     }
  }
}

And here’s the result, which shows no errors and indicates DynamoDB’s configuration was successfully updated:

{
   "data": {
     "cloudConfigureIntegration": {
        "errors": [],
        "integrations": [
          {
            "id": 177184,
            "metricsPollingInterval": 1800,
            "name": "DynamoDB",
            "tagKey": "mdw-test",
            "tagValue": null,
            "updatedAt": 1551139957
          }
        ]
      }
   }
}

I can now return to New Relic Infrastructure and refresh the DynamoDB configuration page:

Refreshing the DynamoDB configuration in New Relic Infrastructure.

Our mutation changed the metric polling interval from 300 seconds (5 minutes) to 1800 seconds (30 minutes), and entered tag key value of mdw-test.

That’s it! I’ve successfully updated the configuration of a New Relic Infrastructure integration using the GraphiQL.

New Relic and GraphQL—the future is API first

As these examples show, GraphQL is extremely flexible and lightweight, and dramatically reduces the overhead of working with your New Relic data. That’s only the beginning. Going forward, we’re working to make all new APIs available through the New Relic GraphQL API. We’re building API first, so you have the same data access our curated UIs are built on.

We’re passionate about making life for developers as easy as possible, and we’re excited for you and your teams to innovate alongside us.

Mark Weitzel is General Manager, New Relic One at New Relic. View posts by .

Interested in writing for New Relic Blog? Send us a pitch!