今回はLaravel5.7+GraphQLでエラーハンドリングについての記事です。
GraphQL実行時に例外発生した際にエラーメッセージをログに出力してくれなかったのでその対処法を残します。
シリーズ記事
- LaravelとGraphQLでAPI開発
- Laravel 5.7 + GraphQL(Install編)
- Laravel 5.7 + GraphQL(ScalarType編)
- Laravel 5.7 + GraphQL(Relation編)
- Laravel 5.7 + GraphQL(Dump Server編)
- Laravel 5.7 + GraphQL(Pagination編)
- Laravel 5.7 + GraphQL(ErrorHandling編)
- Laravel 5.7 + GraphQL(Test編)
例外を発生させてみる
GraphQLの特徴なのですが、
例外が発生した場合も 200 レスポンスが返り errors.messages
に例外メッセージが出力されます。
app/GraphQL/Query/PostQuery.php
public function resolve($root, $args, $context, ResolveInfo $info) : Post
{
throw new \Exception('test error');
$query = Post::query();
if (isset($args['id'])) {
$query->where('id', $args['id']);
}
return $query->first();
}
ここまではOKなのですが、
何と発生した例外メッセージがログファイルに出力されません...😭
GraphQL例外時に実行される関数
config/graphql.php
'error_formatter' => [\Folklore\GraphQL\GraphQL::class, 'formatError'],
Folklore\GraphQL\GraphQL
の formatError
関数が実行されます。
https://github.com/Folkloreatelier/laravel-graphql/blob/develop/src/Folklore/GraphQL/GraphQL.php#L287-L306
public static function formatError(Error $e)
{
$error = [
'message' => $e->getMessage()
];
$locations = $e->getLocations();
if (!empty($locations)) {
$error['locations'] = array_map(function ($loc) {
return $loc->toArray();
}, $locations);
}
$previous = $e->getPrevious();
if ($previous && $previous instanceof ValidationError) {
$error['validation'] = $previous->getValidatorMessages();
}
return $error;
}
ログ出力してないですね💦
App\Exceptions\Handler
の report
関数も通らないので注意です。
暫定対応
- https://github.com/ucan-lab/practice-laravel-graphql/commit/d1a8e1dffc48c01c2b73995b5ab9f18d3fdba4d7
- https://github.com/ucan-lab/practice-laravel-graphql/commit/ba52b25ed15174ced07ab1d9785a2487bda33abb
$ php artisan make:exception GraphQLException
src/app/Exceptions/GraphQLException.php
<?php
declare(strict_types = 1);
namespace App\Exceptions;
use Folklore\GraphQL\GraphQL;
use Folklore\GraphQL\Error\ValidationError;
use GraphQL\Error\Error;
class GraphQLException extends GraphQL
{
public static function formatError(Error $e)
{
$error = parent::formatError($e);
// Logging
logger()->error($error);
logger()->error(request()->all());
logger()->error($e);
return $error;
}
}
レスポンス、リクエスト、例外情報をログに出力する処理を追加します。
あんまり推奨されるやり方ではない気がしますが、とりあえずログ出力できることを確認しました。
もっと良いやり方があればコメントで教えてください😊
config/graphql.php
'error_formatter' => [App\Exceptions\GraphQLException::class, 'formatError'],
storage/logs/laravel.log
[2018-10-23 08:03:08] local.ERROR: array (
'message' => 'test error',
'locations' =>
array (
0 =>
array (
'line' => 2,
'column' => 3,
),
),
)
[2018-10-23 08:03:08] local.ERROR: array (
'query' => '{
post {
id
title
}
}',
'variables' => NULL,
'operationName' => NULL,
)
[2018-10-23 08:03:08] local.ERROR: Exception: test error in /Users/ucan/study/practice-laravel-graphql/app/GraphQL/Query/PostQuery.php:63
Stack trace: