-
Notifications
You must be signed in to change notification settings - Fork 5
Gradle GraphQL Schema Analysis Tool
Sometimes choosing an effective GraphQL schema truncation strategy is a difficult task. And the Kobby schema analysis tool can help us solve it.
To run the analysis tool, use the kobbySchemaAnalyze task:
gradle kobbySchemaAnalyze
By default, the analysis tool prints a report for the root of the GraphQL schema - the Query, Mutation, and
Subscription types:
[kobby] GraphQL schema ready to analyze! (Kobby pattern case sensitive)
[kobby] Analyzed schema weight: 15 (7 objects, 2 interfaces, 1 unions, 2 enums, 3 inputs).
Query (weight: 10)
country: Country (weight: 9)
countries: Country (weight: 9)
film: Film (weight: 9)
films: Film (weight: 9)
actor: Actor (weight: 9)
actors: Actor (weight: 9)
taggable: Taggable (weight: 9)
Mutation (weight: 13)
createCountry: Country (weight: 9)
createFilm: Film (weight: 11)
createActor: Actor (weight: 11)
updateBirthday: Actor (weight: 9)
associate: Boolean
tagFilm: Boolean
tagActor: Boolean
Subscription (weight: 10)
countryCreated: Country (weight: 9)
filmCreated: Film (weight: 9)
actorCreated: Actor (weight: 9)
To configure analysis tool, use the analyze section in the kobby.schema section:
kobby {
schema {
// Configuration of kobbySchemaAnalyze task to print a report to the console
// with all GraphQL types and fields that match the query.
analyze {
// true - use a truncated GraphQL schema for analysis.
// false - use the original GraphQL schema for analysis.
truncatedSchema = true // default
// GraphQL schema analysis depth.
// Use -1 to analyse a schema with unlimited depth.
depth = 1 // default
// GraphQL schema analysis report length limit.
// Use -1 to print a report with unlimited length.
reportLengthLimit = 10000 // default
// The minimum weight of a GraphQL type that should be printed in the report.
printMinWeight = 2 // default
// Print "override sign" (`^`) in report for overridden GraphQL type fields.
printOverride = false // default
// Print GraphQL field argument types in a report.
printArgumentTypes = false // default
// Print GraphQL field supertypes in report (`<-` followed by a list of supertypes).
printSuperTypes = false // default
// Print GraphQL field subtypes in report (`->` followed by a list of subtypes).
printSubTypes = false // default
// Is Regex enabled in GraphQL schema analysis query.
// By default, a simplified Kobby Pattern is used.
regexEnabled = false // default
// Are patterns used in a GraphQL schema analysis query case sensitive.
caseSensitive = true // default
// A query used to analyze the GraphQL schema.
// The kobbySchemaAnalyze task prints a report to the console
// with the GraphQL types and fields matches to the given query.
byQuery {
// Schema analysis query (GSEL)
}
}
}
}You can select the GraphQL types and fields to analyze using a GSEL query
(see byQuery section) and customize how the report is displayed when printed using the printXXX properties.
Let's look at some examples of using the schema analysis tool to select a truncation strategy.
In our examples, we will analyze the
Cinema
schema from the kobby-gradle-example project.
Let's find all the fields of type Actor in our schema:
kobby {
schema {
analyze {
byQuery {
forAny {
include {
dependency("Actor")
}
}
}
}
}
}Analysis report:
[kobby] GraphQL schema ready to analyze! (Kobby pattern case sensitive)
[kobby] Analyzed schema weight: 15 (7 objects, 2 interfaces, 1 unions, 2 enums, 3 inputs).
Query (weight: 10)
actor: Actor (weight: 9)
actors: Actor (weight: 9)
Mutation (weight: 13)
createActor: Actor (weight: 11)
updateBirthday: Actor (weight: 9)
Subscription (weight: 10)
actorCreated: Actor (weight: 9)
Country (weight: 9)
actor: Actor (weight: 9)
actors: Actor (weight: 9)
Film (weight: 9)
actors: Actor (weight: 9)
[kobby] Analyzed schema weight: 15 (7 objects, 2 interfaces, 1 unions, 2 enums, 3 inputs).
Okay, but how is the Actor type accessible from the root of the GraphQL schema? This is important to know in order to
choose an adequate schema truncation strategy. Let's find all transitive dependencies of the Actor type from the root
of the GraphQL schema:
kobby {
schema {
analyze {
byQuery {
forRoot {
include {
transitiveDependency("Actor")
}
}
}
}
}
}Analysis report:
[kobby] GraphQL schema ready to analyze! (Kobby pattern case sensitive)
[kobby] Analyzed schema weight: 15 (7 objects, 2 interfaces, 1 unions, 2 enums, 3 inputs).
Query (weight: 10)
country: Country (weight: 9)
countries: Country (weight: 9)
film: Film (weight: 9)
films: Film (weight: 9)
actor: Actor (weight: 9)
actors: Actor (weight: 9)
taggable: Taggable (weight: 9)
Mutation (weight: 13)
createCountry: Country (weight: 9)
createFilm: Film (weight: 11)
createActor: Actor (weight: 11)
updateBirthday: Actor (weight: 9)
Subscription (weight: 10)
countryCreated: Country (weight: 9)
filmCreated: Film (weight: 9)
actorCreated: Actor (weight: 9)
[kobby] Analyzed schema weight: 15 (7 objects, 2 interfaces, 1 unions, 2 enums, 3 inputs).
As we can see, the Actor type is accessible from almost all fields of the schema root. But how can we find out more
details about the access paths to the Actor type from the schema root? Let's increase the report depth. By default,
the depth is 1. Let's make it 2:
kobby {
schema {
analyze {
depth = 2
byQuery {
forRoot {
include {
transitiveDependency("Actor")
}
}
}
}
}
}Analysis report:
[kobby] GraphQL schema ready to analyze! (Kobby pattern case sensitive)
[kobby] Analyzed schema weight: 15 (7 objects, 2 interfaces, 1 unions, 2 enums, 3 inputs).
Query (weight: 10)
country: Country (weight: 9)
film: Film (weight: 9)
films: Film (weight: 9)
actor: Actor (weight: 9)
actors: Actor (weight: 9)
taggable: Taggable (weight: 9)
native: Native (weight: 9)
countries: Country (weight: 9)
film: Film (weight: 9)
films: Film (weight: 9)
actor: Actor (weight: 9)
actors: Actor (weight: 9)
taggable: Taggable (weight: 9)
native: Native (weight: 9)
film: Film (weight: 9)
country: Country (weight: 9)
actors: Actor (weight: 9)
films: Film (weight: 9)
country: Country (weight: 9)
actors: Actor (weight: 9)
actor: Actor (weight: 9)
country: Country (weight: 9)
films: Film (weight: 9)
actors: Actor (weight: 9)
country: Country (weight: 9)
films: Film (weight: 9)
taggable: Taggable (weight: 9)
Film (weight: 9)
country: Country (weight: 9)
actors: Actor (weight: 9)
Actor (weight: 9)
country: Country (weight: 9)
films: Film (weight: 9)
Mutation (weight: 13)
createCountry: Country (weight: 9)
film: Film (weight: 9)
films: Film (weight: 9)
actor: Actor (weight: 9)
actors: Actor (weight: 9)
taggable: Taggable (weight: 9)
native: Native (weight: 9)
createFilm: Film (weight: 11)
country: Country (weight: 9)
actors: Actor (weight: 9)
createActor: Actor (weight: 11)
country: Country (weight: 9)
films: Film (weight: 9)
updateBirthday: Actor (weight: 9)
country: Country (weight: 9)
films: Film (weight: 9)
Subscription (weight: 10)
countryCreated: Country (weight: 9)
film: Film (weight: 9)
films: Film (weight: 9)
actor: Actor (weight: 9)
actors: Actor (weight: 9)
taggable: Taggable (weight: 9)
native: Native (weight: 9)
filmCreated: Film (weight: 9)
country: Country (weight: 9)
actors: Actor (weight: 9)
actorCreated: Actor (weight: 9)
country: Country (weight: 9)
films: Film (weight: 9)
[kobby] Analyzed schema weight: 15 (7 objects, 2 interfaces, 1 unions, 2 enums, 3 inputs).
To output a report with infinite depth, set the report depth to -1. This way, you will see the full dependency paths in the report (except for infinite dependency loops - they are artificially broken). But the report can be very large.
Okay, so what about the weight in the report? What is it? It's the number of GraphQL types (excluding scalars) that are reachable for a query on a field that returns the given type. Using weights, we can estimate which fields contribute the most to the number of data types generated by the Kobby plugin. Let's find fields with a given weight range:
kobby {
schema {
analyze {
byQuery {
forRoot {
include {
minWeight(10)
maxWeight(20)
}
}
}
}
}
}Analysis report:
[kobby] GraphQL schema ready to analyze! (Kobby pattern case sensitive)
[kobby] Analyzed schema weight: 15 (7 objects, 2 interfaces, 1 unions, 2 enums, 3 inputs).
Mutation (weight: 13)
createFilm: Film (weight: 11)
createActor: Actor (weight: 11)
[kobby] Analyzed schema weight: 15 (7 objects, 2 interfaces, 1 unions, 2 enums, 3 inputs).
Okay. What other details can we see in the report? Let's enable all available options:
kobby {
schema {
analyze {
truncatedSchema = true
depth = 1
reportLengthLimit = 10000
printMinWeight = 0
printOverride = true
printArgumentTypes = true
printSuperTypes = true
printSubTypes = true
regexEnabled = false
caseSensitive = true
byQuery {
forType("Country") {}
}
}
}
}Analysis report:
[kobby] GraphQL schema ready to analyze! (Kobby pattern case sensitive)
[kobby] Analyzed schema weight: 15 (7 objects, 2 interfaces, 1 unions, 2 enums, 3 inputs).
Country (weight: 9) <- Entity
id^: ID (weight: 0)
fields(String)^: JSON (weight: 0)
name: String (weight: 0)
film(ID): Film (weight: 9) <- Entity, Taggable, Native
films(String, Genre, Int): Film (weight: 9) <- Entity, Taggable, Native
actor(ID): Actor (weight: 9) <- Entity, Taggable, Native
actors(String, Date, Gender, Int): Actor (weight: 9) <- Entity, Taggable, Native
taggable(String): Taggable (weight: 9) <- Entity -> Film, Actor
native: Native (weight: 9) -> Film, Actor
[kobby] Analyzed schema weight: 15 (7 objects, 2 interfaces, 1 unions, 2 enums, 3 inputs).
-
truncatedSchema- Use a truncated or original schema for analysis (defaulttrue- truncated schema). -
depth- GraphQL schema analysis depth. Use -1 to analyse a schema with unlimited depth. (default 1). -
reportLengthLimit- GraphQL schema analysis report length limit. Use -1 to print a report with unlimited length ( default 10000). -
printMinWeight- The minimum weight of a GraphQL type that should be printed in the report (default 2). -
printOverride- Print "override sign" (^) in report for overridden GraphQL type fields. -
printArgumentTypes- Print GraphQL field argument types in a report. -
printSuperTypes- Print GraphQL field supertypes in report (<-followed by a list of supertypes). -
printSubTypes- Print GraphQL field subtypes in report (->followed by a list of subtypes). -
regexEnabled- Is Regex enabled in GraphQL schema analyze query (by default uses Kobby Pattern). -
caseSensitive- Are patterns used in a GraphQL schema analyze query case sensitive (defaulttrue).