diff --git a/sdk/monitor/Azure.Monitor.Query/CHANGELOG.md b/sdk/monitor/Azure.Monitor.Query/CHANGELOG.md index 206c4a044a12..2f3493a7c2f4 100644 --- a/sdk/monitor/Azure.Monitor.Query/CHANGELOG.md +++ b/sdk/monitor/Azure.Monitor.Query/CHANGELOG.md @@ -3,7 +3,7 @@ ## 1.6.0-beta.1 (Unreleased) ### Features Added - +- Add 'StartTime' and 'EndTime' parameters to 'MetricsQueryResourcesOptions' to allow for querying a specific time range ### Breaking Changes ### Bugs Fixed diff --git a/sdk/monitor/Azure.Monitor.Query/README.md b/sdk/monitor/Azure.Monitor.Query/README.md index a3f60cb420fb..8cb296386259 100644 --- a/sdk/monitor/Azure.Monitor.Query/README.md +++ b/sdk/monitor/Azure.Monitor.Query/README.md @@ -721,6 +721,34 @@ foreach (MetricsQueryResult value in metricsQueryResults.Values) } ``` +The `MetricsQueryResourcesOptions`-typed argument also has a `StartTime` and `EndTime` property to allow for querying a specific time range. If only the `StartTime` is set, the `EndTime` default becomes the current time. When the `EndTime` is specified, the `StartTime` is necessary as well. The following example demonstrates the use of these properties: +```C# Snippet:QueryResourcesMetricsWithOptionsStartTimeEndTime +string resourceId = + "/subscriptions//resourceGroups//providers//storageAccounts/"; +var client = new MetricsClient( + new Uri("https://.metrics.monitor.azure.com"), + new DefaultAzureCredential()); +var options = new MetricsQueryResourcesOptions +{ + StartTime = DateTimeOffset.Now.AddHours(-4), + EndTime = DateTimeOffset.Now.AddHours(-1), + OrderBy = "sum asc", + Size = 10 +}; + +Response result = await client.QueryResourcesAsync( + resourceIds: new List { new ResourceIdentifier(resourceId) }, + metricNames: new List { "Ingress" }, + metricNamespace: "Microsoft.Storage/storageAccounts", + options).ConfigureAwait(false); + +MetricsQueryResourcesResult metricsQueryResults = result.Value; +foreach (MetricsQueryResult value in metricsQueryResults.Values) +{ + Console.WriteLine(value.Metrics.Count); +} +``` + #### Register the client with dependency injection To register a client with the dependency injection container, invoke the corresponding extension method. diff --git a/sdk/monitor/Azure.Monitor.Query/api/Azure.Monitor.Query.net8.0.cs b/sdk/monitor/Azure.Monitor.Query/api/Azure.Monitor.Query.net8.0.cs index 08fcb0530b75..4967ae55c43c 100644 --- a/sdk/monitor/Azure.Monitor.Query/api/Azure.Monitor.Query.net8.0.cs +++ b/sdk/monitor/Azure.Monitor.Query/api/Azure.Monitor.Query.net8.0.cs @@ -157,11 +157,14 @@ public partial class MetricsQueryResourcesOptions { public MetricsQueryResourcesOptions() { } public System.Collections.Generic.IList Aggregations { get { throw null; } } + public System.DateTimeOffset? EndTime { get { throw null; } set { } } public string Filter { get { throw null; } set { } } public System.TimeSpan? Granularity { get { throw null; } set { } } public string OrderBy { get { throw null; } set { } } public System.Collections.Generic.IList RollUpBy { get { throw null; } } public int? Size { get { throw null; } set { } } + public System.DateTimeOffset? StartTime { get { throw null; } set { } } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] public Azure.Monitor.Query.QueryTimeRange? TimeRange { get { throw null; } set { } } } [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)] diff --git a/sdk/monitor/Azure.Monitor.Query/api/Azure.Monitor.Query.netstandard2.0.cs b/sdk/monitor/Azure.Monitor.Query/api/Azure.Monitor.Query.netstandard2.0.cs index 41e38f81678e..c2e6edd340a1 100644 --- a/sdk/monitor/Azure.Monitor.Query/api/Azure.Monitor.Query.netstandard2.0.cs +++ b/sdk/monitor/Azure.Monitor.Query/api/Azure.Monitor.Query.netstandard2.0.cs @@ -157,11 +157,14 @@ public partial class MetricsQueryResourcesOptions { public MetricsQueryResourcesOptions() { } public System.Collections.Generic.IList Aggregations { get { throw null; } } + public System.DateTimeOffset? EndTime { get { throw null; } set { } } public string Filter { get { throw null; } set { } } public System.TimeSpan? Granularity { get { throw null; } set { } } public string OrderBy { get { throw null; } set { } } public System.Collections.Generic.IList RollUpBy { get { throw null; } } public int? Size { get { throw null; } set { } } + public System.DateTimeOffset? StartTime { get { throw null; } set { } } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] public Azure.Monitor.Query.QueryTimeRange? TimeRange { get { throw null; } set { } } } [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)] diff --git a/sdk/monitor/Azure.Monitor.Query/assets.json b/sdk/monitor/Azure.Monitor.Query/assets.json index 5f9a259c23f0..7a1eadcd757d 100644 --- a/sdk/monitor/Azure.Monitor.Query/assets.json +++ b/sdk/monitor/Azure.Monitor.Query/assets.json @@ -2,5 +2,5 @@ "AssetsRepo": "Azure/azure-sdk-assets", "AssetsRepoPrefixPath": "net", "TagPrefix": "net/monitor/Azure.Monitor.Query", - "Tag": "net/monitor/Azure.Monitor.Query_26f5d5d32f" + "Tag": "net/monitor/Azure.Monitor.Query_3bd28d9e3d" } diff --git a/sdk/monitor/Azure.Monitor.Query/src/MetricsClient.cs b/sdk/monitor/Azure.Monitor.Query/src/MetricsClient.cs index 21d346f9926d..f8ec2277781f 100644 --- a/sdk/monitor/Azure.Monitor.Query/src/MetricsClient.cs +++ b/sdk/monitor/Azure.Monitor.Query/src/MetricsClient.cs @@ -148,11 +148,24 @@ private async Task> ExecuteBatchAsync(IEnu if (options != null) { - if (options.TimeRange != null) + if (options.TimeRange.HasValue) { startTime = options.TimeRange.Value.Start.ToIsoString(); endTime = options.TimeRange.Value.End.ToIsoString(); } + else + { + // Use values from Start and End TimeRange properties if they are set + if (options.StartTime.HasValue) + { + startTime = options.StartTime.Value.ToIsoString(); + } + if (options.EndTime.HasValue) + { + endTime = options.EndTime.Value.ToIsoString(); + } + } + aggregations = MetricsClientExtensions.CommaJoin(options.Aggregations); top = options.Size; orderBy = options.OrderBy; diff --git a/sdk/monitor/Azure.Monitor.Query/src/MetricsQueryResourcesOptions.cs b/sdk/monitor/Azure.Monitor.Query/src/MetricsQueryResourcesOptions.cs index 9c52dff5845f..91d59b1a4e9b 100644 --- a/sdk/monitor/Azure.Monitor.Query/src/MetricsQueryResourcesOptions.cs +++ b/sdk/monitor/Azure.Monitor.Query/src/MetricsQueryResourcesOptions.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.ComponentModel; using Azure.Core; using Azure.Monitor.Query.Models; @@ -16,10 +17,20 @@ public class MetricsQueryResourcesOptions /// /// Gets or sets the timespan over which the metric will be queried. If only the starttime is set, the endtime default becomes the current time. When the endtime is specified, the starttime is necessary as well. Duration is disregarded. /// + [EditorBrowsable(EditorBrowsableState.Never)] [CodeGenMember("TimeSpan")] - // TODO: https://github.com/Azure/azure-sdk-for-net/issues/46454 public QueryTimeRange? TimeRange { get; set; } + /// + /// Gets the of the query. If only the is set, the default becomes the current time. When the is specified, the is necessary as well. + /// + public DateTimeOffset? StartTime { get; set; } + + /// + /// Gets the of the query. If only the is set, the default becomes the current time. When the is specified, the is necessary as well. + /// + public DateTimeOffset? EndTime { get; set; } + /// /// /// Gets the list of metric aggregations to retrieve. diff --git a/sdk/monitor/Azure.Monitor.Query/tests/MetricsClientLiveTests.cs b/sdk/monitor/Azure.Monitor.Query/tests/MetricsClientLiveTests.cs index 41d8d8023450..56c020429bdf 100644 --- a/sdk/monitor/Azure.Monitor.Query/tests/MetricsClientLiveTests.cs +++ b/sdk/monitor/Azure.Monitor.Query/tests/MetricsClientLiveTests.cs @@ -173,5 +173,69 @@ public void MetricsQueryResourcesInvalid() metricNames: new List { "Ingress" }, metricNamespace: "Microsoft.Storage/storageAccounts")); } + + [RecordedTest] + public async Task MetricsQueryResourcesWithStartTimeRangeAsync() + { + MetricsClient client = CreateMetricsClient(); + + var resourceId = TestEnvironment.StorageAccountId; + // If only starttime is specified, then endtime defaults to the current time. + DateTimeOffset start = Recording.UtcNow.Subtract(TimeSpan.FromHours(4)); + + Response metricsResultsResponse = await client.QueryResourcesAsync( + resourceIds: new List { new ResourceIdentifier(resourceId) }, + metricNames: new List { "Ingress" }, + metricNamespace: "Microsoft.Storage/storageAccounts", + options: new MetricsQueryResourcesOptions { StartTime = start }).ConfigureAwait(false); + + Assert.AreEqual(200, metricsResultsResponse.GetRawResponse().Status); + MetricsQueryResourcesResult metricsQueryResults = metricsResultsResponse.Value; + Assert.AreEqual(1, metricsQueryResults.Values.Count); + Assert.AreEqual(TestEnvironment.StorageAccountId + "/providers/Microsoft.Insights/metrics/Ingress", metricsQueryResults.Values[0].Metrics[0].Id); + Assert.AreEqual("Microsoft.Storage/storageAccounts", metricsQueryResults.Values[0].Namespace); + } + + [RecordedTest] + public async Task MetricsQueryResourcesWithStartTimeEndTimeRangeAsync() + { + MetricsClient client = CreateMetricsClient(); + + var resourceId = TestEnvironment.StorageAccountId; + + DateTimeOffset start = Recording.UtcNow.Subtract(TimeSpan.FromHours(4)); + DateTimeOffset end = Recording.UtcNow; + + Response metricsResultsResponse = await client.QueryResourcesAsync( + resourceIds: new List { new ResourceIdentifier(resourceId) }, + metricNames: new List { "Ingress" }, + metricNamespace: "Microsoft.Storage/storageAccounts", + options: new MetricsQueryResourcesOptions { StartTime = start, EndTime = end }).ConfigureAwait(false); + + Assert.AreEqual(200, metricsResultsResponse.GetRawResponse().Status); + MetricsQueryResourcesResult metricsQueryResults = metricsResultsResponse.Value; + Assert.AreEqual(1, metricsQueryResults.Values.Count); + Assert.AreEqual(TestEnvironment.StorageAccountId + "/providers/Microsoft.Insights/metrics/Ingress", metricsQueryResults.Values[0].Metrics[0].Id); + Assert.AreEqual("Microsoft.Storage/storageAccounts", metricsQueryResults.Values[0].Namespace); + } + + [Test] + [SyncOnly] + public void MetricsQueryResourcesWithEndTimeRange() + { + MetricsClient client = CreateMetricsClient(); + + var resourceId = TestEnvironment.StorageAccountId; + + // If only the endtime parameter is given, then the starttime parameter is required. + DateTimeOffset end = new DateTimeOffset(TestStartTime).Subtract(TimeSpan.FromHours(4)); + + Assert.Throws(() => + client.QueryResources( + resourceIds: new List { new ResourceIdentifier(resourceId) }, + metricNames: new List { "Ingress" }, + metricNamespace: "Microsoft.Storage/storageAccounts", + options: new MetricsQueryResourcesOptions { EndTime = end })); + } } } diff --git a/sdk/monitor/Azure.Monitor.Query/tests/MetricsQueryClientSamples.cs b/sdk/monitor/Azure.Monitor.Query/tests/MetricsQueryClientSamples.cs index 323e2985aa52..18a1c97a4c64 100644 --- a/sdk/monitor/Azure.Monitor.Query/tests/MetricsQueryClientSamples.cs +++ b/sdk/monitor/Azure.Monitor.Query/tests/MetricsQueryClientSamples.cs @@ -307,5 +307,47 @@ public void CreateClientsWithOptions() logsQueryClientOptions); #endregion } + + [Test] + public async Task QueryResourcesMetricsWithOptionsStartTimeEndTime() + { + #region Snippet:QueryResourcesMetricsWithOptionsStartTimeEndTime +#if SNIPPET + string resourceId = + "/subscriptions//resourceGroups//providers//storageAccounts/"; + var client = new MetricsClient( + new Uri("https://.metrics.monitor.azure.com"), + new DefaultAzureCredential()); +#else + string resourceId = TestEnvironment.StorageAccountId; + var client = new MetricsClient( + new Uri(TestEnvironment.ConstructMetricsClientUri()), + new DefaultAzureCredential(), + new MetricsClientOptions() + { + Audience = TestEnvironment.GetMetricsClientAudience() + }); +#endif + var options = new MetricsQueryResourcesOptions + { + StartTime = DateTimeOffset.Now.AddHours(-4), + EndTime = DateTimeOffset.Now.AddHours(-1), + OrderBy = "sum asc", + Size = 10 + }; + + Response result = await client.QueryResourcesAsync( + resourceIds: new List { new ResourceIdentifier(resourceId) }, + metricNames: new List { "Ingress" }, + metricNamespace: "Microsoft.Storage/storageAccounts", + options).ConfigureAwait(false); + + MetricsQueryResourcesResult metricsQueryResults = result.Value; + foreach (MetricsQueryResult value in metricsQueryResults.Values) + { + Console.WriteLine(value.Metrics.Count); + } + #endregion Snippet:QueryResourcesMetricsWithOptionsStartTimeEndTime + } } }