Working with Router

Configuring GraphOS Router for Apollo Connectors


Preview
Apollo Connectors are currently in public preview. To get started, you need an Apollo account with a GraphOS Trial or Enterprise plan.

Overriding baseURL for environment-specific API hosts

When using a self-hosted router, the baseURL of a @source directive can be overridden in the router configuration file.

For example, this configuration overrides the baseURL for all @connect directives in the subgraph that reference the v1 source:

YAML
Base URL override example
1preview_connectors:
2  subgraphs:
3    example: # The name of the subgraph
4      sources:
5        v1: # Refers to @source(name: "v1")
6          override_url: "https://api.example.com/v1/beta"
 note
If a @connect directive doesn't specify the source attribute, its URL can't be overridden.

Configuration and environment variables

You may want to use a configuration value or environment variable as part of a request. You can do this per subgraph in the router configuration by using the $config section of each connectors subgraph:

YAML
router.yaml
1preview_connectors:
2  subgraphs:
3    name_of_the_subgraph:
4      $config:
5        name_of_the_variable: value

You can then access the value using the $config variable in the schema, for example in the URL template or header of a connector:

GraphQL
1type Query {
2  something: String!
3    @connect(
4      http: {
5        GET: "https://api.example.com/products/{$config.name_of_the_variable}"
6        headers: [
7          {
8            name: "Authorization"
9            value: "Bearer {$config.name_of_variable_containing_token}"
10          }
11        ]
12      }
13      selection: ""
14    )
15}

You can use $config in the same locations as $this and $args.

You can also access nested values using dot notation. For example $config.nested.value would refer to:

YAML
router.yaml
1preview_connectors:
2  subgraphs:
3    name_of_the_subgraph:
4      $config:
5        nested:
6          value: "some value"

Router configuration also lets you inject environment variables, like this:

YAML
router.yaml
1preview_connectors:
2  subgraphs:
3    name_of_the_subgraph:
4      $config:
5        name_of_the_variable: ${env.VARIABLE_NAME}

Request Limits

The maximum number of REST API requests for each GraphQL operation can be configured in the router. This can help avoid overwhelming upstream services. Once the limit has been reached, a null value will be returned in the GraphQL result for any fields with @connect directives whose requests were not executed. Additionally, a GraphQL error will be returned in the errors array of the response. Partial data may still be returned for portions of the operation that were not affected by the limit.

The limit can be set generally in the router config YAML:

YAML
router.yaml
1preview_connectors:
2  max_requests_per_operation_per_source: 100

This will limit the number of requests made to each connector source for a given GraphQL operation. If a connector does not define a source, then this limit is applied at the connector level.

The limit can also be configured for each individual connector source:

YAML
router.yaml
1preview_connectors:
2  subgraphs:
3    subgraph_name:
4      sources:
5        source_name:
6          max_requests_per_operation: 50

Limits set on an individual source will override the general max_requests_per_operation_per_source limit.

The limit can also be configured by setting the environment variable APOLLO_CONNECTORS_MAX_REQUESTS_PER_OPERATION. Any configuration in the YAML file will override the environment variable setting.

Telemetry

Router telemetry can be configured for connectors.

Attributes

Attributes can be attached to telemetry such as instruments and events. These attributes are used to filter and group data in your application performance monitor (APM).

The following standard attributes are available for connectors:

AttributeDescription
subgraph.nameThe name of the subgraph containing the connector
connector.source.nameThe name of the @source associated with this connector, if any
connector.http.methodThe HTTP method for the connector (GET or POST, for example)
connector.url.templateThe URL template for the connector
Selectors

A selector is used to extract data from connectors requests and responses and attach the data to telemetry such as instruments and events.

Apollo Connectors for REST APIs make HTTP calls to the upstream HTTP API. The selectors in the following table let you extract metrics from these HTTP requests and responses.

SelectorDefaultableValuesDescription
subgraph_nameNotrue|falseThe name of the subgraph containing the connector
connector_source NonameThe name of the @source associated with this connector, if any
connector_http_request_headerYesThe name of a connector request header
connector_http_response_headerYesThe name of a connector response header
connector_http_response_statusNocode|reasonThe status of a connector response
connector_http_methodNotrue|falseThe HTTP method of a connector request
connector_url_template Notrue|falseThe URL template of a connector request
staticNoA static string value
errorNoreasonA string value containing error reason when it's a critical error

Instruments

An instrument in the router collects data and reports measurements to a metric backend. Supported instruments include standard instruments from OpenTelemetry, standard instruments for the router's request lifecycle, and custom instruments. Supported instrument kinds are counters and histograms.

You can configure instruments in router.yaml with telemetry.instrumentation.instruments.

OpenTelemetry standard instruments

OpenTelemetry specifies multiple standard metric instruments that are available for connectors HTTP requests and responses:

  • http.client.request.body.size - A histogram of request body sizes for connectors HTTP requests.

  • http.client.request.duration - A histogram of request durations for connectors HTTP requests.

  • http.client.response.body.size - A histogram of response body sizes for connectors HTTP responses.

These instruments are configurable in router.yaml:

YAML
router.yaml
1telemetry:
2  instrumentation:
3    instruments:
4      connector:
5        http.client.request.body.size: true
6        http.client.request.duration: true
7        http.client.response.body.size: true

The default_requirement_level setting configures whether or not these instruments are enabled by default. They can be customized by attaching or removing attributes. See attributes to learn more about configuring attributes.

YAML
router.yaml
1telemetry:
2  instrumentation:
3    instruments:
4      connector:
5        http.client.request.duration:
6          attributes:
7            connector.source.name: true
Custom instruments
This feature is only available with a GraphOS Dedicated or Enterprise plan. You can test it out by signing up for a free GraphOS trial. To compare GraphOS feature support across all plan types, see the pricing page.

You can define custom instruments on connectors HTTP requests and responses.

For example, the following custom instrument provides the number of 404 response statuses from a specific REST API:

YAML
router.yaml
1telemetry:
2  instrumentation:
3    instruments:
4      connector:
5        acme.user.not.found:
6          value: unit
7          type: counter
8          unit: count
9          description: "Count of 404 responses from the user API"
10          condition:
11            all:
12              - eq:
13                  - 404
14                  - connector_http_response_status: code
15              - eq:
16                  - "user_api"
17                  - connector_source: name

See the router documentation for more details about configuring instruments.

Events

An event is used to signal when something of note happens, such as a connector request or response.

You can configure events for each service in router.yaml. Events can be standard or custom, and they can be triggered by configurable conditions.

See the router documentation for more details about configuring events.

Standard events

Standard events can be configured for connectors. The following enables standard connector HTTP response events at the INFO level:

YAML
router.yaml
1events:
2  connector:
3    request: off
4    response: info
5    error: error
Custom events

Custom events can also be configured for connectors. The following example defines a custom event for each connector HTTP response at the INFO level:

YAML
router.yaml
1events:
2  connector:
3    connector.response:
4      message: "Connector response"
5      level: info
6      on: response
7      attributes:
8        connector.http.method: true
9        connector.url.template: true
10        response_status:
11          connector_http_response_status: code

If you have a stdout logging exporter, the router will then log each connector response with the attributes defined above:

Text
1INFO  connector.http.method=GET connector.url.template=/users response_status=200 Connector response kind=connector.response
2INFO  connector.http.method=GET connector.url.template=/users/{$this.id}/posts response_status=200 Connector response kind=connector.response

Authentication

Apollo Connectors can be used to call AWS HTTP APIs using AWS Signature Version 4 (SigV4). For example, you can use Apollo Connectors to invoke an AWS Lambda function and select fields from the JSON result to include in your GraphQL response:

GraphQL
1@source(
2  name: "lambda"
3  http: { baseURL: "https://lambda.us-east-1.amazonaws.com" }
4)
5...
6  @connect(
7    source: "lambda"
8    http: {
9      POST: "/2015-03-31/functions/function_name/invocations"
10      body: "argument: $this.function_argument"
11    }
12    selection: "$.function_output"
13  )

SigV4 authentication is configured separately for each connector source, allowing you to specify a role with the least-privilege necessary to invoke the AWS API for that source:

YAML
router.yaml
1authentication:
2  connector:
3    sources:
4      subgraph_name.connector_source_name:
5        aws_sig_v4:
6          default_chain:
7            profile_name: "default"
8            region: "us-east-1"
9            service_name: "lambda"
10            assume_role:
11              role_arn: "arn:aws:iam::XXXXXXXXXXXX:role/lambaexecute"
12              session_name: "connector"

Authentication with coprocessors

You can use coprocessors to fetch authentication tokens for connectors. This is useful when you need to fetch a token from a different source, such as a database or a third-party service, before making a request to an API.

Start by configuring the coprocessor for the Execution Request stage and enabling the expose_sources_in_context feature of connectors:

YAML
router.yaml
1preview_connectors:
2  expose_sources_in_context: true
3coprocessor:
4  url: http://localhost:4001
5  execution:
6    request:
7      context: true

In the context of the coprocessor request, you will find a list of subgraph and source names from the query plan. You can use this information to determine which identity providers (IDPs) to query for tokens.

JSON
Coprocessor request
1{
2  "version": 1,
3  "stage": "ExecutionRequest",
4  "control": "continue",
5  "id": "d0a8245df0efe8aa38a80dba1147fb2e",
6  "context": {
7    "entries": {
8      "apollo_connectors::sources_in_query_plan": [
9        { "subgraph_name": "products", "source_name": "v1" }
10      ]
11    }
12  }
13}

In the coprocessor response, you can add the API keys for each source to the context:

JSON
Coprocessor response
1{
2  "version": 1,
3  "stage": "ExecutionRequest",
4  "control": "continue",
5  "id": "d0a8245df0efe8aa38a80dba1147fb2e",
6  "context": {
7    "entries": {
8      "apollo_connectors::sources_in_query_plan": [
9        { "subgraph_name": "products", "source_name": "v1" }
10      ],
11      "api_keys": {
12        "products_v1": "abcd1234"
13      }
14    }
15  }
16}

Then in the configuration for your connector source, you can use the keys from the context as header values:

GraphQL
products.graphql
1extend schema
2  @source(
3    name: "v1"
4    http: {
5      baseURL: "https://api.example.com/v1"
6      headers: [
7        {
8          name: "Authorization"
9          value: "Bearer {$context.api_keys.products_v1}"
10        }
11      ]
12    }
13  )
Preview
During the preview, a few limitations apply to connectors and router features. Learn more.
Feedback

Forums