Skip to content

Commit 882f9d9

Browse files
authored
Add Monitor Query README section for metric splitting (Azure#36053)
* Add Monitor Query README section for metric splitting * React to feedback * Enable query metrics tests * Move comment
1 parent 407b666 commit 882f9d9

File tree

4 files changed

+101
-10
lines changed

4 files changed

+101
-10
lines changed

sdk/monitor/Azure.Monitor.Query/README.md

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ All client instance methods are thread-safe and independent of each other ([guid
9999
- [Metrics query](#metrics-query)
100100
- [Handle metrics query response](#handle-metrics-query-response)
101101
- [Query metrics with options](#query-metrics-with-options)
102+
- [Split a metric by dimension](#split-a-metric-by-dimension)
102103
- [Register the client with dependency injection](#register-the-client-with-dependency-injection)
103104

104105
### Logs query
@@ -429,7 +430,7 @@ var client = new MetricsQueryClient(new DefaultAzureCredential());
429430

430431
Response<MetricsQueryResult> results = await client.QueryResourceAsync(
431432
resourceId,
432-
new[] { "SuccessfulCalls", "TotalCalls" }
433+
new[] { "Query Success Rate", "Query Count" }
433434
);
434435

435436
foreach (MetricResult metric in results.Value.Metrics)
@@ -479,11 +480,12 @@ A `MetricsQueryOptions` object may be used to support more granular metrics quer
479480
```C# Snippet:QueryMetricsWithAggregations
480481
string resourceId =
481482
"/subscriptions/<subscription_id>/resourceGroups/<resource_group_name>/providers/Microsoft.KeyVault/vaults/TestVault";
483+
string[] metricNames = new[] { "Availability" };
482484
var client = new MetricsQueryClient(new DefaultAzureCredential());
483485

484486
Response<MetricsQueryResult> result = await client.QueryResourceAsync(
485487
resourceId,
486-
new[] { "Availability" },
488+
metricNames,
487489
new MetricsQueryOptions
488490
{
489491
Aggregations =
@@ -505,6 +507,48 @@ foreach (MetricTimeSeriesElement element in metric.TimeSeries)
505507
}
506508
```
507509

510+
#### Split a metric by dimension
511+
512+
The [MetricsQueryOptions.Filter](https://learn.microsoft.com/dotnet/api/azure.monitor.query.metricsqueryoptions.filter?view=azure-dotnet#azure-monitor-query-metricsqueryoptions-filter) property can be used for [splitting a metric](https://learn.microsoft.com/azure/azure-monitor/essentials/metrics-charts#metric-splitting) by a dimension when its filter value is set to an asterisk. Consider the following example for an App Service resource named *TestWebApp*. The code queries the resource's `Http2xx` metric and splits it by the `Instance` dimension.
513+
514+
```C# Snippet:QueryMetricsWithSplitting
515+
string resourceId =
516+
"/subscriptions/<subscription_id>/resourceGroups/<resource_group_name>/providers/Microsoft.Web/sites/TestWebApp";
517+
string[] metricNames = new[] { "Http2xx" };
518+
// Use of asterisk in filter value enables splitting on Instance dimension.
519+
string filter = "Instance eq '*'";
520+
var client = new MetricsQueryClient(new DefaultAzureCredential());
521+
var options = new MetricsQueryOptions
522+
{
523+
Aggregations =
524+
{
525+
MetricAggregationType.Average,
526+
},
527+
Filter = filter,
528+
TimeRange = TimeSpan.FromDays(2),
529+
};
530+
Response<MetricsQueryResult> result = await client.QueryResourceAsync(
531+
resourceId,
532+
metricNames,
533+
options);
534+
535+
foreach (MetricResult metric in result.Value.Metrics)
536+
{
537+
foreach (MetricTimeSeriesElement element in metric.TimeSeries)
538+
{
539+
foreach (MetricValue value in element.Values)
540+
{
541+
// Prints a line that looks like the following:
542+
// Thursday, May 4, 2023 9:42:00 PM, webwk000002, Http2xx, 1
543+
Console.WriteLine(
544+
$"{value.TimeStamp:F}, {element.Metadata["Instance"]}, {metric.Name}, {value.Average}");
545+
}
546+
}
547+
}
548+
```
549+
550+
For an inventory of metrics and dimensions available for each Azure resource type, see [Supported metrics with Azure Monitor](https://learn.microsoft.com/azure/azure-monitor/essentials/metrics-supported).
551+
508552
#### Register the client with dependency injection
509553

510554
To register `LogsQueryClient` with the dependency injection (DI) container, invoke the `AddLogsQueryClient` method. To register `MetricsQueryClient` with the dependency injection (DI) container, invoke the `AddMetricsQueryClient` method. For more information, see [Register client](https://learn.microsoft.com/dotnet/azure/sdk/dependency-injection#register-client).

sdk/monitor/Azure.Monitor.Query/src/MetricsQueryClient.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ protected MetricsQueryClient()
9090
///
9191
/// Response&lt;MetricsQueryResult&gt; results = await client.QueryResourceAsync(
9292
/// resourceId,
93-
/// new[] { &quot;SuccessfulCalls&quot;, &quot;TotalCalls&quot; }
93+
/// new[] { &quot;Query Success Rate&quot;, &quot;Query Count&quot; }
9494
/// );
9595
///
9696
/// foreach (MetricResult metric in results.Value.Metrics)
@@ -151,7 +151,7 @@ public virtual Response<MetricsQueryResult> QueryResource(string resourceId, IEn
151151
///
152152
/// Response&lt;MetricsQueryResult&gt; results = await client.QueryResourceAsync(
153153
/// resourceId,
154-
/// new[] { &quot;SuccessfulCalls&quot;, &quot;TotalCalls&quot; }
154+
/// new[] { &quot;Query Success Rate&quot;, &quot;Query Count&quot; }
155155
/// );
156156
///
157157
/// foreach (MetricResult metric in results.Value.Metrics)

sdk/monitor/Azure.Monitor.Query/src/MetricsQueryOptions.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ public class MetricsQueryOptions
3131
/// </para>
3232
/// <para>
3333
/// Although this collection cannot be set, it can be modified.
34-
/// See <see href="https://docs.microsoft.com/dotnet/csharp/programming-guide/classes-and-structs/object-and-collection-initializers#object-initializers-with-collection-read-only-property-initialization">Object initializers with collection read-only property initialization</see>.
34+
/// See <see href="https://learn.microsoft.com/dotnet/csharp/programming-guide/classes-and-structs/object-and-collection-initializers#object-initializers-with-collection-read-only-property-initialization">Object initializers with collection read-only property initialization</see>.
3535
/// </para>
3636
/// </summary>
3737
public IList<MetricAggregationType> Aggregations { get; } = new List<MetricAggregationType>();
@@ -45,7 +45,7 @@ public class MetricsQueryOptions
4545
/// <summary>
4646
/// Gets or sets the filter that is used to refine the set of metric data returned.
4747
/// <example>
48-
/// MetricResult contains metadata A, B and C.<br/>
48+
/// <see cref="MetricResult"/> contains metadata A, B, and C.<br/>
4949
/// <br/>
5050
/// - Return all time series of C where A = a1 and B = b1 or b2:<br/>
5151
/// <c>A eq 'a1' and B eq 'b1' or B eq 'b2' and C eq '*'</c><br/>

sdk/monitor/Azure.Monitor.Query/tests/MetricsQueryClientSamples.cs

Lines changed: 51 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using System;
55
using System.Threading.Tasks;
66
using Azure.Core.TestFramework;
7+
using Azure.Identity;
78
using Azure.Monitor.Query.Models;
89
using NUnit.Framework;
910

@@ -12,7 +13,6 @@ namespace Azure.Monitor.Query.Tests
1213
public class MetricsQueryClientSamples: SamplesBase<MonitorQueryTestEnvironment>
1314
{
1415
[Test]
15-
[Ignore("https://github.com/Azure/azure-sdk-for-net/issues/21657")]
1616
public async Task QueryMetrics()
1717
{
1818
#region Snippet:QueryMetrics
@@ -28,7 +28,7 @@ public async Task QueryMetrics()
2828

2929
Response<MetricsQueryResult> results = await client.QueryResourceAsync(
3030
resourceId,
31-
new[] { "SuccessfulCalls", "TotalCalls" }
31+
new[] { "Query Success Rate", "Query Count" }
3232
);
3333

3434
foreach (MetricResult metric in results.Value.Metrics)
@@ -48,21 +48,22 @@ public async Task QueryMetrics()
4848
}
4949

5050
[Test]
51-
[Ignore("https://github.com/Azure/azure-sdk-for-net/issues/21657")]
5251
public async Task QueryMetricsWithAggregations()
5352
{
5453
#region Snippet:QueryMetricsWithAggregations
5554
#if SNIPPET
5655
string resourceId =
5756
"/subscriptions/<subscription_id>/resourceGroups/<resource_group_name>/providers/Microsoft.KeyVault/vaults/TestVault";
57+
string[] metricNames = new[] { "Availability" };
5858
#else
5959
string resourceId = TestEnvironment.MetricsResource;
60+
string[] metricNames = new[] { "Heartbeat" };
6061
#endif
6162
var client = new MetricsQueryClient(new DefaultAzureCredential());
6263

6364
Response<MetricsQueryResult> result = await client.QueryResourceAsync(
6465
resourceId,
65-
new[] { "Availability" },
66+
metricNames,
6667
new MetricsQueryOptions
6768
{
6869
Aggregations =
@@ -84,5 +85,51 @@ public async Task QueryMetricsWithAggregations()
8485
}
8586
#endregion
8687
}
88+
89+
[Test]
90+
public async Task QueryMetricsWithSplitting()
91+
{
92+
#region Snippet:QueryMetricsWithSplitting
93+
#if SNIPPET
94+
string resourceId =
95+
"/subscriptions/<subscription_id>/resourceGroups/<resource_group_name>/providers/Microsoft.Web/sites/TestWebApp";
96+
string[] metricNames = new[] { "Http2xx" };
97+
// Use of asterisk in filter value enables splitting on Instance dimension.
98+
string filter = "Instance eq '*'";
99+
#else
100+
string resourceId = TestEnvironment.MetricsResource;
101+
string[] metricNames = new[] { "Average_% Available Memory" };
102+
string filter = "Computer eq '*'";
103+
#endif
104+
var client = new MetricsQueryClient(new DefaultAzureCredential());
105+
var options = new MetricsQueryOptions
106+
{
107+
Aggregations =
108+
{
109+
MetricAggregationType.Average,
110+
},
111+
Filter = filter,
112+
TimeRange = TimeSpan.FromDays(2),
113+
};
114+
Response<MetricsQueryResult> result = await client.QueryResourceAsync(
115+
resourceId,
116+
metricNames,
117+
options);
118+
119+
foreach (MetricResult metric in result.Value.Metrics)
120+
{
121+
foreach (MetricTimeSeriesElement element in metric.TimeSeries)
122+
{
123+
foreach (MetricValue value in element.Values)
124+
{
125+
// Prints a line that looks like the following:
126+
// Thursday, May 4, 2023 9:42:00 PM, webwk000002, Http2xx, 1
127+
Console.WriteLine(
128+
$"{value.TimeStamp:F}, {element.Metadata["Instance"]}, {metric.Name}, {value.Average}");
129+
}
130+
}
131+
}
132+
#endregion
133+
}
87134
}
88135
}

0 commit comments

Comments
 (0)