mirror of
https://github.com/zhigang1992/apollo.git
synced 2026-01-12 08:53:57 +08:00
Rename Platform section to Workflows (and dir)
Also, rename Apollo Platform to Apollo platform (casing)
This commit is contained in:
@@ -23,7 +23,7 @@ module.exports = {
|
||||
'tutorial/local-state'
|
||||
// 'tutorial/whats-next'
|
||||
],
|
||||
Platform: [
|
||||
Workflows: [
|
||||
'platform/schema-registry',
|
||||
'platform/schema-validation',
|
||||
'platform/client-awareness',
|
||||
|
||||
@@ -25,13 +25,13 @@ module.exports = {
|
||||
|
||||
There are a few different ways you can link your client to a schema:
|
||||
|
||||
1. Use the Apollo [schema registry](/platform/schema-registry/)
|
||||
1. Use the Apollo [schema registry](/workflows/schema-registry/)
|
||||
1. With a remote endpoint (from a running server)
|
||||
1. With a local schema file
|
||||
|
||||
#### _Option 1_: Use the Apollo schema registry
|
||||
|
||||
To link your client to a schema through the Apollo schema registry, you'll need to have at least one version of your schema uploaded to the [registry](/platform/schema-registry/).
|
||||
To link your client to a schema through the Apollo schema registry, you'll need to have at least one version of your schema uploaded to the [registry](/workflows/schema-registry/).
|
||||
|
||||
With Engine set up, you can point your client directly to your graph's schema by putting your graph's Engine ID in your Apollo config, like so:
|
||||
|
||||
@@ -43,7 +43,7 @@ module.exports = {
|
||||
};
|
||||
```
|
||||
|
||||
> **Note:** you must have a [registered schema](/platform/schema-registry/#registering-a-schema) for features like VS Code intellisense, which requires knowledge of your schema, to work properly.
|
||||
> **Note:** you must have a [registered schema](/workflows/schema-registry/#registering-a-schema) for features like VS Code intellisense, which requires knowledge of your schema, to work properly.
|
||||
|
||||
If you're tracking different versions of your schema in the registry using schema variants, you can link your client to a specific variant like so:
|
||||
|
||||
|
||||
@@ -50,7 +50,7 @@ Graphs in Engine have globally unique IDs. We recommend that you prefix your ID
|
||||
|
||||
### Managing environments
|
||||
|
||||
Each graph in Engine should represent a single application, and environments within your application should be tracked using [_variants_](https://www.apollographql.com/docs/platform/schema-registry.html#schema-tags). All metrics that your server reports to Engine and all schema versions that you register should be tagged with their environment, and you'll be able to filter and look at the data for individual variants within Engine.
|
||||
Each graph in Engine should represent a single application, and environments within your application should be tracked using [_variants_](https://www.apollographql.com/docs/workflows/schema-registry.html#schema-tags). All metrics that your server reports to Engine and all schema versions that you register should be tagged with their environment, and you'll be able to filter and look at the data for individual variants within Engine.
|
||||
|
||||
#### API keys
|
||||
|
||||
|
||||
@@ -3,50 +3,48 @@ title: Apollo Engine proxy (deprecated)
|
||||
description: Configuring and running the Engine proxy
|
||||
---
|
||||
|
||||
> DEPRECATED: The engine proxy is not maintained, and to integrate with the Apollo platform's metrics, we recommend using Apollo Server's native reporting functionality. To integrate a non-Node server, take a look at our guide [here](/references/setup-analytics/#other-servers).
|
||||
> DEPRECATED: The engine proxy is not maintained, and to integrate with the Apollo platform's metrics, we recommend using Apollo Server's native reporting functionality. To integrate a non-Node server, take a look at our guide [here](https://www.apollographql.com/docs/workflows/setup-analytics#other-servers)
|
||||
|
||||
## Background
|
||||
|
||||
The Apollo Engine proxy is a small process that can be run in front of your GraphQL server. Its primary functions are:
|
||||
|
||||
1. Sending **performance metrics** data from your server, which extends its responses with [`apollo-tracing`](https://github.com/apollographql/apollo-tracing) information, to the Engine cloud service.
|
||||
1. Proving a **full query caching** layer, which is controlled using the [`cacheControl`](https://github.com/apollographql/apollo-cache-control) directive and configured to be either in-memory or shared through Memcache.
|
||||
1. Automatically **persisting queries** through a caching layer that can map query IDs to full query strings, allowing clients to send just query IDs over the wire.
|
||||
|
||||
The proxy has been **deprecated since Apollo Server 2** was released. Apollo Server 2+ has [metrics reporting](https://www.apollographql.com/docs/apollo-server/features/metrics), [data source caching](https://www.apollographql.com/docs/apollo-server/features/data-sources), [persisted queries](https://www.apollographql.com/docs/apollo-server/features/apq), and [full query caching](https://github.com/apollographql/apollo-server/blob/release-2.5.0/docs/source/features/caching.md) (starting at Apollo Server 2.5) as built-in features, and using it allows you to forego running the proxy. The newest features in Apollo Engine are not supported in the Engine proxy and we recommend that all Node users use Apollo Server 2+ instead of running the proxy.
|
||||
The proxy has been **deprecated since Apollo Server 2** was released. Apollo Server 2+ has [metrics reporting](https://www.apollographql.com/docs/apollo-server/features/metrics.html), [data source caching](https://www.apollographql.com/docs/apollo-server/features/data-sources.html), [persisted queries](https://www.apollographql.com/docs/apollo-server/whats-new.html#Automatic-Persisted-Queries), and [full query caching](https://github.com/apollographql/apollo-server/blob/release-2.5.0/docs/source/features/caching.md) (starting with Apollo Server 2.5) as built-in features, and using it allows you to forego running the proxy. The newest features in Apollo Engine are not supported in the Engine proxy and we recommend that all Node users use Apollo Server 2+ instead running the proxy.
|
||||
|
||||
That said, the proxy is still a good option for getting set up with Engine in a few **specific** circumstances:
|
||||
|
||||
1. You are not using Apollo Server, your server has an [`apollo-tracing`](https://github.com/apollographql/apollo-tracing) plugin, and you want to get **performance metrics** insights.
|
||||
1. You are not using Apollo Server and you want to use Apollo's **automatic persisted queries**.
|
||||
|
||||
## Setup
|
||||
|
||||
To get started with using Engine through the Engine proxy, you will need to:
|
||||
|
||||
1. [Install a package in your GraphQL server that adds `extension` data (in the Apollo Tracing format) to each request's response.](#instrument-your-server)
|
||||
1. [Get your Engine API key.](#get-your-api-key)
|
||||
1. [Configure and deploy the Engine proxy to run in front of your server using either Docker or npm.](#run-the-proxy)
|
||||
1. [Install a package in your GraphQL server that adds `extension` data (in the Apollo Tracing format) to each request's response.](#Instrument-your-server)
|
||||
1. [Get your Engine API key.](#Get-your-API-key)
|
||||
1. [Configure and deploy the Engine proxy to run in front of your server using either Docker or npm.](#Run-the-proxy)
|
||||
|
||||
### Instrument your server
|
||||
|
||||
To get the performance metrics value out of Engine, you'll need to install a package in your server that adds the `apollo-tracing` GraphQL extension. If you want to set up response caching, you'll also need to install a package that adds the `apollo-cache-control` extension.
|
||||
|
||||
> **Note:** If you're installing the Engine proxy _just_ to set up automatic persisited queries, you can skip ahead to the [next section](#get-your-api-key).
|
||||
> **Note:** If you don't want performance metrics or caching (i.e. you're installing the Engine proxy _just_ to set up automatic persisited queries), you can skip ahead to the [next section](#Get-your-API-key).
|
||||
|
||||
The `apollo-tracing` and `apollo-cache-control` extensions are open specifications that can be implemented by any GraphQL server, and the following is a list of implementations:
|
||||
|
||||
1. **Node** with [Apollo Server](https://www.apollographql.com/docs/apollo-server/) natively supports tracing and cache control. See [Node setup instructions](#run-the-proxy) for a more streamlined Node setup option.
|
||||
1. **Node** with [Apollo Server](https://www.apollographql.com/docs/apollo-server/) natively supports tracing and cache control. See [Node setup instructions](./setup-node.html) for a more streamlined Node setup option.
|
||||
1. **Ruby** with [GraphQL-Ruby](http://graphql-ruby.org/) supports tracing with the [apollo-tracing-ruby](https://github.com/uniiverse/apollo-tracing-ruby) gem.
|
||||
1. **Java** with [GraphQL-Java](https://github.com/graphql-java/graphql-java) natively supports tracing. [Read the docs about using Apollo tracing.](https://www.graphql-java.com/documentation/master/instrumentation/)
|
||||
1. **Scala** with [Sangria](https://github.com/sangria-graphql/sangria) supports tracing with [sangria-slowlog](https://github.com/sangria-graphql/sangria-slowlog#apollo-tracing-extension) project.
|
||||
1. **Elixir** with [Absinthe](https://github.com/absinthe-graphql/absinthe) supports tracing with the [apollo-tracing-elixir](https://github.com/sikanhe/apollo-tracing-elixir) package.
|
||||
|
||||
> **Note:** Using a different server? Let us know at support@apollographql.com. The development of Apollo tracing implementations is community driven and we would love to start a conversation with you!
|
||||
|
||||
You can test that you’ve correctly enabled Apollo Tracing by running any query against your API using GraphiQL.
|
||||
|
||||
The `tracing` field should now be returned as part of the response's `extensions` like below. Don’t worry, this data won’t make it back to your clients once you've set up the Engine proxy, because the proxy will filter it out.
|
||||
|
||||
```js{3-5}
|
||||
```js line=3-5
|
||||
{
|
||||
"data": { ... },
|
||||
"extensions": {
|
||||
@@ -57,24 +55,25 @@ The `tracing` field should now be returned as part of the response's `extensions
|
||||
|
||||
### Get your API key
|
||||
|
||||
[Log into Apollo Engine](http://engine.apollographql.com/?_ga=2.233930590.1351805406.1542648368-1704540304.1492481658) and create a graph to get an API key. We’ll be using your new key in the next step.
|
||||
[Log into Apollo Engine](http://engine.apollographql.com/?_ga=2.233930590.1351805406.1542648368-1704540304.1492481658) and create a service to get an API key. We’ll be using your new key in the next step.
|
||||
|
||||
### Run the proxy
|
||||
|
||||
The proxy is a small process written in Go that you host and run inside your infrastructure. It's designed to allow all of your requests and responses to pass through normally while it collects trace data, caches results, and identifies persisted queries. It's designed to handle large volumes of traffic comfortably without overloading. It does not rely on accessing the Engine cloud service to run or perform caching functions, but if it cannot talk to the Engine cloud service it will not be able to report metrics.
|
||||
|
||||
Apollo distributes the Engine proxy in two forms: as an **npm package** and as a **Docker container**. You can use any one of the following options for running the proxy, depending what works best for you and your team:
|
||||
1. [Run the proxy with Apollo Server](#proxy-with-apollo-server)
|
||||
1. [Run a standalone proxy using Node](#standalone-proxy-with-node)
|
||||
1. [Run a standalone proxy using Docker](#standalone-proxy-with-docker)
|
||||
1. [Run the proxy through a Platform as a Service (eg. Heroku)](#platform-as-a-service)
|
||||
1. [Run the proxy in a serverless environment (eg. Lambda)](#serverless)
|
||||
|
||||
1. [Run the proxy with Apollo Server](#option-1-running-the-proxy-with-apollo-server)
|
||||
1. [Run a standalone proxy using Node](#option-2-running-a-standalone-proxy-using-node)
|
||||
1. [Run a standalone proxy using Docker](#option-3-running-a-standalone-proxy-with-docker)
|
||||
1. [Run the proxy through a Platform as a Service (eg. Heroku)](#option-4-running-the-proxy-through-a-platform-as-a-service-eg-heroku)
|
||||
1. [Run the proxy in a serverless environment (eg. Lambda)](#option-5-running-the-proxy-in-a-serverless-environment-eg-lambda)
|
||||
|
||||
#### Option 1: Running the proxy with Apollo Server
|
||||
<h4 style="position: relative;">
|
||||
<span id="proxy-with-apollo-server" style="position: absolute; top: -100px;" ></span>
|
||||
Option 1: Running the proxy with Apollo Server
|
||||
</h4>
|
||||
|
||||
The two cases where you should be running the Engine proxy with Apollo Server are:
|
||||
|
||||
1. You are using Apollo Server 1 and want the Apollo platform features that Engine brings.
|
||||
1. You are using Apollo Server >2 & <2.5+ and want full query caching using the Engine proxy.
|
||||
|
||||
@@ -92,9 +91,9 @@ Then import the `ApolloEngine` constructor and create a new Engine instance. You
|
||||
|
||||
```js
|
||||
// Import ApolloEngine
|
||||
const { ApolloEngine } = require('apollo-engine');
|
||||
const { ApolloServer } = require('apollo-server-express');
|
||||
const express = require('express');
|
||||
const { ApolloEngine } = require("apollo-engine");
|
||||
const { ApolloServer } = require("apollo-server-express");
|
||||
const express = require("express");
|
||||
|
||||
// Initialize Apollo Server
|
||||
const server = new ApolloServer({
|
||||
@@ -121,7 +120,7 @@ server.applyMiddleware({ app });
|
||||
// set the ENGINE_API_KEY environment variable when you
|
||||
// run your program.
|
||||
const engine = new ApolloEngine({
|
||||
apiKey: 'API_KEY_HERE'
|
||||
apiKey: "API_KEY_HERE"
|
||||
});
|
||||
|
||||
// Call engine.listen(...) instead of app.listen(port) as you usually would
|
||||
@@ -131,9 +130,12 @@ engine.listen({
|
||||
});
|
||||
```
|
||||
|
||||
Engine is now wrapping your endpoint and processing your GraphQL requests and responses like normal. If you call your endpoint again, your requests will be routed through the Engine proxy to your server and back. If everything is working, you will no longer see `tracing` data in your responses because your Engine proxy is filtering and processing that information for you.
|
||||
Engine is now wrapping your endpoint and processing your GraphQL requests and responses like normal. If you call your endpoint again, your requests will be routed through the Engine proxy to your server and back. If everything is working, you will no longer see `tracing` data in your responses because your Engine proxy is filtering and processing that information for you.
|
||||
|
||||
#### Option 2: Running a standalone proxy using Node
|
||||
<h4 style="position: relative;">
|
||||
<span id="standalone-proxy-with-node" style="position: absolute; top: -100px;" ></span>
|
||||
Option 2: Running a standalone proxy using Node
|
||||
</h4>
|
||||
|
||||
Even if your GraphQL server is not implemented with Node, you may find it easier to run a tiny Node program in your hosting environment than to run a Docker container. If so, this proxy deployment option is for you.
|
||||
|
||||
@@ -154,30 +156,24 @@ const { ApolloEngineLauncher } = require('apollo-engine');
|
||||
const launcher = new ApolloEngineLauncher({
|
||||
// Note: you can also provide this in the ENGINE_API_KEY environment variable.
|
||||
apiKey: 'API_KEY_HERE',
|
||||
origins: [
|
||||
{
|
||||
http: {
|
||||
// The URL that the proxy should use to connect to your GraphQL server.
|
||||
url: 'http://localhost:4000/api/graphql'
|
||||
}
|
||||
}
|
||||
],
|
||||
origins: [{
|
||||
http: {
|
||||
// The URL that the proxy should use to connect to your GraphQL server.
|
||||
url: 'http://localhost:4000/api/graphql',
|
||||
},
|
||||
}],
|
||||
// Tell the proxy which ports to listen to and which paths should
|
||||
// be treated as GraphQL instead of transparently proxied as raw HTTP.
|
||||
frontends: [
|
||||
{
|
||||
port: 3000, // default if left out: process.env.PORT
|
||||
endpoints: ['/api/graphql'] // default if left out: /['/graphql]
|
||||
}
|
||||
]
|
||||
frontends: [{
|
||||
port: 3000, // default if left out: process.env.PORT
|
||||
endpoints: ['/api/graphql'], // default if left out: /['/graphql]
|
||||
}],
|
||||
});
|
||||
|
||||
// Start the Proxy; crash on errors.
|
||||
launcher.start().catch(err => {
|
||||
throw err;
|
||||
});
|
||||
launcher.start().catch(err => { throw err; });
|
||||
```
|
||||
> **Note:** Every deployment has its unique needs and we provide a variety of configuration options to fulfill them. For more configuration options, please see the [proxy config docs](/references/proxy-config/).
|
||||
> **Note:** Every deployment has its unique needs and we provide a variety of configuration options to fulfill them. For more configuration options, please see the [proxy config docs](./proxy-config.html). // TODO(dman): get proper link for proxy config docs
|
||||
|
||||
> **Note:** The argument to `new ApolloEngineLauncher()` is generally the same as the argument Node GraphQL users pass to `new ApolloEngine()`. The main differences are that you need to specify the origin's HTTP URL yourself with `new ApolloEngineLauncher()`, and the frontend `port` and `endpoints` are specified inside the constructor instead of as options to `listen()`.
|
||||
|
||||
@@ -185,12 +181,14 @@ If you run this program with Node, the proxy will start up and start accepting c
|
||||
|
||||
If you open up GraphiQL on http://localhost:3000, you'll notice that the `tracing` extension data is no longer in the result of your query. This is because Engine is consuming it! You can verify that everything is working correctly by checking the Engine UI for your new service and confirming that you see data in the Metrics section.
|
||||
|
||||
#### Option 3: Running a standalone proxy with Docker
|
||||
<h4 style="position: relative;">
|
||||
<span id="standalone-proxy-with-docker" style="position: absolute; top: -100px;" ></span>
|
||||
Option 3: Running a standalone proxy with Docker
|
||||
</h4>
|
||||
|
||||
The Engine proxy is also distributed as a Docker image that you can deploy and manage separate from your server. It does not matter where you choose to deploy and manage your proxy, though it's more efficient if your proxy is located on the same machine or network as your GraphQL server.
|
||||
|
||||
The Docker container distribution of Engine proxy is configured using a JSON `engine-config.json` configuration file, like so:
|
||||
|
||||
```js
|
||||
{
|
||||
"apiKey": "API_KEY_HERE",
|
||||
@@ -206,32 +204,35 @@ The Docker container distribution of Engine proxy is configured using a JSON `en
|
||||
}
|
||||
```
|
||||
|
||||
> **Note:** Every deployment has its unique needs, and we provide a variety of configuration options to fulfill them. For example, if your origin GraphQL server is running in a virtual-hosted environment (e.g. Heroku, AWS), you may need to override the `Host` header sent to HTTP origins. For more details and instruction on configuration options, please see the [proxy config docs](/references/proxy-config/).
|
||||
> **Note:** Every deployment has its unique needs, and we provide a variety of configuration options to fulfill them. For example, if your origin GraphQL server is running in a virtual-hosted environment (e.g. Heroku, AWS), you may need to override the `Host` header sent to HTTP origins. For more details and instruction on configuration options, please see the [proxy config docs](./proxy-config.html). // TODO(dman): get proper proxy docs link
|
||||
|
||||
As it is JSON file, all object keys must be quoted, and trailing commas and comments are not allowed. Any reference in our docs to options passed to `new ApolloEngine()` otherwise translates directly into the engine config file. Like with `ApolloEngineLauncher`, you need to specify your GraphQL server's origin http URL (or other origin type like Lambda) inside the config file, and you need to specify the frontend port and GraphQL paths inside the config file rather than separately (if you're not using the default values of `process.env.PORT` and `['/graphql']`).
|
||||
As it is JSON file, all object keys must be quoted, and trailing commas and comments are not allowed. Any reference in our docs to options passed to `new ApolloEngine()` otherwise translates directly into the engine config file. Like with `ApolloEngineLauncher`, you need to specify your GraphQL server's origin http URL (or other origin type like [Lambda](./setup-lambda.html)) inside the config file, and you need to specify the frontend port and GraphQL paths inside the config file rather than separately (if you're not using the default values of `process.env.PORT` and `['/graphql']`).
|
||||
|
||||
Next, make sure you have a working [Docker installation](https://docs.docker.com/engine/installation/) and type the following lines in your shell:
|
||||
|
||||
```
|
||||
{% codeblock %}
|
||||
$ ENGINE_PORT=3000
|
||||
$ docker run --env "ENGINE_CONFIG=$(cat engine-config.json)" -p "${ENGINE_PORT}:${ENGINE_PORT}" gcr.io/mdg-public/engine:1.1
|
||||
```
|
||||
$ docker run --env "ENGINE_CONFIG=$(cat engine-config.json)" -p "${ENGINE_PORT}:${ENGINE_PORT}" gcr.io/mdg-public/engine:{% proxyDockerVersion %}
|
||||
{% endcodeblock %}
|
||||
|
||||
> **Note:** We use [semver](https://semver.org/) to name Engine Proxy release versions, and we release version 1.2.3 under the tags `1.2.3`, `1.2`, and `1`. If you want to pin to a precise version, use the `1.2.3` tag. If you'd like to take patch upgrades but not minor upgrades, use the `1.2` tag. If you'd like to take minor upgrades, use the `1` tag.
|
||||
> **Note:** We use [semver](https://semver.org/) to name Engine Proxy release versions, and we release version 1.2.3 under the tags `1.2.3`, `1.2`, and `1`. If you want to pin to a precise version, use the `1.2.3` tag. If you'd like to take patch upgrades but not minor upgrades, use the `1.2` tag. If you'd like to take minor upgrades, use the `1` tag.
|
||||
|
||||
This will run the Engine Proxy via Docker, routing port 3000 inside the container to port 3000 outside the container. (You can also pass `--net=host` instead of the `-p 3000:3000` to just allow the Proxy direct access to your host's network.)
|
||||
|
||||
The Proxy should start up and accept connections at http://localhost:3000 and forward all requests to your server at http://localhost:4000. Load GraphiQL through Engine at http://localhost:3000/graphiql (or wherever you have configured your app to serve GraphiQL) and run any query. You should no longer see the `tracing` data in the result since Engine is now consuming it! Checking the Engine UI for your service, you should see data from the request you sent via GraphiQL come through in the metrics tab.
|
||||
|
||||
You can find the complete documentation for Engine configuration options on the [full API docs](/references/proxy-config/) page, and some commonly-used fields worth knowing about are described in the [`new ApolloEngineLauncher()` docs](/references/proxy-config/#top-level-options).
|
||||
You can find the complete documentation for Engine configuration options on the [full API docs](./proxy-config.html) page, and some commonly-used fields worth knowing about are described in the [`new ApolloEngineLauncher()` docs](#api-apollo-engine-launcher).
|
||||
|
||||
#### Option 4: Running the proxy through a Platform as a Service (eg. Heroku)
|
||||
<h4 style="position: relative;">
|
||||
<span id="platform-as-a-service" style="position: absolute; top: -100px;" ></span>
|
||||
Option 4: Running the proxy through a Platform as a Service (eg. Heroku)
|
||||
</h4>
|
||||
|
||||
It may be most convenient for you to run and host the Engine proxy outside your app's deployment altogether. If that is the case, automatically running the proxy on a Platform as a Service like Heroku might be the easiest option for you.
|
||||
|
||||
We have an example repository with a guide for [running the Engine proxy on Heroku](https://github.com/apollographql/engine-heroku-example) that you can follow along in. Like running a [standalone proxy with Docker](#option-3-running-a-standalone-proxy-with-docker), you'll need to configure your proxy with an `engine-config.json` file like so:
|
||||
We have an example repository with a guide for [running the Engine proxy on Heroku](https://github.com/apollographql/engine-heroku-example) that you can follow along in. Like running a [standalone proxy with Docker](#standalone-proxy-with-docker), you'll need to configure your proxy with an `engine-config.json` file like so:
|
||||
|
||||
```json
|
||||
```
|
||||
{
|
||||
"apiKey": "<ENGINE_API_KEY>",
|
||||
"origins": [
|
||||
@@ -254,11 +255,14 @@ We have an example repository with a guide for [running the Engine proxy on Hero
|
||||
}
|
||||
```
|
||||
|
||||
> **Note:** For Virtual Hosted environments where the `PORT` is dynamically set in an environment variable named `$PORT`, you can leave out the `port` option. If your environment uses a different environment variable, you can name it with the `portFromEnv` option instead. For more details and instruction on configuration options, please see the [proxy config docs](/references/proxy-config/).
|
||||
> **Note:** For Virtual Hosted environments where the `PORT` is dynamically set in an environment variable named `$PORT`, you can leave out the `port` option. If your environment uses a different environment variable, you can name it with the `portFromEnv` option instead. For more details and instruction on configuration options, please see the [proxy config docs](./proxy-config.html). // TODO(dman): get proper link for proxy config docs
|
||||
|
||||
It does not matter where you choose to deploy and manage your Engine proxy. We've built this guide for Heroku because they have an easy deployment mechanism for Docker containers, but we run our own Engine proxy on Amazon's [EC2 Container Service](https://aws.amazon.com/ecs/).
|
||||
|
||||
#### Option 5: Running the proxy in a serverless environment (eg. Lambda)
|
||||
<h4 style="position: relative;">
|
||||
<span id="serverless" style="position: absolute; top: -100px;" ></span>
|
||||
Option 5: Running the proxy in a serverless environment (eg. Lambda)
|
||||
</h4>
|
||||
|
||||
Last but not least, you may be wondering how to use Engine if you run your application in a serverless environment like Lamdba. If so, this is the guide for you!
|
||||
|
||||
@@ -267,16 +271,14 @@ Last but not least, you may be wondering how to use Engine if you run your appli
|
||||
To use Engine when running in serverless environments, we will need to configure and deploy the Engine proxy as a standalone docker container that is **separate** from your cloud function. The Engine proxy is stateful (it collects and aggregates your metrics across requests), and as such it should not be deployed with your cloud function, but separately.
|
||||
|
||||
The only available option for running the Engine proxy with cloud functions is to run the proxy in a standalone docker container. To do that, you can follow one of our guides here:
|
||||
|
||||
1. [Run a standalone proxy using Node](#option-2-running-a-standalone-proxy-using-node)
|
||||
1. [Run a standalone proxy using Docker](#option-3-running-a-standalone-proxy-with-docker)
|
||||
1. [Run the proxy through a Platform as a Service (eg. Heroku)](#option-4-running-the-proxy-through-a-platform-as-a-service-eg-heroku)
|
||||
1. [Run a standalone proxy using Node](#standalone-proxy-with-node)
|
||||
1. [Run a standalone proxy using Docker](#standalone-proxy-with-docker)
|
||||
1. [Run the proxy through a Platform as a Service (eg. Heroku)](#platform-as-a-service)
|
||||
|
||||
The proxy needs to be run separately from your function because it's responsible for capturing, aggregating, and sending to Engine the trace data from each Lamdba instance GraphQL response.
|
||||
|
||||
The main difference between setting up the proxy to work with cloud functions versus setting it up with a persistent server is in how you configure it. You'll want an `engine-config.json` that looks something like this:
|
||||
|
||||
```json
|
||||
```
|
||||
{
|
||||
"apiKey": "<ENGINE_API_KEY>",
|
||||
"origins": [
|
||||
@@ -298,7 +300,7 @@ The main difference between setting up the proxy to work with cloud functions ve
|
||||
}
|
||||
```
|
||||
|
||||
> **Note:** This example is for AWS Lambda specifically, for which we have a special `origins` type. Other cloud functions are supported with the standard HTTP invocation, and for non-AWS cloud functions see [the standalone docs](#option-3-running-a-standalone-proxy-with-docker) for instructions on settup up the Engine proxy as a standalone API gateway to your cloud function. For full configuration details see [proxy config](/references/proxy-config/).
|
||||
> **Note:** This example is for AWS Lambda specifically, for which we have a special `origins` type. Other cloud functions are supported with the standard HTTP invocation, and for non-AWS cloud functions see [the standalone docs](#standalone-proxy-with-docker) for instructions on settup up the Engine proxy as a standalone API gateway to your cloud function. For full configuration details see [Proxy config] (//TODO(dman: get the proxy docs link).
|
||||
|
||||
The Engine proxy will invoke the Lambda function as if it was called from Amazon's [API Gateway](https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-set-up-simple-proxy.html#api-gateway-simple-proxy-for-lambda-input-format), and the function should return a value suitable for [API Gateway](https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-set-up-simple-proxy.html#api-gateway-simple-proxy-for-lambda-output-format).
|
||||
|
||||
@@ -307,42 +309,40 @@ If you've got a proxy running and successfully configured to talk to your cloud
|
||||
## Feature configuration
|
||||
|
||||
The following proxy features require specific setup steps to get working.
|
||||
|
||||
1. [Automatically **persisting** your queries](#automatic-persisted-queries-apq)
|
||||
1. [Automatically **persisting** your queries](#automatic-persisted-queries)
|
||||
1. [**Caching** full query responses](#caching)
|
||||
1. [Integrating with your **CDN**](#cdn-integration)
|
||||
1. [Integrating with your **CDN**](#cdn)
|
||||
1. [Using the Engine proxy with **query batching**](#query-batching)
|
||||
|
||||
### Automatic Persisted Queries (APQ)
|
||||
<h3 id="automatic-persisted-queries">Automatic Persisted Queries (APQ)</h3>
|
||||
|
||||
Automatically persisting your queries is a performance technique in which you send a query hash to your server instead of the entire GraphQL query string. Your server keeps track of the map between these hashes and their full query strings and does the lookup on its end, saving you the bandwidth of sending the full query string over the wire.
|
||||
|
||||
An added benefit of using APQs with GraphQL is that it's an easy mechanism to transform your GraphQL POST requests into GET requests, allowing you to easily leverage any CDN infrastructure you may already have in place.
|
||||
|
||||
> **Note:** Apollo Server 2 reduces the setup necessary to use automatic persisted queries, and these instructions are only necessary when using the Apollo Engine Proxy. To find out more visit the [Apollo Server](https://www.apollographql.com/docs/apollo-server/features/apq/) docs.
|
||||
> **Note:** Apollo Server 2 reduces the setup necessary to use automatic persisted queries, and these instructions are only necessary when using the Apollo Engine Proxy. To find out more visit the [Apollo Server](/docs/apollo-server/whats-new.html#Automatic-Persisted-Queries) docs.
|
||||
|
||||
The query registry that maps query hashes to query strings is stored in a user-configurable cache and read by the Engine proxy. This can either be an in-memory store (configured by default to be 50MB) within each Engine proxy instance, or an external, configurable [memcached](https://memcached.org/) store.
|
||||
|
||||
To use automatic persisted queries with the Engine proxy:
|
||||
|
||||
- Use Engine proxy `v1.0.1` or newer.
|
||||
- If your GraphQL server is hosted on a different origin domain from where it will be accessed, setup the appropriate [CORS headers](https://en.wikipedia.org/wiki/Cross-origin_resource_sharing) using the `overrideGraphqlResponseHeaders` object on the proxy's `frontend` configuration:
|
||||
* Use Engine proxy `v1.0.1` or newer.
|
||||
* If your GraphQL server is hosted on a different origin domain from where it will be accessed, setup the appropriate [CORS headers](https://en.wikipedia.org/wiki/Cross-origin_resource_sharing) using the `overrideGraphqlResponseHeaders` object on the proxy's `frontend` configuration:
|
||||
|
||||
```javascript
|
||||
frontends: [{
|
||||
overrideGraphqlResponseHeaders: {
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
},
|
||||
}],
|
||||
```
|
||||
|
||||
```javascript
|
||||
frontends: [{
|
||||
overrideGraphqlResponseHeaders: {
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
},
|
||||
}],
|
||||
```
|
||||
* Configure your client to use APQs. If you're using Apollo Client, you can easily use [`apollo-link-persisted-queries`](https://github.com/apollographql/apollo-link-persisted-queries#automatic-persisted-queries) to set this up.
|
||||
<!-- * Verify APQ is working properly using the [verification procedure] (// TODO(dman): get link to new article). -->
|
||||
<!-- * Read [how it works] (// TODO(dman): get link to new article) for additional details. -->
|
||||
|
||||
If everything is set up correctly, you should see your client sending hashes insteady of query strings over the network, but receiving data as if it had sent a normal query.
|
||||
|
||||
### Caching
|
||||
<h3 id="caching">Caching</h3>
|
||||
|
||||
To bring caching to GraphQL we've developed [Apollo Cache Control](https://github.com/apollographql/apollo-cache-control), an open standard that allows servers to specify exactly which parts of a response can be cached and how long they can be cached for.
|
||||
|
||||
@@ -353,41 +353,43 @@ The Engine proxy computes a cache privacy level and expiration date by combining
|
||||
The Engine proxy reads Apollo Cache Control extensions, caching whole query responses based on the computed cacheability of each new query. The Engine UI will visualize how each query was impacted by the cache policy set on it.
|
||||
|
||||
There are just a few steps to enable response caching in Engine proxy, and one of them is optional!
|
||||
1. [Extend your server's responses with `cacheControl` extensions.](#add-cache-extensions)
|
||||
1. [Annotate your schema and/or resolvers with cache control hints.](#annotate-your-responses)
|
||||
1. [_Optional:_ Configure cache options in your Engine Proxy configuration.](#configure-cache-options)
|
||||
|
||||
1. [Extend your server's responses with `cacheControl` extensions.](#1-add-cachecontrol-extensions-to-your-sevrer)
|
||||
1. [Annotate your schema and/or resolvers with cache control hints.](#2-add-cache-hints-to-your-responses)
|
||||
1. [_Optional:_ Configure cache options in your Engine Proxy configuration.](#3-optional-configure-cache-options)
|
||||
|
||||
#### 1. Add `cacheControl` extensions to your sevrer
|
||||
<h4 style="position: relative;">
|
||||
<span id="add-cache-extensions" style="position: absolute; top: -100px;" ></span>
|
||||
1. Add `cacheControl` extensions to your sevrer
|
||||
</h4>
|
||||
|
||||
If you're using Apollo Server for your Node GraphQL server, the only server code change required is to add `cacheControl: true` to the options passed to your Apollo Server configuration.
|
||||
|
||||
```js
|
||||
```js line=5,12
|
||||
// Apollo Server 2:
|
||||
const server = new ApolloServer({
|
||||
typeDefs,
|
||||
resolvers,
|
||||
cacheControl: true // highlight-line
|
||||
cacheControl: true,
|
||||
});
|
||||
|
||||
// Apollo Server 1.2 and onwards:
|
||||
app.use(
|
||||
'/graphql',
|
||||
bodyParser.json(),
|
||||
graphqlExpress({
|
||||
schema,
|
||||
context: {},
|
||||
cacheControl: true // highlight-line
|
||||
})
|
||||
);
|
||||
app.use('/graphql', bodyParser.json(), graphqlExpress({
|
||||
schema,
|
||||
context: {},
|
||||
cacheControl: true
|
||||
}));
|
||||
|
||||
```
|
||||
|
||||
We're working with the community to add support for Apollo Cache Control to non-Node GraphQL server libraries. Contact us at suppot@apollogrqphql.com if you're interested in joining the community to work on support for `express-graphql` or non-Node GraphQL servers.
|
||||
|
||||
#### 2. Add cache hints to your responses
|
||||
|
||||
<h4 style="position: relative;">
|
||||
<span id="annotate-your-responses" style="position: absolute; top: -100px;" ></span>
|
||||
2. Add cache hints to your responses
|
||||
</h4>
|
||||
|
||||
Next we'll add some cache hints to our GarphQL responses. There are two ways to do this -- either dynamically in your resolvers or statically on your schema types and fields. Each `cacheControl` hint has two parameters:
|
||||
|
||||
- The `maxAge` parameter defines the number of seconds that Engine Proxy should serve the cached response.
|
||||
- The `scope` parameter declares that a unique response should be cached for every user (`PRIVATE`) or a single response should be cached for all users (`PUBLIC`/default).
|
||||
|
||||
@@ -413,10 +415,9 @@ This verification is performed by HTTP request, to the URL specified in `tokenAu
|
||||
The token auth URL will receive an HTTP POST containing: `{"token": "AUTHENTICATION-TOKEN"}`.
|
||||
It should return an HTTP `200` response if the token is still considered valid.
|
||||
It may optionally return a JSON body:
|
||||
|
||||
- `{"ttl": 300}` to indicate the session token check can be cached for 300 seconds.
|
||||
- `{"id": "alice"}` to indicate an internal user ID that should be used for identification. By returning a persistent identifier such as a database key, Engine's cache can follow a user across sessions and devices.
|
||||
- `{"ttl": 600, "id": "bob"}` to combine both.
|
||||
* `{"ttl": 300}` to indicate the session token check can be cached for 300 seconds.
|
||||
* `{"id": "alice"}` to indicate an internal user ID that should be used for identification. By returning a persistent identifier such as a database key, Engine's cache can follow a user across sessions and devices.
|
||||
* `{"ttl": 600, "id": "bob"}` to combine both.
|
||||
|
||||
Authentication checks with `ttl>0` will be cached in a `store` named in `sessionAuth`, or in the default 50MB in-memory store.
|
||||
|
||||
@@ -445,7 +446,7 @@ type Author @cacheControl(maxAge: 60) {
|
||||
|
||||
You should receive cache control data in the `extensions` field of your response:
|
||||
|
||||
```json
|
||||
```js
|
||||
"cacheControl": {
|
||||
"version": 1,
|
||||
"hints": [
|
||||
@@ -475,20 +476,18 @@ You should receive cache control data in the `extensions` field of your response
|
||||
|
||||
For the above schema, there are a few ways to generate different TTLs depending on your query. Take the following examples:
|
||||
|
||||
_Example 1_
|
||||
|
||||
*Example 1*
|
||||
```graphql
|
||||
query getPostsForAuthor {
|
||||
Author {
|
||||
posts
|
||||
Author {
|
||||
posts
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
`getPostsForAuthor` will have `maxAge` of 60 seconds, even though the `Post` object has `maxAge` of 240 seconds.
|
||||
|
||||
_Example 2_
|
||||
|
||||
*Example 2*
|
||||
```graphql
|
||||
query getTitleForPost {
|
||||
Post {
|
||||
@@ -499,14 +498,13 @@ query getTitleForPost {
|
||||
|
||||
`getTitleForPost` will have `maxAge` of 240 seconds (inherited from Post), even though the `title` field has no `maxAge` specified.
|
||||
|
||||
_Example 3_
|
||||
|
||||
*Example 3*
|
||||
```graphql
|
||||
query getVotesForPost {
|
||||
Post {
|
||||
votes
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
`getVotesForPost` will have `maxAge` of 240 seconds, even though the `votes` field has a higher `maxAge`.
|
||||
@@ -535,23 +533,22 @@ Just like when you set `@cacheControl(maxAge: 5)` explicitly on a field or a typ
|
||||
For example, for Express:
|
||||
|
||||
```javascript
|
||||
app.use(
|
||||
'/graphql',
|
||||
bodyParser.json(),
|
||||
graphqlExpress({
|
||||
schema,
|
||||
context: {},
|
||||
tracing: true,
|
||||
cacheControl: {
|
||||
defaultMaxAge: 5
|
||||
}
|
||||
})
|
||||
);
|
||||
app.use('/graphql', bodyParser.json(), graphqlExpress({
|
||||
schema,
|
||||
context: {},
|
||||
tracing: true,
|
||||
cacheControl: {
|
||||
defaultMaxAge: 5,
|
||||
},
|
||||
}));
|
||||
```
|
||||
|
||||
Setting `defaultMaxAge` requires `apollo-server-*` 1.3.4 or newer.
|
||||
|
||||
#### 3. Optional: Configure cache options
|
||||
<h4 style="position: relative;">
|
||||
<span id="configure-cache-options" style="position: absolute; top: -100px;" ></span>
|
||||
3. _Optional:_ Configure cache options
|
||||
</h4>
|
||||
|
||||
As long as you're using a version of the Engine proxy that's greater than `1.0`, you won't have to configure anything to use public response caching. The proxy comes with a default 50MB in-memory cache. To enable private response caching or to configure details of how caching works, there are a few fields in the Engine configuration (ie, argument to `new ApolloServer`) that are relevant.
|
||||
|
||||
@@ -560,13 +557,11 @@ Since no `privateFullQueryStore` is provided, `scope: PRIVATE` responses will no
|
||||
|
||||
```js
|
||||
const engine = new ApolloEngine({
|
||||
stores: [
|
||||
{
|
||||
memcache: {
|
||||
url: ['localhost:4567']
|
||||
}
|
||||
}
|
||||
]
|
||||
stores: [{
|
||||
memcache: {
|
||||
url: ['localhost:4567'],
|
||||
},
|
||||
}],
|
||||
// ...
|
||||
});
|
||||
```
|
||||
@@ -576,36 +571,35 @@ By using a private response cache, we guarantee that a response affecting multip
|
||||
|
||||
```js
|
||||
const engine = new ApolloEngine({
|
||||
stores: [
|
||||
{
|
||||
name: 'privateResponseMemcache',
|
||||
memcache: {
|
||||
url: ['localhost:4567']
|
||||
}
|
||||
}
|
||||
],
|
||||
stores: [{
|
||||
name: 'privateResponseMemcache',
|
||||
memcache: {
|
||||
url: ['localhost:4567'],
|
||||
},
|
||||
}],
|
||||
sessionAuth: {
|
||||
header: 'Authorization',
|
||||
tokenAuthUrl: 'https://auth.mycompany.com/engine-auth-check'
|
||||
tokenAuthUrl: 'https://auth.mycompany.com/engine-auth-check',
|
||||
},
|
||||
queryCache: {
|
||||
privateFullQueryStore: 'privateResponseMemcache'
|
||||
privateFullQueryStore: 'privateResponseMemcache',
|
||||
// By not mentioning publicFullQueryStore, we keep it enabled with
|
||||
// the default empty-string-named in-memory store.
|
||||
}
|
||||
},
|
||||
// ...
|
||||
});
|
||||
```
|
||||
|
||||
|
||||
**stores**
|
||||
|
||||
Stores is an array of places for Engine to store data such as: query responses, authentication checks, or persisted queries.
|
||||
|
||||
Every store must have a unique `name`. The empty string is a valid name; there is a default in-memory 50MB cache with the empty string for its name which is used for any caching feature if you don't specify a store name. You can specify the name of `"disabled"` to any caching feature to turn off that feature.
|
||||
Every store must have a unique `name`. The empty string is a valid name; there is a default in-memory 50MB cache with the empty string for its name which is used for any caching feature if you don't specify a store name. You can specify the name of `"disabled"` to any caching feature to turn off that feature.
|
||||
|
||||
Engine supports two types of stores:
|
||||
|
||||
- `inMemory` stores provide a bounded LRU cache embedded within the Engine Proxy.
|
||||
* `inMemory` stores provide a bounded LRU cache embedded within the Engine Proxy.
|
||||
Since there's no external servers to configure, in-memory stores are the easiest to get started with.
|
||||
Since there's no network overhead, in-memory stores are the fastest option.
|
||||
However, if you're running multiple copies of Engine Proxy, their in-memory stores won't be shared --- a cache hit on one server may be a cache miss on another server.
|
||||
@@ -613,7 +607,7 @@ Engine supports two types of stores:
|
||||
|
||||
The only configuration required for in memory stores is `cacheSize` --- an upper limit specified in bytes. It defaults to 50MB.
|
||||
|
||||
- `memcache` stores use external [Memcached](https://memcached.org/) server(s) for persistence.
|
||||
* `memcache` stores use external [Memcached](https://memcached.org/) server(s) for persistence.
|
||||
This provides a shared location for multiple copies of Engine Proxy to achieve the same cache hit rate.
|
||||
This location is also not wiped across Engine Proxy restarts.
|
||||
|
||||
@@ -644,30 +638,31 @@ One of the best parts about using caching via the Engine proxy is that you can e
|
||||
|
||||

|
||||
|
||||
|
||||
#### How HTTP headers affect caching
|
||||
|
||||
The main way that your GraphQL server specifies cache behavior is through the `cacheControl` GraphQL extension, which is rendered in the body of a GraphQL response. However, Engine also understands and sets several caching-related HTTP headers.
|
||||
|
||||
**HTTP headers interpreted by Engine**
|
||||
|
||||
Engine will never decide to cache responses in its response cache unless you tell it to with the `cacheControl` GraphQL extension. However, Engine does observe some HTTP headers and can use them to restrict caching further than what the extension says. These headers include:
|
||||
Engine will never decide to cache responses in its response cache unless you tell it to with the `cacheControl` GraphQL extension. However, Engine does observe some HTTP headers and can use them to restrict caching further than what the extension says. These headers include:
|
||||
|
||||
- `Cache-Control` **response** header: If the `Cache-Control` response header contains `no-store`, `no-cache`, or `private`, Engine will not cache the response. If the `Cache-Control` response header contains `max-age` or `s-maxage` directives, then Engine will not cache any data for longer than the specified amount of time. (That is, data will be cached for the minimum of the header-provided `max-age` and the extension-provided `maxAge`.) `s-maxage` takes precedence over `max-age`.
|
||||
- `Cache-Control` **request** header: If the `Cache-Control` request header contains `no-cache`, Engine will not look in the cache for responses. If the `Cache-Control` request header contains `no-store`, Engine will not cache the response.
|
||||
- `Expires` response header: If the `Expires` response header is present, then Engine will not cache any data past the given date. The `Cache-Control` directives `s-maxage` and `max-age` take precedence over `Expires`.
|
||||
- `Vary` response header: If the `Vary` response header is present, then Engine will not return this response to any request whose headers named in the `Vary` header don't match the request that created this response. (For example, if a request had a `Accept-Language: de` header and the response had a `Vary: Accept-Language` header, then that response won't be returned from the cache to any response that does not also have a `Accept-Language: de` header.) Additionally, Engine uses a heuristic to store requests that have different values for headers that it suspects may show up in the response `Vary` header under different cache keys; currently that heuristic is that it assumes that any header that has ever shown up in a `Vary` header in a GraphQL response may be relevant.
|
||||
* `Cache-Control` **response** header: If the `Cache-Control` response header contains `no-store`, `no-cache`, or `private`, Engine will not cache the response. If the `Cache-Control` response header contains `max-age` or `s-maxage` directives, then Engine will not cache any data for longer than the specified amount of time. (That is, data will be cached for the minimum of the header-provided `max-age` and the extension-provided `maxAge`.) `s-maxage` takes precedence over `max-age`.
|
||||
* `Cache-Control` **request** header: If the `Cache-Control` request header contains `no-cache`, Engine will not look in the cache for responses. If the `Cache-Control` request header contains `no-store`, Engine will not cache the response.
|
||||
* `Expires` response header: If the `Expires` response header is present, then Engine will not cache any data past the given date. The `Cache-Control` directives `s-maxage` and `max-age` take precedence over `Expires`.
|
||||
* `Vary` response header: If the `Vary` response header is present, then Engine will not return this response to any request whose headers named in the `Vary` header don't match the request that created this response. (For example, if a request had a `Accept-Language: de` header and the response had a `Vary: Accept-Language` header, then that response won't be returned from the cache to any response that does not also have a `Accept-Language: de` header.) Additionally, Engine uses a heuristic to store requests that have different values for headers that it suspects may show up in the response `Vary` header under different cache keys; currently that heuristic is that it assumes that any header that has ever shown up in a `Vary` header in a GraphQL response may be relevant.
|
||||
|
||||
**HTTP headers set by Engine**
|
||||
|
||||
When returning a GraphQL response which is eligible for the full-query cache (ie, all of the data has a non-zero `maxAge` set in the `cacheControl` GraphQL extension), Engine sets the `Cache-Control` header with a `max-age` directive equal to the minimum `maxAge` of all data in the response. If any of the data in the response has a `scope: PRIVATE` hint, the `Cache-Control` header will include the `private` directive; otherwise it will include the `public` directive. This header completely replaces any `Cache-Control` and `Expires` headers provided by your GraphQL server.
|
||||
|
||||
### CDN integration
|
||||
<h3 id="cdn">CDN integration</h3>
|
||||
|
||||
Many high-traffic web services use content delivery networks (CDNs) such as [Cloudflare](https://www.cloudflare.com/), [Akamai](https://www.akamai.com/) or [Fastly](https://www.fastly.com/) to cache their content as close to their clients as possible.
|
||||
|
||||
> Apollo Server 2 supports CDN integration out of the box and doesn't require the Engine Proxy. To learn how, read through the [guide on CDN integration](https://www.apollographql.com/docs/apollo-server/features/apq#cdn). For other server implementations, the Engine Proxy makes it straightforward to use CDNs with GraphQL queries whose responses can be cached while still passing more dynamic queries through to your GraphQL server.
|
||||
> Apollo Server 2 supports CDN integration out of the box and doesn't require the Engine Proxy. To learn how, read through the [guide on CDN integration](/docs/apollo-server/whats-new.html#CDN-integration). For other server implementations, the Engine Proxy makes it straightforward to use CDNs with GraphQL queries whose responses can be cached while still passing more dynamic queries through to your GraphQL server.
|
||||
|
||||
To use the Engine proxy behind a CDN, you need to be able to tell the CDN which GraphQL responses it's allowed to cache and you need to make sure that your GraphQL requests arrive in a format that CDNs cache. Engine Proxy supports this by combining its [caching](#caching) and [automatic persisted queries](#automatic-persisted-queries-apq) featues. This section explains the basic steps for setting up these features to work with CDNs; for more details on how to configure these features, see their respective sections.
|
||||
To use the Engine proxy behind a CDN, you need to be able to tell the CDN which GraphQL responses it's allowed to cache and you need to make sure that your GraphQL requests arrive in a format that CDNs cache. Engine Proxy supports this by combining its [caching](#caching) and [automatic persisted queries](#automatic-persisted-queries) featues. This section explains the basic steps for setting up these features to work with CDNs; for more details on how to configure these features, see their respective sections.
|
||||
|
||||
#### 1. Set up caching using Apollo Cache Contol
|
||||
|
||||
@@ -679,15 +674,16 @@ Once you have your server sending responses with cache hints in the `response.ex
|
||||
|
||||
At this point, GraphQL requetss are still POST requests. Most CDNs will only cache GET requests, and GET requests generally work best if the URL is of a bounded size. To work with this, enable Apollo Engine Proxy's Automatic Persisted Queries (APQ) support. This allows clients to send short hashes instead of full queries, and you can configure it to use GET requests for those queries.
|
||||
|
||||
To do this, follow the steps in the [guide above](#automatic-persisted-queries-apq). After completing the steps in that section of the guide, you should be able to observe queries being sent as `GET` requests with the appropriate `Cache-Control` response headers using your browser's developer tools.
|
||||
To do this, follow the steps in the [guide above](#automatic-persisted-queries). After completing the steps in that section of the guide, you should be able to observe queries being sent as `GET` requests with the appropriate `Cache-Control` response headers using your browser's developer tools.
|
||||
|
||||
|
||||
#### 3. Set up your CDN
|
||||
|
||||
How precisely this works relies upon which CDN you chose. Configure your CDN to send requests to your Engine proxy-powered GraphQL app. For some CDNs, you may need to specially configure your CDN to honor origin Cache-Control headers. For example, here is [Akamai's documentation on that setting](https://learn.akamai.com/en-us/webhelp/ion/oca/GUID-57C31126-F745-4FFB-AA92-6A5AAC36A8DA.html). If all is well, your cacheable queries should now be cached by your CDN! Note that requests served directly by your CDN will not show up in your Engine dashboard.
|
||||
|
||||
### Query batching
|
||||
<h3 id="query-batching">Query batching</h3>
|
||||
|
||||
Query batching allows your client to batch multiple queries into one request. This means that if you render several view components within a short time interval, for example a navbar, sidebar, and content, and each of those do their own GraphQL query, the queries can be sent together in a single roundtrip.
|
||||
Query batching allows your client to batch multiple queries into one request. This means that if you render several view components within a short time interval, for example a navbar, sidebar, and content, and each of those do their own GraphQL query, the queries can be sent together in a single roundtrip.
|
||||
|
||||
A batch of queries can be sent by simply sending a JSON-encoded array of queries in the request:
|
||||
|
||||
@@ -718,86 +714,84 @@ A batch of queries can be sent by simply sending a JSON-encoded array of queries
|
||||
|
||||
Batched requests to servers that don’t support batching fail without explicit code to handle batching, however the Engine proxy has batched request handling built-in.
|
||||
|
||||
If a batch of queries is sent, the batches are fractured by the Engine proxy and individual queries are sent to origins in parallel. Engine will wait for all the responses to complete and send a single response back to the client. The response will be an array of GraphQL results:
|
||||
If a batch of queries is sent, the batches are fractured by the Engine proxy and individual queries are sent to origins in parallel. Engine will wait for all the responses to complete and send a single response back to the client. The response will be an array of GraphQL results:
|
||||
|
||||
```js
|
||||
[
|
||||
{
|
||||
data: {
|
||||
feed: [
|
||||
{
|
||||
postedBy: {
|
||||
login: 'AleksandraKaminska'
|
||||
},
|
||||
repository: {
|
||||
name: 'GitHubApp',
|
||||
owner: {
|
||||
login: 'AleksandraKaminska'
|
||||
}
|
||||
}
|
||||
[{
|
||||
"data": {
|
||||
"feed": [
|
||||
{
|
||||
"postedBy": {
|
||||
"login": "AleksandraKaminska"
|
||||
},
|
||||
{
|
||||
postedBy: {
|
||||
login: 'ashokhein'
|
||||
},
|
||||
repository: {
|
||||
name: 'memeryde',
|
||||
owner: {
|
||||
login: 'ashokhein'
|
||||
}
|
||||
"repository": {
|
||||
"name": "GitHubApp",
|
||||
"owner": {
|
||||
"login": "AleksandraKaminska"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"postedBy": {
|
||||
"login": "ashokhein"
|
||||
},
|
||||
"repository": {
|
||||
"name": "memeryde",
|
||||
"owner": {
|
||||
"login": "ashokhein"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
data: {
|
||||
currentUser: {
|
||||
__typename: 'User',
|
||||
avatar_url: 'https://avatars2.githubusercontent.com/u/11861843?v=4',
|
||||
login: 'johannakate'
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"currentUser": {
|
||||
"__typename": "User",
|
||||
"avatar_url": "https://avatars2.githubusercontent.com/u/11861843?v=4",
|
||||
"login": "johannakate"
|
||||
}
|
||||
}
|
||||
];
|
||||
}]
|
||||
```
|
||||
|
||||
If your origin supports batching and you'd like to pass entire batches through instead of having the Engine proxy break them up, set `supportsBatch: true` within the origins section of the configuration:
|
||||
|
||||
```js
|
||||
const engine = new ApolloEngine({
|
||||
apiKey: 'ENGINE_API_KEY',
|
||||
origins: [
|
||||
{
|
||||
supportsBatch: true
|
||||
}
|
||||
]
|
||||
apiKey: "ENGINE_API_KEY",
|
||||
origins: [{
|
||||
supportsBatch: true,
|
||||
}],
|
||||
});
|
||||
```
|
||||
|
||||
#### Batching in Apollo Client with Engine
|
||||
|
||||
Apollo Client has built-in support for batching queries in your client application. To learn how to use query batching with Apollo Client, visit the in-depth guide on our package [`apollo-link-batch-http`](https://www.apollographql.com/docs/link/links/batch-http/).
|
||||
Apollo Client has built-in support for batching queries in your client application. To learn how to use query batching with Apollo Client, visit the in-depth guide on our package [`apollo-link-batch-http`](/docs/link/links/batch-http.html).
|
||||
|
||||
If you have questions, we're always available at support@apollographql.com.
|
||||
|
||||
## Proxy configuration
|
||||
|
||||
View our [full proxy configuration doc](/references/proxy-config/) for information on every available configuration option for the Engine proxy.
|
||||
View our [full proxy configuration doc](/docs/references/proxy-config.html) for information on every available configuration option for the Engine proxy.
|
||||
|
||||
## Release notes
|
||||
|
||||
View our [proxy release notes doc](/references/engine-proxy-release-notes/) for documentation on each proxy version that's been released and a changelog of what that version contained.
|
||||
View our [proxy release notes doc](/docs/references/release-notes.html) for documentation on each proxy version that's been released and a changelog of what that version contained.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
If you hit any issues in setting up Engine for your GraphQL service, we're here to help! First, follow these troubleshooting steps to check for any obvious issues.
|
||||
|
||||
#### Check that your server is supported
|
||||
|
||||
Check that your server is one of the supported GraphQL servers listed [here](https://github.com/apollographql/apollo-tracing#supported-graphql-servers).
|
||||
Check that your server is one of the supported GraphQL servers listed [here](apollo-tracing.html).
|
||||
|
||||
If it is, please make sure you're running the [currently tested version](https://github.com/apollographql/apollo-engine-js/blob/master/package.json) of Apollo Server and your Node HTTP server package (Express, Connect, Hapi, Koa, etc), and the latest released versions of the Engine and Apollo packages.
|
||||
|
||||
You can enter the following into the commandline to see the latest package version, or look in `package.json`.
|
||||
You can enter the following into the commandline to see the latest package version, or look in `package.json`.
|
||||
|
||||
```
|
||||
$ npm view apollo-engine version
|
||||
@@ -810,8 +804,8 @@ Support may request that you set the Engine Proxy logging level to DEBUG or high
|
||||
```js
|
||||
const engine = new ApolloEngine({
|
||||
logging: {
|
||||
level: 'DEBUG' // Engine Proxy logging level. DEBUG, INFO, WARN or ERROR
|
||||
}
|
||||
level: 'DEBUG' // Engine Proxy logging level. DEBUG, INFO, WARN or ERROR
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
@@ -819,7 +813,7 @@ const engine = new ApolloEngine({
|
||||
|
||||
Test that you enabled Apollo Tracing by checking if your GraphQL server returns trace extensions in GraphQL responses when not executed through Engine. If it does, it's is a sign that Apollo Tracing is properly configured.
|
||||
|
||||
### Troubleshooting FAQs
|
||||
<h3 id="troubleshooting-faqs">Troubleshooting FAQs</h3>
|
||||
|
||||
#### I'm getting an error saying “The query failed!”, how do I fix it?
|
||||
|
||||
@@ -837,7 +831,7 @@ There is a health check URL at `[engine-frontend-url]/.well-known/apollo/engine-
|
||||
|
||||
Each time the Engine proxy starts, you should see the following two lines in the logs indicating the Engine proxy is healthy:
|
||||
|
||||
```console
|
||||
```
|
||||
INFO[0000] Started HTTP server. address="[::]:50485"
|
||||
INFO[0000] Engine proxy started. version=2018.02-93-ge050c6b93
|
||||
```
|
||||
@@ -847,19 +841,20 @@ These lines say what port Engine is listening on and the internal version number
|
||||
```js
|
||||
const engine = new ApolloEngine({
|
||||
logging: {
|
||||
level: 'WARN'
|
||||
}
|
||||
level: 'WARN',
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
### Submit a support ticket
|
||||
<h3 id="get-support">Submit a support ticket</h3>
|
||||
|
||||
Please include the following when submitting an issue to our support team:
|
||||
|
||||
- Platform of GraphQL server
|
||||
- Are you using `new ApolloEngine`, `new ApolloEngineLauncher`, or the Docker container?
|
||||
- Engine configuration: arguments to `new ApolloEngine` or `new ApolloEngineLauncher`, or the JSON configuration file for the Docker container
|
||||
- Platform of GraphQL server
|
||||
- The query submitted and the full response
|
||||
* Platform of GraphQL server
|
||||
* Are you using `new ApolloEngine`, `new ApolloEngineLauncher`, or the Docker container?
|
||||
* Engine configuration: arguments to `new ApolloEngine` or `new ApolloEngineLauncher`, or the JSON configuration file for the Docker container
|
||||
* Platform of GraphQL server
|
||||
* The query submitted and the full response
|
||||
|
||||
Submit your issue to support@apollographql.com or you can join us in the public [#engine Slack Channel](https://www.apollographql.com/slack).
|
||||
|
||||
Submit your issue to support at apollographql.com or you can join us in [Apollo's Spectrum community](https://spectru.chat/apollo).
|
||||
|
||||
@@ -108,7 +108,7 @@ Many apps and sites are powered almost completely by an API such as a GraphQL sc
|
||||
|
||||
[Apollo Engine](https://www.apollographql.com/platform) is a great tool to track many of these things. It allows close inspection of fields to make it easy to see both total response times as well as how long each field took to execute.
|
||||
|
||||
Apollo Engine also has some integrations to make monitoring easier. The [Slack Integration](https://www.apollographql.com/docs/platform/integrations#slack) delivers daily reports to give teams a quick overview of the health of their schema. The [DataDog integration](https://www.apollographql.com/docs/platform/integrations#datadog)) works with existing DataDog accounts, to help teams track schema performance.
|
||||
Apollo Engine also has some integrations to make monitoring easier. The [Slack Integration](https://www.apollographql.com/docs/workflows/integrations#slack) delivers daily reports to give teams a quick overview of the health of their schema. The [DataDog integration](https://www.apollographql.com/docs/workflows/integrations#datadog)) works with existing DataDog accounts, to help teams track schema performance.
|
||||
|
||||
## Moving a product to GraphQL
|
||||
|
||||
@@ -126,6 +126,6 @@ Keeping all schema code together makes sense for smaller projects, but once a pr
|
||||
|
||||
#### How can I safely make changes to the schema?
|
||||
|
||||
Schemas naturally evolve over time. GraphQL schemas are more resilient to change than other APIs, but there are still occasions where breaking changes will need to happen to support new functionality. The [versioning guide](/platform/schema-registry/#registering-a-schema) explains in more detail what kinds of changes are safe to make, and what kinds could break existing clients.
|
||||
Schemas naturally evolve over time. GraphQL schemas are more resilient to change than other APIs, but there are still occasions where breaking changes will need to happen to support new functionality. The [versioning guide](/workflows/schema-registry/#registering-a-schema) explains in more detail what kinds of changes are safe to make, and what kinds could break existing clients.
|
||||
|
||||
Additionally, using the [Apollo CLI](https://www.npmjs.com/package/apollo) with Apollo Engine provides the tools needed to [validate schema changes](https://www.apollographql.com/docs/engine/features/schema-history.html) over time. This makes collaboration easier and more transparent.
|
||||
|
||||
@@ -164,7 +164,7 @@ An in-browser IDE for GraphQL development and workflow. Added benefits exist suc
|
||||
|
||||
## GraphQL Service
|
||||
|
||||
The server that contains a GraphQL schema and the ability to run it. Services have runtime information, and through features of the Apollo Platform they can send metrics and maintain a history of the schemas that have been run on that service in the past.
|
||||
The server that contains a GraphQL schema and the ability to run it. Services have runtime information, and through features of the Apollo platform they can send metrics and maintain a history of the schemas that have been run on that service in the past.
|
||||
|
||||
## GraphiQL
|
||||
|
||||
@@ -343,7 +343,7 @@ type Query {
|
||||
|
||||
## Schema first development
|
||||
|
||||
A [development approach](/intro/platform/#workflows) for designing and building modern UIs that involves the frontend and backend teams agreeing on a Schema first, which serves as a contract between the UI and the backend before any API engineering happens.
|
||||
A [development approach](/intro/workflows/#workflows) for designing and building modern UIs that involves the frontend and backend teams agreeing on a Schema first, which serves as a contract between the UI and the backend before any API engineering happens.
|
||||
|
||||
## Schema registry
|
||||
|
||||
@@ -351,7 +351,7 @@ A central source of truth for your schema in Apollo Engine. It enables schema re
|
||||
|
||||
## Schema versioning
|
||||
|
||||
Refers to the need to evolve a schema over time. As a schema evolves, there is a potential for introducing breaking changes to clients. The Apollo CLI assists schema evolution by validating schema changes and checking for breaking changes using Apollo Engine. Read more in our article about [schema change validation](/platform/schema-validation/#set-up-schema-validation).
|
||||
Refers to the need to evolve a schema over time. As a schema evolves, there is a potential for introducing breaking changes to clients. The Apollo CLI assists schema evolution by validating schema changes and checking for breaking changes using Apollo Engine. Read more in our article about [schema change validation](/workflows/schema-validation/#set-up-schema-validation).
|
||||
|
||||
## Schema stitching
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ support to your server language of choice.
|
||||
|
||||
Filtering queries by client enables isolation of issues that affect a portion
|
||||
of all clients. In the opposite sense, if a client becomes problematic, such as
|
||||
requesting expensive fields or using deprecated fields, the Apollo Platform
|
||||
requesting expensive fields or using deprecated fields, the Apollo platform
|
||||
enables tracking down the faulty client to start solving the issue with the
|
||||
owner. When changing, replacing, or deprecating a field in the API, the client
|
||||
metadata enables quickly identifying the client-side changes that need to
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
title: Connecting Apollo to your editor
|
||||
title: Editor plugins
|
||||
description: How to get the most out of your editor with Apollo
|
||||
---
|
||||
|
||||
@@ -7,49 +7,45 @@ GraphQL has the potential to create incredible developer experiences, thanks to
|
||||
|
||||
<img src="../images/editors/jump-to-def.gif" width="80%" style="margin: 5%" alt="Using jump to definition on a fragment">
|
||||
|
||||
## Apollo VS Code
|
||||
<h2 id="vscode">Apollo VS Code</h2>
|
||||
|
||||
The [VS Code extension](https://marketplace.visualstudio.com/items?itemName=apollographql.vscode-apollo) for Apollo brings an all-in-one tooling experience for developing apps with Apollo.
|
||||
|
||||
- Add [syntax highlighting](#syntax-highlighting) for GraphQL files and gql templates inside JavaScript files
|
||||
- Get instant feedback and [intelligent autocomplete](#intelligent-autocomplete) for fields, arguments, types, and variables as you write queries
|
||||
- Manage client side schema alongside remote schema
|
||||
- See [performance information](#performance-insights) inline with your query definitions
|
||||
- Add [syntax highlighting](#syntax) for GraphQL files and gql templates inside JavaScript files
|
||||
- Get instant feedback and [intelligent autocomplete](#autocomplete) for fields, arguments, types, and variables as you write queries
|
||||
- Seamlessly manage your client side schema alongside your remote one
|
||||
- [See performance information](#performance-insights) inline with your query definitions
|
||||
- Validate field and argument usage in operations
|
||||
- [Navigate projects more easily](#navigating-projects) with jump-to and peek-at definitions
|
||||
- [Navigate projects](#navigating-projects) easier with jump-to and peek-at definitions and more
|
||||
- Manage [client-only](#client-only-schemas) schemas
|
||||
- [Switch schema tags](#schema-variant-switching) to work with schemas running on different environments
|
||||
- [Switch schema tags](#commands) to work on upcoming features
|
||||
|
||||
## Getting started
|
||||
<h2 id="getting-started">Getting started</h2>
|
||||
|
||||
To get all of the benefits of the VS Code experience, it's best to link the schema that is being developed against **before** installing the extension. The best way to do that is by [publishing a schema](/platform/schema-registry/#registering-a-schema) to the Apollo schema registry. Once that is done, two steps are needed:
|
||||
To get all of the benefits of the VS Code experience, it's best to link the schema that is being developed against **before** installing the extension. The best way to do that is by [publishing a schema](./schema-registry.html#publish) to the Apollo schema registry. Once that is done, two steps are needed:
|
||||
|
||||
1. Create an `apollo.config.js` at the root of the project
|
||||
2. Copy an API key from the Engine dashboard of the published service
|
||||
|
||||
### Setting up an Apollo config
|
||||
|
||||
<h3 id="apollo-config">Setting up an Apollo config</h3>
|
||||
In order for the VS Code plugin to know how to find the schema, it needs to be linked to either a published schema or a local one. To link a project to a published schema, edit the `apollo.config.js` file to look like this:
|
||||
|
||||
```js
|
||||
module.exports = {
|
||||
client: {
|
||||
service: 'my-graphql-app'
|
||||
}
|
||||
service: 'my-graphql-app',
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
The `service` name here is the ID of the graph you've created in [Engine](https://engine.apollographql.com).
|
||||
The service name is the id of the service created in Engine and can be found in the services dashboard of [Engine](https://engine.apollographql.com)
|
||||
|
||||
> **Note:** The ID of your graph can be found in its URL in Engine. We use the ID so you can change your graph's name freely without having to update this. This will be easier to manage in the future.
|
||||
|
||||
### Setting up an API key
|
||||
> Important note: If the name of the service in Engine is changed, this value should be the service id. This can be found in the url when browsing the service in Engine. This will be easier to manage in the near future
|
||||
|
||||
<h3 id="api-key">Setting up an API key</h3>
|
||||
To authenticate with Engine to pull down the schema, create a file next to the `apollo.config.js` called `.env`. This should be an untraced file (i.e. don't push it to GitHub). Go to the settings page of the published service and create a new API key.
|
||||
|
||||
To authenticate with Engine to pull down the schema, create a file next to the `apollo.config.js` called `.env`. This should be an untraced file (i.e. don't push it to GitHub). Go to the settings page of your graph in Engine to get the API key.
|
||||
|
||||
> **Note:** It is best practice to create a new API key for each member of the team and name the key so its easy to find and revoke if needed. This will be easier to manage in the future.
|
||||
> It is best practice to create a new API key for each member of the team and name the key so its easy to find and revoke if needed
|
||||
|
||||
After the key is found, add the following line to the `.env` file:
|
||||
|
||||
@@ -57,9 +53,9 @@ After the key is found, add the following line to the `.env` file:
|
||||
ENGINE_API_KEY=<enter copied key here>
|
||||
```
|
||||
|
||||
After this is done, VS Code can be reloaded and the Apollo integration will connect to Engine to provide autocomplete, validation, and more.
|
||||
After this is done, VS Code can be restarted and the editor integration will start providing autocomplete, validation, and more!
|
||||
|
||||
### Local schemas
|
||||
<h3 id="local-schemas">Local schemas</h3>
|
||||
|
||||
Sometimes it may make sense to link the editor to a locally running version of a schema to try out new designs that are in active development. To do this, the `apollo.config.js` file can be linked to a local service definition:
|
||||
|
||||
@@ -68,19 +64,21 @@ module.exports = {
|
||||
client: {
|
||||
service: {
|
||||
name: 'my-graphql-app',
|
||||
url: 'http://localhost:4000/graphql'
|
||||
}
|
||||
}
|
||||
url: 'http://localhost:4000/graphql',
|
||||
},
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
Linking to the local schema won't provide all features such as switching schema tags and performance metrics. See [the Apollo config docs][] for more details on configuration options.
|
||||
> Linking to the local schema won't provide all features such as switching schema tags and performance metrics.
|
||||
|
||||
### Client-only schemas
|
||||
More information about configuring an Apollo project can be found [here](../workflows/apollo-config.html)
|
||||
|
||||
<h3 id="client-only-schemas">Client-only schemas</h3>
|
||||
|
||||
One of the best features of the VS Code extension is the automatic merging of remote schemas and local ones when using integrated state management with Apollo Client. This happens automatically whenever schema definitions are found within a client project. By default, the VS Code extension will look for all files under `./src` to find both the operations and schema definitions for building a complete schema for the application.
|
||||
|
||||
Client side schema definitions can be spread throughout the client app project and will be merged together to create one single schema. The default behavior can be controlled by adding specifictions to the `apollo.config.js`:
|
||||
Client side schema definitions can be spread throughout the client app project and will be merged together to create one single schema. If the default behavior isn't ideal, this can be controlled through the `apollo.config.js` at the root of the project:
|
||||
|
||||
```js
|
||||
module.exports = {
|
||||
@@ -92,65 +90,64 @@ module.exports = {
|
||||
}
|
||||
```
|
||||
|
||||
### Get the extension
|
||||
<h3 id="get-the-extension">Get the extension</h3>
|
||||
|
||||
Once you have a config set up and a schema published, [install the Apollo GraphQL extension](https://marketplace.visualstudio.com/items?itemName=apollographql.vscode-apollo), then try opening a file containing a GraphQL operation.
|
||||
Once you have a config set up and a schema published, **install the Apollo GraphQL extension** by using this [link](https://marketplace.visualstudio.com/items?itemName=apollographql.vscode-apollo) or by searching `Apollo` in the VS Code extension marketplace. After installation, try opening a file containing a GraphQL operation.
|
||||
|
||||
When a file open, clicking the status bar icon will open the output window and print stats about the project associated with that file. This is helpful when confirming the project is setup properly.
|
||||
|
||||
<img src="../images/editors/stats.gif" width="80%" style="margin: 5%" alt="Clicking the status bar icon to open the output pane">
|
||||
|
||||
## Features
|
||||
<h2 id="features">Features</h2>
|
||||
|
||||
Apollo for VS Code brings many helpful features for working on a GraphQL project.
|
||||
|
||||
### Intelligent autocomplete
|
||||
<h3 id="autocomplete">Intelligent autocomplete</h3>
|
||||
|
||||
Once configured, editors have full knowledge of the schema clients are running operations against, including client-only schemas (for things like local state mutations). Because of this, editors have the ability to autocomplete fields and arguments as you type.
|
||||
|
||||
<img src="../images/editors/autocomplete.gif" width="80%" style="margin: 5%" alt="vscode completing a field when typing">
|
||||
|
||||
### Inline errors and warnings
|
||||
<h3 id="errors-and-warnings">Inline errors and warnings</h3>
|
||||
|
||||
Editors can use local or published schemas to validate operations before running them. **Syntax errors**, **invalid fields or arguments**, and even **deprecated fields** instantly appear as errors or warnings right in your editor, ensuring all developers are working with the most up-to-date production schemas.
|
||||
|
||||
<img src="../images/editors/warnings-and-errors.gif" width="80%" style="margin: 5%" alt="tooltip showing a field deprecation warning and error">
|
||||
|
||||
### Inline field type information
|
||||
<h3 id="field-type-info">Inline field type information</h3>
|
||||
|
||||
Because of GraphQL's strongly-typed schema, editors not only know about which fields and arguments are valid, but also what types are expected. Hover over any type in a valid GraphQL operation to see what type that field returns and whether or not it can be null.
|
||||
|
||||
<img src="../images/editors/type-info.png" width="80%" style="margin: 5%" alt="a tooltip showing a Boolean type for a field">
|
||||
|
||||
### Performance insights
|
||||
<h3 id="performance-insights">Performance insights</h3>
|
||||
|
||||
GraphQL's flexibility can make it difficult to predict the cost of an operation. Without insight into how expensive an operation is, developers can accidentally write queries that place strain on their graph API's underlying backends. Thanks to the Apollo platform's integration with VS Code and our trace warehouse, teams can avoid these performance issues altogether by instantly seeing the cost of a query right in their editor.
|
||||
|
||||
To turn on tracing for your GraphQL server, please visit our [guide](/references/setup-analytics/).
|
||||
To turn on tracing for your GraphQL server, please visit our [guide](./setup-analytics.html).
|
||||
|
||||
The VS Code extension will show inline performance diagnostics when connected to a service with reported metrics in Engine. As operations are typed, any fields that take longer than 1ms to respond will be annoated to the right of the field inline! This gives team members a picture of how long the operation will take as more and more fields are added to operations or fragments.
|
||||
The VS Code extension will show inline performance diagnostics when connected to a service with reported metrics in Engine. As operations are typed, any fields that take longer than 1ms to respond will be annotated to the right of the field inline! This gives team members a picture of how long the operation will take as more and more fields are added to operations or fragments.
|
||||
|
||||
<img src="../images/editors/perf-annotation.png" width="80%" style="margin: 5%" alt="Performance annotation next to a field">
|
||||
|
||||
### Syntax highlighting
|
||||
<h3 id="syntax">Syntax highlighting</h3>
|
||||
|
||||
Apollo's editor extension provides syntax highlighting for all things GraphQL, including schema definitions in `.graphql` files, complex queries in TypeScript, and even client-only schema extensions. Syntax highlighting for GraphQL works out-of-the-box for `.graphql`, `.gql`, `.js` and `.ts` file types.
|
||||
Apollo's editor extension provides syntax highlighting for all things GraphQL, including schema definitions in `.graphql` files, complex queries in TypeScript, and even client-only schema extensions. Syntax highlighting for GraphQL works out-of-the-box for `.graphql`, `.gql`, `.js` and `.ts` file types!
|
||||
|
||||
### Navigating projects
|
||||
<h3 id="navigating-projects">Navigating projects</h3>
|
||||
|
||||
Navigating large codebases can be difficult, but the Apollo GraphQL extension makes this easier. Right-clicking on any field in operations or schemas gives you the ability to jump to (or peek at) definitions, as well as find any other references to that field in your project.
|
||||
Navigating large codebases can be difficult, but the Apollo GraphQL extension makes this easier than ever. Right-clicking on any field in operations or schemas gives you the ability to jump to (or peek at) definitions, as well as find any other references to that field in your project. Searching a project for any occurrence of a certain field is now a thing of the past!
|
||||
|
||||
<img src="../images/editors/jump-to-def.gif" width="80%" style="margin: 5%" alt="Using jump to definition on a fragment">
|
||||
|
||||
### Schema variant switching
|
||||
<h3 id="commands">Schema tag switching</h3>
|
||||
|
||||
Apollo supports publishing multiple versions ([variants](/platform/schema-registry/#registering-schemas-to-a-variant)) of a schema. This is useful for developing on a future development schema and preparing your clients to conform to that schema. To switch between schema variants, open the Command Palette (`cmd + shift + p` on mac), search "Apollo" and choose the "Apollo: Select Schema Tag" option.
|
||||
The Apollo GraphQL platform supports publishing multiple versions (tags) of a schema. This is useful for developing on a future development schema and preparing your clients to conform to that schema. To choose another schema tag, open the Command Palette (`cmd + shift + p` on mac), search "Apollo" and choose the "Apollo: Select Schema Tag" option.
|
||||
|
||||
## Troubleshooting
|
||||
<h2 id="troubleshooting">Troubleshooting</h2>
|
||||
|
||||
The most common errors are configuration errors, like a missing `.env` file or incorrect service information in the `apollo.config.js` file. Please see [the Apollo config docs][] for more configuration guidance.
|
||||
|
||||
[the Apollo config docs]: /references/apollo-config/
|
||||
The most common errors are configuration errors, like a missing `.env` file or incorrect service information in the `apollo.config.js` file.
|
||||
There is more information about configuring an Apollo projects [here](../workflows/apollo-config.html).
|
||||
|
||||
Other errors may be caused from an old version of a published schema. To reload a schema, open the Command Palette (`cmd + shift + p` on mac), search "Apollo" and choose the "Apollo: Reload Schema" option.
|
||||
|
||||
@@ -11,7 +11,7 @@ One of our fundamental beliefs is that our Apollo workflows should hook into and
|
||||
|
||||
## GitHub
|
||||
|
||||
Building tools to help you safely collaborate on the evolution of your graph is one of our biggest focuses at Apollo. To make [schema change validation](/platform/schema-validation/) as easy to set up as possible, we've built an Apollo app for GitHub that provides status checks on pull requests when schema changes are proposed.
|
||||
Building tools to help you safely collaborate on the evolution of your graph is one of our biggest focuses at Apollo. To make [schema change validation](/workflows/schema-validation/) as easy to set up as possible, we've built an Apollo app for GitHub that provides status checks on pull requests when schema changes are proposed.
|
||||
|
||||

|
||||
|
||||
@@ -62,7 +62,7 @@ jobs:
|
||||
fi
|
||||
```
|
||||
|
||||
> **Note:** Your `apollo service:check` command needs a source to from which to fetch your schema. This is most commonly provided as a URL to a running server (with introspection enabled), but can also be provided as a path to a file with your schema in it. See [Using the Schema Registry](/platform/schema-registry/#using-the-schema-registry) setup for other options.
|
||||
> **Note:** Your `apollo service:check` command needs a source to from which to fetch your schema. This is most commonly provided as a URL to a running server (with introspection enabled), but can also be provided as a path to a file with your schema in it. See [Using the Schema Registry](/workflows/schema-registry/#using-the-schema-registry) setup for other options.
|
||||
|
||||
The `apollo schema:check` command checks for differences in your schema between what's on your current branch and the last version you uploaded to Engine. If you've removed or changed any types or fields, it will validate that those changes won't break any of the queries that your clients have made recently. If your changes do break any queries, the check will fail.
|
||||
|
||||
@@ -5,11 +5,11 @@ description: How to secure your graph by enforcing a safelist of registered oper
|
||||
|
||||
## Overview
|
||||
|
||||
> **Note:** Operation safelisting is an Apollo Platform feature that is only available to subscribers of the [_Apollo Team_ and _Enterprise_ plans](https://www.apollographql.com/plans/). Visit [this guide](https://www.apollographql.com/docs/intro/platform.html) to learn more about the Apollo Platform.
|
||||
> **Note:** Operation safelisting is an Apollo platform feature that is only available to subscribers of the [_Apollo Team_ and _Enterprise_ plans](https://www.apollographql.com/plans/). Visit [this guide](https://www.apollographql.com/docs/intro/platform.html) to learn more about the Apollo platform.
|
||||
|
||||
Any API requires security and confidence prior to going to production. During development, GraphQL offers front-end engineers the ability to explore all the data available to them and fetch exactly what they need for the components they're building. However, in production, it can be unnecessary and undesirable to provide this flexibility.
|
||||
|
||||
The Apollo Platform comes with an **operation registry** and **safelisting** mechanism built into it, which allows organizations to:
|
||||
The Apollo platform comes with an **operation registry** and **safelisting** mechanism built into it, which allows organizations to:
|
||||
|
||||
- Provide demand control for their production GraphQL APIs.
|
||||
- Permit the exact operations necessary for their client applications.
|
||||
@@ -58,7 +58,7 @@ npm install apollo --save-dev
|
||||
|
||||
### 2. Push your schema to the Apollo schema registry
|
||||
|
||||
> **Note:** If this server's schema has already been registered using `apollo service:push`, you can skip this step. For additional options and details, see the [documentation for the schema registry](/platform/schema-registry/).
|
||||
> **Note:** If this server's schema has already been registered using `apollo service:push`, you can skip this step. For additional options and details, see the [documentation for the schema registry](/workflows/schema-registry/).
|
||||
|
||||
First, make sure Apollo Server is running and that introspection is enabled (it is often disabled in production).
|
||||
|
||||
@@ -132,5 +132,5 @@ const server = new ApolloServer({
|
||||
Keeping your schema up-to-date in Apollo's registry will ensure that you get the best experience from Apollo's tools that connect to the registry:
|
||||
|
||||
- The [Apollo VS Code extension](https://marketplace.visualstudio.com/items?itemName=apollographql.vscode-apollo) provides built-in linting on queries by validating against the schema in your registry. It also annotates fields with their descriptions and with performance indicators collected in Apollo's trace warehouse.
|
||||
- The [schema validation](/platform/schema-validation/) workflow protects your team from accidentally making breaking schema changes. It creates a diff between your local schema and the last schema pushed to the registry, and validates this diff against live traffic seen on your endpoint to warn you about problematic changes.
|
||||
- The [schema validation](/workflows/schema-validation/) workflow protects your team from accidentally making breaking schema changes. It creates a diff between your local schema and the last schema pushed to the registry, and validates this diff against live traffic seen on your endpoint to warn you about problematic changes.
|
||||
- Your schema's full history and current usage can be seen in [Apollo Engine](https://engine.apollographql.com). The History page tracks changes made over time, and the Explorer page shows which clients and which queries are using each field in your schema.
|
||||
308
docs/source/workflows/schema-validation.md
Normal file
308
docs/source/workflows/schema-validation.md
Normal file
@@ -0,0 +1,308 @@
|
||||
---
|
||||
title: Validating schema changes
|
||||
description: Check if proposed schema changes are safe or breaking by comparing against live server traffic
|
||||
---
|
||||
|
||||
As GraphQL scales within an organization, evolving the schema to contain necessary fields only while guaranteeing that no query or client will break from a change. Some organizations take the approach of _never_ making schema changes that might be breaking, which leads to an ever-growing schema and reduced api accessibility. In reality, removing field removal and updating return types is safe with tools to guarantee that no change will ever break an active query.
|
||||
|
||||
As such, schema change validation is one of the cornerstones of the [Apollo platform](/docs/intro/platform.html) and we've built a set of tools to make the workflow possible.
|
||||
|
||||
> **Note:** Schema validation is an Apollo platform feature available on the [_Team_ and _Enterprise_ plans](https://www.apollographql.com/plans/). To get started with the Apollo platform, begin with [the documentation](https://www.apollographql.com/docs/). If you already have an Engine account, upgrade to a Team plan [here](https://engine.apollographql.com/trypro).
|
||||
|
||||
<h2 id="schema-validation">How it works</h2>
|
||||
|
||||
The schema validation mechanism utilizes both Apollo's schema registry and Apollo's trace warehouse. The **schema registry** is used to compute a "schema diff" with changes between schema versions. The **trace warehouse** is used to identify which schema fields have been recently used by clients and operations seen in a deployed system. We compare each change in the schema diff against the live usage data to determine if that change is "breaking change" for any clients.
|
||||
|
||||
Here's how it works:
|
||||
|
||||
1. You run `apollo service:check` locally or in CI. The proposed schema is sent to Engine's schema registry.
|
||||
1. Engine creates a diff between the local schema and the most recently published schema in the registry.
|
||||
1. Engine fetches a list of all operations sent to your service in your plan's maximum time window (time window is [configurable](#cli-advanced)).
|
||||
1. Engine walks through the schema diff change-by-change and compares against the operation list to see if the changes will affect the behavior of any operations.
|
||||
1. Engine will return the schema diff and indicate any breaking changes found.
|
||||
1. The CLI will print the output of this check with a link to _view more details in the Engine UI_.
|
||||
|
||||
<h3 id="algorithm">Breaking change detection</h3>
|
||||
|
||||
Engine's cloud service uses an algorithm to detect breaking changes in a schema diff. The following sections describe the rules that determine when a change type _fails_ the `apollo service:check` command, which returns a non-zero exit code. If these changes are deployed without additional scrutiny, clients could experience unexpected behavior.
|
||||
|
||||
#### Removals
|
||||
|
||||
Each of these changes removes a schema element. If the element is actively used by an operation and removed, the GraphQL layer will return an error to the dependent operation.
|
||||
|
||||
<ul>
|
||||
<li id="FIELD_REMOVED">
|
||||
<code>FIELD_REMOVED</code> Field used by at least one operation was removed
|
||||
</li>
|
||||
<li id="TYPE_REMOVED">
|
||||
<code>TYPE_REMOVED</code> Type(scalar, object) used by at least one operation was removed
|
||||
</li>
|
||||
<li id="ARG_REMOVED">
|
||||
<code>ARG_REMOVED</code> Argument was removed from a field used by at least one operation
|
||||
</li>
|
||||
<li id="TYPE_REMOVED_FROM_UNION">
|
||||
<code>TYPE_REMOVED_FROM_UNION</code> Type was removed from a union used by at least one operation
|
||||
</li>
|
||||
<li id="INPUT_FIELD_REMOVED">
|
||||
<code>INPUT_FIELD_REMOVED</code> Field removed from an input type referenced by an argument on a field used by at least one operation
|
||||
</li>
|
||||
<li id="VALUE_REMOVED_FROM_ENUM">
|
||||
<code>VALUE_REMOVED_FROM_ENUM</code> A value removed from an enum used by at least one operation
|
||||
</li>
|
||||
<li id="TYPE_REMOVED_FROM_INTERFACE">
|
||||
<code>TYPE_REMOVED_FROM_INTERFACE</code> An object removed from an interface used by at least one operation
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
#### Required arguments
|
||||
|
||||
Each of these changes adds a required input to a schema element. If an existing operation uses the schema element, the GraphQL layer will return an error to the dependent operation.
|
||||
|
||||
<ul>
|
||||
<li id="REQUIRED_ARG_ADDED">
|
||||
<code>REQUIRED_ARG_ADDED</code> Non-nullable argument added to field used by at least one operation
|
||||
</li>
|
||||
<li id="NON_NULL_INPUT_FIELD_ADDED">
|
||||
<code>NON_NULL_INPUT_FIELD_ADDED</code> Non-null field added to an input object used by at least one operation
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
#### In-place updates
|
||||
|
||||
Each of these changes updates an existing schema element. Any operation that uses the schema element could receive an error or in some cases an unexpected result.
|
||||
|
||||
> Note: in some rare cases, these changes are compatible with the client at runtime, such as a type rename or an object to interface conversion with the same fields. Schema validation marks these breaking changes, since validation does not have enough information to ensure safety and the changes deserve extra scrutiny, such as their impact on type generation.
|
||||
|
||||
<ul>
|
||||
<li id="FIELD_CHANGED_TYPE">
|
||||
<code>FIELD_CHANGED_TYPE</code> Field used by at least one operation changed return type
|
||||
</li>
|
||||
<li id="INPUT_FIELD_CHANGED_TYPE">
|
||||
<code>INPUT_FIELD_CHANGED_TYPE</code> Field in input object changed type and is referenced by argument on field used by at least one operation
|
||||
</li>
|
||||
<li id="TYPE_CHANGED_KIND">
|
||||
<code>TYPE_CHANGED_KIND</code> Type used by at least one operation changed, ex: scalar to object or enum to union
|
||||
</li>
|
||||
<li id="ARG_CHANGED_TYPE">
|
||||
<code>ARG_CHANGED_TYPE</code> Argument changed type on field used by at least one operation
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
#### Type extensions
|
||||
|
||||
These changes add a type to an existing union or interface. Any operation that uses the union or interface could receive an unexpected result depending on the fragment spreads requested.
|
||||
|
||||
<ul>
|
||||
<li id="TYPE_ADDED_TO_UNION">
|
||||
<code>TYPE_ADDED_TO_UNION</code> Type added to a union used by at least one operation
|
||||
</li>
|
||||
<li id="TYPE_ADDED_TO_INTERFACE">
|
||||
<code>TYPE_ADDED_TO_INTERFACE</code> Interface added to an object used by at least one operation
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
#### Default arguments
|
||||
|
||||
These changes update the default value for an argument. If an operation does not specify a value for this argument and relies on the value, the operation can experience unexpected results, which can lead to modified client behavior.
|
||||
|
||||
<ul>
|
||||
<li id="ARG_DEFAULT_VALUE_CHANGE">
|
||||
<code>ARG_DEFAULT_VALUE_CHANGE</code> Default value added or changed for argument on a field used by at least one operation
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
> For the rest of the changes returned by `service:check`, see the [list of compatible changes](#compatible-changes)
|
||||
|
||||
A failed `apollo service:check` command will exit with a non-0 exit code and fail CI checks! There are many cases where it is safe to make a potentially breaking change, as long as the change is made intentionally with an understanding of its impact.
|
||||
|
||||
Since breaking changes are detected using live traffic, **your service will need active metrics** for the change algorithm to detect failures. If there are no metrics associated with your service, _all_ changes will be assigned the `NOTICE` severity as opposed to the `FAILURE` severity.
|
||||
|
||||
### Validation output
|
||||
|
||||
Running a schema validation check is as simple as running `apollo service:check` on the command line from within a service repository that has been configured to be an Apollo project.
|
||||
|
||||
> **Note:** [Skip to the setup section](#setup) for details on how to configure your project for schema change validation.
|
||||
|
||||
Running the `apollo service:check` command will output the diff of all schema changes found and highlight changes determined to be breaking as `FAILURE`. Here's an example:
|
||||
|
||||
```console
|
||||
~example$ npx apollo service:check --tag=prod
|
||||
✔ Loading Apollo Project
|
||||
✔ Validated local schema against tag prod on service engine
|
||||
✔ Compared 8 schema changes against 110 operations over the last 24 hours
|
||||
✖ Found 3 breaking changes and 5 compatible changes
|
||||
→ breaking changes found
|
||||
|
||||
FAIL ARG_REMOVED `ServiceMutation.checkSchema` arg `gitContext` was removed
|
||||
FAIL FIELD_REMOVED `Schema.fieldCount` was removed
|
||||
FAIL FIELD_REMOVED `Schema.typeCount` was removed
|
||||
|
||||
PASS FIELD_ADDED `SchemaTag.schemaRepoID` was added
|
||||
PASS FIELD_CHANGED_TYPE `ServiceMutation.uploadPartialSchema` changed type from `UploadPartialSchemaResponse!` to `CompositionResult!`
|
||||
PASS FIELD_DEPRECATION_REMOVED `IntrospectionSchema.fieldCount` is no longer deprecated
|
||||
PASS FIELD_DEPRECATION_REMOVED `IntrospectionSchema.typeCount` is no longer deprecated
|
||||
PASS TYPE_REMOVED `UploadPartialSchemaResponse` removed
|
||||
|
||||
View full details at: https://engine.apollographql.com/service/example-1234/check/<DETAILS>
|
||||
```
|
||||
|
||||
If there are any changes to the schema, `FAILURE` or `NOTICE`, a URL to Engine will be generated with details showing which clients and operations are affected by the changes specifically:
|
||||
|
||||
<img src="../img/schema-validation/service-check-page.png" width="100%" alt="Service check page in the Engine UI">
|
||||
|
||||
The Service Check page in Engine will have full details on the changes in the diff and which clients are affected by the changes, if any.
|
||||
|
||||
> **Note:** If you [set up your checks on GitHub](#github), the "Details" link in your checks will take you to this special URL as well.
|
||||
|
||||
<h2 id="setup">Set up schema validation</h2>
|
||||
|
||||
You will need to be actively sending traces to the Apollo trace warehouse and registering schemas to the Apollo schema registry to properly use schema validation. Follow these guides to set those up:
|
||||
|
||||
1. [Set up trace reporting to Apollo Engine](/docs/workflows/setup-analytics.html) (either through Apollo Server 2+ or the Engine proxy).
|
||||
1. [Set up schema registration in your continuous delivery pipeline](/docs/workflows/schema-registry.html).
|
||||
|
||||
For the `apollo service:check` command to be configured properly, you will also need:
|
||||
|
||||
1. [A `.env` file with an `ENGINE_API_KEY`](/docs/workflows/schema-registry.html#Get-your-Engine-API-key).
|
||||
1. [An `apollo.config.js` file with a `service` configured](/docs/workflows/schema-registry.html#Create-an-apollo-config-js-file).
|
||||
|
||||
If you have set up schema registration, your project may already have its `.env` file and `apollo.config.js` file configured. Once you've got these set up, running your schema check is as simple as running:
|
||||
|
||||
```console
|
||||
$ npm install apollo
|
||||
$ npx apollo service:check
|
||||
```
|
||||
|
||||
The command can be placed in any continuous integration pipeline. To surface results, `apollo` emits an exit code and [integrates with GitHub statuses](#github). The check command validates against traffic from the past day by default, but this time window can be [configured](#cli-advanced) to be a longer range.
|
||||
|
||||
> **Note:** The Apollo CLI will be looking in your Apollo config for a location from which to fetch your local schema and using your ENGINE_API_KEY to authenticate its requests with the Engine service.
|
||||
|
||||
<h3 id="service-check-on-ci">Run validation on each commit</h3>
|
||||
|
||||
We highly recommended that you add validation to your continuous integration workflow (e.g. Jenkins, CircleCI, etc.). In doing so, you can detect potential problems automatically and display the results of checks directly on pull requests.
|
||||
|
||||
Here's a example of how to add a schema validation check to CircleCI:
|
||||
|
||||
```yaml line=29
|
||||
version: 2
|
||||
|
||||
jobs:
|
||||
build:
|
||||
docker:
|
||||
- image: circleci/node:8
|
||||
|
||||
steps:
|
||||
- checkout
|
||||
|
||||
- run: npm install
|
||||
|
||||
# Start the GraphQL server. If a different command is used to
|
||||
# start the server, use it in place of `npm start` here.
|
||||
- run:
|
||||
name: Starting server
|
||||
command: npm start
|
||||
background: true
|
||||
|
||||
# make sure the server has enough time to start up before running
|
||||
# commands against it
|
||||
- run: sleep 5
|
||||
|
||||
# This will authenticate using the `ENGINE_API_KEY` environment
|
||||
# variable. Configure your endpoint's location in your Apollo config.
|
||||
- run: npx apollo service:check
|
||||
```
|
||||
|
||||
> **Note:** With a GitHub status check, to allow continuous integration to complete without failing early, ignore the exit code of the `apollo service:check` command. The exit code can be ignored by appending `|| echo 'validation failed'` to the command call.
|
||||
|
||||
<h3 id="github">GitHub integration</h3>
|
||||
|
||||
<div style="text-align:center">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
Like most tools, schema validation is best used when it is integrated directly into the rest of your workflow. If you're using GitHub, you can install the Apollo Engine GitHub app. This will enable Apollo's systems to send a webhook back to your project on each `apollo service:check`, providing built-in pass/fail status checks on your pull requests.
|
||||
|
||||
Go to [https://github.com/apps/apollo-engine](https://github.com/apps/apollo-engine) and click the `Configure` button to install the Apollo Engine integration on the appropriate GitHub profile or organization.
|
||||
|
||||
<h3 id="multiple-environments">Multiple environments</h3>
|
||||
|
||||
Product cycles move fast, and it’s common for schemas to be slightly different across environments as changes make their way through your system. To accommodate for this, schemas can be registered under specific schema tags and checks can be performed against specific schema tags.
|
||||
|
||||
Tags mostly commonly represent environments and can also indicate branches or future schemas. Passing the `--tag` flag to `apollo service:check` specifies which schema to compare against, such as `prod` or `staging`. It's common to run checks against multiple different schema tags during continuous integration to ensure that all important deployments are accounted for. Checking multiple tags will result in check statuses similar to:
|
||||
|
||||
<div style="text-align:center">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
<h2 id="cli-advanced">Adjusting validation parameters</h2>
|
||||
|
||||
Depending on the requirements of your application, you may want to configure the timeframe to validate operations against. You can do so by providing a `validationPeriod` flag to the CLI. The timeframe will always end at "now", and go back in time by the amount specified.
|
||||
|
||||
```bash
|
||||
apollo service:check --validationPeriod=P2W
|
||||
```
|
||||
|
||||
> Valid durations are represented in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601#Durations). It can also be provided as a number in seconds, i.e. 86400 for a single day.
|
||||
|
||||
Two other parameters for customizing the results of `service:check` are threshold values. For example, you may wish to drop support for an old version of an app in order to remove some deprecated fields. Using these parameters, you can decide what amount of breakage is acceptable before shipping any breaking changes.
|
||||
|
||||
- `queryCountThreshold` - This flag will only validate the schema against operations that have been executed at least the specified number of times within the provided duration.
|
||||
- `queryCountThresholdPercentage` - Similar to `queryCountThreshold`, but expressed as a percentage of all operation volume.
|
||||
> Note: these flags are compatible with each other. In the case that both are provided, an operation must meet or exceed both thresholds.
|
||||
|
||||
If you have requests for other filtering or threshold mechanisms, we'd love to hear them! Please feel free to submit a [feature request](https://github.com/apollographql/apollo-tooling/issues/new?template=feature-request.md) or PR to the [apollo-tooling](https://github.com/apollographql/apollo-tooling/) repo.
|
||||
|
||||
```bash
|
||||
npx apollo service:check \
|
||||
# Validate the schema against operations that have run in the last 5 days
|
||||
--validationPeriod=P5D \
|
||||
# Only validate against operations that have run at least 5 times during the 5 day duration
|
||||
--queryCountThreshold=5 \
|
||||
# Only validate against operations that account for at least 3% of total operation volume
|
||||
--queryCountThresholdPercentage=3
|
||||
```
|
||||
|
||||
<h2 id="compatible-changes">Compatible Changes</h2>
|
||||
|
||||
The following changes are compatible with existing clients by default, since they will not affect the behavior of clients.
|
||||
|
||||
#### Optional arguments
|
||||
|
||||
Optional arguments include changes that add any input that can be nullable.
|
||||
Existing operations will not include the new value. The behavior of the clients will
|
||||
stay the same provided the result of the operation remains the same with a <code>null</code> input.
|
||||
|
||||
<ul>
|
||||
<li id="OPTIONAL_ARG_ADDED"><code>OPTIONAL_ARG_ADDED</code> Nullable argument added to a field</li>
|
||||
<li id="NULLABLE_FIELD_ADDED_TO_INPUT_OBJECT"><code>NULLABLE_FIELD_ADDED_TO_INPUT_OBJECT</code> Nullable field added to an input object</li>
|
||||
</ul>
|
||||
|
||||
#### Additions
|
||||
|
||||
Additions are changes that will not affect client behavior, since clients
|
||||
will not access the new schema elements.
|
||||
|
||||
<ul>
|
||||
<li id="FIELD_ADDED"><code>FIELD_ADDED</code> Field added to a type</li>
|
||||
<li id="TYPE_ADDED"><code>TYPE_ADDED</code> Type added to the schema</li>
|
||||
<li id="VALUE_ADDED_TO_ENUM"><code>VALUE_ADDED_TO_ENUM</code> Value added to an enum. If clients contain a switch case on the enum and do not include the `default`, this change could cause unexpected behavior</li>
|
||||
</ul>
|
||||
|
||||
#### Deprecations
|
||||
|
||||
Deprecations will not affect the behavior of the clients directly, since
|
||||
they are a signal to developer to avoid the schema element rather than a
|
||||
behavior change.
|
||||
|
||||
<ul>
|
||||
<li id="FIELD_DEPRECATED"><code>FIELD_DEPRECATED</code> Field deprecated</li>
|
||||
<li id="FIELD_DEPRECATION_REMOVED"><code>FIELD_DEPRECATION_REMOVED</code> Field no longer deprecated</li>
|
||||
<li id="FIELD_DEPRECATED_REASON_CHANGE"><code>FIELD_DEPRECATED_REASON_CHANGE</code> Reason for deprecation changed</li>
|
||||
<li id="ENUM_DEPRECATED"><code>ENUM_DEPRECATED</code> Enum deprecated</li>
|
||||
<li id="ENUM_DEPRECATION_REMOVED"><code>ENUM_DEPRECATION_REMOVED</code> Enum no longer deprecated</li>
|
||||
<li id="ENUM_DEPRECATED_REASON_CHANGE"><code>ENUM_DEPRECATED_REASON_CHANGE</code> Reason for enum deprecation changed</li>
|
||||
</ul>
|
||||
@@ -7,7 +7,7 @@ There are many types of schema changes that can be potentially breaking to clien
|
||||
|
||||
Apollo provides a tool to protect for exactly this scenario called **schema validation**.
|
||||
|
||||
> **Note:** Schema validation is an Apollo Platform feature available on the [Team and Enterprise plans](https://www.apollographql.com/plans/) of [Apollo Engine](https://engine.apollographql.com).
|
||||
> **Note:** Schema validation is an Apollo platform feature available on the [Team and Enterprise plans](https://www.apollographql.com/plans/) of [Apollo Engine](https://engine.apollographql.com).
|
||||
|
||||
## How it works
|
||||
|
||||
@@ -182,7 +182,7 @@ Since breaking changes are detected using live traffic, your service will _need
|
||||
To set up schema validation, you wlil need to be both actively sending traces and registering schemas to Apollo:
|
||||
|
||||
1. [Set up trace reporting to Apollo Engine](/references/setup-analytics/)
|
||||
1. [Set up schema registration in your continuous delivery pipeline](/platform/schema-registry/)
|
||||
1. [Set up schema registration in your continuous delivery pipeline](/workflows/schema-registry/)
|
||||
|
||||
Then, you will need to configure your project for the `apollo service:check` command:
|
||||
|
||||
16
docs/static/_redirects
vendored
16
docs/static/_redirects
vendored
@@ -1,13 +1,13 @@
|
||||
/ /docs/
|
||||
|
||||
# Redirect Removed Guides to Platform Features
|
||||
/docs/guides/security.html /docs/platform/operation-registry.html
|
||||
/docs/guides/monitoring.html /docs/platform/integrations.html
|
||||
/docs/guides/versioning.html /docs/platform/schema-validation.html#versioning
|
||||
/docs/guides/security.html /docs/workflows/operation-registry.html
|
||||
/docs/guides/monitoring.html /docs/workflows/integrations.html
|
||||
/docs/guides/versioning.html /docs/workflows/schema-validation.html#versioning
|
||||
|
||||
# This lived here for a short period of time.
|
||||
/docs/resources/apollo-config.html /docs/platform/apollo-config.html
|
||||
/docs/platform/setup-analytics.html /docs/references/setup-analytics.html
|
||||
/docs/resources/apollo-config.html /docs/workflows/apollo-config.html
|
||||
/docs/workflows/setup-analytics.html /docs/references/setup-analytics.html
|
||||
|
||||
# Redirect Removed Guides to Client & Server Docs
|
||||
/docs/guides/schema-design.html /docs/apollo-server/essentials/schema.html
|
||||
@@ -15,11 +15,11 @@
|
||||
/docs/guides/state-management.html /docs/react/essentials/local-state.html
|
||||
/docs/guides/access-control.html /docs/apollo-server/features/authentication.html
|
||||
|
||||
/docs/platform/tracing.html /docs/platform/performance.html
|
||||
/docs/platform/errors.html /docs/platform/performance.html
|
||||
/docs/workflows/tracing.html /docs/workflows/performance.html
|
||||
/docs/workflows/errors.html /docs/workflows/performance.html
|
||||
|
||||
# File uploads no longer have a home, but the blog post is the same content.
|
||||
/docs/guides/file-uploads.html https://blog.apollographql.com/file-uploads-with-apollo-server-2-0-5db2f3f60675
|
||||
|
||||
# Move our Apollo config docs to the References section
|
||||
/docs/platform/apollo-config.html /docs/references/apollo-config.html
|
||||
/docs/workflows/apollo-config.html /docs/references/apollo-config.html
|
||||
|
||||
Reference in New Issue
Block a user