error-tracking について
サービス全体に Sentry のエラー追跡とパフォーマンス監視を適用するためのスキルです。API、ワークフロー、cron ジョブ、データベース操作を計測する開発者向けです。
主な機能
- 01コンテキスト付きエラー捕捉
- 02Sentry スパンによる処理追跡
- 03データベース性能計測パターン
- 04cron ジョブ計測の指針
- 05重大度と導入のチェックリスト
活用シーン
- 01API エラーへの Sentry 処理追加
- 02データベースクエリ性能の追跡
- 03cron ジョブやワークフローの計測
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ diet103/ claude-code-infrastructure-showcase --skill error-trackingインストール後、Claude Code で/error-trackingを入力して読み込まれたか確認します。
詳細
Sentry 統合スキル
目的
このスキルでは、Sentry v8 のパターンに従って、すべてのサービスで包括的な Sentry エラートラッキングとパフォーマンス監視を実施します。
このスキルを使用する場面
- コードにエラーハンドリングを追加するとき
- 新しいコントローラーやルートを作成するとき
- cron ジョブを計測するとき
- データベースのパフォーマンスを追跡するとき
- パフォーマンススパンを追加するとき
- ワークフローのエラーを処理するとき
🚨 重大なルール
すべてのエラーを Sentry に記録する必要があります。例外はありません。console.error だけを使用してはいけません。
現在の状況
例:API サービス ✅ 完了
- Sentry v8 を全面的に統合済み
- すべてのワークフローエラーを追跡
- バックグラウンドジョブプロセッサーを計測済み
- テスト用エンドポイントを利用可能
Sentry 統合パターン
1. コントローラーのエラーハンドリング
// ✅ CORRECT - Use BaseController
import { BaseController } from '../controllers/BaseController';
export class MyController extends BaseController {
async myMethod() {
try {
// ... your code
} catch (error) {
this.handleError(error, 'myMethod'); // Automatically sends to Sentry
}
}
}
2. ルートのエラーハンドリング(BaseController を使用しない場合)
import * as Sentry from '@sentry/node';
router.get('/route', async (req, res) => {
try {
// ... your code
} catch (error) {
Sentry.captureException(error, {
tags: { route: '/route', method: 'GET' },
extra: { userId: req.user?.id }
});
res.status(500).json({ error: 'Internal server error' });
}
});
3. ワークフローのエラーハンドリング
これは、元の本番プロジェクトで使用されていた、ドメイン固有の Sentry ヘルパーの例です。このようなヘルパーをドメイン用に作成すると、呼び出し元は次のようになります。
import { WorkflowSentryHelper } from '../workflow/utils/sentryHelper';
WorkflowSentryHelper.captureWorkflowError(error, {
workflowCode: 'INVOICE_APPROVAL',
instanceId: 123,
stepId: 456,
userId: 'user-123',
operation: 'stepCompletion',
metadata: { additionalInfo: 'value' }
});
ヘルパーを使用しなくても、通常の Sentry はどこでも使用できます。
Sentry.captureException(error, {
tags: { operation: 'stepCompletion' },
extra: { workflowCode: 'INVOICE_APPROVAL', instanceId: 123, userId: 'user-123' }
});
4. cron ジョブ(必須パターン)
#!/usr/bin/env node
// FIRST LINE after shebang - CRITICAL!
import '../instrument';
import * as Sentry from '@sentry/node';
async function main() {
return await Sentry.startSpan({
name: 'cron.job-name',
op: 'cron',
attributes: {
'cron.job': 'job-name',
'cron.startTime': new Date().toISOString(),
}
}, async () => {
try {
// Your cron job logic
} catch (error) {
Sentry.captureException(error, {
tags: {
'cron.job': 'job-name',
'error.type': 'execution_error'
}
});
console.error('[Job] Error:', error);
process.exit(1);
}
});
}
main()
.then(() => {
console.log('[Job] Completed successfully');
process.exit(0);
})
.catch((error) => {
console.error('[Job] Fatal error:', error);
process.exit(1);
});
5. データベースのパフォーマンス監視
これは、元の本番プロジェクトの例です。DB 呼び出しを Sentry スパンでラップする小さなヘルパーです。コードベースに合わせて調整してください。
import { DatabasePerformanceMonitor } from '../utils/databasePerformance';
const result = await DatabasePerformanceMonitor.withPerformanceTracking(
'findMany',
'UserProfile',
async () => {
return await PrismaService.main.userProfile.findMany({
take: 5,
});
}
);
どこでも使える同等の方法は、Sentry スパンを直接使用することです。
const result = await Sentry.startSpan({
name: 'db.userProfile.findMany',
op: 'db.query',
attributes: { 'db.model': 'UserProfile', 'db.operation': 'findMany' }
}, async () => {
return await prisma.userProfile.findMany({ take: 5 });
});
6. スパンを使った非同期処理
import * as Sentry from '@sentry/node';
const result = await Sentry.startSpan({
name: 'operation.name',
op: 'operation.type',
attributes: {
'custom.attribute': 'value'
}
}, async () => {
// Your async operation
return await someAsyncOperation();
});
エラーレベル
適切な重大度レベルを使用してください。
- fatal:システムが使用不能(データベース停止、重大なサービス障害)
- error:操作に失敗し、すぐに対応が必要
- warning:回復可能な問題、パフォーマンスの低下
- info:情報メッセージ、成功した操作
- debug:詳細なデバッグ情報(開発時のみ)
必須コンテキスト
import * as Sentry from '@sentry/node';
Sentry.withScope((scope) => {
// ALWAYS include these if available
scope.setUser({ id: userId });
scope.setTag('service', 'api'); // your service name
scope.setTag('environment', process.env.NODE_ENV);
// Add operation-specific context
scope.setContext('operation', {
type: 'workflow.start',
workflowCode: 'INVOICE_APPROVAL',
entityId: 123
});
Sentry.captureException(error);
});
サービス統合の例
API サービス(例)
場所:./api/src/instrument.ts
import * as Sentry from '@sentry/node';
import { nodeProfilingIntegration } from '@sentry/profiling-node';
Sentry.init({
dsn: process.env.SENTRY_DSN,
environment: process.env.NODE_ENV || 'development',
integrations: [
nodeProfilingIntegration(),
],
tracesSampleRate: 0.1,
profilesSampleRate: 0.1,
});
主なヘルパー:
- ドメイン固有のエラーに対応したカスタム Sentry ヘルパー
DatabasePerformanceMonitor- DB クエリの追跡BaseController- コントローラーのエラーハンドリング
通知サービス(例)
場所:./notifications/src/instrument.ts
import * as Sentry from '@sentry/node';
import { nodeProfilingIntegration } from '@sentry/profiling-node';
Sentry.init({
dsn: process.env.SENTRY_DSN,
environment: process.env.NODE_ENV || 'development',
integrations: [
nodeProfilingIntegration(),
],
tracesSampleRate: 0.1,
profilesSampleRate: 0.1,
});
主なヘルパー:
- ドメインエラーに対応したサービス固有の Sentry ヘルパー
BaseController- コントローラーのエラーハンドリング
設定(config.ini)
[sentry]
dsn = your-sentry-dsn
environment = development
tracesSampleRate = 0.1
profilesSampleRate = 0.1
[databaseMonitoring]
enableDbTracing = true
slowQueryThreshold = 100
logDbQueries = false
dbErrorCapture = true
enableN1Detection = true
Sentry 統合のテスト
テスト用エンドポイントの例
# Test basic error capture
curl http://localhost:3000/api/sentry/test-error
# Test performance tracking
curl http://localhost:3000/api/sentry/test-performance
# Test database performance
curl http://localhost:3000/api/sentry/test-database-performance
Sentry 統合がエンドツーエンドで正しく動作することを確認するため、各サービスにテスト用エンドポイントを作成してください。
パフォーマンス監視
要件
- すべての API エンドポイントでトランザクションを追跡する必要があります
- 100ms を超えるデータベースクエリは自動的にフラグ付けされます
- N+1 クエリを検出して報告します
- cron ジョブの実行時間を追跡する必要があります
トランザクションの追跡
import * as Sentry from '@sentry/node';
// Automatic transaction tracking for Express routes
app.use(Sentry.Handlers.requestHandler());
app.use(Sentry.Handlers.tracingHandler());
// Manual transaction for custom operations
const transaction = Sentry.startTransaction({
op: 'operation.type',
name: 'Operation Name',
});
try {
// Your operation
} finally {
transaction.finish();
}
避けるべきよくある間違い
❌ Sentry を使わずに console.error を使用してはいけません
❌ エラーを黙って握りつぶしてはいけません
❌ エラーコンテキストに機密データを含めてはいけません
❌ コンテキストのない汎用的なエラーメッセージを使用してはいけません
❌ 非同期処理でエラーハンドリングを省略してはいけません
❌ cron ジョブの最初の行で instrument.ts をインポートし忘れてはいけません
実装チェックリスト
新しいコードに Sentry を追加する場合:
- Sentry または適切なヘルパーをインポートした
- すべての try/catch ブロックで Sentry にエラーを記録する
- エラーに有用なコンテキストを追加した
- 適切なエラーレベルを使用した
- エラーメッセージに機密データを含めていない
- 遅い処理にパフォーマンス追跡を追加した
- エラーハンドリングの経路をテストした
- cron ジョブの場合:
instrument.tsを最初にインポートした
主なファイル(一般的な構成)
サービスごと
src/instrument.ts- Sentry の初期化(最初にインポート)src/utils/sentryHelper.ts- ドメイン固有のエラーヘルパーsrc/utils/databasePerformance.ts- DB の監視src/controllers/BaseController.ts- Sentry を備えたコントローラーのベース
設定
config.iniまたは.env- Sentry DSN と設定sentry.ini- 共通の Sentry 設定(任意)