Azure Data Factory (ADF) / Synpase Analytics / Fabric でパイプラインを作成し、アクティビティの実行時にエラーとなったことを検知する方法についてまとめておきたいと思います。
Contents
基本的なエラーの検知方法
パイプライン実行時のエラーの検知方法としては、一般的なものとして次の 2 種類のドキュメントがあるのではないでしょうか。
- Azure Data Factory を監視する
- 実際に使用するのは Azure Monitor リソース ログ / Kusto クエリ になります。
- Fabric では、診断ログで Log Analytics 実行状況を連携することができないため、この方法は使用できません
- Azure Data Factory または Azure Synapse パイプラインを使用して電子メールを送信する
- Fabric の場合は、パイプラインで直接 Outlook / Teams のアクティビティを使用することができるため Logic App を使用しくてもパイプラインを構築することができます。
今回はエラーの通知方法についての検討となっていますが、エラー処理の実装については、エラーと条件付き実行 も合わせて確認するとよいのではないでしょうか。
Azure Monitor を使用したエラーの検知
「1.」の方法は、Azure Monitor を使用したエラーの検知となり、この方法は ADF / Synapse で使用することができます。
Fabric では、Azure の診断設により Log Analytics Workspace に診断ログを連携することができないため、この方法を使用することはできません。
診断設定が利用できる環境では「パイプライン」「アクティビティ」「トリガー」の実行状況を、診断設定で Log Analytics Workspace に連携することができます。
Kusto クエリ に記載されている内容のような KQL を使用することで、実行状況を使用したアラートルールを設定して通知を行うことができます。
データとしては Log Analytics に格納されているデータを基にしてアラートを発生させるため、エラーが発生してからアラートルールで検知できるまで数分のタイムラグが発生する可能性があります。
Azure Monitor でのログ データ インジェスト時間 に記載されますが、ログデータが連携されて実際に使用できるようになるまでは「20秒~3分」のタイムラグがあります。
ログ データを取り込むための平均待機時間は "20 秒から 3 分" です。
取り込まれたデータの時間については インジェスト時間のチェック に記載されている 3 種類があり、パイプラインの実行時間を含めると次のような情報をログから使用することができます。
ADFPipelineRun | where PipelineName =~ "Mail Send Activity" and Status =~"Failed" | project Start, End, TimeGenerated, _TimeReceived, ingestion_time()
テーブルのレコード名 | 内容 | 値の例 |
Start | パイプラインの実行開始日時 | 2024-05-08T00:27:02Z |
End | パイプラインの実行終了日時 | 2024-05-08T00:27:16Z |
TimeGenerated | レコード内に指定した生成日時 | 2024-05-08T00:27:16.43958Z |
_TimeReceived | レコードの受信日時 | 2024-05-08T00:28:35Z |
$IngestionTime | クエリで使用できるようになった日時 | 2024-05-08T00:28:40.8806769Z |
アラートルールは、数分間隔でクエリを実行することで該当するログの存在を確認し、ログが存在した場合にアラートを発生させるものとなりますので、実際にエラーが発生してから、ログで検索できるようになるまでタイムラグが発生します。
上記の例であれば、「2024-05-08T00:27:16」に発生したエラーが実際に検索できるようになるのは「2024-05-08T00:28:40」となっているため、実際に通知が行われるまで「1:30」のタイムラグが発生します。
エラーが発生してから数分してから検知が行われても問題がないのであれば、Azure Monitor を使用してアラートルールを設定するのは、設定の容易性と集中管理を実現することができます。
パイプライン内にエラー通知用のアクティビティを設定してエラーを検知
「2.」の方法はこちらになります。
今回はメール通知を行っていますが、 Web アクティビティを使用すれば任意の REST API を呼び出すことができますので、メール通知以外の方法も可能です。
パイプライン内のアクティビティからメールを送信する方法としては、Learn のドキュメントでは以下の二種類が公開されているかと思います。
ADF / Synapse は Outlook のアクティビティが存在しないため、Logc App を使用してメールの送信を行う必要があります。
Fabric については、「Office 365 Outlook」のアクティビティが提供されていますので、直接 Outlook でメールを送信することが可能です。
この方法でエラーを通知する場合、パイプラインの中にメール送信のアクティビティを配置するため、エラーが発生した場合は通知の処理が即時実行されることになり、Azure Monitor と比較して、エラーの通知のタイムラグは短くなります。
このメール送信の部分を SendGrid で実施するのが本投稿の主目的となります。
エラー発生時に SendGrid を使用してメールを送信する
SendGrid の Free で 1 日に送信可能なメール数
https://sendgrid.kke.co.jp/plan/ から SendGrid のプランを確認することができます。
2024/4/1 より前は Free で送信可能なメール数は 12,000通/月 がありましたが、2024/4/1 以降は Free の送信可能上限が変更され、100通/日 となっています。
継続的な検証を実行していると、この上限に達してしまう可能性はありますので、Free で送信可能なメール数は意識しておくとよいのではないでしょうか。
SendGrid を使用したメール送信のサンプル
API を使用したメール送信については次のようなドキュメントが参考となります。
APIKEY を使用して API をコールすることでメールの送信を実行することができますので、これを Web アクティビティで実装することになります。
Web アクティビティを使用したメール送信
アクティビティの「失敗時」の次のステップとして Web アクティビティを設定し、アクティビティのエラー時に Web アクティビティを実行するように設定します。
今回はパラメーターとして次のような設定を行っています。
"parameters": { "to": { "type": "string", "defaultValue": "<To Mail Address>" }, "from": { "type": "string", "defaultValue": "<From Mail Address>" }, "DatadogAPIKEY": { "type": "string", "defaultValue": "<API KEY>" } }
Web アクティビティとしては、次の設定となります。
{ "name": "Web1", "type": "WebActivity", "dependsOn": [ { "activity": "Script1", "dependencyConditions": [ "Failed" ] } ], "policy": { "timeout": "0.12:00:00", "retry": 0, "retryIntervalInSeconds": 30, "secureOutput": false, "secureInput": false }, "userProperties": [], "typeProperties": { "method": "POST", "headers": { "Authorization": { "value": "Bearer @{pipeline().parameters.DatadogAPIKEY}", "type": "Expression" }, "Content-Type": "application/json" }, "url": "https://api.sendgrid.com/v3/mail/send", "body": { "value": "{\n \"personalizations\": [\n {\n \"to\": [\n {\n \"email\": \"@{pipeline().parameters.to}\"\n }\n ]\n }\n ],\n \"from\": {\n \"email\": \"@{pipeline().parameters.from}\"\n },\n \"subject\": \"Error [@{pipeline().Pipeline}]\",\n \"content\": [\n {\n \"type\": \"text/plain\",\n \"value\": \"@{pipeline().Pipeline} の実行でエラーが発生しました。\\n- Start Time (UTC): @{pipeline().TriggerTime}\\n- Error Code: @{activity('Script1').error.errorCode}\\n- RunID:@{pipeline().RunID}\"\n }\n ]\n}", "type": "Expression" } } },
パラメーターに指定した情報を使用して、SendGrid の API 経由でメールの送信を行っています。
想定通り動作が行われると、次のようなメールが送信されます。
エラー発生時に Web アクティビティが実行され、次のようなメールが送信されます。
今回はスクリプトで「SELECT @VERSION AS version」という誤った構文の作成を行っていましたので、これを正しい構文に修正します。
そうすると、スクリプトアクティビティでエラーが発生しなくなるため、Web アクティビティは実行されずエラーの通知は行われません。
SendGrid を使用すること亜で、パイプラインの設定だけでメールの送信設定を制御できるため、Logic App を使用した場合と比較して、設定を一元的に制御できるパイプラインになっているのではないでしょうか。
最後に実行するアクティビティをエラーとする
今回はスクリプトアクティビティでエラーが発生すると Web アクティビティが実行され、メールによる通知が行われます。
このようなパイプライン実行となった場合の、実行状況を確認すると、次のようにパイプラインの実行状態が「成功」となっています。
これは最後に実行した Web アクティビティによるメール送信が成功しているため、パイプライン実行としては成功となってしまっているのかと思います。
このパイプラインの構成では、Web アクティビティの実行が失敗した場合は、パイプライン実行は失敗になるのですが、それより前に実行したアクティビティで失敗したい場合はパイプラインを失敗の状態にしたいケースのほうが多いのではないでしょうか。
そのような場合は、Fail アクティビティ を使用します。
Web アクティビティの「完了時」に実行されるアクティビティに Fail アクティビティを設定します。
この Fail アクティビティは次のような設定を行っており、スクリプトアクティビティ (Script1) のエラー情報を連携するようにしています。
{ "name": "Fail1", "type": "Fail", "dependsOn": [ { "activity": "Web1", "dependencyConditions": [ "Completed" ] } ], "userProperties": [], "typeProperties": { "message": { "value": "@activity('Script1').error.Message", "type": "Expression" }, "errorCode": { "value": "@activity('Script1').error.errorCode", "type": "Expression" } } }
このようなパイプラインを設定した場合、Web アクティビティの完了後に Fail アクティビティが実行されます。
パイプライン実行の結果としても「失敗」となっており、エラーの内容については、スクリプトアクティビティの内容が出力されていることが確認できます。
このような状態となっていれば、パイプライン実行としてもエラーとなりますので、診断設定を行っておけば、Log Analytics 上もエラーが発生したパイプライン実行として認識することができますので、アラートルールによる検知も可能です。