しばやん雑記

Azure とメイドさんが大好きなフリーランスのプログラマーのブログ

Application Insights を Elastic Beanstalk にデプロイした ASP.NET アプリケーションから利用してみる

わざわざ Application Insights を Azure 以外から使う理由があるのかと言われそうですが、Application Insights Basic の課金はよくある APM のホスト数での課金ではなく、容量課金となっているので頻繁にインスタンスを使い捨てる場合などで、使いやすいことがあります。

Enterprise の場合はホスト数での課金 + 容量課金となるので少し注意です。

Application Insights 自体は Azure に限定したものではなく、オンプレミスや他のサービスでも使えるようになっているので問題ありません。設定は Visual Studio で完結します。

Azure Portal から Application Insights を単体で作成します。ASP.NET アプリケーションを選びます。

f:id:shiba-yan:20170626224318p:plain

リソースを作成したら、Visual Studio から Application Insights の設定を行います。Visual Studio 2017 では昔に比べて、かなり簡単にいろんな設定が行えるようになっていました。

公開コメントは無効にしても良いかもしれませんが、とりあえず有効のままです。

f:id:shiba-yan:20170626224841p:plain

このアプリケーションをそのまま Elastic Beanstalk にデプロイすれば、Application Insights で各パフォーマンスカウンターなどの値が確認できるようになります。

Cloud Role Instance は Windows のマシン名になっていますが、スケーリングした時には同じマシン名になるので、このままだと区別がつきません。

f:id:shiba-yan:20170626224335p:plain

この部分ですが Application Insights のデフォルトでは Azure Cloud Services と Web Apps だけの対応なので、EC2 向けに専用の TelemetryInitializer を作成して対応します。

EC2 は Instance Metadata を稼働中のインスタンス内から簡単に取れるようになってるので、それを利用してインスタンス ID を取得します。

public class AwsEc2EnvironmentTelemetryInitializer : ITelemetryInitializer
{
    public AwsEc2EnvironmentTelemetryInitializer()
    {
        try
        {
            _roleInstanceName = new WebClient().DownloadString("http://169.254.169.254/latest/meta-data/instance-id");
        }
        catch
        {
        }
    }
        
    private readonly string _roleInstanceName;

    public void Initialize(ITelemetry telemetry)
    {
        if (string.IsNullOrEmpty(telemetry.Context.Cloud.RoleInstance))
        {
            telemetry.Context.Cloud.RoleInstance = _roleInstanceName;
        }

        if (string.IsNullOrEmpty(telemetry.Context.GetInternalContext().NodeName))
        {
            telemetry.Context.GetInternalContext().NodeName = _roleInstanceName;
        }
    }
}

取得したインスタンス ID で RoleInstance と NodeName を置き換えます。

作成した TelemetryInitializer は ApplicationInsights.config に追加します。元々あった Cloud Services と Web Apps 用の Initializer は削除しておきます。

<?xml version="1.0" encoding="utf-8"?>
<ApplicationInsights xmlns="http://schemas.microsoft.com/ApplicationInsights/2013/Settings">
  <TelemetryInitializers>
    <Add Type="Microsoft.ApplicationInsights.DependencyCollector.HttpDependenciesParsingTelemetryInitializer, Microsoft.AI.DependencyCollector" />
    <!--<Add Type="Microsoft.ApplicationInsights.WindowsServer.AzureRoleEnvironmentTelemetryInitializer, Microsoft.AI.WindowsServer" />-->
    <!--<Add Type="Microsoft.ApplicationInsights.WindowsServer.AzureWebAppRoleEnvironmentTelemetryInitializer, Microsoft.AI.WindowsServer" />-->
    <Add Type="WebApplication1.AwsEc2EnvironmentTelemetryInitializer, WebApplication1" />
    <Add Type="Microsoft.ApplicationInsights.WindowsServer.BuildInfoConfigComponentVersionTelemetryInitializer, Microsoft.AI.WindowsServer" />
    <!-- 省略 -->
  </TelemetryInitializers>
</ApplicationInsights>

ローカルか EC2 上かの判別は組み込んでいないので、このままだといまいちですが上手く判別する方法が見つからなかったので、とりあえずは保留にします。

この変更を行った ASP.NET アプリケーションを Elastic Beanstalk にデプロイすると、インスタンス別にメトリックを確認できるようになりました。

f:id:shiba-yan:20170626231430p:plain

ASP.NET アプリケーション向けに使う場合には、Application Insights も割と良い選択肢になるかと思いました。エージェント無しでパフォーマンスに関するメトリックが取れるのは結構良いです。

Dependency 周りは別途インストールが必要かもしれないですが、確認はまた今度にします。