/
Enabling debugging in GraphQL APIs

Enabling debugging in GraphQL APIs

When developing for GraphQL APIs, you might want to get detailed information about a specific request, to help you understand what is going on in more detail.

The GraphQL API supports multiple debugging modes that will return additional data when enabled. These settings should only be used during development, not on production systems.

Enabling performance data

You can enable performance data by adding either of the following lines into your config.php, above the final line that includes setuplib.php (only one or the other is required):

define('MDL_PERF', true);

$CFG->perfdebug = 15;  // Any number greater than 7 will trigger the inclusion of performance data

Types of performance data

Performance data

When enabled, each response will include additional performance data with the request. This provides information such as execution time, memory usage, number of database queries, caching information, etc., to help you understand your query's performance implications. The performance data is located within the extensions property in a property called performance_data:

{
  "data": {
    "core_course": {
      "id": "2",
      "fullname": "Course 1",
      "category": {
        "id": "1",
        "name": "Miscellaneous"
      }
    }
  },
  "extensions": {
    "performance_data": {
      "core": {
        "cache": { ... },
        "db": {
          "reads": 13,
          "writes": 3,
          "time": 0.081470000000000001
        },
        "filters": { ... },
        "includecount": 633,
        "logwrites": 0,
        "memory": {
          "total": 19839072,
          "growth": 19405176,
          "peak": 28621824
        },
        "posix_times": {
          "ticks": 57,
          "utime": 25,
          "stime": 11,
          "cutime": 0,
          "cstime": 0
        },
        "realtime": 0.56207599999999991,
        "server_load": "1.38",
        "session": {
          "size": "11.6KB",
          "handler": "core\\session\\file"
        },
        "strings": { ... }
      }
    }
  }
}

Complexity data - external API only

When performance data is enabled, the external API will include additional information about the query complexity in the response. This data is not shown for other endpoint types.

This provides information on the calculated complexity of the query, as defined by the rate-limiting code. This information is used to apply restrictions to external API usage in complexity points per minute. So, this data can be used to understand the cost of a specific query. The complexity data is located within the extensions property in a property called complexity_data:

{
	"data": { ... }
    "extensions": {
        "complexity_data": {
            "query_complexity": 10
        },
        "performance_data": { ... }
    }
}

See API rate limiting and query complexity for more information on how complexity is calculated and used.

Levels of debugging

Different API endpoints handle debugging levels in different ways.

External endpoint

You can control the level of debugging output displayed in the response by setting the response_debug totara_api setting in your config.php as follows:

// Determines the amount of information returned by an API response when an error occurs.
// - ERROR_RESPONSE_LEVEL_NONE (0)
// - ERROR_RESPONSE_LEVEL_NORMAL (1)
// - ERROR_RESPONSE_LEVEL_DEVELOPER (2)
$CFG->forced_plugin_settings['totara_api'] = array(
    'response_debug' =>  1
);

The default is normal (1), which displays basic debugging information about what went wrong via the debugMessage property:

{
  "errors": [
    {
      "debugMessage": "This is the specific error message",
      "message": "Internal server error",
      "extensions": {
        "category": "internal"
      },
      "locations": [
        {
          "line": 4,
          "column": 7
        }
      ],
      "path": [
        "core_user_users",
        "items",
        0,
        "id"
      ]
    }
  ]
}

Setting to none (0) removes the debugMessage property and just gives a generic error:

{
  "errors": [
    {
      "message": "Internal server error",
      "extensions": {
        "category": "internal"
      },
      "locations": [
        {
          "line": 4,
          "column": 7
        }
      ],
      "path": [
        "core_user_users",
        "items",
        0,
        "id"
      ]
    }
  ]
}

while developer (2) includes detailed stack trace and line numbers to the output:

{
  "errors": [
    {
      "debugMessage": "This is the specific error message",
      "message": "Internal server error",
      "extensions": {
        "category": "internal"
      },
      "locations": [
        {
          "line": 4,
          "column": 7
        }
      ],
      "path": [
        "core_user_users",
        "items",
        0,
        "id"
      ],
      "trace": [
        {
          "file": "/var/www/totara/src/main/server/totara/webapi/classes/default_resolver.php",
          "line": 91,
          "call": "core\\webapi\\resolver\\type\\user::resolve('id', instance of core\\entity\\user, array(1), inst