Sentry の エラー通知を Chatwork へ投げたい
こんにちは、エンジニアの柿添です。
この夏は本当に暑いですね。
日光にあたらないように出勤時のルートを涼しいルートへ変更しました。
多少は効果があるかと思いますが、暑さにはやはり勝てません。
ダイエットは忘れて食欲の秋を待ちわびています。
今回のテーマは、Sentry のエラー通知を Chatwork へ投げる方法です。 この手法を使うことで、エラー発生時にリアルタイムでの対応が可能となります。
実際に稼働しているLaravelアプリケーションで、SentryとChatworkを連携させる方法を紹介いたします。
そもともSentryとは
Sentryはエラーモニタリングとデバッグの専門サービスです。
アプリケーションが稼働中に発生するエラーや問題をリアルタイムでキャッチし、その詳細情報を明確に報告します。
この機能によって、開発者はエラーの即時認識と、それに対する効率的な対応が可能になります。
さらに、エラーの発生傾向や根本原因を分析することで、アプリケーションの全体的な品質を高める助けともなります。
Sentry がサポートしているPlatforms
Sentryは多くのプログラミング言語とフレームワークをサポートしています。
主なものは以下の通りです。
- JavaScript (React, Angular, Vue.js など)
- Python (Django, Flask など)
- Java (Android, Spring など)
- Ruby (Ruby on Rails)
- PHP (Laravel, Symfony など)
- C# (.NET, Unity)
- Go
- Swift / Objective-C (iOS)
- C/C++
- Rust
Sentry の用語
Sentryを使う上で覚えておきたい用語をいくつか紹介します。
詳細はSentry公式ドキュメントを参照してください。
- DSN (Data Source Name): Sentryにデータを送信するための認証情報が含まれたURL。
- Event: アプリケーションで発生した特定のエラーまたは問題。
- Issue: 一連の同じタイプのEventsをグループ化したもの。
- Release: ソフトウェアの新しいバージョン。Releasesを設定すると、どのバージョンでエラーが発生したかを追跡できます。
- Scope: イベントデータのコンテキストを設定するためのオブジェクト。
- Tag: イベントに追加情報を付与するためのキーワード。
- Alerts: Sentry内で設定するエラーまたはイベントに対する通知ルール。
- Attachments: イベントに関連付けられる追加データファイル。
- Data: Sentryに送信されるエラーやイベントの情報。
- Environment: アプリケーションが動作している環境(例:開発、ステージング、本番など)。
- Error: アプリケーションで発生した問題点、通常はEventとしてSentryに報告されます。
- Performance Monitoring: アプリケーションのパフォーマンスをリアルタイムで監視する機能。
- Project: Sentry内で特定のアプリケーションまたはサービスを管理するための単位。
Sentryのプラン
Sentryはさまざまなプランが用意されています。
無料のプランからエンタープライズプランまで、用途や規模に応じて選ぶことができます。
無料プランでも基本的なエラーモニタリング機能は十分に使用できますが、
高度な分析機能やサポートが必要な場合は、有料プランを検討する価値があります。
いつでもアップグレードまたはダウングレードでき、
次の請求サイクルの開始時に料金が自動的に調整されます。
詳細は Sentry Pricing を参照してください。
Sentry Developer 無料プラン
試しにSentry Developerの無料プランを使ってみます。 最大5,000イベント/月までの使用が可能な $0/月 の無料プランです。
- プロジェクトごとに最大1名のユーザーを追加可能
- すべての言語をサポート
- リリース追跡
- データは最大1GBまで
Sentry の Laravel パッケージをインストール
LaravelでSentryを利用するために、SentryのLaravelパッケージをインストールします。
composer require sentry/sentry-laravel
Sentry の.env設定
次に、.env
ファイルにSentryのDSNを設定します。
SENTRY_LARAVEL_DSN=your_dsn_here
Sentry 利用のための Handler を設定
また App/Exceptions/Handler.php の report メソッドに以下のコードを追加します。
public function report(Exception $exception)
{
if (app()->bound('sentry') && $this->shouldReport($exception)) {
app('sentry')->captureException($exception);
}
parent::report($exception);
}
Sentry の送信テスト
Laravelのアプリケーションでエラーを発生させ、Sentryに送信されるか確認します。
php artisan sentry:test
これでLaravel側の設定は完了です。
さらに詳しい内容についてはSentry公式ドキュメントを参照してください。
Sentry Alert の設定
Sentryでは、エラー発生時に通知を送るためのAlert機能があります。 この機能を使うことで、エラー発生時にリアルタイムで通知を受け取ることができます。
Sentry の Webhook を使う
SentryにはWebhook機能があり、エラー発生時に特定のURLに通知を送ることができます。 この機能を利用し、Cloudflare Workersを経由してChatwork APIを呼び出すことで、エラー情報をChatworkに送信します。
Alert -> Edit Alert Rule から Webhook を追加します。
Cloudflare Workers で Chatwork へ通知する
Cloudflare Workersを使用して、SentryからのWebhookを受け取り、それをChatworkへリレーします。
JavaScriptで短いスクリプトを書くだけで、連携を実現できます。
Cloudflare Workers の設定
Cloudflare Workersを使用するには、Cloudflareのアカウントが必要です。
アカウントを持っていない場合は、こちらから登録してください。
Workers & Pagesを選択し、Workersを有効にします。
クイック編集を選択し、以下の環境変数を設定します。
- CHATWORK_API_TOKEN: Chatwork APIのトークン
- CHATWORK_ROOM_ID: ChatworkのルームID
Chatwork APIのトークンは、こちらから取得できます。
Cloudflare Workers のコード
workerの名前は worker-relaying-alerts
とします。
今回はwranglerを使わずに、Cloudflare Workersのコードを直接編集します。
(wranglerとは、Cloudflare Workersを開発するためのコマンドラインツールです。)
const toJapanTime = (timestamp) => {
if (!timestamp) return "UnKnown";
const date = new Date(timestamp * 1000);
const offset = 9 * 60;
const localTime = new Date(date.getTime() + offset * 60000);
return localTime.toLocaleString("ja-JP");
};
const formatSentryData = (data) => {
const eventData = data.event || {};
return `
[info]Timestamp: ${toJapanTime(eventData.timestamp)}
Sentry URL: ${data.url || "UnKnown"}
[/info]
[code]- Project: ${data.project_name || "UnKnown"}
- Level: ${data.level || "UnKnown"}
- Culprit: ${data.culprit || "UnKnown"}
- Message: ${data.message || "UnKnown"}
- Platform: ${eventData.platform || "UnKnown"}
- Environment: ${eventData.environment || "UnKnown"}
- User: ${(eventData.user && eventData.user.email) || "UnKnown"} (${(eventData.user && eventData.user.ip_address) || "UnKnown"})
[/code]
Error Details:
--------------
${(eventData.logentry && eventData.logentry.formatted) || "UnKnown"}
Stacktrace:
-----------
${(eventData.stacktrace && eventData.stacktrace.frames) ? eventData.stacktrace.frames.map(frame => `${frame.filename}:${frame.lineno} in ${frame.function}`).join('\n') : "UnKnown"}
[hr]
Context:
[code]
${JSON.stringify(eventData.contexts || {}, null, 2)}
[/code]
`;
};
const sendMessageToChatwork = async (env, message) => {
const CHATWORK_URL = `https://api.chatwork.com/v2/rooms/${env.CHATWORK_ROOM_ID}/messages`;
const CHATWORK_HEADERS = {
'X-ChatWorkToken': env.CHATWORK_API_TOKEN,
'Content-Type': 'application/x-www-form-urlencoded'
};
const body = `body=${encodeURIComponent(message)}`;
return await fetch(CHATWORK_URL, {
method: 'POST',
headers: CHATWORK_HEADERS,
body: body
});
};
export default {
async fetch(request, env, ctx) {
if (request.method !== 'POST') {
return new Response('Method not supported.', { status: 405 });
}
try {
const requestData = await request.json();
const message = formatSentryData(requestData);
const chatworkMessage = `[info][title]Sentry Error Notification[/title]${message}[/info]`;
const chatworkResponse = await sendMessageToChatwork(env, chatworkMessage);
if (!chatworkResponse.ok) {
throw new Error('Failed to send notification to Chatwork.');
}
return new Response('Notification sent to Chatwork.', { status: 200 });
} catch (error) {
await sendMessageToChatwork(env, `Webhook Error: ${error.message || error}`);
return new Response(`Error: ${error}`, { status: 500 });
}
},
};
受け取り時のチェックは行っていないので、必要に応じて追加してください。
通知メッセージには、Sentryから送られてきたエラー情報を含めていますが、必要に応じて変更してください。
Sentryの管理画面へ戻り、 Project -> Alert Settings へ のCloudflare WorkersのURLを設定してください。
Sentry のアカウントを準備、Laravel での設定、Cloudflare Workers の設定、Cloudflare Workers のコードを設定したら、Sentry からの通知を Chatwork へ投げる準備は完了です。
test通知をChatworkで受け取った例
[info][title]Sentry Error Notification[/title]
[info]Timestamp: 2023/8/31 03:49:51
Sentry URL: XXXXXXXXXX
[/info]
[code]- Project: climber-test-php-laravel
- Level: error
- Culprit: raven.scripts.runner in main
- Message: This is an example Python exception
- Platform: python
- Environment: prod
- User: sentry@example.com (127.0.0.1)
[/code]
Error Details:
--------------
This is an example Python exception
Stacktrace:
-----------
raven/base.py:303 in build_msg
raven/base.py:459 in capture
raven/base.py:577 in captureMessage
raven/scripts/runner.py:77 in send_test_message
raven/scripts/runner.py:112 in main
[hr]
Context:
[code]
{
"browser": {
"name": "Chrome",
"version": "28.0.1500",
"type": "browser"
},
"client_os": {
"name": "Windows",
"version": "8",
"type": "os"
}
}
[/code]
[/info]
まとめ
この記事で取り上げたテーマは、エラーモニタリングサービスであるSentryと、コミュニケーションプラットフォームであるChatworkを連携させる方法です。
特に、SentryのWebhook機能とCloudflare
Workersを活用し、リアルタイムでエラー情報をChatworkに送信する設定に焦点を当てました。
この連携により、エラー発生時の対応がより迅速に、そして効率的に行えるようになります。
加えて、Sentryの基本的な用語やプラン、さらにはLaravelでの設定方法も簡単に触れました。
これらの知識を組み合わせることで、より効果的なエラーモニタリングと問題解決が可能となります。
この連携手法を是非とも試して、開発プロセスの効率化をはかってください。
そして、どの通知先が最も効果的か、どのような通知内容が必要かはプロジェクトやチームによって異なるため、是非とも自分たちに合った設定を行ってください。
それでは、より効率的な開発ライフをお送りください。
良いコーディングを!