v0.13.0
Pre-releaseRelease Notes
This release accomplishes the following:
- Adds GraphiQL IDE to the main WPGraphQL plugin (deprecates the need for separate WPGraphiQL plugin)
- Adds GraphQL Settings Page with API to register more fields and field sections
- Adds Query Logs and Tracing to the main WPGraphQL plugin (deprecates the need for separate WPGraphQL Insights plugin)
GraphiQL IDE
WPGraphQL now has GraphiQL IDE built in to WPGraphQL!
GraphiQL IDE is an incredibly useful tool for working with GraphQL APIs, and now it's available to all users of WPGraphQL without needing to find and install a separate plugin.
With WPGraphQL Active, there is now an Admin Menu for GraphQL, and within that menu is "GraphiQL IDE" link
There's also an Admin Bar short-link for GraphiQL IDE:
Clicking either link will open GraphiQL in the WP Admin:
You can now browse the WPGraphQL Schema and test Queries and Mutations all from within the WordPress Dashboard.
Settings Page (and API)
WPGraphQL now has a settings page where some common configurations can be set, without needing to touch code.
In the Admin Menu, there's now a "GraphQL > Settings" link
Clicking that will take you to a Settings Page:
Settings Overview
These settings can be used to accomplish some common tasks with WPGraphQL that previously required code (filters/constants) to accomplish.
- GraphQL Endpoint: You can now change the endpoint to be something other than
/graphql
. - Enable GraphiQL IDE: You can enable/disable GraphiQL IDE in the Admin. Now that GraphiQL is bundled, you can turn it off if you prefer not to have it.
- Delete Data on Deactivation: You can opt in or out of having any data WPGraphQL stores be deleted when WPGraphQL is de-activated. Things like the settings for this settings page get stored in the database. You can choose to keep data (for example temporary de-activations) or delete all data on de-activation to keep your data clean.
- Enable GraphQL Debug Mode: When errors occur in GraphQL requests, the default message is "Internal Server Error" to ensure implementation details are not leaked to the public. Enabling GraphQL Debug Mode shows more detailed messages, allowing developers to identify issues more quickly.
- Enable GraphQL Tracing: Enabling tracing will track performance of the entire request and each field within the request. The trace data will be returned as part of the "extensions" portion of the GraphQL response, alongside the data. This feature was previously part of WPGraphQL Insights, but can now be enabled by checking this setting. Trace data can be helpful for identifying bottlenecks (slow resolvers)
- Tracing Role: With Tracing Enabled, it can be limited to a certain roles. Only the selected role (or all) will see the trace data in results of GraphQL requests
- Enable Query Logs: Enabling Query Logs will return MySQL Query logs in the "extensions" portion of the GraphQL response. This is essentially like Query Monitor for WPGraphQL. You can see the specific MySQL queries being executed to resolve GraphQL requests.
- Query Log Role: If Query Logs are enabled, they will execute, but the results can be limited to a specific user role, or all user roles (public requests allowed).
Settings API
Along with the Settings Page, there are some basic APIs to allow 3rd party plugins to easily add GraphQL Settings.
register_graphql_settings_section
This function should be used within the graphql_register_settings
action, and allows new Settings Sections to be registered to the Settings Page.
usage:
add_action( 'graphql_register_settings', function() {
register_graphql_settings_section( 'graphql_my_section', [
'title' => __( 'My Section', 'your-textdomain' ),
]);
});
This will add a new section to the settings page like so:
register_graphql_settings_field
This function will register a new settings field to the specified settings section:
usage:
add_action( 'graphql_register_settings', function() {
register_graphql_settings_field( 'graphql_my_section', [
'name' => 'my_field',
'label' => __( 'My Field', 'your-textdomain' ),
'desc' => __( 'Your field description...', 'your-textdomain' ),
'type' => 'text',
'default' => "my default value...",
]);
});
This registers a text field named with the "My Field" label to the "graphql_my_section" section.
register_graphql_settings_fields
This allows multiple settings fields to be registered to a section.
usage:
add_action( 'graphql_register_settings', function() {
register_graphql_settings_section( 'graphql_new_section', [
'title' => __( 'New Section', 'your-textdomain' ),
] );
register_graphql_settings_fields( 'graphql_new_section', [
[
'name' => 'text',
'label' => __( 'Text Input', 'wp-graphql' ),
'desc' => __( 'Text input description', 'wp-graphql' ),
'type' => 'text',
'default' => 'Title'
],
[
'name' => 'textarea',
'label' => __( 'Textarea Input', 'wp-graphql' ),
'desc' => __( 'Textarea description', 'wp-graphql' ),
'type' => 'textarea'
],
[
'name' => 'checkbox',
'label' => __( 'Checkbox', 'wp-graphql' ),
'desc' => __( 'Checkbox Label', 'wp-graphql' ),
'type' => 'checkbox'
],
[
'name' => 'radio',
'label' => __( 'Radio Button', 'wp-graphql' ),
'desc' => __( 'A radio button', 'wp-graphql' ),
'type' => 'radio',
'options' => [
'yes' => 'Yes',
'no' => 'No'
]
],
[
'name' => 'multicheck',
'label' => __( 'Multile checkbox', 'wp-graphql' ),
'desc' => __( 'Multi checkbox description', 'wp-graphql' ),
'type' => 'multicheck',
'options' => [
'one' => 'One',
'two' => 'Two',
'three' => 'Three',
'four' => 'Four'
]
],
[
'name' => 'selectbox',
'label' => __( 'A Dropdown', 'wp-graphql' ),
'desc' => __( 'Dropdown description', 'wp-graphql' ),
'type' => 'select',
'default' => 'no',
'options' => [
'yes' => 'Yes',
'no' => 'No'
]
],
[
'name' => 'password',
'label' => __( 'Password', 'wp-graphql' ),
'desc' => __( 'Password description', 'wp-graphql' ),
'type' => 'password',
'default' => ''
],
[
'name' => 'file',
'label' => __( 'File', 'wp-graphql' ),
'desc' => __( 'File description', 'wp-graphql' ),
'type' => 'file',
'default' => ''
],
[
'name' => 'color',
'label' => __( 'Color', 'wp-graphql' ),
'desc' => __( 'Color description', 'wp-graphql' ),
'type' => 'color',
'default' => ''
],
[
'name' => 'user_role',
'label' => __( 'User Role', 'wp-graphql' ),
'desc' => __( 'Description for selecting a User Role.', 'wp-graphql' ),
'type' => 'user_role_select',
'default' => "administrator",
],
] );
} );
get_graphql_setting
This function should be used to get settings values from GraphQL Settings pages. Each settings section is stored in a serialized array in the options table. This function will properly get the value and return it.
usage:
If you wanted to get the "color" setting from the "graphql_new_section" section, and have it default to "blue" if no value is set, you would do so like:
$option_name = 'color';
$default_value = 'blue';
$section = 'graphql_new_section';
$value = get_graphql_setting( $option_name, $default_value, $section );
Tracing
We saw that there are settings for Tracing, but what exactly is Tracing?
Tracing is performance tracking for the entire GraphQL request and each field of the request. This data can be helpful when debugging bottlenecks.
With Tracing enabled from the Settings Page, executing a GraphQL Query will show the trace data in the "extensions" portion of the request:
There is data for the entire request:
- startTime
- endTime
- duration
And data for each field within the request:
- path
- parentType
- fieldName
- returnType
- startOffset
- duration
This data can be very helpful when debugging bottlenecks.
Let's take a look at an example.
Executing the following query:
{
posts {
nodes {
id
title
}
}
}
We would see the following Trace data for the request:
...
"tracing": {
"version": 1,
"startTime": "1600294443.335",
"endTime": "1600294443.381",
"duration": 45998,
"execution": {
...
The request duration is 45998
microseconds (0.045998
seconds).
And if we scrolled down, we'd see the following trace data for the id
field of the first post:
...,
{
"path": [
"posts",
"nodes",
0,
"title"
],
"parentType": "Post",
"fieldName": "title",
"returnType": "String",
"startOffset": 27518,
"duration": 797
},
...
Here, we can see that the duration was 797
microseconds (0.000797 seconds
)
Let's override this field resolver like so:
add_filter( 'graphql_Post_fields', function( $fields ) {
$fields['title']['resolve'] = function( \WPGraphQL\Model\Post $post ) {
// Sleep for 1 second to simulate something taking a long time
sleep(1);
return $post->titleRendered;
};
return $fields;
});
Now, if we look at the trace data, we can see:
"tracing": {
"version": 1,
"startTime": "1600294618.1841",
"endTime": "1600294628.2435",
"duration": 10059434,
The entire request duration is now 10059434
microseconds ( 10.059434
seconds).
Something is clearly wrong! This request used to take well under 1 second, and now it's taking more than 10 seconds! 😱
If we scroll down we will see that the duration of each title field is looking quite long:
```json
...
{
"path": [
"posts",
"nodes",
0,
"title"
],
"parentType": "Post",
"fieldName": "title",
"returnType": "String",
"startOffset": 27518,
"duration": 1000964
},
...
The duration for the title field is now 1000964
microseconds (1.000964
seconds).
Now, we as developers know what field to start troubleshooting.
In our case we know that the title field had a sleep(1)
in the resolver, so we can remove that and we're back to super speedy execution!
Query Logs
Query Logs are a super helpful debugging tool. A lot of things happen under the hood to resolve a GraphQL Query, and sometimes it can be a mystery.
Enabling Query Logs can give insight into what SQL Queries are being executed, how long they're taking, the raw SQL that is executed and the stacktrace to where in the codebase the query is being executed from.
This can be super helpful when things don't seem to be behaving as you'd expect. Sometimes you get results that you don't expect, and analyzing the raw SQL queries can help identify why things are misbehaving. Sometimes it's a rogue plugin that's filtering WP_Query args too aggressively, or perhaps a GraphQL input argument isn't properly mapping to WP_Query.
In any case, seeing the raw SQL queries and the path to the code that called it can be a huge time saver when debugging.