NewRelicは、PHPやRuby、Javaだけでなく .NETのプロファイリングも優れています。
今回は、ASP.NETのアプリケーションの前段にARRを使ったリバースプロキシを置いた時に、アプリケーション本体のみをプロファイルさせるための方法について説明します。
事前に読んでおくといいもの
- そもそもNewRelic Agentのコンフィグをどこでやるか把握しましょう
https://docs.newrelic.com/docs/agents/net-agent/installation-configuration/net-agent-configuration
- .NETでできないことも把握しましょう
https://docs.newrelic.com/docs/agents/net-agent/installation-configuration/known-issues-net
やりたいこと
IIS上に、ASP.NET MVCなアプリをホスティングしているとしましょう。
ここで、前段にARR(Application Request Routing) を利用したリバースプロキシを置いているとします。よくあるnginxを前段において、アプリをバックエンドをIISで組んでいるケースと思ってください。
つまり以下のような構成です。

さて、NewRelicにやらせたいことの1つはアプリケーションのモニタリング・監視ですね。この辺がピンとこない方は、@ITでid:kkamegawaさんが簡潔にきっちりまとめられている記事が参考になるでしょう。
https://www.atmarkit.co.jp/ait/articles/1501/19/news114.html
このNewRelicによる監視をもう少し実用面で考えます。
.NET Agent の副作用は凄まじい
さて、このまま .NET Agentを入れて問題ないでしょうか?
NewRelic .NET Agentは、RubyやPHPのAgentと同様にプロファイルします。さて、どこでというと、このケースではIISにdllを突っ込んでです。
結果どうなるかというと、アプリケーションのパフォーマンスが低下します。アプリの構成にもよりますが、30%~50%弱影響を受けるケースもざらにあります。
監視はしたいけど、パフォーマンスをむやみに下げたくないですよね? 特にIIS上で、複数のWebサイトを同居させていている場合は顕著です。
アプリケーション と リバースプロキシではプロファイル制御したい
さらに今回の構成のようなリバースプロキシのサイトでもプロファイルが走ると、アプリケーションのThroughputだけ見たくてもリバースプロキシサイト分が追加されて2倍になります。これは良くない。大変良くない。
リバースプロキシは単純にリダイレクト書けるだけなので、NewRelic .NET Agentを走らせる意味が(ほぼ)皆無です。無駄といえます。
とすると、同じIIS上でプロファイルを走らせるサイトと走らせないサイトが出てきますね? これをどうやるかが本題です。
つまりこれを目指します。

NewRelic のプロファイラを制御する
IIS 上の設定
Webサイトごとにアプリケーションプールは分離させよう
IISのWebSiteは、WorkerProcess(w3wp.exe) をアプリケーションプール単位で動作させています。
NewRelic .NET Agentは、WebSite単位でプロファイルをしているのですが、その対象はアプリケーションプールです。Webサイトごとにアプリケーションプールを分離させて置くことは大事です。
アプリケーションプールの実行ユーザーが問題となる
WorkerProcessを何で動かしているかはNewRelic .NET Agentの設定に関して影響します。
ふつーはApplicationPoolIdentityでしょう。しかし、アクセス制御をしたいなど多くのシーンではSpecific Userにしていることが多いでしょう。このSpecific Userの時に困ります。
いずれのパターンでも対応可能ですし後述しますが、自分がなぜそのアプリケーション実行ユーザーにしているかは把握しておくことを推奨します。
newrelic.config は罠
さて、NewRelic Agentは、newrelic.configで制御可能とNewRelic docには書いてあります。セクションとしてはinstrumentation SectionのApplications element (instrumentation)がいかにもそれっぽいでしょう。
https://docs.newrelic.com/docs/agents/net-agent/installation-configuration/net-agent-configuration

結論からいうと、これではアプリケーションプール単位での制御ができないケースもあります。
どういうことかというと、ApplicationPoolをApplicationPoolIdentityではなく、ApplicationPoolIdentityで動かしているとNewRelic Agentがアプリケーションプール名を取得できません。なんてこった!
NewRelic agentは、IISRESETでプロファイルが再開された時にログを吐くのですが、そこでApplicationPool名をとれているか確認できます。
This application pool () is not explicitly configured to be
アプリケーションプールが誰で実行されていてもプロファイルを制御する
newrelic.configでアプリケーションプール単位の制御ができないとわかりました。
ではどうするか。そのヒントはここにあります。(何と答えがNewRelic doc上にない)
https://docs.newrelic.com/docs/agents/net-agent/instrumentation/instrumenting-non-iis-apps

これがポイントです。
<add key="NewRelic.AgentEnabled" value="true" />
では、IISのWebサイト単位でどうやって制御するかといえば web.config です。(user.config で転換している場合はそっちでok)
プロファイルを取りたくないサイトに対して、アプリケーション名を明示して、プロファイルの実行をfalseとすればokです。(プロファイルを取りたい場合は、trueにしましょう。)
<appSettings> <add key="NewRelic.AppName" value="my_web_app" /> <add key="NewRelic.AgentEnabled" value="false" /> </appSettings>
あとは、ASP.NETアプリをデプロイした際にNewRelicのプロファイルはこの web.configに従ってプロファイルを停止します。
まとめ
NewRelic Profilerの制御は大事です。現在NewRelic.configは使わない方向にNewRelicは移行しており、Onlineで大体設定可能になっています。つまりNewRelic.configオワコン。
ASP.NETに限らず、プロファイルの制御はアプリサイドのコンフィグで可能なので web.config や .exe.config で制御してください。
特にリバースプロキシを持っているIISの場合は必須ですよ。お気を付けて。
ずっと書こうと思っていながら1か月以上放置していました*1
*1:いつも通り