本連載では分散型マイクロブログ用ソフトウェアMisskeyの開発に関する紹介と、関連するWeb技術について解説を行っています。
今回はMisskeyで使用可能なサードパーティのエラートラッキングサービス、Sentryとその活用について紹介します。
エラートラッキングとは
Misskey 2024.
エラートラッキングサービスは、ソフトウェア内で発生したエラーを一元化して収集・
エラートラッキングサービスはいくつか存在しますが、SentryはWebブラウザ・
ノート:
Sentryの一部機能は有料プランが必要となっていますが、OSSのための利用であれば申請を行うことで当該機能を無料で使用することが可能です。
導入
Sentryでは各プラットフォーム用のSDKが提供されていますのでそれを使用します。今回はバックエンド側の実装を紹介します。
まずSDKをインストールします。
npm install --save @sentry/node @sentry/profiling-node
次に、Sentry SDKの初期化を行うためのファイルsentry.
)
import * as Sentry from '@sentry/node';
import { nodeProfilingIntegration } from '@sentry/profiling-node';
Sentry.init({
dsn: 'https://examplePublicKey@o0.ingest.sentry.io/0',
integrations: [
nodeProfilingIntegration(),
],
tracesSampleRate: 1.0,
profilesSampleRate: 1.0,
});
なお、dsn
はSentryの個々のプロジェクトごとに発行されるものを入れます。
最後に、アプリケーションのエントリーファイルで上記のファイルをimportします。
import './sentry.js';
これでSentryの導入はできました。
ノート:
nodeProfilingIntegration
は後述するパフォーマンス計測のためのプラグインなので、純粋にエラートラッキングするだけであれば不要です。
エラーのトラック
実際にエラーSentry.
メソッドを利用して例外オブジェクトを直接渡したり、Sentry.
メソッドを利用してカスタムメッセージを渡します。
Misskeyのバックエンドでは、API呼び出し時にハンドルされない例外が発生するとSentryに報告する実装になっています。
当該箇所の実装は以下となっています。
Sentry.captureMessage(`Internal error occurred in ${ep.name}: ${err.message}`, {
level: 'error',
extra: {
ep: ep.name,
ps: data,
e: {
message: err.message,
code: err.name,
stack: err.stack,
id: errId,
},
},
});
captureMessage
では、extra
オプション内に追加の情報を含めることができます。
このようにSentryに報告されたエラーは、Sentryのダッシュボードにて詳細を確認できます。
Resolve, Archive, Assign
報告されたエラーの対応には大まかに3パターンあり、修正(Resolve)・
Resolveは、当該エラーを修正したときに行います。もしResolveした後に同様のエラーが発生すると、リグレッションとして再通知されます。
Archiveは、当該エラーを無視したいときに行います。例えば、一時的なエラーで修正の必要がなかったり、修正が難しいようなエラーを通知したくないときにアーカイブします。
エラーサンプリング
大規模なアプリケーションでは発生するエラーの数も多くなる場合があります。それらすべてをSentryに送信していると負荷も高まりますし料金も高くなってしまいます。
そこでSentryでは発生したエラーをサンプリングして報告するオプションがあり、SDK初期化時にレートをsampleRate
で指定できます。デフォルトは1
で、これは発生したエラーをすべて報告する設定です。50%の確率で報告するようにしたい場合は0.
にします。
パフォーマンス計測
Sentryにはエラーのトラッキング以外にもパフォーマンス計測機能が用意されています。
Misskeyのバックエンドでは、API呼び出しごとにパフォーマンス計測を行うようにし、どのAPIの負荷が高いのか調べられるようにしています。
パフォーマンス計測を行うにはSentry.
メソッドを利用します。
Sentry.startSpan({ name: 'some expensive functions' }, async () => {
await foo();
await bar();
});
startSpan
のコールバック内で実行される処理はパフォーマンス計測の対象になり、ダッシュボードで確認できるようになります。
クエリ監視
データベースに対するクエリのパフォーマンスを計測する機能もあり、N+1クエリの発見にも役立ちます。
N+1クエリとは、典型的には列挙された値一つ一つに対してクエリを発行してしまうことです。例えばユーザーIDが10個含まれるリストがあったとして、そのリストに含まれるユーザー情報をデータベースから取得する際に10回クエリを発行してしまうようなケースです。この場合、本来はIN
などのSQLを使うことでクエリは1回で済むので無駄な処理になってしまっています。
Sentryではそのようなクエリがないか監視できます。
なお、対応しているデータベースドライバを使用している場合、この機能を使うのに特に設定は要りません。
サードパーティインテグレーション
Sentryでは、様々なプラットフォームと連携して機能を拡張するオプションが用意されています
Misskeyの開発チームではDiscordをコミュニケーションツールとして利用していますが、SentryのDiscord連携機能を活用することで、ステージング環境内でエラーが発生した際にリアルタイムでDiscordに通知するような仕組みを構築しています。
Discord連携に関するドキュメントは以下にあります。
もちろんSlackなど他プラットフォームにも対応しています。
まとめ
Misskeyの開発用ステージング環境でSentryとDiscord連携を導入することによって、今まで気づいていなかったようなエラーの炙り出しを行うことができ、デバッグの効率化が行えました。
ソフトウェアの正式リリース前はこのようなエラーを早期発見することが品質を保証する上で重要です。
今のところバックエンドのみの導入ですが、今後フロントエンドにも導入予定なので、その際はVueとの連携について等、また解説を行いたいと思います。