Azureの小ネタ (改)

~Azureネタを中心に、色々とその他の技術的なことなどを~

Visual Studio 2022 に Emacs Extensionをインストールする

Visual Studio 2022 がローンチしたので恒例の Emacs Extension のビルドの時期がやってまいりました。2019 のときは、特に難儀もしなかったのでスルーしていたきがします。

以下の記事を思い出してビルドしましょう。

statemachine.hatenablog.com

statemachine.hatenablog.com

今回は先人がいて、VS2022 対応をした人がいたので、ラクショーかと思っていたのですが、ライブラリをガリガリ削るのは一緒でした。

github.com

メインとなるライブラリは以下です。依存があらかじめついているので、プロジェクトを開いたときに警告になるライブラリは、がっつり消していきましょう。

https://www.nuget.org/packages/Microsoft.VisualStudio.SDK/

そうすると警告は沢山でますが、ビルドに成功して、vsix ファイルができるはずです。一旦VS2022 を終了して、インストーラーを実行しますと、以下のようなダイアログが出てインストールできるでしょう。

f:id:StateMachine:20211210140733p:plain

再び VS2022 を起動すると、一瞬だけ UAC の画面がでますので、OK しましょう。何らかのファイルコピープロセスが走ります。

インストール後にオプションを開き、キーボード設定画面がら「Emacs」が一覧にあれば OK です。選択して、Ctrl-A とかで先頭にカーソルが移動していればOKでしょう。

f:id:StateMachine:20211210140854p:plain

というわけで、VS2022でもEmacs Extension が使えそうで寿命が延びました!

Application Insights for Java 3.2 が GA してた

別のBlogとかにちょっと浮気していたら、コチラに書くのは一年以上たってしましたが、今回はApplication Insights についてです。

あまりウォッチしていない間に、3.2が GAしていて、現時点で3.2.3 がリリース中です。前回、Application Insights にふれたときは、3.0 が Preview 中でしたの、リリースが重ねられ改良されてきたことがうかがえます。

JavaからAzure Application Insightsを使う(3) - Azureの小ネタ (改)

おさらい

3.0 系のApplication Insights は エージェント式で、なんらアプリケーションに組み込まなくても問題ありません。Java起動時に、-javaagent:/applicationinsights.jar のようにライブラリを指定すればかってにJVMの仕組みをつかって、メトリクスやログをフックして出力してくれます。

さらに、Web Apps/Functionsでは、 プラットフォーム上で組み込んでくれるので、なんら意識することすらありませんでした。

とはいえ、アプリケーションに組み込む 2.6系と比べて、劣る部分もあって、3.0系のエージェント方式では独自のテレメトリを送信できませんでした。どうするかというと、3.0系のエージェントを組み込みつつ、2.6系のSDKでカスタムするという、2.6系と3.0系を混合するような方法しかありませんでした。これでも、Application Insights 側がよしなにやってくれるので、問題はなかったのです。

カスタムテレメトリ対応

ようやく 3.2 でカスタムテレメトリに対応しました。リリース履歴をみると、PREVIEW機能として提供されていたっぽいのですが知りませんでした。 3.0系では、アプリケーションに組み込むような Application Insights SDK は提供されないそうで、標準APIでの対応となるそうです。そこで使われるのが Open Telemetry とのことです。

github.com

このOpen Telemetry をつかってカスタムテレメトリに対応するそうですが、現時点ですべての機能に対応しているわけではなさそうで、2.6系のSDKにくらべて、Open Telemetry は対応がすくないです。

f:id:StateMachine:20211111230106p:plain

https://docs.microsoft.com/en-us/azure/azure-monitor/app/java-in-process-agent より

ユースケースとしては、リクエストテレメトリに何らかの情報を追加したい場合が多いので、とりあえずこれがサポートされたことは喜ばし感じです。

試してみる

現時点で、WebApps で利用される Application Insights for Javaのバージョンは、 3.1.1 ですので、すぐに利用することはできません。どうしてもというなら、コンテナ化してデプロイするとよいでしょう。ただし、コンテナ側のApplication Insights をDisable にする必要があると思います(適当)

Docsをみると依存は、 1.6.0 でしたが、最新の1.7.1 で問題なさそうです。

        <dependency>
            <groupId>io.opentelemetry</groupId>
            <artifactId>opentelemetry-api</artifactId>
            <version>1.7.1</version>
        </dependency>

リクエストテレメトリのカスタムディメンジョンにプロパティを追加するには、io.opentelemetry.api.trace.Span から current を取り出し属性を追加すれば、このリクエストに対応するテレメトリに記録されます。

    @GetMapping("/")
    String root() {
        Span.current().setAttribute("foo","bar");
        Span.current().setAttribute("user.name","shibayan");
        Span.current().setAttribute("user.age","40");

        retrun ...;
    }

結果、このようにカスタムディメンジョンに記録されます。

f:id:StateMachine:20211111232142p:plain

ライブメトリクス の サンプルテレメトリ

ライブメトリクスはサポートされていましたが、右側のペインに表示されるべき サンプルテレメトリは、長い間対応していませんでしたが、ようやく対応されました。

f:id:StateMachine:20211111231815p:plain

リクエストを送ると、ほぼリアルタイムでテレメトリがあがってきて、ログを眺めるのに便利です。

というわけで、ログは出さないと出ませんので(進次郎構文)、転ばぬ先の杖としてちゃんと設定しておきましょう。

Postgresql のログをApplication Insightsに出力する

.NETフレームワークの場合、SQL DBの情報は勝手にApplication Insightsに送信してくれますが、Postgresの場合は自動で送信してくれません。ちょっと調べたのですが、執筆時点でそういう仕組みとかサンプルも無さそうでした。

逆にJavaなどは、JDBCレベルでApplication Insightsにデータを送信してくれるので、DBがMySQLやPostgresの場合でも問題なく情報を送信してくれます。

ということで、ここでは NET + Postgres を使った場合のデータ送信の方法について試したことを備忘録としての残してオコますが、もっと良いやり方があるかもしれまえんので、ご参考程度に。

Postgres

Windows環境を汚したくないので、Dockerとかでインストールして接続しましょう。以下の例ですと、postgresというDBが作成されます。適当にテーブル作成し、データをINSERTしておきましょう。

docker run --name my-postgres -e POSTGRES_PASSWORD=mypassword -p 5432:5432 -d postgres
docker container exec -it my-postgres bash

NET

Postgresへの接続ライブラリは以下を利用します。

www.npgsql.org

また幸いEntity Frameworkに対応しているので試してみます。以下のコマンドでコンテキストクラスとPOCOクラスが生成されでしょう。

dotnet ef dbcontext scaffold "Host=127.0.0.1;Database=postgres;Username=postgres;Password=mypassword" Npgsql.EntityFrameworkCore.PostgreSQL -o database

ログクラスの実装

ログについては、以下の通りですが、ログプロパイダとログ出力クラス自身を実装する必要があります。

www.npgsql.org

適当にログを垂れ流すサンプルを作成してみました。単純にStringが渡されてくるだけなので、ログに意味を持たせることは難しいです。

以下の実装では、

  • 例外は例外テレメトリへ
  • 普通のメッセージは、トレーステレメトリに出力すればいいのですが、Application Insightsで依存関係を見たい場合は、依存テレメトリにも出力できます(例では2つ書いてかります)

ただ、依存テレメトリ出力する場合、Durationが分らないのでゼロを指定していますが、Azure ポータルで見たときにちょっとかっこ悪いです。

sing System;
using Microsoft.ApplicationInsights;
using Npgsql.Logging;

namespace webapi.Logger
{
    public class PgsqlAppInsightsLoggingProvider : INpgsqlLoggingProvider
    {
        private TelemetryClient _client;
        private NpgsqlLogLevel _minLevel;

        public PgsqlAppInsightsLoggingProvider(TelemetryClient client, NpgsqlLogLevel minLevel)
        {
            _client = client;
            _minLevel = minLevel;
        }

        public NpgsqlLogger CreateLogger(string name)
        {
            return new PgsqlAppInsightLogger(name, _client, _minLevel);
        }
    }

    public class PgsqlAppInsightLogger : NpgsqlLogger
    {
        private string _name;
        private TelemetryClient _client;
        private NpgsqlLogLevel _minLevel;

        public PgsqlAppInsightLogger(string name, TelemetryClient client, NpgsqlLogLevel minLevel)
        {
            _name = name;
            _client = client;
            _minLevel = minLevel;
        }

        public override bool IsEnabled(NpgsqlLogLevel level) => level >= _minLevel;


        public override void Log(NpgsqlLogLevel level, int connectorId, string msg, Exception exception = null)
        {
            if (!IsEnabled(level))
            {
                return;
            }

            if (exception == null)
            {
                _client.TrackTrace(msg);
                _client.TrackDependency("postgres", "sql", msg, DateTimeOffset.UtcNow, TimeSpan.Zero, true);
            }
            else
            {
                _client.TrackException(exception);
            }

            Console.WriteLine(msg);
        }
    }
}

ポータルで確認

依存テレメトリに出した場合は以下ように、リクエスト配下にちゃんと表示されます。3つ出ているのは、Connection Open/クエリ実行/Connection Closeとなっています。

そして、Durationがゼロなので時間軸の帯が正しく出力されなくて、ちょっとかっこ悪いです。

f:id:StateMachine:20201029110840p:plain

まとめ

たんに文字列の垂れ流しなので、いまいちSQL DBと同等のメトリクスにはならないのが残念ですが、もうちょっとましなイベントを拾ったりできるのかもしれません。

パフォーマンスカウンタ機能もあるようなのですが、今後その機能は廃止されそうなので使ってません。

Performance | Npgsql Documentation

Npgsql 3.2 includes support for performance counters, which provide visibility into connections and the connection pool - this helps you understand what your application is doing in real-time, whether there's a connection leak, etc. Npgsql counter support is very similar to that of other ADO.NET providers, such as SqlClient, it's recommended that your read that page first. The feature was removed in Npgsql 5.0.

と言うわけで以上です。