diff --git a/app/graphql/types/query_complexity_type.rb b/app/graphql/types/query_complexity_type.rb
new file mode 100644
index 0000000000000000000000000000000000000000..82809fac22fb6b3641eb052a2f9b9708263351db
--- /dev/null
+++ b/app/graphql/types/query_complexity_type.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+module Types
+ # rubocop: disable Graphql/AuthorizeTypes
+ class QueryComplexityType < ::Types::BaseObject
+ ANALYZER = GraphQL::Analysis::QueryComplexity.new { |_query, complexity| complexity }
+
+ graphql_name 'QueryComplexity'
+
+ alias_method :query, :object
+
+ field :limit, GraphQL::INT_TYPE,
+ null: true,
+ method: :max_complexity,
+ see: {
+ 'GitLab documentation on this limit' =>
+ 'https://docs.gitlab.com/ee/api/graphql/index.html#max-query-complexity'
+ },
+ description: 'GraphQL query complexity limit.'
+
+ field :score, GraphQL::INT_TYPE,
+ null: true,
+ description: 'GraphQL query complexity score.'
+
+ def score
+ ::GraphQL::Analysis.analyze_query(query, [ANALYZER]).first
+ end
+ end
+ # rubocop: enable Graphql/AuthorizeTypes
+end
diff --git a/app/graphql/types/query_type.rb b/app/graphql/types/query_type.rb
index 8b7b9f0107be6d0a01a219b44033e48f970efc00..d2c67aea95cecd715a08650203a8e3106b611189 100644
--- a/app/graphql/types/query_type.rb
+++ b/app/graphql/types/query_type.rb
@@ -36,6 +36,10 @@ class QueryType < ::Types::BaseObject
resolver: Resolvers::MetadataResolver,
description: 'Metadata about GitLab.'
+ field :query_complexity, Types::QueryComplexityType,
+ null: true,
+ description: 'Information about the complexity of the GraphQL query.'
+
field :snippets,
Types::SnippetType.connection_type,
null: true,
@@ -170,6 +174,10 @@ def ci_application_settings
def application_settings
Gitlab::CurrentSettings.current_application_settings
end
+
+ def query_complexity
+ context.query
+ end
end
end
diff --git a/doc/api/graphql/getting_started.md b/doc/api/graphql/getting_started.md
index ade3ad1f9b66ce2a1489669c4293ead6f2321266..5b482d15c5125eb05933b14bf4c8d7ab3df7724d 100644
--- a/doc/api/graphql/getting_started.md
+++ b/doc/api/graphql/getting_started.md
@@ -298,6 +298,24 @@ query IssueTypes {
More about introspection:
[GraphQL documentation](https://graphql.org/learn/introspection/)
+### Query complexity
+
+The calculated [complexity score and limit](index.md#max-query-complexity) for a query can be revealed to clients by
+querying for `queryComplexity`.
+
+```graphql
+query {
+ queryComplexity {
+ score
+ limit
+ }
+
+ project(fullPath: "gitlab-org/graphql-sandbox") {
+ name
+ }
+}
+```
+
## Sorting
Some of the GitLab GraphQL endpoints allow you to specify how to sort a
diff --git a/doc/api/graphql/index.md b/doc/api/graphql/index.md
index e495b916b181b75aae981335e25719c40bbb8441..b7a82dba7e990eb36ca0bf4d671ebc26f822290c 100644
--- a/doc/api/graphql/index.md
+++ b/doc/api/graphql/index.md
@@ -166,7 +166,7 @@ The complexity of a single query is limited to a maximum of:
- `200` for unauthenticated requests.
- `250` for authenticated requests.
-There is no way to discover the complexity of a query except by exceeding the limit.
+The complexity score of a query and limit for the request [can be queried for](getting_started.md#query-complexity).
If a query exceeds the complexity limit an error message response will
be returned.
diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md
index 803e8a3b44b3fffef44de76ca44e794ea7671f62..21f5115747d431acfcfc4b363cab890968fbd803 100644
--- a/doc/api/graphql/reference/index.md
+++ b/doc/api/graphql/reference/index.md
@@ -286,6 +286,12 @@ four standard [pagination arguments](#connection-pagination-arguments):
| `sort` | [`String`](#string) | Sort order of results. |
| `topics` | [`[String!]`](#string) | Filters projects by topics. |
+### `Query.queryComplexity`
+
+Information about the complexity of the GraphQL query.
+
+Returns [`QueryComplexity`](#querycomplexity).
+
### `Query.runner`
Find a runner. Available only when feature flag `runner_graphql_query` is enabled.
@@ -12335,6 +12341,15 @@ Pypi metadata.
| `id` | [`PackagesPypiMetadatumID!`](#packagespypimetadatumid) | ID of the metadatum. |
| `requiredPython` | [`String`](#string) | Required Python version of the Pypi package. |
+### `QueryComplexity`
+
+#### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| `limit` | [`Int`](#int) | GraphQL query complexity limit. See [GitLab documentation on this limit](https://docs.gitlab.com/ee/api/graphql/index.html#max-query-complexity). |
+| `score` | [`Int`](#int) | GraphQL query complexity score. |
+
### `RecentFailures`
Recent failure history of a test case.
diff --git a/doc/development/api_graphql_styleguide.md b/doc/development/api_graphql_styleguide.md
index 75ab8359d0e3123e47a623bb5c66e261d95e4f18..c12b66a94a778e11653cb174f16d7b5539f2dc8f 100644
--- a/doc/development/api_graphql_styleguide.md
+++ b/doc/development/api_graphql_styleguide.md
@@ -68,9 +68,7 @@ Complexity is explained [on our client-facing API page](../api/graphql/index.md#
Fields default to adding `1` to a query's complexity score, but developers can
[specify a custom complexity](#field-complexity) when defining a field.
-To estimate the complexity of a query, you can run the
-[`gitlab:graphql:analyze`](rake_tasks.md#analyze-graphql-queries)
-Rake task.
+The complexity score of a query [can itself be queried for](../api/graphql/getting_started.md#query-complexity).
### Request timeout
diff --git a/spec/graphql/types/query_complexity_type_spec.rb b/spec/graphql/types/query_complexity_type_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..6b2330f2b13fef61efeaeb4b7348ffc3ca12002a
--- /dev/null
+++ b/spec/graphql/types/query_complexity_type_spec.rb
@@ -0,0 +1,35 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe GitlabSchema.types['QueryComplexity'] do
+ include GraphqlHelpers
+
+ specify do
+ expect(described_class).to have_graphql_fields(:limit, :score).only
+ end
+
+ it 'works when executed' do
+ query = <<-GQL
+ query {
+ queryComplexity {
+ score
+ limit
+ }
+
+ currentUser {
+ name
+ }
+ }
+ GQL
+
+ query_result = run_with_clean_state(query).to_h
+
+ data = graphql_dig_at(query_result, :data, :queryComplexity)
+
+ expect(data).to include(
+ 'score' => be > 0,
+ 'limit' => GitlabSchema::DEFAULT_MAX_COMPLEXITY
+ )
+ end
+end