Web Apps on Linux で ASP.NET Core のダンプを採って開いてみる

#はじめに
本記事は、Microsoft Azure Tech Advent Calendar 2020 の投稿です。いつものごとくいつものように、Azure Web Apps をトラブルシューティングしてみます。今回は敢えて Windows ではなく、Linux で ASP.NET Core アプリケーションのプロセスダンプを採取し、それを解析というか開くところまでやってみたいと思います

#事前準備
まず、シンプルな ASP.NET Core の Web アプリケーションを用意する必要があります。とりあえず Visual Studio 2019 を起動し、新しいプロジェクトとして ASP.NET Core Web アプリケーションを選びましょう。ASP.NET Core のバージョンは 3.1 を選択します（以下手順に必要な .NET Core の最低バージョンは 3.1.7 以降です）。他はプロジェクトテンプレートに従ってお好きなものを選択してください。

次に Azure 上に Azure Web Apps を作成しますが、[オペレーティングシステム] として "Linux"、[公開] を "コード"、[ランタイムスタック] を ".NET Core 3.1(LTS)" を選びます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212814/a878084d-b9fa-670a-a9a1-38840f776b64.png)

あとは、Visual Studio 2019 から、この Azure Web Apps へデプロイしておきます。https://<作成した Web Apps 名>.azurewebsites.net/ にアクセスし、実装したページが表示されることを確認しておきます。

#事前知識
Azure Web Apps でも、オペレーティングシステムが "Windows" であればダンプや CLR Profiler の採取は比較的容易かなと思います。該当の Azure Web Apps を開き、[問題の診断と解決] ブレードから、テキストボックスに Collect と入力して、出てくる選択肢から Collect Memory Dump や Collect .NET Profiler Trace を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212814/f9722006-6a6d-9d0d-70cf-f84c4e3cd9fc.png)

Collect Memory Dump であれば以下のように、複数インスタンスでダンプを採取し、ストレージに保存、さらに "Collect and Analyze Data" を選んでいれば自動解析の結果（下部 Reports からリンク）も得られます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212814/9b78b0f1-d5e2-810f-62a9-4ba7498e75f1.png)

しかし、Azure Web Apps on Linux では、同じ項目が [問題の診断と解決] には出て来ません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212814/d8be484e-ea5f-9654-1608-895f2f3beffb.png)

なので、じゃあどうするの？というのがこの記事のキモでございます。

#ダンプ採取
一般的な方法としては二つ考えられ、

- LLDB などの Linux 向けネイティブデバッガーを使うか
- procdump for Linux を使うか

のどちらかだと思います。後者については下記を参照してください。
https://github.com/microsoft/ProcDump-for-Linux

新しもの好きということで、今回は第三の手法、dotnet-dump コマンドを使いましょう。オプション等の詳細については下記リファレンスを参照してください。
https://docs.microsoft.com/ja-jp/dotnet/core/diagnostics/dotnet-dump

1) 該当の Azure Web Apps を開き、[SSH] を選択して "移動" をクリックします

2) SSH が表示されたら、/home/logfiles へ移動します

3) dotnet-dump コマンドを ps オプションでを実行します。現在動作中の .NET プロセスが列挙されます（事前に Web ページが表示されることを確認しておきます）。冒頭に表示されるプロセス ID を控えます。下記であれば 27 です。

```CMD
root@nnnnnnnnnnnn:~/logfiles# dotnet-dump ps
        27 dotnet     /usr/share/dotnet/dotnet
```

4) dotnet-dump コマンドを collect オプションで実行します。--process-id に 3) で控えたプロセス ID、ヒープメモリーも保存するので --type に Full を指定します

```CMD
root@nnnnnnnnnnnn:~/logfiles# dotnet-dump collect --process-id 27 --type Full

Writing full to /home/logfiles/core_20201205_110848
Complete
```

5) 採取されたダンプファイル、上記で言えば core_20201205_110848 を取り出します。ブラウザであれば、https://<作成した Web Apps 名>.scm.azurewebsites.net/api/zip/LogFiles にアクセスすれば logfile 以下が zip でダウンロードできます。

#ダンプ解析
では次に解析です。Linux 上で、、、と想像されたかもしれませんがご安心を。Visual Studio 2019 バージョン 16.8 には Linux で採取されたダンプを解析する機能があるんです。やってみましょう。

1) Visual Studio を開きます。出来れば、事前準備で作成した ASP.NET Core のプロジェクトを開いておくとスムーズです

2) [ファイル] - [開く] - [ファイル] から、ダウンロードしたダンプファイルを指定します。さらに、そのまま [開く] ボタンを押すのではなく、[ファイルを開くアプリケーションの選択] を選びます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212814/b3fcbbc0-625e-c139-3de6-3216f3611564.png)

3) [プログラムから開く] のダイアログで "マネージド Linux コアダンプファイルの概要" を選びます。Visual Studio のバージョンが古かったりすると出てこないのではないかと思います
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212814/32d138dd-aeb9-42cf-22f2-428e13402bad.png)

4) ダンプが開かれたら右上、"アクション" で [マネージドのみ でデバッグ] を選びます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212814/812f19c5-aa0b-f747-cf26-eb1a66121c35.png)

5) タスク、並列スタック、呼び出し履歴、などデバッグ系のウィンドウが表示されることを確認します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212814/e70aecba-5f3a-79c1-f821-601d17a1051c.png)

#まとめ
このように、Azure Web Apps on Linux でも、dotnet-dump コマンドを使用してプロセスダンプファイルの採取が出来、さらに解析には Visual Studio 2019 を使用することが出来ます。Visual Studio の Linux 向けダンプ解析はまだまだこれからも発展していく機能ではありますが、是非ご期待をいただければと。

Cross Platform Managed Memory Dump Debugging
https://devblogs.microsoft.com/visualstudio/linux-managed-memory-dump-debugging/

#おまけ
Web Apps on Linux で、ダンプではなくて .NET CLR Profiler（ETW）が取りたい？
では、こちらのツールはいかがでしょうか？
https://docs.microsoft.com/en-us/dotnet/core/diagnostics/dotnet-trace