Azure DataFactory Tips タイムスライスの再実行

Microsoft Azure Advent Calendar 2016 3日目として書きました。

Azure DataFactory(以下ADF)は、データの移動や変換を自動化するクラウドベースのデータインテグレーションサービスです。 ADFには、コピーアクティビティとデータ変換アクティビティの2種類があります。このうちコピーアクティビティは、単純なETLツールで優れたパフォーマンスとリーズナブルな価格で魅力的なサービスです。個人的にはコピーアクティビティはシンプルでなかなかよく出来ており、お気にいりました。データ変換アクティビティはクラスタを上げて変換処理をするのが利点でもあり難点でもあるって感じですね。

今回は、スクリプトからのエラーリカバリ、タイムスライスの再実行について記述します。ADFでは実行はタイムスライス単位で行われデータソースの問題で複数のタイムスライスが失敗した時などエラーの数が多くなり勝ちです。エラーが多くなるとポータルの画面から再実行をするのはポチポチが多くなってとても面倒になります。そんな時にはということで、Azure PowerShell から、失敗したタイムスライスを再実行してみます。

参照: この記事の基本は概ね、Azure Data Factory のパイプラインの監視と管理に書いてありますので、そちらもどうぞ。

原因究明

まずは、エラーの原因を確認します。エラーが大量に出ていると面倒なので、下記のようなスクリプトでエラーメッセージでサマります。やっていることは、 ログのsort | uniq -cです。

エラーの確認を実行

下記の様に実行すると、DatasetName, ErrorMessage でサマった数が表示されます。下記の例だとエラーメッセージが長過ぎて最後まで見れませんが、コマンド行に、| Out-String -Width 4096[1]を追加すると最後まで表示されます。(幅は随時変更してください)

$ .\adferror1.ps1 -ResourceGroupName "TestADF01" -DataFactoryName "APITutorial" -StartDateTime 2016-08-09T10:00:00 -EndDateTime 2016-08-09T11:00:00

Count DatasetName                ErrorMessage
----- -----------                ------------
    7 DatasetAzureSqlDestination Copy activity encountered a user error at Sink:tcp:kinmugisql01.database.windows.net,1433 s...

簡単にスクリプトの説明をします。Get-AzureRmDataFactorySlice でエラーになっているタイムスライスを取得して Get-AzureRmDataFactoryRun で、そのタイムスライスの詳細な情報を取得し、最後にエラーメッセージでグルーピングしてカウントしています。

再実行

これでエラーが分かるので問題を修正して、再実行します。

Azure DataFactoryのタイムスライスの再実行には、スライスの状態遷移を理解しなければなりません。そんなに複雑なことは無く、タイムスライスの状態遷移図は下記のようになっており、再実行は、Failed 状態から Waiting に変更することで行います。

https://docs.microsoft.com/ja-jp/azure/data-factory/media/data-factory-monitor-manage-pipelines/state-diagram.png

問題の修正が完了したら、下記のスクリプトで、失敗したタイムスライスを再実行します、スクリプトでは失敗したタイムスライスを古いものから順にWaitingにするだけです。タイムスライス毎に設定をしているので、pipelineで指定したバックフィルの順序が反映されません。タイムスライス間に依存関係がある場合は問題が出るかもしれませんので注意してください。

実行には、上記で確認したエラーになったデータセットを指定します。再実行になったタイムスライスを表示します。

$ .\\adfrerun.ps1 -ResourceGroupName "TestADF01" -DataFactoryName "APITutorial" -DatasetName "DatasetAzureSqlDestination" -StartDateTime 2016-08-09T10:00:00 -EndDateTime 2016-08-09T11:00:00

DatasetName                Start
-----------                -----
DatasetAzureSqlDestination 2016/08/09 9:00:00
DatasetAzureSqlDestination 2016/08/09 10:00:00
DatasetAzureSqlDestination 2016/08/09 11:00:00
DatasetAzureSqlDestination 2016/08/09 22:00:00
DatasetAzureSqlDestination 2016/08/09 23:00:00

下記のようなコマンドで、タイムスライスの状態を確認することができます。ここでは、Ready以外を表示しています。

$ Get-AzureRmDataFactorySlice -ResourceGroupName "TestADF01" -DataFactoryName "APITutorial" -DatasetName "DatasetAzureSqlDestination" -StartDateTime 2016-08-09T10:00:00 -EndDateTime 2016-08-09T11:00:00 | ? {$_.State -ne 'Ready'}

最後に

Azure PowerShellを使っていると、PowerShellのオブジェクトパイプランが強力さを肌で感じます。パイプで繋いで、%, ?とやるのが気に入ってしまいました。

今回ちょっと分かり辛らかったのは、 タイムスライスを返すGet-AzureRmDataFactorySliceと タイムスライス の実行結果を返すGet-AzureRmDataFactoryRunの関係でした。最初Get-AzureRmDataFactoryRunがデータセットの実行結果を取得するのかと勘違いしていたこともあり、どのようなパラメータを渡せば良いのかが分からず… このコマンドが、タイムスライスの実行結果を返すもので、タイムスライス(slice)のIDとして開始時間を渡すということに大分時間を無駄にしました。後で、マニュアル[2]見たらちゃんと書いてあったんですが、、、、

Set-AzureRmDataFactorySliceStatusは、期間を渡せるので、個々のタイムスライスを指定するのではなく。期間をわたしてざっくり再実行でも良いかもしれません。その場合は、エラーになったタイムスライスを探して、その周辺の時間帯をざっくり再実行って感じですかね。それはそれで、実用性は高そうな気がしてきました。

締めは、Azure DataFactory はいいぞ!ということで。

脚注

[1]poshのデフォルトではコンソール出力はコンソールバッファーの幅で省略されます。この仕様は余計なお世話な気がします。そのまま出してくれれば良いのに。
[2]Get-AzureRmDataFactoryRun