0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Part 7: エラーハンドリングの設計パターン (エラーログ管理・リトライ機構)

Posted at

Part 7: エラーハンドリングの設計パターン (エラーログ管理・リトライ機構)

前回は テストクラスでのエラーハンドリングカスタム例外の活用 について解説しました。
今回は 実際の運用で役立つエラーハンドリングの設計パターン として、
エラーログの管理リトライ機構 (再試行) の実装 を解説します。


1. エラーログ管理の重要性

1.1. なぜエラーログが必要か?

Apex の処理がエラーで停止すると、管理者や開発者に通知されない限り問題に気づきにくい です。
そのため、エラーログを記録し、エラーを監視できる仕組みを作ることが重要 です。


1.2. エラーログの作成

Salesforce には カスタムオブジェクト を作成してエラーを記録するのが一般的です。
以下のような ErrorLog__c オブジェクト を作成しましょう。

項目名 API名 説明
エラーメッセージ Message__c 長いテキスト 発生したエラー内容
クラス名 ClassName__c テキスト 例外が発生したクラス名
メソッド名 MethodName__c テキスト 例外が発生したメソッド名
行番号 LineNumber__c 数値 エラー発生行
スタックトレース StackTrace__c 長いテキスト 詳細なエラー情報
発生日時 OccurredAt__c 日時 エラー発生時刻

1.3. エラーログを記録する共通メソッド

エラーを ErrorLog__c に記録するメソッドを作成します。
こうすることで、どこでエラーが発生しても統一的にログを記録できます

✅ OK 例: ErrorLogService クラス

public class ErrorLogService {
    public static void logError(Exception e, String className, String methodName) {
        try {
            ErrorLog__c log = new ErrorLog__c();
            log.Message__c = e.getMessage();
            log.ClassName__c = className;
            log.MethodName__c = methodName;
            log.LineNumber__c = e.getLineNumber();
            log.StackTrace__c = e.getStackTraceString();
            log.OccurredAt__c = System.now();
            insert log;
        } catch (Exception ex) {
            System.debug('ログ記録中にエラー発生: ' + ex.getMessage());
        }
    }
}

1.4. 例外発生時にログを記録

例外が発生したときに、エラーログを記録するように try-catch を実装 します。

✅ OK 例: AccountService クラス

public class AccountService {
    public static void createAccount(Account acc) {
        try {
            insert acc;
        } catch (DmlException e) {
            ErrorLogService.logError(e, 'AccountService', 'createAccount');
            throw e;
        }
    }
}

1.5. エラーログを可視化

エラーログを管理するには、カスタムレポートやダッシュボードを作成 し、
管理者がエラーを確認できるようにするとよいでしょう。

また、フローやプロセスビルダーでエラー発生時に通知を送る のも効果的です。


2. リトライ機構 (再試行) の実装

2.1. なぜリトライが必要か?

Salesforce の API 制限や一時的なネットワークエラーのために、
DML 操作や外部システムとの通信が一時的に失敗することがあります

特に以下のようなケースでは、リトライ機構を実装することで処理の成功率を高められます

  • DmlException: ガバナ制限 による DML 失敗
  • CalloutException: 外部 API の一時的な障害 によるコールアウト失敗
  • QueryException: SOQL クエリの一時的な制限 によるエラー

2.2. 再試行の基本設計

一定回数までリトライし、それでも失敗したらエラーログに記録する 形が一般的です。


2.3. DML 操作のリトライ

✅ OK 例: DMLHelper クラス

public class DMLHelper {
    public static void insertWithRetry(SObject record, Integer maxRetries) {
        Integer attempts = 0;
        Boolean success = false;
        
        while (attempts < maxRetries && !success) {
            try {
                insert record;
                success = true;
            } catch (DmlException e) {
                attempts++;
                if (attempts == maxRetries) {
                    ErrorLogService.logError(e, 'DMLHelper', 'insertWithRetry');
                    throw e; // 最大リトライ回数に達した場合は例外をスロー
                }
                System.debug('DML 失敗、リトライ ' + attempts + ' 回目');
            }
        }
    }
}

このメソッドは DML 操作が失敗した場合に最大 maxRetries 回までリトライ します。
それでも失敗した場合は、エラーログを記録して例外をスロー します。


2.4. 外部 API コールアウトのリトライ

外部システムとの連携では、ネットワーク障害やタイムアウト が発生することがあります。
CalloutException が発生した場合に、一定回数リトライする 実装をします。

✅ OK 例: CalloutHelper クラス

public class CalloutHelper {
    public static String makeCallout(String endpoint, Integer maxRetries) {
        Integer attempts = 0;
        Boolean success = false;
        String response = '';

        while (attempts < maxRetries && !success) {
            try {
                Http http = new Http();
                HttpRequest req = new HttpRequest();
                req.setEndpoint(endpoint);
                req.setMethod('GET');
                HttpResponse res = http.send(req);
                
                if (res.getStatusCode() == 200) {
                    response = res.getBody();
                    success = true;
                } else {
                    throw new CalloutException('HTTPエラー: ' + res.getStatusCode());
                }
            } catch (CalloutException e) {
                attempts++;
                if (attempts == maxRetries) {
                    ErrorLogService.logError(e, 'CalloutHelper', 'makeCallout');
                    throw e;
                }
                System.debug('Callout 失敗、リトライ ' + attempts + ' 回目');
            }
        }
        return response;
    }
}

このメソッドは 外部 API のコールアウトが失敗した場合に最大 maxRetries 回までリトライ します。


まとめ

今回は エラーハンドリングの設計パターン として、
エラーログ管理リトライ機構 について解説しました。

  • ErrorLog__c カスタムオブジェクトでエラーを管理
  • ErrorLogService で例外を一元的に記録
  • DML 操作・API コールアウトのリトライ機構を実装
  • リトライ回数を制限し、最大回数を超えたらログを記録

次の Part 8 では、トリガー (Trigger) におけるエラーハンドリングとリカバリ方法 を解説します!

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?