This CLI tool can be used to predict how GraphQL queries may be planned by Apollo Router.
This repository is maintained by Apollo GraphQL's Federation Core team.
In order to accurately predict the behavior of a query on Apollo Router, it is necessary to compute the correct query plan as it will be computed on Router. However, the reality is that it is not just one single query plan, it’s actually a number of possible query plans that could be generated, since both the Router (via progressive override states and coprocessors) and the client (via authentication) can influence how query plans are calculated.
Currently, this tool can enumerate all possible combinations of (progressive) override labels and generate query plans for all of them. Since each progressive override label can be turned on or off individually, the number of combinations will be
There are several other factors that can influence generated query plans as following. However, this CLI tool does not consider the effects of those.
- Authentication policy may remove certain selections from the input query.
- This CLI tool assumes all selections are allowed.
- Note: Removal of one or more selections may change the generated query plan significantly.
- Router’s plugins and coprocessors may control the progressive overrides.
- Note: Not all combinations of overrides that are generated by this CLI tool may actually be feasible.
This tool uses the same native query planner as Apollo Router versions 1.59 and up (also, 1.49~1.58 versions with the native query planner enabled).
Prerequisite: Rust toolchain (latest stable version recommended)
- To install Rust, please follow instructions on https://rust-lang.org/tools/install/.
Execute the following cargo command to build:
cargo build --release
The qp-analyzer binary will be produced under target/release directory.
Usage: qp-analyzer <COMMAND>
Commands:
list-overrides List all override condition labels in supergraph schema
plan Plan all possible query plans for supergraph schema and query
plan-one Plan a query plan for supergraph schema, query and override conditions
compare-plans Compare two query plan JSON files (produced using the plan-one command)
help Print this message or the help of the given subcommand(s)
Options:
-h, --help Print help
Lists all override condition labels in the supergraph schema.
Usage: qp-analyzer list-overrides <SCHEMA>
Arguments:
<SCHEMA> Path to the supergraph schema file
Command line:
% qp-analyzer list-overrides example/supergraph.graphql
Console output:
percent(50)
percent(90)
Plans all possible query plans for a given schema and query.
Usage: qp-analyzer plan [OPTIONS] <SCHEMA> <QUERY>
Arguments:
<SCHEMA> Path to the supergraph schema file
<QUERY> Path to the query file, `-` for stdin
Options:
--json
Output results in JSON format
--disable-generate-query-fragments
Disable optimization of subgraph fetch queries using fragments
--disable-defer-support
Disable defer support
--experimental-type-conditioned-fetching
Enable type conditioned fetching
--experimental-plans-limit <EXPERIMENTAL_PLANS_LIMIT>
Sets a limit to the number of generated query plans [default: 10000]
--experimental-paths-limit <EXPERIMENTAL_PATHS_LIMIT>
Specify a per-path limit to the number of options considered. No limit is applied by default. Also, if set to `0`, it is treated as no limit [default: 0]
Command line:
% qp-analyzer plan example/supergraph.graphql example/op.graphql
Console output:
-----------------------------------------------------------------------
Override Combination #0: []
-----------------------------------------------------------------------
QueryPlan {
Sequence {
Fetch(service: "entrypoint") {
{
test {
__typename
id
}
}
},
Flatten(path: "test") {
Fetch(service: "monolith") {
{
... on T {
__typename
id
}
} =>
{
... on T {
data1
data2
}
}
},
},
},
}
-----------------------------------------------------------------------
Override Combination #1: ["percent(50)"]
-----------------------------------------------------------------------
...
Plans a query plan for supergraph schema, query and override conditions.
Usage: qp-analyzer plan-one [OPTIONS] <SCHEMA> <QUERY> [OVERRIDE_CONDITIONS]...
Arguments:
<SCHEMA> Path to the supergraph schema file
<QUERY> Path to the query file, `-` for stdin
[OVERRIDE_CONDITIONS]... Override conditions labels
Options:
--override-all
Override all conditions (equivalent to specifying all labels)
--json
Output results in JSON format
--disable-generate-query-fragments
Disable optimization of subgraph fetch queries using fragments
--disable-defer-support
Disable defer support
--experimental-type-conditioned-fetching
Enable type conditioned fetching
--experimental-plans-limit <EXPERIMENTAL_PLANS_LIMIT>
Sets a limit to the number of generated query plans [default: 10000]
--experimental-paths-limit <EXPERIMENTAL_PATHS_LIMIT>
Specify a per-path limit to the number of options considered. No limit is applied by default. Also, if set to `0`, it is treated as no limit [default: 0]
Notes on OVERRIDE_CONDITIONS:
- All arguments following the
<QUERY>argument are considered override labels. - If one or more override labels are provided,
@overridedirectives with the specified labels will take effect. - If no labels are provided, none of the
@overridedirectives will take effect. - If
--override-alloption is used, it is equivalent to specifying all override labels asOVERRIDE_CONDITIONSarguments.
Command line examples:
% qp-analyzer plan-one example/supergraph.graphql example/op.graphql 'percent(50)'
% qp-analyzer plan-one example/supergraph.graphql example/op.graphql 'percent(50)' 'percent(90)'
% qp-analyzer plan-one example/supergraph.graphql example/op.graphql --override-all
Compare two query plan JSON files (produced using the plan-one command)
Usage: qp-analyzer-cli compare-plans <SCHEMA> <PLAN1> <PLAN2>
Arguments:
<SCHEMA> Path to the supergraph schema file
<PLAN1> First query plan result JSON file path
<PLAN2> Second query plan result JSON file path
Create one plan and store its JSON output
% qp-analyzer plan-one example/supergraph.graphql example/op.graphql --json > plan1.json
Create another plan and store its JSON output
% qp-analyzer plan-one example/supergraph.graphql example/op.graphql 'percent(50)' --json > plan2.json
Compare the two JSON files
% qp-analyzer compare-plans example/supergraph.graphql plan1.json plan2.json