Azure Logic Apps におけるエラーと例外の処理

適用対象: Azure Logic Apps (従量課金プラン + Standard)

あらゆる統合アーキテクチャに言えることですが、依存システムに起因するダウンタイムや問題の適切な処理方法には難しい問題が伴うことがあります。 問題やエラーを円滑に処理する堅牢で回復力の高い統合を構築しやすいよう、Azure Logic Apps には、エラーと例外の処理に関してきわめて優れた機能が用意されています。

再試行ポリシー

最も基本的な例外とエラー処理では、HTTP アクションなどのトリガーまたはアクションでサポートされている場合は、"再試行ポリシー" を使用できます。 トリガーまたはアクションの元の要求がタイムアウトまたは失敗し、408、429、または 5xx 応答が発生した場合は、ポリシー設定に従ってトリガーまたはアクションで要求を再送信するよう、再試行ポリシーで指定します。

再試行ポリシーの制限

再試行ポリシー、設定、制限、および他のオプションについて詳しくは、「再試行ポリシーの制限」をご覧ください。

再試行ポリシーの種類

再試行ポリシーをサポートするコネクタ操作では、別の再試行ポリシーを選択しない限り、既定のポリシーが使用されます。

再試行ポリシー 説明
[Default] ほとんどの操作では、既定の再試行ポリシーは指数間隔ポリシーです。これは、"指数関数的に増加する" 間隔で最大 4 回の再試行を送信します。 これらの間隔の増加係数は 7.5 秒であり、下限と上限はそれぞれ 5 秒と 45 秒です。 いくつかの操作では、固定間隔ポリシーなど、別の既定の再試行ポリシーが使用されます。 詳細については、既定の再試行ポリシーの種類を確認してください。
なし 要求を再送信しません。 詳細については、「なし - 再試行ポリシーなし」を参照してください。
指数間隔 このポリシーでは、指数関数的に増加する範囲から選ばれたランダムな間隔だけ待ってから、次の要求を送信します。 詳細については、指数間隔ポリシーの種類を確認してください。
固定間隔 このポリシーは、指定された間隔を待ち時間として、次の要求を送信します。 詳細については、固定間隔ポリシーの種類を確認してください。

デザイナーで再試行ポリシーの種類を変更する

  1. Azure portal で、ロジック アプリ ワークフローをデザイナーで開きます。

  2. 従量課金または Standard ワークフローのどちらで作業しているかに基づいて、トリガーまたはアクションの [設定] を開きます。

    • 従量課金: アクションのシェイプで、省略記号メニュー [...] を開き、[設定] を選びます。

    • Standard: デザイナーでアクションを選びます。 詳細ペインで、[設定] を選びます。

  3. トリガーまたはアクションが再試行ポリシーをサポートしている場合、[再試行ポリシー] で目的のポリシーの種類を選びます。

コード ビュー エディターで再試行ポリシーの種類を変更する

  1. 必要な場合は、デザイナーで前記の手順を完了して、トリガーまたはアクションが再試行ポリシーをサポートしているかどうかを確認します。

  2. コード ビュー エディターでロジック アプリ ワークフローを開きます。

  3. トリガーまたはアクションの定義で、そのトリガーまたはアクションの inputs オブジェクトに retryPolicy JSON オブジェクトを追加します。 それ以外の場合、retryPolicy オブジェクトが存在しない場合は、トリガーまたはアクションで default 再試行ポリシーを使います。

    "inputs": {
       <...>,
       "retryPolicy": {
          "type": "<retry-policy-type>",
          // The following properties apply to specific retry policies.
          "count": <retry-attempts>,
          "interval": "<retry-interval>",
          "maximumInterval": "<maximum-interval>",
          "minimumInterval": "<minimum-interval>"
       },
       <...>
    },
    "runAfter": {}
    

    必須

    プロパティ 種類 説明
    type <retry-policy-type> String 使用する再試行ポリシーの種類: defaultnonefixed、または exponential
    count <retry-attempts> Integer fixedexponential のポリシーの種類では、再試行の回数 (1 から 90 の値)。 詳しくは、固定間隔指数間隔に関する説明をご覧ください。
    interval <retry-interval> String fixedexponential のポリシーの種類では、再試行の間隔の値 (ISO 8601 形式)。 exponential ポリシーの場合は、必要に応じて最大と最小の間隔を指定することもできます。 詳しくは、固定間隔指数間隔に関する説明をご覧ください。

    従量課金: 5 秒 (PT5S) から 1 日 (P1D)。
    Standard: ステートフル ワークフローの場合、5 秒 (PT5S) から 1 日 (P1D)。 ステートレス ワークフローの場合、1 秒 (PT1S) から 1 分 (PT1M)。

    省略可能

    プロパティ 種類 説明
    maximumInterval <maximum-interval> String exponential ポリシーで、ランダムに選ばれる間隔の最大値です (ISO 8601 形式)。 既定値は 1 日 (P1D) です。 詳しくは、指数間隔に関する説明をご覧ください。
    minimumInterval <minimum-interval> String exponential ポリシーで、ランダムに選ばれる間隔の最少値です (ISO 8601 形式)。 既定値は 5 秒 (PT5S) です。 詳しくは、指数間隔に関する説明をご覧ください。

既定の再試行ポリシー

再試行ポリシーをサポートするコネクタ操作では、別の再試行ポリシーを選択しない限り、既定のポリシーが使用されます。 ほとんどの操作では、既定の再試行ポリシーは指数間隔ポリシーです。これは、"指数関数的に増加する" 間隔で最大 4 回の再試行を送信します。 これらの間隔の増加係数は 7.5 秒であり、下限と上限はそれぞれ 5 秒と 45 秒です。 いくつかの操作では、固定間隔ポリシーなど、別の既定の再試行ポリシーが使用されます。

ワークフロー定義では、トリガーまたはアクションの定義で既定のポリシーが明示的に定義されませんが、次の例は、HTTP アクションに対する既定の再試行ポリシーの動作を示しています。

"HTTP": {
   "type": "Http",
   "inputs": {
      "method": "GET",
      "uri": "http://myAPIendpoint/api/action",
      "retryPolicy" : {
         "type": "exponential",
         "interval": "PT7S",
         "count": 4,
         "minimumInterval": "PT5S",
         "maximumInterval": "PT1H"
      }
   },
   "runAfter": {}
}

なし - 再試行ポリシーなし

失敗した要求を再試行しないようアクションまたはトリガーに指定するには、<retry-policy-type> を none に設定します。

固定間隔の再試行ポリシー

指定した間隔の経過後に次の要求を送信するようアクションまたはトリガーに指定するには、<retry-policy-type> を fixed に設定します。

この再試行ポリシーは、最新のニュースを取得する要求が失敗した後、2 回の再試行を行います。それぞれの再試行間には 30 秒の延期期間が設けられます。

"Get_latest_news": {
   "type": "Http",
   "inputs": {
      "method": "GET",
      "uri": "https://mynews.example.com/latest",
      "retryPolicy": {
         "type": "fixed",
         "interval": "PT30S",
         "count": 2
      }
   }
}

指数間隔の再試行ポリシー

指数間隔の再試行ポリシーでは、次の要求を送信する前に、トリガーまたはアクションがランダムな間隔だけ待つことを指定します。 このランダムな間隔は、指数関数的に増加する範囲から選ばれます。 必要に応じて、従量課金または Standard のどちらのロジック アプリ ワークフローを使用しているのかに基づいて、独自の最小間隔と最大間隔を指定することにより、既定の最小間隔と最大間隔をオーバーライドできます。

名前 従量課金の制限 Standard の制限 メモ
最大待ち時間 (1 ~ 32767秒) 既定値: 1 日 既定値: 1 時間 従量課金ロジック アプリ ワークフローの既定の制限を変更するには、再試行ポリシー パラメーターを使います。

Standard ロジック アプリ ワークフローの既定の制限を変更するには、「シングルテナントの Azure Logic Apps でロジック アプリのホストとアプリの設定を編集する」を参照してください。

最小遅延 既定値: 5 秒 既定値: 5 秒 従量課金ロジック アプリ ワークフローの既定の制限を変更するには、再試行ポリシー パラメーターを使います。

Standard ロジック アプリ ワークフローの既定の制限を変更するには、「シングルテナントの Azure Logic Apps でロジック アプリのホストとアプリの設定を編集する」を参照してください。

ランダム変数の範囲

次の表では、指数間隔の再試行ポリシーについて、再試行ごとに指定された範囲内で一様なランダム変数を生成するために Azure Logic Apps で使われる一般的なアルゴリズムを示します。 範囲では、最大の再試行回数 (その値を含む) を指定できます。

再試行回数 最小間隔 最大間隔
1 max(0, <minimum-interval>) min(interval, <maximum-interval>)
2 max(interval, <minimum-interval>) min(2 * interval, <maximum-interval>)
3 max(2 * interval, <minimum-interval>) min(4 * interval, <maximum-interval>)
4 max(4 * interval, <minimum-interval>) min(8 * interval, <maximum-interval>)

"実行条件" の動作を管理する

ワークフロー デザイナーでアクションを追加するときは、それらのアクションを実行するために使う順序を暗黙的に宣言します。 アクションの実行が完了した後、そのアクションは SucceededFailedSkippedTimedOut などの状態でマークされます。 既定では、デザイナーで追加するアクションは、先行処理が Succeeded 状態で完了した後にのみ実行されます。 アクションの基になっている定義では、runAfter プロパティによって、最初に完了する必要がある先行処理アクションと、後続処理アクションが実行される前にその先行処理に許可される状態が指定されます。

アクションが未処理エラーまたは例外をスローした場合、アクションは Failed としてマークされ、後続処理アクションはすべて Skipped としてマークされます。 並列分岐があるアクションに対してこの動作が発生した場合、Azure Logic Apps エンジンはその他の分岐に従い、完了状態を確認します。 たとえば、分岐が Skipped アクションで終了した場合、その分岐の完了状態はそのスキップされたアクションの先行処理状態に基づきます。 ワークフローの実行が完了すると、すべての分岐の状態を評価することによって、実行全体の状態がエンジンによって決定されます。 分岐のいずれかが失敗すると、ワークフローの実行全体が Failed としてマークされます。

Conceptual diagram with examples that show how run statuses are evaluated.

先行処理の状態にかかわらずアクションを引き続き実行できるようにするには、アクションの "実行条件" 動作を変更して、先行処理の失敗状態を処理できます。 それにより、先行処理の状態が SucceededFailedSkippedTimedOut、またはこれらすべての状態のときに、アクションが実行されます。

たとえば、Excel Online の行をテーブルに追加先行処理アクションが Succeeded ではなく Failed とマークされた後で、Office 365 Outlook のメール送信アクションを実行するには、デザイナーまたはコード ビュー エディターを使って "実行条件" 動作を変更します。

注意

デザイナーでは、トリガーの実行が成功してからでないと最初のアクションは実行できないので、トリガーの直後にあるアクションには "実行条件" の設定は適用されません。

デザイナーで "実行条件" の動作を変更する

  1. Azure portal に移動し、ロジック アプリ ワークフローをデザイナーで開きます。

  2. デザイナーでアクションのシェイプを選びます。 詳細ペインで、[実行までの期間] を選びます。

    Screenshot showing Standard workflow designer and current action details pane with

    [実行までの期間] ペインには、現在選ばれているアクションの先行処理アクションが表示されます。

    Screenshot showing Standard designer, current action, and

  3. 先行処理アクション ノードを展開して、すべての "実行条件" の状態を表示します。

    既定では、"実行条件" の状態は [に成功しました] に設定されています。 そのため、現在選ばれているアクションが実行できるためには、先行処理アクションが正常に実行される必要があります。

    Screenshot showing Standard designer, current action, and default

  4. "実行条件" の動作を希望の状態に変更します。 既定のオプションをオフにする前に、オプションをまず選択してください。 常に少なくとも 1 つのオプションが選ばれている必要があります。

    次の例では、[に失敗しました] が選ばれています。

    Screenshot showing Standard designer, current action, and

  5. 先行処理アクションが FailedSkipped、または TimedOut としてマークされているかどうかに関係なく現在のアクションを実行するように指定するには、他の状態を選びます。

    Screenshot showing Standard designer, current action, and multiple

  6. 複数の先行処理アクションが実行されるように要求するには、それぞれの独自の "実行条件" の状態で、[操作の選択] の一覧を展開します。 必要な先行処理アクションを選び、必要な "実行条件" の状態を指定します。

    Screenshot showing Standard designer, current action, and multiple predecessor actions available.

  7. 準備ができたら、 [完了] を選択します。

コード ビュー エディターで "実行条件" の動作を変更する

  1. Azure portal に移動し、ロジック アプリ ワークフローをコード ビュー エディターで開きます。

  2. アクションの JSON 定義で、次のような構文の runAfter プロパティを編集します。

    "<action-name>": {
       "inputs": {
          "<action-specific-inputs>"
       },
       "runAfter": {
          "<preceding-action>": [
             "Succeeded"
          ]
       },
       "type": "<action-type>"
    }
    
  3. たとえば、runAfter プロパティを Succeeded から Failed に変更します。

    "Send_an_email_(V2)": {
       "inputs": {
          "body": {
             "Body": "<p>Failed to add row to table: @{body('Add_a_row_into_a_table')?['Terms']}</p>",
             "Subject": "Add row to table failed: @{body('Add_a_row_into_a_table')?['Terms']}",
             "To": "Sophia.Owen@fabrikam.com"
          },
          "host": {
             "connection": {
                "name": "@parameters('$connections')['office365']['connectionId']"
             }
          },
          "method": "post",
          "path": "/v2/Mail"
       },
       "runAfter": {
          "Add_a_row_into_a_table": [
             "Failed"
          ]
       },
       "type": "ApiConnection"
    }
    
  4. 先行処理アクションが FailedSkipped または TimedOut としてマークされている場合にアクションを実行するように指定するには、その他の状態を追加します。

    "runAfter": {
       "Add_a_row_into_a_table": [
          "Failed", "Skipped", "TimedOut"
       ]
    },
    

スコープとその結果を使用してアクションを評価する

"実行条件" の設定で個々のアクションの後の手順を実行するのと同じように、アクションをスコープ内にまとめることができます。 アクションを論理的にグループ化し、スコープの集合的な状態を調査し、その状態に基づいてアクションを実行する場合は、スコープを使用できます。 そのスコープ内のすべてのアクションの実行が完了すると、スコープが独自の状態を取得します。

スコープの状態を調べるには、ワークフローの実行状態を調べるのと同じ条件 (SucceededFailed など) を使用できます。

既定では、スコープのすべてのアクションが成功すると、そのスコープの状態は Succeeded とマークされます。 スコープの最後のアクションが Failed または Aborted とマークされると、スコープの状態は Failed とマークされます。

Failed スコープの例外をキャッチして、そのエラーを処理するアクションを実行するには、その Failed スコープの"実行条件" の設定を使用できます。 このように、スコープ内の "いずれかの" アクションが失敗したときに、そのスコープに対して "実行条件" の設定を使用している場合、エラーをキャッチする 1 つのアクションを作成できます。

スコープの制限については、制限と構成に関するページをご覧ください。

エラーのコンテキストと結果を取得する

スコープからエラーをキャッチするのは便利ですが、正確な失敗したアクションとエラーまたは状態コードを把握するには、さらにコンテキストが必要になる場合もあります。 result() 関数は、スコープ付きアクションの最上位レベルのアクションからの結果を返します。 この関数は、パラメーターとしてスコープの名前だけを受け取り、それらの最上位レベルのアクションの結果を含む配列を返します。 これらのアクションのオブジェクトには、actions() 関数によって返される属性と同じ属性 (アクションの開始時刻、終了時刻、状態、入力、相関 ID、出力など) があります。

注意

result() 関数からは、最上位レベルのアクションからの結果 "だけ" が返され、スイッチ アクションや条件アクションなど、より深い入れ子のアクションからは返されません。

スコープ内の失敗したアクションに関するコンテキストを取得するには、スコープの名前と "実行条件" の設定を指定した @result() 式を使用します。 返された配列を、Failed 状態のアクションに絞り込むには、配列のフィルター処理アクションを追加できます。 返された失敗アクションに対してアクションを実行するには、返されたフィルター処理済みの配列を取得し、For each ループを使用します。

次の JSON の例では、My_Scope というスコープ アクション内で失敗したすべてのアクションの応答本文を含む HTTP POST 要求が送信されます。 例の後に詳細な説明があります。

"Filter_array": {
   "type": "Query",
   "inputs": {
      "from": "@result('My_Scope')",
      "where": "@equals(item()['status'], 'Failed')"
   },
   "runAfter": {
      "My_Scope": [
         "Failed"
      ]
    }
},
"For_each": {
   "type": "foreach",
   "actions": {
      "Log_exception": {
         "type": "Http",
         "inputs": {
            "method": "POST",
            "body": "@item()['outputs']['body']",
            "headers": {
               "x-failed-action-name": "@item()['name']",
               "x-failed-tracking-id": "@item()['clientTrackingId']"
            },
            "uri": "http://requestb.in/"
         },
         "runAfter": {}
      }
   },
   "foreach": "@body('Filter_array')",
   "runAfter": {
      "Filter_array": [
         "Succeeded"
      ]
   }
}

次の手順では、この例で行われていることを説明します。

  1. My_Scope 内のすべてのアクションの結果を取得するため、配列のフィルター処理アクションでは、@result('My_Scope') というフィルター式が使用されます

  2. [配列のフィルター処理] の条件は、状態が Failed と等しいすべての @result() 要素です。 この条件により、My_Scope のすべてのアクションの結果を含む配列がフィルター処理され、失敗したアクションの結果のみを抽出した配列が得られます。

  3. "フィルター後の配列" の出力に対して For_each ループ アクションを実行します。 このステップでは、フィルター処理済みの失敗したアクションの結果ごとに特定のアクションが実行されます。

    スコープ内の 1 つのアクションが失敗した場合、For_each ループ内のアクションは 1 回だけ実行されます。 失敗したアクションが複数ある場合は、エラーごとに 1 つのアクションが実行されます。

  4. For_each 項目の応答本文すなわち @item()['outputs']['body'] 式で HTTP POST を送信します。

    @result() 項目の構造は @actions() と同じであり、同じ方法で解析することができます。

  5. @item()['name']@item()['clientTrackingId'] という 2 つのカスタム ヘッダーが含まれます。前者は失敗したアクションの名前、後者は失敗した実行のクライアント追跡 ID です。

参考例として、前述の例で解析した namebodyclientTrackingId の各プロパティを含む 1 つの @result() 要素を次に示します。 For_each アクションの外側では、@result() によってこれらのオブジェクトの配列が返されます。

{
   "name": "Example_Action_That_Failed",
   "inputs": {
      "uri": "https://myfailedaction.azurewebsites.net",
      "method": "POST"
   },
   "outputs": {
      "statusCode": 404,
      "headers": {
         "Date": "Thu, 11 Aug 2016 03:18:18 GMT",
         "Server": "Microsoft-IIS/8.0",
         "X-Powered-By": "ASP.NET",
         "Content-Length": "68",
         "Content-Type": "application/json"
      },
      "body": {
         "code": "ResourceNotFound",
         "message": "/docs/folder-name/resource-name does not exist"
      }
   },
   "startTime": "2016-08-11T03:18:19.7755341Z",
   "endTime": "2016-08-11T03:18:20.2598835Z",
   "trackingId": "bdd82e28-ba2c-4160-a700-e3a8f1a38e22",
   "clientTrackingId": "08587307213861835591296330354",
   "code": "NotFound",
   "status": "Failed"
}

この記事の前出の式を使用することで、さまざまな例外処理パターンを実行できます。 フィルターで抽出したエラーの配列全体を、スコープ外の単一の例外処理アクションに渡して実行してもかまいません。その場合、For_each は不要です。 前述した \@result() の応答には、他にも便利なプロパティがあるので、それらを含めることもできます。

Azure Monitor ログを設定する

上記のパターンは、実行内で発生したエラーと例外を処理する便利な方法です。 ただし、実行とは別に発生したエラーを特定して対応することもできます。 ログやメトリックを監視したり、それらを好きな監視ツールに発行したりすることによって、実行の状態を評価することができます。

たとえば、Azure Monitor では、すべての実行とアクションの状態など、すべてのワークフロー イベントを宛先に送信する効率的な方法が提供されます。 Azure Monitor では、特定のメトリックとしきい値のアラートを設定できます。 ワークフロー イベントを Log Analytics ワークスペース または Azure ストレージ アカウントに送信することもできます。 または、すべてのイベントを Azure Event Hubs 経由で Azure Stream Analytics にストリーミングすることもできます。 Stream Analytics では、診断ログから得られる異常、平均値、またはエラーに基づいて適宜必要なクエリを記述できます。 Stream Analytics を使用して、キュー、トピック、SQL、Azure Cosmos DB、Power BI などのその他のデータ ソースに情報を送信できます。

詳細については、「Azure Monitor ログを設定し、Azure Logic Apps の診断データを収集する」を参照してください。

次の手順