下記を使います。
Repository はこちら。
この SDK を使えば Azure Monitor に対して ReadOnly なクエリをよしなに実行して結果を得られるみたいですね。これまでは Azure Portal 上からメトリクス見て~と判断していたものを、プログラム上から簡単に出来そうな期待が持てます。README を参考に Service Bus のメトリクスを取得してみます。
Service Bus のメトリクスを取ってみる
コードはシンプルで、取得したいリソースの resourceId
があればとりあえず OK です。あとは取得したいメトリクスを QueryResourceAsync に渡します。サンプルでは Service Bus
の Active Message Count
を取得するようにしてみます。
var client = new MetricsQueryClient(new DefaultAzureCredential()); var result = await client.QueryResourceAsync( "resourceId", new[] { "ActiveMessages" });
第二引数にメトリクス名を入れていますが、正確には MetricsId
が求められます。Azure Portal 上の表記と MetricsId の対比が書かれているドキュメントがなかったのでこちらにまとめました。
まじでこれだけでメトリクスが取得出来てしまいます。ただ一点注意してもらいたいのが、上記のコードだと Service Bus の名前空間全体に対するメトリクスを取得しているという事です。つまり各 Entity ごとのメトリクスではないという事です。
また、ActiveMessage
の場合は Average
の値しか取れません。おそらくこちらの表に書いてある Aggregation type
しか取れないのではないかと思います。
実際のユースケースでは特定 queue のメトリクスが欲しいとか Max
の値が欲しいとか様々だと思います。MetricsQueryClientOptions を使うとうまくできるので、ユースケースごとの実装パターンを残しときます。
特定 Queue/Topic のメトリクスを取得したい
Filter を使って取得対象の Entity
を絞り込めます。
var filteredNyQueueNameOptions = new MetricsQueryOptions { Filter = @"EntityName eq 'hogehoge' or EntityName eq 'fugafuga'" }; var filteredNyQueueNameMetrics = await client.QueryResourceAsync( "resourceId", new[] { "ActiveMessages" }, filteredNyQueueNameOptions );
厄介だなぁと思うのが、in
など sql
で使い慣れた句が使えないという事です。複数の Queue 名で絞り込みたい時は、サンプルのように冗長な記述になってしまいます。この辺りは今後に期待ですね。
ここで指定した Entity
が戻り値の Metadata として戻ってきます。なので、KeyName
ごとの Active Message 数
の Dictionary
に変換したい時は以下のようなことをやってます。
var m = resources.Value.Metrics .SelectMany(m => m.TimeSeries) .Select(d => { return new { EntityName = d.Metadata.Values.First(), MaxCount = d.Values.Max(v => v.Average) }; }).ToDictionary(v => v.EntityName, v => v.MaxCount);
ちなみにですが、名前空間に存在しない Entity
を指定してもエラーにはなりませんでした。その Entity
のメトリクスが取得できない、というだけです。ディメンション分割のために Filter
に *
も指定出来るみたいです。
過去 3 時間分のメトリクスを 30 分間隔で集計したい
TimeRange と Granularity を使います。
var rangeOptions = new MetricsQueryOptions { Filter = @"EntityName eq 'hogehoge' or EntityName eq 'fugefuge'", TimeRange = new QueryTimeRange(TimeSpan.FromHours(3)), Granularity = TimeSpan.FromMinutes(30) }; var rangeOptionsMetrics = await client.QueryResourceAsync( "resourceId", new[] { "ActiveMessages" } , rangeOptions);
TimeRange
のほうはコンストラクタのオーバーロードも複数あって柔軟性が高そうです。サンプルの TimeRange
のみを指定するパターンだと、取得した日時を起点に duration
分過去 (例だと 3時間分) のメトリクスを取得します。何も指定しない場合は過去 1 時間分のメトリクスを取得します。
Granularity
のほうは TimSpan
を渡すだけなのでシンプルですね。一点注意なのが、サポートされている粒度が限られているという事です。以下の粒度しか指定出来ず。これら以外を指定すると実行時エラーが起きます。
- 1 分
- 5 分
- 15 分
- 30 分
- 1 時間
- 6 時間
- 12 時間
- 1 日
何も指定しない場合は、1 分の粒度になります。
過去 1 時間分のメトリクスの最大値を取得して最大値の降順に並べたい
Aggregations と OrderBy を使います。
var orderByMaxOptions = new MetricsQueryOptions { Filter = @"EntityName eq 'hogehoge' or EntityName eq 'fugefuge'", OrderBy = "Maximum desc" }; orderByMaxOptions.Aggregations.Add(MetricAggregationType.Maximum); var resources = await client.QueryResourceAsync( "resourceId", new[] { "ActiveMessages" }, orderByMaxOptions);
Aggregations
には setter が用意されていないのでこのようにします。
複数の AggregationType
は指定できないようです。指定した場合、一つ目の AggregationType
のみが取得されます。例えば以下の場合、Maximus
のメトリクスのみ取得出来、Average
は全て Null となってしまいます。
orderByMaxOptions.Aggregations.Add(MetricAggregationType.Maximum); orderByMaxOptions.Aggregations.Add(MetricAggregationType.Average);
なんでだろうと思ってコードを読んでみたのですが、よくわからず。。。Aggregation Type が複数あればそれらを join しているのでいけると思ったのですがね。。。内部的には REST API を使ってるみたいだし、Aggregation Type を複数指定出来てるし。謎です。
カスタムメトリクスを取得する
MetricNamespace を使います。何も指定しなければ、既定 (?) の名前空間のメトリクスを取得します。Service Bus の場合は microsoft.servicebus/namespaces
です。
そもそも各リソースにどのようなメトリクス名前空間が知るには GetMetricNamespacesAsync を使います。戻り値に FullyQualifiedName
というプロパティがあるので、この値を MetricNamespace
に指定します。
var customMetricsOption = new MetricsQueryOptions { MetricNamespace = "custom metrics" }; var customMetrics= await client.QueryResourceAsync( "resourceId", new[] { "ActiveMessages" }, customMetricsOption);
としてあげるだけです。
Queue の状態によってどうなるのか
Service Bus 固有の話になってしまいますが、Queue の状態毎にメトリクスがどうなるのかまとめです。Service Bus の Queue には以下の 4 種類の Status が存在します。
- Active
- Diabled
- SendDisabled
- ReceiveDisabled
これらの Status
と取得したメトリクスの関係のまとめです。
Status | Metrics |
---|---|
Active | 取れる |
Diabled | 取れる |
SendDisabled | 取れる |
ReceiveDisabled | 取れる |
結論、関係ないです。
MetricResult の Error
Error というプロパティがあります。コードを読んだ感じ、200 以外が返ってきたときは全て Exception になるので、200 でかつ何かしらのエラーがある時。
API Client の方には InvalidSamplingType
というのが返ってきているが、試してもうまくいかず。。。
Service Bus のメトリクスと MetricsId
Azure Portal 上のメトリクス名 | MetricsId |
---|---|
CompletedMessages | CompleteMessage |
Count of Active messages in Queue/Topic | ActiveMessages |