SentryにGraphQLのOperationを表示する
🤖できたもの
Sentryのコンソール画面にGraphQLのOperationを表示するようにしました。
具体的には以下のようなgqlがあったとします。このクエリが実行されて、何かエラーが発生した場合、operationName(=HeroNameAndFriends)
とvariables(=$episode)
をSentryで表示するようにしました。(gqlは公式から拝借しています。)
query HeroNameAndFriends($episode: Episode) {
hero(episode: $episode) {
name
friends {
name
}
}
}
※上記はイメージです。また、Apollo Clientを利用しています。
🗒️記事の要点
- Linkで Apollo Client と GraphQL サーバー間のデータの流れを制御できる
- onError Linkはサーバーからのレスポンスにエラーがないかチェックできる
- onError Linkでoperationにアクセスできる
- operationをSentryのcontextにセットすれば、Sentryのコンソールで表示できる
📝詳細
背景
参画しているプロジェクトでSentryに送られているgraphqlの情報が少なく、エラー原因の把握に時間がかかっていました。graphqlはエンドポイントも単一なのでそれに拍車をかけていました。
Sentry公式ではApollo Server側で設定する方法が紹介されていましたが[1]、プロジェクトで利用していなかったので、Apollo Client(フロント)側でうまく設定する方法を探していました。
実装したコード
フロントはjavascriptです。コードの説明がしやすいように、コード内のコメントアウトの数字とコード下の文章の数字を対応させています。
const errorLink = onError(({ graphQLErrors, operation }) => { // 1
if (graphQLErrors) {
Sentry.withScope(scope => { // 2
scope.setContext('Apollo GraphQL Operation', { // 3
operationName: operation.operationName,
variables: operation.variables
})
})
}
})
new ApolloClient({
link: ApolloLink.from([errorLink]), // 4
})
- 今回表示するために必要な情報はoperation[2]に入っています。今回のクエリでいえば、
operation.nameがHeroNameAndFriends
、operation.variables
が"episode": "JEDI"
に対応しています。 - SentrySDKの
withScope
を利用します[3]。スコープには、イベントとともに送信されるべき有用な情報が格納されます。例えばSentryのコンソールに表示されるコンテキストやパンくずはスコープに保存されています[4]。同じようなメソッドにconfigureScope
があるようですが、こちらはSentryに送るイベント全体に設定するメソッドのようです[5]。 - setContextでSentryのコンソールで確認できるようにします[6]。contextはSentryのコンソールのこの部分です。
- 最後にApolloClientのインスタンスを作成する際に、
ApolloLink.from
メソッドに渡せばOKです!
😄終わりに
上記の情報がSentryで確認できることで、エラー原因の発見が格段に速くなりました。もし同様なことで困っている方がいたら、ぜひ試してみて下さい。もし、もっといいやり方、こういうやり方があるよって方がいらっしゃれば、お気軽にコメントください!
🙏参考・引用サイト
以下のサイトを参考にさせていただきました。
-
https://blog.sentry.io/handling-graphql-errors-using-sentry/ ↩︎
-
https://www.apollographql.com/docs/react/api/link/introduction/#the-operation-object ↩︎
-
https://docs.sentry.io/platforms/javascript/enriching-events/scopes/#local-scopes ↩︎
-
https://docs.sentry.io/platforms/javascript/enriching-events/scopes/#whats-a-scope-whats-a-hub ↩︎
-
https://docs.sentry.io/platforms/javascript/enriching-events/scopes/#configuring-the-scope ↩︎
-
https://docs.sentry.io/platforms/javascript/enriching-events/context ↩︎
Discussion