From 540c10b3829df56209a5f4b785d14239a1b03774 Mon Sep 17 00:00:00 2001 From: nisha-bhatia <67986960+nisha-bhatia@users.noreply.github.com> Date: Mon, 29 Jan 2024 15:56:29 -0800 Subject: [PATCH 01/23] wip --- .../src/LogsQueryClient.cs | 10 +++- .../src/LogsQueryClientOptions.cs | 6 ++ .../src/MetricsBatchQueryClient.cs | 2 +- .../src/MetricsBatchQueryClientOptions.cs | 2 +- .../src/MetricsQueryClientOptions.cs | 6 ++ .../src/Models/LogsQueryAudience.cs | 59 +++++++++++++++++++ .../src/Models/MetricsQueryAudience.cs | 59 +++++++++++++++++++ sdk/monitor/Azure.Monitor.Query/tests.yml | 8 +++ .../tests/LogsQueryClientClientLiveTests.cs | 3 +- .../tests/MetricsQueryClientLiveTests.cs | 59 +++++++++++-------- .../tests/MonitorQueryTestEnvironment.cs | 45 ++++++++++++++ 11 files changed, 231 insertions(+), 28 deletions(-) create mode 100644 sdk/monitor/Azure.Monitor.Query/src/Models/LogsQueryAudience.cs create mode 100644 sdk/monitor/Azure.Monitor.Query/src/Models/MetricsQueryAudience.cs diff --git a/sdk/monitor/Azure.Monitor.Query/src/LogsQueryClient.cs b/sdk/monitor/Azure.Monitor.Query/src/LogsQueryClient.cs index 58ba047fa7de..4e0d4d91d7dc 100644 --- a/sdk/monitor/Azure.Monitor.Query/src/LogsQueryClient.cs +++ b/sdk/monitor/Azure.Monitor.Query/src/LogsQueryClient.cs @@ -69,7 +69,15 @@ public LogsQueryClient(Uri endpoint, TokenCredential credential, LogsQueryClient Endpoint = endpoint; options ??= new LogsQueryClientOptions(); - var scope = $"{endpoint.AbsoluteUri}/.default"; + string scope; + if (string.IsNullOrEmpty(options.Audience?.ToString())) + { + scope = $"{endpoint.AbsoluteUri}/.default"; + } + else + { + scope = $"{options.Audience}/.default"; + } endpoint = new Uri(endpoint, options.GetVersionString()); _clientDiagnostics = new ClientDiagnostics(options); diff --git a/sdk/monitor/Azure.Monitor.Query/src/LogsQueryClientOptions.cs b/sdk/monitor/Azure.Monitor.Query/src/LogsQueryClientOptions.cs index 4b84ef1b6876..c7f048090d48 100644 --- a/sdk/monitor/Azure.Monitor.Query/src/LogsQueryClientOptions.cs +++ b/sdk/monitor/Azure.Monitor.Query/src/LogsQueryClientOptions.cs @@ -52,5 +52,11 @@ internal string GetVersionString() _ => throw new ArgumentException(@"Unknown version {_version}") }; } + + /// + /// Gets or sets the audience to use for authentication with Microsoft Entra ID. The audience is not considered when using a shared key. + /// + /// If null, will be assumed. + public LogsQueryAudience? Audience { get; set; } } } diff --git a/sdk/monitor/Azure.Monitor.Query/src/MetricsBatchQueryClient.cs b/sdk/monitor/Azure.Monitor.Query/src/MetricsBatchQueryClient.cs index a2142a97a617..d2c812ba0211 100644 --- a/sdk/monitor/Azure.Monitor.Query/src/MetricsBatchQueryClient.cs +++ b/sdk/monitor/Azure.Monitor.Query/src/MetricsBatchQueryClient.cs @@ -14,7 +14,7 @@ namespace Azure.Monitor.Query /// /// The allows you to query multiple Azure Monitor Metric services. /// - public class MetricsBatchQueryClient + internal class MetricsBatchQueryClient { private readonly MetricsBatchRestClient _metricBatchClient; private readonly ClientDiagnostics _clientDiagnostics; diff --git a/sdk/monitor/Azure.Monitor.Query/src/MetricsBatchQueryClientOptions.cs b/sdk/monitor/Azure.Monitor.Query/src/MetricsBatchQueryClientOptions.cs index b6b2f8bc5c33..9cba1276ccb8 100644 --- a/sdk/monitor/Azure.Monitor.Query/src/MetricsBatchQueryClientOptions.cs +++ b/sdk/monitor/Azure.Monitor.Query/src/MetricsBatchQueryClientOptions.cs @@ -8,7 +8,7 @@ namespace Azure.Monitor.Query /// /// Provides the client configuration options for connecting to Azure Monitor Metrics service. /// - public class MetricsBatchQueryClientOptions: ClientOptions + internal class MetricsBatchQueryClientOptions: ClientOptions { private readonly ServiceVersion _version; diff --git a/sdk/monitor/Azure.Monitor.Query/src/MetricsQueryClientOptions.cs b/sdk/monitor/Azure.Monitor.Query/src/MetricsQueryClientOptions.cs index c3ee62d8483d..22292b9bd504 100644 --- a/sdk/monitor/Azure.Monitor.Query/src/MetricsQueryClientOptions.cs +++ b/sdk/monitor/Azure.Monitor.Query/src/MetricsQueryClientOptions.cs @@ -42,5 +42,11 @@ public enum ServiceVersion V2018_01_01 = 1, #pragma warning restore CA1707 // Identifiers should not contain underscores } + + /// + /// Gets or sets the audience to use for authentication with Microsoft Entra ID. The audience is not considered when using a shared key. + /// + /// If null, will be assumed. + public MetricsQueryAudience? Audience { get; set; } } } diff --git a/sdk/monitor/Azure.Monitor.Query/src/Models/LogsQueryAudience.cs b/sdk/monitor/Azure.Monitor.Query/src/Models/LogsQueryAudience.cs new file mode 100644 index 000000000000..a9b3f2b6dd2d --- /dev/null +++ b/sdk/monitor/Azure.Monitor.Query/src/Models/LogsQueryAudience.cs @@ -0,0 +1,59 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.ComponentModel; +using Azure.Core; + +namespace Azure.Monitor.Query +{ + /// Cloud audiences available for Query. + public readonly partial struct LogsQueryAudience : IEquatable + { + private readonly string _value; + + /// + /// Initializes a new instance of the object. + /// + /// The Microsoft Entra audience to use when forming authorization scopes. For the language service, this value corresponds to a URL that identifies the Azure cloud where the resource is located. For more information: . + /// is null. + /// Use one of the constant members over creating a custom value, unless you have special needs for doing so. + public LogsQueryAudience(string value) + { + Argument.AssertNotNullOrEmpty(value, nameof(value)); + _value = value; + } + + private const string AzureChinaValue = "https://api.loganalytics.azure.cn"; + private const string AzureGovernmentValue = "https://api.loganalytics.us"; + private const string AzurePublicCloudValue = "https://api.loganalytics.io"; + + /// Azure China. + public static LogsQueryAudience AzureChina { get; } = new LogsQueryAudience(AzureChinaValue); + + /// Azure US Government. + public static LogsQueryAudience AzureGovernment { get; } = new LogsQueryAudience(AzureGovernmentValue); + + /// Azure Public Cloud. + public static LogsQueryAudience AzurePublicCloud { get; } = new LogsQueryAudience(AzurePublicCloudValue); + + /// Determines if two values are the same. + public static bool operator ==(LogsQueryAudience left, LogsQueryAudience right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(LogsQueryAudience left, LogsQueryAudience right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator LogsQueryAudience(string value) => new LogsQueryAudience(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is LogsQueryAudience other && Equals(other); + /// + public bool Equals(LogsQueryAudience other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + /// + public override string ToString() => _value; + } +} diff --git a/sdk/monitor/Azure.Monitor.Query/src/Models/MetricsQueryAudience.cs b/sdk/monitor/Azure.Monitor.Query/src/Models/MetricsQueryAudience.cs new file mode 100644 index 000000000000..9581d4d850cf --- /dev/null +++ b/sdk/monitor/Azure.Monitor.Query/src/Models/MetricsQueryAudience.cs @@ -0,0 +1,59 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.ComponentModel; +using Azure.Core; + +namespace Azure.Monitor.Query +{ + /// Cloud audiences available for Query. + public readonly partial struct MetricsQueryAudience : IEquatable + { + private readonly string _value; + + /// + /// Initializes a new instance of the object. + /// + /// The Microsoft Entra audience to use when forming authorization scopes. For the language service, this value corresponds to a URL that identifies the Azure cloud where the resource is located. For more information: . + /// is null. + /// Use one of the constant members over creating a custom value, unless you have special needs for doing so. + public MetricsQueryAudience(string value) + { + Argument.AssertNotNullOrEmpty(value, nameof(value)); + _value = value; + } + + private const string AzureChinaValue = "https://management.chinacloudapi.cn"; + private const string AzureGovernmentValue = "https://management.usgovcloudapi.net"; + private const string AzurePublicCloudValue = "https://management.azure.com"; + + /// Azure China. + public static MetricsQueryAudience AzureChina { get; } = new MetricsQueryAudience(AzureChinaValue); + + /// Azure US Government. + public static MetricsQueryAudience AzureGovernment { get; } = new MetricsQueryAudience(AzureGovernmentValue); + + /// Azure Public Cloud. + public static MetricsQueryAudience AzurePublicCloud { get; } = new MetricsQueryAudience(AzurePublicCloudValue); + + /// Determines if two values are the same. + public static bool operator ==(MetricsQueryAudience left, MetricsQueryAudience right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(MetricsQueryAudience left, MetricsQueryAudience right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator MetricsQueryAudience(string value) => new MetricsQueryAudience(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is MetricsQueryAudience other && Equals(other); + /// + public bool Equals(MetricsQueryAudience other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + /// + public override string ToString() => _value; + } +} diff --git a/sdk/monitor/Azure.Monitor.Query/tests.yml b/sdk/monitor/Azure.Monitor.Query/tests.yml index 2498ec29ae4f..d6a1c6d883e3 100644 --- a/sdk/monitor/Azure.Monitor.Query/tests.yml +++ b/sdk/monitor/Azure.Monitor.Query/tests.yml @@ -4,5 +4,13 @@ extends: template: /eng/pipelines/templates/stages/archetype-sdk-tests.yml parameters: ServiceDirectory: monitor + CloudConfig: + Public: + SubscriptionConfiguration: $(sub-config-azure-cloud-test-resources) + UsGov: + SubscriptionConfiguration: $(sub-config-gov-test-resources) + China: + SubscriptionConfiguration: $(sub-config-cn-test-resources) + SupportedClouds: 'Public,UsGov,China' Project: Azure.Monitor.Query TimeoutInMinutes: 120 diff --git a/sdk/monitor/Azure.Monitor.Query/tests/LogsQueryClientClientLiveTests.cs b/sdk/monitor/Azure.Monitor.Query/tests/LogsQueryClientClientLiveTests.cs index 231de96a4b9d..932755dfdf87 100644 --- a/sdk/monitor/Azure.Monitor.Query/tests/LogsQueryClientClientLiveTests.cs +++ b/sdk/monitor/Azure.Monitor.Query/tests/LogsQueryClientClientLiveTests.cs @@ -36,7 +36,8 @@ private LogsQueryClient CreateClient() TestEnvironment.Credential, InstrumentClientOptions(new LogsQueryClientOptions() { - Diagnostics = { IsLoggingContentEnabled = true } + Diagnostics = { IsLoggingContentEnabled = true }, + Audience = TestEnvironment.GetLogsAudience() }) )); } diff --git a/sdk/monitor/Azure.Monitor.Query/tests/MetricsQueryClientLiveTests.cs b/sdk/monitor/Azure.Monitor.Query/tests/MetricsQueryClientLiveTests.cs index 1323d7b157d8..723bfc86ea80 100644 --- a/sdk/monitor/Azure.Monitor.Query/tests/MetricsQueryClientLiveTests.cs +++ b/sdk/monitor/Azure.Monitor.Query/tests/MetricsQueryClientLiveTests.cs @@ -24,7 +24,10 @@ private MetricsQueryClient CreateClient() return InstrumentClient(new MetricsQueryClient( TestEnvironment.MetricsEndpoint, TestEnvironment.Credential, - InstrumentClientOptions(new MetricsQueryClientOptions()) + InstrumentClientOptions(new MetricsQueryClientOptions() + { + Audience = TestEnvironment.GetMetricsAudience() + }) )); } @@ -339,26 +342,30 @@ public async Task CanGetMetricByNameInvalid() [RecordedTest] public async Task MetricsBatchQueryAsync() { - MetricsBatchQueryClient client = CreateBatchClient(); + // MetricsBatch endpoint currently exists only for Azure Public Cloud, so we do not want to run this test when we are in other clouds + if (TestEnvironment.GetMetricsAudience() == MetricsQueryAudience.AzurePublicCloud) + { + MetricsBatchQueryClient client = CreateBatchClient(); - var resourceId = TestEnvironment.StorageAccountId; + var resourceId = TestEnvironment.StorageAccountId; - Response metricsResultsResponse = await client.QueryBatchAsync( - resourceIds: new List { resourceId }, - metricNames: new List { "Ingress" }, - metricNamespace: "Microsoft.Storage/storageAccounts").ConfigureAwait(false); + Response metricsResultsResponse = await client.QueryBatchAsync( + resourceIds: new List { resourceId }, + metricNames: new List { "Ingress" }, + metricNamespace: "Microsoft.Storage/storageAccounts").ConfigureAwait(false); - MetricsBatchResult metricsQueryResults = metricsResultsResponse.Value; - Assert.AreEqual(1, metricsQueryResults.Values.Count); - Assert.AreEqual(TestEnvironment.StorageAccountId, metricsQueryResults.Values[0].ResourceId.ToString()); - Assert.AreEqual("Microsoft.Storage/storageAccounts", metricsQueryResults.Values[0].Namespace); - for (int i = 0; i < metricsQueryResults.Values.Count; i++) - { - foreach (MetricResult value in metricsQueryResults.Values[i].Metrics) + MetricsBatchResult metricsQueryResults = metricsResultsResponse.Value; + Assert.AreEqual(1, metricsQueryResults.Values.Count); + Assert.AreEqual(TestEnvironment.StorageAccountId, metricsQueryResults.Values[0].ResourceId.ToString()); + Assert.AreEqual("Microsoft.Storage/storageAccounts", metricsQueryResults.Values[0].Namespace); + for (int i = 0; i < metricsQueryResults.Values.Count; i++) { - for (int j = 0; j < value.TimeSeries.Count; j++) + foreach (MetricResult value in metricsQueryResults.Values[i].Metrics) { - Assert.GreaterOrEqual(value.TimeSeries[j].Values[i].Total, 0); + for (int j = 0; j < value.TimeSeries.Count; j++) + { + Assert.GreaterOrEqual(value.TimeSeries[j].Values[i].Total, 0); + } } } } @@ -368,15 +375,19 @@ public async Task MetricsBatchQueryAsync() [RecordedTest] public void MetricsBatchInvalid() { - MetricsBatchQueryClient client = CreateBatchClient(); - - Assert.Throws(()=> + // MetricsBatch endpoint currently exists only for Azure Public Cloud, so we do not want to run this test when we are in other clouds + if (TestEnvironment.GetMetricsAudience() == MetricsQueryAudience.AzurePublicCloud) { - client.QueryBatch( - resourceIds: new List(), - metricNames: new List { "Ingress" }, - metricNamespace: "Microsoft.Storage/storageAccounts"); - }); + MetricsBatchQueryClient client = CreateBatchClient(); + + Assert.Throws(() => + { + client.QueryBatch( + resourceIds: new List(), + metricNames: new List { "Ingress" }, + metricNamespace: "Microsoft.Storage/storageAccounts"); + }); + } } } } diff --git a/sdk/monitor/Azure.Monitor.Query/tests/MonitorQueryTestEnvironment.cs b/sdk/monitor/Azure.Monitor.Query/tests/MonitorQueryTestEnvironment.cs index 9e4664811d6c..39945c9e84e8 100644 --- a/sdk/monitor/Azure.Monitor.Query/tests/MonitorQueryTestEnvironment.cs +++ b/sdk/monitor/Azure.Monitor.Query/tests/MonitorQueryTestEnvironment.cs @@ -3,6 +3,7 @@ using System; using Azure.Core.TestFramework; +using Azure.Identity; namespace Azure.Monitor.Query.Tests { @@ -25,5 +26,49 @@ public class MonitorQueryTestEnvironment : TestEnvironment public string ConnectionString => GetRecordedOptionalVariable("CONNECTION_STRING"); public string StorageAccountId => GetRecordedOptionalVariable("STORAGE_ID"); public string StorageAccountConnectionString => GetRecordedOptionalVariable("STORAGE_CONNECTION_STRING"); + + public string GetLogsAudience() + { + Uri authorityHost = new(AuthorityHostUrl); + + if (authorityHost == AzureAuthorityHosts.AzurePublicCloud) + { + return LogsQueryAudience.AzurePublicCloud.ToString(); + } + + else if (authorityHost == AzureAuthorityHosts.AzureChina) + { + return LogsQueryAudience.AzureChina.ToString(); + } + + else if (authorityHost == AzureAuthorityHosts.AzureGovernment) + { + return LogsQueryAudience.AzureGovernment.ToString(); + } + + throw new NotSupportedException($"Cloud for authority host {authorityHost} is not supported."); + } + + public string GetMetricsAudience() + { + Uri authorityHost = new(AuthorityHostUrl); + + if (authorityHost == AzureAuthorityHosts.AzurePublicCloud) + { + return MetricsQueryAudience.AzurePublicCloud.ToString(); + } + + else if (authorityHost == AzureAuthorityHosts.AzureChina) + { + return MetricsQueryAudience.AzureChina.ToString(); + } + + else if (authorityHost == AzureAuthorityHosts.AzureGovernment) + { + return MetricsQueryAudience.AzureGovernment.ToString(); + } + + throw new NotSupportedException($"Cloud for authority host {authorityHost} is not supported."); + } } } From e0e7912daa2d6cf1a3a35c7ccdd3ec75e8bdac90 Mon Sep 17 00:00:00 2001 From: nisha-bhatia <67986960+nisha-bhatia@users.noreply.github.com> Date: Mon, 29 Jan 2024 15:58:46 -0800 Subject: [PATCH 02/23] Update CHANGELOG.md --- sdk/monitor/Azure.Monitor.Query/CHANGELOG.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/sdk/monitor/Azure.Monitor.Query/CHANGELOG.md b/sdk/monitor/Azure.Monitor.Query/CHANGELOG.md index 0478c1627ce4..b9fc0220d231 100644 --- a/sdk/monitor/Azure.Monitor.Query/CHANGELOG.md +++ b/sdk/monitor/Azure.Monitor.Query/CHANGELOG.md @@ -1,14 +1,17 @@ # Release History -## 1.3.0-beta.3 (Unreleased) +## 1.3.0 (2023-31-01) ### Features Added ### Breaking Changes ### Bugs Fixed +- Enable national cloud support for US Gov and China clouds ### Other Changes +- Removed the `MetricsBatchQueryClient` client to support batch querying of metrics. This client is currently only available in beta release. +- Removed `QueryBatch` and `QueryBatchAsync` methods to `MetricsBatchQueryClient`. These methods are currently only available in beta release. ## 1.3.0-beta.2 (2023-12-05) From 728310253cf452df54ee19281d37b548f9108a14 Mon Sep 17 00:00:00 2001 From: nisha-bhatia <67986960+nisha-bhatia@users.noreply.github.com> Date: Mon, 29 Jan 2024 16:01:10 -0800 Subject: [PATCH 03/23] wip --- .../api/Azure.Monitor.Query.netstandard2.0.cs | 52 ++++++++++++++----- 1 file changed, 38 insertions(+), 14 deletions(-) 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 82d4dd649a40..70e2742f2ed5 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 @@ -5,6 +5,25 @@ public partial class LogsBatchQuery public LogsBatchQuery() { } public virtual string AddWorkspaceQuery(string workspaceId, string query, Azure.Monitor.Query.QueryTimeRange timeRange, Azure.Monitor.Query.LogsQueryOptions options = null) { throw null; } } + [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)] + public readonly partial struct LogsQueryAudience : System.IEquatable + { + private readonly object _dummy; + private readonly int _dummyPrimitive; + public LogsQueryAudience(string value) { throw null; } + public static Azure.Monitor.Query.LogsQueryAudience AzureChina { get { throw null; } } + public static Azure.Monitor.Query.LogsQueryAudience AzureGovernment { get { throw null; } } + public static Azure.Monitor.Query.LogsQueryAudience AzurePublicCloud { get { throw null; } } + public bool Equals(Azure.Monitor.Query.LogsQueryAudience other) { throw null; } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + public override bool Equals(object obj) { throw null; } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + public override int GetHashCode() { throw null; } + public static bool operator ==(Azure.Monitor.Query.LogsQueryAudience left, Azure.Monitor.Query.LogsQueryAudience right) { throw null; } + public static implicit operator Azure.Monitor.Query.LogsQueryAudience (string value) { throw null; } + public static bool operator !=(Azure.Monitor.Query.LogsQueryAudience left, Azure.Monitor.Query.LogsQueryAudience right) { throw null; } + public override string ToString() { throw null; } + } public partial class LogsQueryClient { protected LogsQueryClient() { } @@ -28,6 +47,7 @@ public LogsQueryClient(System.Uri endpoint, Azure.Core.TokenCredential credentia public partial class LogsQueryClientOptions : Azure.Core.ClientOptions { public LogsQueryClientOptions(Azure.Monitor.Query.LogsQueryClientOptions.ServiceVersion version = Azure.Monitor.Query.LogsQueryClientOptions.ServiceVersion.V1) { } + public Azure.Monitor.Query.LogsQueryAudience? Audience { get { throw null; } set { } } public enum ServiceVersion { V1 = 1, @@ -42,21 +62,24 @@ public LogsQueryOptions() { } public bool IncludeVisualization { get { throw null; } set { } } public System.TimeSpan? ServerTimeout { get { throw null; } set { } } } - public partial class MetricsBatchQueryClient - { - protected MetricsBatchQueryClient() { } - public MetricsBatchQueryClient(System.Uri endpoint, Azure.Core.TokenCredential credential, Azure.Monitor.Query.MetricsBatchQueryClientOptions options = null) { } - public System.Uri Endpoint { get { throw null; } } - public virtual Azure.Response QueryBatch(System.Collections.Generic.List resourceIds, System.Collections.Generic.List metricNames, string metricNamespace, Azure.Monitor.Query.MetricsQueryOptions options = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } - public virtual System.Threading.Tasks.Task> QueryBatchAsync(System.Collections.Generic.List resourceIds, System.Collections.Generic.List metricNames, string metricNamespace, Azure.Monitor.Query.MetricsQueryOptions options = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } - } - public partial class MetricsBatchQueryClientOptions : Azure.Core.ClientOptions + [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)] + public readonly partial struct MetricsQueryAudience : System.IEquatable { - public MetricsBatchQueryClientOptions(Azure.Monitor.Query.MetricsBatchQueryClientOptions.ServiceVersion version = Azure.Monitor.Query.MetricsBatchQueryClientOptions.ServiceVersion.V2023_05_01_PREVIEW) { } - public enum ServiceVersion - { - V2023_05_01_PREVIEW = 1, - } + private readonly object _dummy; + private readonly int _dummyPrimitive; + public MetricsQueryAudience(string value) { throw null; } + public static Azure.Monitor.Query.MetricsQueryAudience AzureChina { get { throw null; } } + public static Azure.Monitor.Query.MetricsQueryAudience AzureGovernment { get { throw null; } } + public static Azure.Monitor.Query.MetricsQueryAudience AzurePublicCloud { get { throw null; } } + public bool Equals(Azure.Monitor.Query.MetricsQueryAudience other) { throw null; } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + public override bool Equals(object obj) { throw null; } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + public override int GetHashCode() { throw null; } + public static bool operator ==(Azure.Monitor.Query.MetricsQueryAudience left, Azure.Monitor.Query.MetricsQueryAudience right) { throw null; } + public static implicit operator Azure.Monitor.Query.MetricsQueryAudience (string value) { throw null; } + public static bool operator !=(Azure.Monitor.Query.MetricsQueryAudience left, Azure.Monitor.Query.MetricsQueryAudience right) { throw null; } + public override string ToString() { throw null; } } public partial class MetricsQueryClient { @@ -75,6 +98,7 @@ public MetricsQueryClient(System.Uri endpoint, Azure.Core.TokenCredential creden public partial class MetricsQueryClientOptions : Azure.Core.ClientOptions { public MetricsQueryClientOptions(Azure.Monitor.Query.MetricsQueryClientOptions.ServiceVersion version = Azure.Monitor.Query.MetricsQueryClientOptions.ServiceVersion.V2018_01_01) { } + public Azure.Monitor.Query.MetricsQueryAudience? Audience { get { throw null; } set { } } public enum ServiceVersion { V2018_01_01 = 1, From 0648455b8f274e96b37a4210dcc886dc3d388bd5 Mon Sep 17 00:00:00 2001 From: nisha-bhatia <67986960+nisha-bhatia@users.noreply.github.com> Date: Mon, 29 Jan 2024 18:46:53 -0800 Subject: [PATCH 04/23] Update MetricsQueryClientLiveTests.cs --- .../tests/MetricsQueryClientLiveTests.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/sdk/monitor/Azure.Monitor.Query/tests/MetricsQueryClientLiveTests.cs b/sdk/monitor/Azure.Monitor.Query/tests/MetricsQueryClientLiveTests.cs index 723bfc86ea80..be86d86fe0b1 100644 --- a/sdk/monitor/Azure.Monitor.Query/tests/MetricsQueryClientLiveTests.cs +++ b/sdk/monitor/Azure.Monitor.Query/tests/MetricsQueryClientLiveTests.cs @@ -339,7 +339,8 @@ public async Task CanGetMetricByNameInvalid() Assert.Throws(() => { results.Value.GetMetricByName("Guinness"); }); } - [RecordedTest] + [Test] + [Ignore("Will replace when Swagger GAs")] public async Task MetricsBatchQueryAsync() { // MetricsBatch endpoint currently exists only for Azure Public Cloud, so we do not want to run this test when we are in other clouds @@ -371,8 +372,8 @@ public async Task MetricsBatchQueryAsync() } } - [SyncOnly] - [RecordedTest] + [Test] + [Ignore("Will replace when Swagger GAs")] public void MetricsBatchInvalid() { // MetricsBatch endpoint currently exists only for Azure Public Cloud, so we do not want to run this test when we are in other clouds From 27449b800083259d0af44ce5d9a71308f8de7532 Mon Sep 17 00:00:00 2001 From: nisha-bhatia <67986960+nisha-bhatia@users.noreply.github.com> Date: Mon, 29 Jan 2024 18:56:59 -0800 Subject: [PATCH 05/23] Update CHANGELOG.md --- sdk/monitor/Azure.Monitor.Query/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/monitor/Azure.Monitor.Query/CHANGELOG.md b/sdk/monitor/Azure.Monitor.Query/CHANGELOG.md index b9fc0220d231..eca9c10f6979 100644 --- a/sdk/monitor/Azure.Monitor.Query/CHANGELOG.md +++ b/sdk/monitor/Azure.Monitor.Query/CHANGELOG.md @@ -1,6 +1,6 @@ # Release History -## 1.3.0 (2023-31-01) +## 1.3.0-beta.3 (Unreleased) ### Features Added From a8a02ca686adfc2ed7b46608e506d2bce75e3c88 Mon Sep 17 00:00:00 2001 From: nisha-bhatia <67986960+nisha-bhatia@users.noreply.github.com> Date: Tue, 30 Jan 2024 14:18:47 -0800 Subject: [PATCH 06/23] wip --- sdk/monitor/Azure.Monitor.Query/src/LogsQueryClient.cs | 2 +- sdk/monitor/Azure.Monitor.Query/src/MetricsQueryClient.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sdk/monitor/Azure.Monitor.Query/src/LogsQueryClient.cs b/sdk/monitor/Azure.Monitor.Query/src/LogsQueryClient.cs index 4e0d4d91d7dc..015e0f489ec5 100644 --- a/sdk/monitor/Azure.Monitor.Query/src/LogsQueryClient.cs +++ b/sdk/monitor/Azure.Monitor.Query/src/LogsQueryClient.cs @@ -76,7 +76,7 @@ public LogsQueryClient(Uri endpoint, TokenCredential credential, LogsQueryClient } else { - scope = $"{options.Audience}/.default"; + scope = $"{options.Audience}.default"; } endpoint = new Uri(endpoint, options.GetVersionString()); diff --git a/sdk/monitor/Azure.Monitor.Query/src/MetricsQueryClient.cs b/sdk/monitor/Azure.Monitor.Query/src/MetricsQueryClient.cs index 0d30ddbe8637..045319c9bccf 100644 --- a/sdk/monitor/Azure.Monitor.Query/src/MetricsQueryClient.cs +++ b/sdk/monitor/Azure.Monitor.Query/src/MetricsQueryClient.cs @@ -57,7 +57,7 @@ public MetricsQueryClient(Uri endpoint, TokenCredential credential, MetricsQuery _clientDiagnostics = new ClientDiagnostics(options); - var scope = $"{endpoint.AbsoluteUri}/.default"; + var scope = $"{endpoint.AbsoluteUri}.default"; Endpoint = endpoint; From 2a6be30fa9f3a3b82b2accad0c7c8b17db1cb6f4 Mon Sep 17 00:00:00 2001 From: nisha-bhatia <67986960+nisha-bhatia@users.noreply.github.com> Date: Tue, 30 Jan 2024 14:35:44 -0800 Subject: [PATCH 07/23] wip --- sdk/monitor/Azure.Monitor.Query/src/LogsQueryClient.cs | 2 +- sdk/monitor/Azure.Monitor.Query/src/MetricsQueryClient.cs | 2 +- .../Azure.Monitor.Query/tests/LogsQueryClientClientLiveTests.cs | 2 +- .../Azure.Monitor.Query/tests/MetricsQueryClientLiveTests.cs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/sdk/monitor/Azure.Monitor.Query/src/LogsQueryClient.cs b/sdk/monitor/Azure.Monitor.Query/src/LogsQueryClient.cs index 015e0f489ec5..4e0d4d91d7dc 100644 --- a/sdk/monitor/Azure.Monitor.Query/src/LogsQueryClient.cs +++ b/sdk/monitor/Azure.Monitor.Query/src/LogsQueryClient.cs @@ -76,7 +76,7 @@ public LogsQueryClient(Uri endpoint, TokenCredential credential, LogsQueryClient } else { - scope = $"{options.Audience}.default"; + scope = $"{options.Audience}/.default"; } endpoint = new Uri(endpoint, options.GetVersionString()); diff --git a/sdk/monitor/Azure.Monitor.Query/src/MetricsQueryClient.cs b/sdk/monitor/Azure.Monitor.Query/src/MetricsQueryClient.cs index 045319c9bccf..0d30ddbe8637 100644 --- a/sdk/monitor/Azure.Monitor.Query/src/MetricsQueryClient.cs +++ b/sdk/monitor/Azure.Monitor.Query/src/MetricsQueryClient.cs @@ -57,7 +57,7 @@ public MetricsQueryClient(Uri endpoint, TokenCredential credential, MetricsQuery _clientDiagnostics = new ClientDiagnostics(options); - var scope = $"{endpoint.AbsoluteUri}.default"; + var scope = $"{endpoint.AbsoluteUri}/.default"; Endpoint = endpoint; diff --git a/sdk/monitor/Azure.Monitor.Query/tests/LogsQueryClientClientLiveTests.cs b/sdk/monitor/Azure.Monitor.Query/tests/LogsQueryClientClientLiveTests.cs index 932755dfdf87..61943a23b923 100644 --- a/sdk/monitor/Azure.Monitor.Query/tests/LogsQueryClientClientLiveTests.cs +++ b/sdk/monitor/Azure.Monitor.Query/tests/LogsQueryClientClientLiveTests.cs @@ -32,7 +32,7 @@ public async Task SetUp() private LogsQueryClient CreateClient() { return InstrumentClient(new LogsQueryClient( - TestEnvironment.LogsEndpoint, + new Uri(TestEnvironment.GetLogsAudience() + "/v1"), TestEnvironment.Credential, InstrumentClientOptions(new LogsQueryClientOptions() { diff --git a/sdk/monitor/Azure.Monitor.Query/tests/MetricsQueryClientLiveTests.cs b/sdk/monitor/Azure.Monitor.Query/tests/MetricsQueryClientLiveTests.cs index be86d86fe0b1..0f88581fd3d7 100644 --- a/sdk/monitor/Azure.Monitor.Query/tests/MetricsQueryClientLiveTests.cs +++ b/sdk/monitor/Azure.Monitor.Query/tests/MetricsQueryClientLiveTests.cs @@ -22,7 +22,7 @@ public MetricsQueryClientLiveTests(bool isAsync) : base(isAsync) private MetricsQueryClient CreateClient() { return InstrumentClient(new MetricsQueryClient( - TestEnvironment.MetricsEndpoint, + new Uri(TestEnvironment.GetMetricsAudience()), TestEnvironment.Credential, InstrumentClientOptions(new MetricsQueryClientOptions() { From 6777da09576689c87f03c0c87d6b95fc0c5a5df5 Mon Sep 17 00:00:00 2001 From: nisha-bhatia <67986960+nisha-bhatia@users.noreply.github.com> Date: Tue, 30 Jan 2024 15:11:53 -0800 Subject: [PATCH 08/23] Update LogsTestData.cs --- sdk/monitor/Azure.Monitor.Query/tests/LogsTestData.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/monitor/Azure.Monitor.Query/tests/LogsTestData.cs b/sdk/monitor/Azure.Monitor.Query/tests/LogsTestData.cs index 6ac0de391adf..2e67a33f9cb2 100644 --- a/sdk/monitor/Azure.Monitor.Query/tests/LogsTestData.cs +++ b/sdk/monitor/Azure.Monitor.Query/tests/LogsTestData.cs @@ -120,7 +120,7 @@ private async Task InitializeData(string workspaceId, string workspaceKey) private async Task QueryCount(string workspaceId) { - var logsClient = new LogsQueryClient(_testEnvironment.LogsEndpoint, _testEnvironment.Credential); + var logsClient = new LogsQueryClient(new Uri(_testEnvironment.GetLogsAudience() + "/v1"), _testEnvironment.Credential); try { var countResponse = await logsClient.QueryWorkspaceAsync(workspaceId, $"{TableAName} | count", DataTimeRange); From 68a76f2f6d0be57c4eddeef60a51327409a946d1 Mon Sep 17 00:00:00 2001 From: nisha-bhatia <67986960+nisha-bhatia@users.noreply.github.com> Date: Tue, 30 Jan 2024 15:53:15 -0800 Subject: [PATCH 09/23] Update test-resources.bicep --- sdk/monitor/test-resources.bicep | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/monitor/test-resources.bicep b/sdk/monitor/test-resources.bicep index c57145aca693..095a23fe872a 100644 --- a/sdk/monitor/test-resources.bicep +++ b/sdk/monitor/test-resources.bicep @@ -173,7 +173,7 @@ resource dataCollectionRuleRoleAssignment 'Microsoft.Authorization/roleAssignmen } @description('The base resource name.') -param storageAccountName string = 'nibhatistorage' +param storageAccountName string = uniqueString(baseName, 'storage') @description('The base resource name.') param storageAccountsku string = 'Standard_LRS' From b6c8324571147fd01417201ecebf20a41de7a87f Mon Sep 17 00:00:00 2001 From: nisha-bhatia <67986960+nisha-bhatia@users.noreply.github.com> Date: Wed, 31 Jan 2024 00:48:25 -0800 Subject: [PATCH 10/23] Update service.proj --- eng/service.proj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eng/service.proj b/eng/service.proj index 33cc8a07eccc..15e3f231b963 100644 --- a/eng/service.proj +++ b/eng/service.proj @@ -47,7 +47,7 @@ From f2a69b2f3b97689483161af872a8d33538a50227 Mon Sep 17 00:00:00 2001 From: nisha-bhatia <67986960+nisha-bhatia@users.noreply.github.com> Date: Wed, 31 Jan 2024 15:50:23 -0800 Subject: [PATCH 11/23] wip --- .../tests/MetricsTestData.cs | 2 ++ .../tests/MonitorQueryTestEnvironment.cs | 24 +++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/sdk/monitor/Azure.Monitor.Query/tests/MetricsTestData.cs b/sdk/monitor/Azure.Monitor.Query/tests/MetricsTestData.cs index 1a4d1b65937c..1b9608dd4a19 100644 --- a/sdk/monitor/Azure.Monitor.Query/tests/MetricsTestData.cs +++ b/sdk/monitor/Azure.Monitor.Query/tests/MetricsTestData.cs @@ -3,10 +3,12 @@ using System; using System.Linq; +using System.Net; using System.Threading.Tasks; using Azure.Core; using Azure.Core.TestFramework; using Azure.Monitor.Query.Models; +using Microsoft.Identity.Client.Platforms.Features.DesktopOs.Kerberos; namespace Azure.Monitor.Query.Tests { diff --git a/sdk/monitor/Azure.Monitor.Query/tests/MonitorQueryTestEnvironment.cs b/sdk/monitor/Azure.Monitor.Query/tests/MonitorQueryTestEnvironment.cs index 39945c9e84e8..c0f4e891b60c 100644 --- a/sdk/monitor/Azure.Monitor.Query/tests/MonitorQueryTestEnvironment.cs +++ b/sdk/monitor/Azure.Monitor.Query/tests/MonitorQueryTestEnvironment.cs @@ -2,6 +2,8 @@ // Licensed under the MIT License. using System; +using System.Net; +using System.Threading.Tasks; using Azure.Core.TestFramework; using Azure.Identity; @@ -70,5 +72,27 @@ public string GetMetricsAudience() throw new NotSupportedException($"Cloud for authority host {authorityHost} is not supported."); } + + protected override async ValueTask IsEnvironmentReadyAsync() + { + // Check that the dynamic resource is ready. + MetricsQueryClientOptions metricsOptions = new() { Audience = GetMetricsAudience() }; + LogsQueryClientOptions logsOptions = new() { Audience = GetLogsAudience() }; + + try + { + MetricsQueryClient metricsClient = new(new Uri(GetMetricsAudience()), new DefaultAzureCredential(), metricsOptions); + await metricsClient.DetectLanguageAsync("Ready!"); + + LogsQueryClient logsClient = new(new Uri(GetLogsAudience() + "/v1"), new DefaultAzureCredential(), logsOptions); + await logsClient.DetectLanguageAsync("Ready!"); + } + catch (RequestFailedException e) when (e.Status == 401) + { + return false; + } + + return true; + } } } From d0e99d24998e94da03c7ba140166b5b1b66538d8 Mon Sep 17 00:00:00 2001 From: nisha-bhatia <67986960+nisha-bhatia@users.noreply.github.com> Date: Tue, 6 Feb 2024 11:29:03 -0800 Subject: [PATCH 12/23] Update service.proj --- eng/service.proj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eng/service.proj b/eng/service.proj index 15e3f231b963..33cc8a07eccc 100644 --- a/eng/service.proj +++ b/eng/service.proj @@ -47,7 +47,7 @@ From 574ad7e0aaf2369d486afacd489058f90b21ad9e Mon Sep 17 00:00:00 2001 From: nisha-bhatia <67986960+nisha-bhatia@users.noreply.github.com> Date: Tue, 6 Feb 2024 11:31:12 -0800 Subject: [PATCH 13/23] Update tests.yml --- sdk/monitor/Azure.Monitor.Query/tests.yml | 7 ------- 1 file changed, 7 deletions(-) diff --git a/sdk/monitor/Azure.Monitor.Query/tests.yml b/sdk/monitor/Azure.Monitor.Query/tests.yml index d6a1c6d883e3..21bb2f5114e1 100644 --- a/sdk/monitor/Azure.Monitor.Query/tests.yml +++ b/sdk/monitor/Azure.Monitor.Query/tests.yml @@ -4,13 +4,6 @@ extends: template: /eng/pipelines/templates/stages/archetype-sdk-tests.yml parameters: ServiceDirectory: monitor - CloudConfig: - Public: - SubscriptionConfiguration: $(sub-config-azure-cloud-test-resources) - UsGov: - SubscriptionConfiguration: $(sub-config-gov-test-resources) - China: - SubscriptionConfiguration: $(sub-config-cn-test-resources) SupportedClouds: 'Public,UsGov,China' Project: Azure.Monitor.Query TimeoutInMinutes: 120 From 4b25b36e63408067fb7acab5ffe65275a951e7c6 Mon Sep 17 00:00:00 2001 From: nisha-bhatia <67986960+nisha-bhatia@users.noreply.github.com> Date: Tue, 6 Feb 2024 11:34:22 -0800 Subject: [PATCH 14/23] wip --- sdk/monitor/Azure.Monitor.Query/src/Models/LogsQueryAudience.cs | 2 +- .../Azure.Monitor.Query/src/Models/MetricsQueryAudience.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sdk/monitor/Azure.Monitor.Query/src/Models/LogsQueryAudience.cs b/sdk/monitor/Azure.Monitor.Query/src/Models/LogsQueryAudience.cs index a9b3f2b6dd2d..e7515f5db86b 100644 --- a/sdk/monitor/Azure.Monitor.Query/src/Models/LogsQueryAudience.cs +++ b/sdk/monitor/Azure.Monitor.Query/src/Models/LogsQueryAudience.cs @@ -15,7 +15,7 @@ namespace Azure.Monitor.Query /// /// Initializes a new instance of the object. /// - /// The Microsoft Entra audience to use when forming authorization scopes. For the language service, this value corresponds to a URL that identifies the Azure cloud where the resource is located. For more information: . + /// The Microsoft Entra audience to use when forming authorization scopes. For the language service, this value corresponds to a URL that identifies the Azure cloud where the resource is located. For more information: . /// is null. /// Use one of the constant members over creating a custom value, unless you have special needs for doing so. public LogsQueryAudience(string value) diff --git a/sdk/monitor/Azure.Monitor.Query/src/Models/MetricsQueryAudience.cs b/sdk/monitor/Azure.Monitor.Query/src/Models/MetricsQueryAudience.cs index 9581d4d850cf..8f5befea3d93 100644 --- a/sdk/monitor/Azure.Monitor.Query/src/Models/MetricsQueryAudience.cs +++ b/sdk/monitor/Azure.Monitor.Query/src/Models/MetricsQueryAudience.cs @@ -15,7 +15,7 @@ namespace Azure.Monitor.Query /// /// Initializes a new instance of the object. /// - /// The Microsoft Entra audience to use when forming authorization scopes. For the language service, this value corresponds to a URL that identifies the Azure cloud where the resource is located. For more information: . + /// The Microsoft Entra audience to use when forming authorization scopes. For the language service, this value corresponds to a URL that identifies the Azure cloud where the resource is located. For more information: . /// is null. /// Use one of the constant members over creating a custom value, unless you have special needs for doing so. public MetricsQueryAudience(string value) From e40a2b2556ccbcde06a409a072040f9959fdeeaa Mon Sep 17 00:00:00 2001 From: nisha-bhatia <67986960+nisha-bhatia@users.noreply.github.com> Date: Tue, 6 Feb 2024 11:56:01 -0800 Subject: [PATCH 15/23] Update Azure.Monitor.Query.netstandard2.0.cs --- .../api/Azure.Monitor.Query.netstandard2.0.cs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) 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 f07a99e2e0ab..70e2742f2ed5 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 @@ -62,6 +62,25 @@ public LogsQueryOptions() { } public bool IncludeVisualization { get { throw null; } set { } } public System.TimeSpan? ServerTimeout { get { throw null; } set { } } } + [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)] + public readonly partial struct MetricsQueryAudience : System.IEquatable + { + private readonly object _dummy; + private readonly int _dummyPrimitive; + public MetricsQueryAudience(string value) { throw null; } + public static Azure.Monitor.Query.MetricsQueryAudience AzureChina { get { throw null; } } + public static Azure.Monitor.Query.MetricsQueryAudience AzureGovernment { get { throw null; } } + public static Azure.Monitor.Query.MetricsQueryAudience AzurePublicCloud { get { throw null; } } + public bool Equals(Azure.Monitor.Query.MetricsQueryAudience other) { throw null; } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + public override bool Equals(object obj) { throw null; } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + public override int GetHashCode() { throw null; } + public static bool operator ==(Azure.Monitor.Query.MetricsQueryAudience left, Azure.Monitor.Query.MetricsQueryAudience right) { throw null; } + public static implicit operator Azure.Monitor.Query.MetricsQueryAudience (string value) { throw null; } + public static bool operator !=(Azure.Monitor.Query.MetricsQueryAudience left, Azure.Monitor.Query.MetricsQueryAudience right) { throw null; } + public override string ToString() { throw null; } + } public partial class MetricsQueryClient { protected MetricsQueryClient() { } From bd876788b24588ad40b6633ef9f4b5ffe8ff0ad8 Mon Sep 17 00:00:00 2001 From: nisha-bhatia <67986960+nisha-bhatia@users.noreply.github.com> Date: Tue, 6 Feb 2024 13:14:12 -0800 Subject: [PATCH 16/23] Update MonitorQueryTestEnvironment.cs --- .../tests/MonitorQueryTestEnvironment.cs | 22 ------------------- 1 file changed, 22 deletions(-) diff --git a/sdk/monitor/Azure.Monitor.Query/tests/MonitorQueryTestEnvironment.cs b/sdk/monitor/Azure.Monitor.Query/tests/MonitorQueryTestEnvironment.cs index c0f4e891b60c..fd57a96be48e 100644 --- a/sdk/monitor/Azure.Monitor.Query/tests/MonitorQueryTestEnvironment.cs +++ b/sdk/monitor/Azure.Monitor.Query/tests/MonitorQueryTestEnvironment.cs @@ -72,27 +72,5 @@ public string GetMetricsAudience() throw new NotSupportedException($"Cloud for authority host {authorityHost} is not supported."); } - - protected override async ValueTask IsEnvironmentReadyAsync() - { - // Check that the dynamic resource is ready. - MetricsQueryClientOptions metricsOptions = new() { Audience = GetMetricsAudience() }; - LogsQueryClientOptions logsOptions = new() { Audience = GetLogsAudience() }; - - try - { - MetricsQueryClient metricsClient = new(new Uri(GetMetricsAudience()), new DefaultAzureCredential(), metricsOptions); - await metricsClient.DetectLanguageAsync("Ready!"); - - LogsQueryClient logsClient = new(new Uri(GetLogsAudience() + "/v1"), new DefaultAzureCredential(), logsOptions); - await logsClient.DetectLanguageAsync("Ready!"); - } - catch (RequestFailedException e) when (e.Status == 401) - { - return false; - } - - return true; - } } } From f80fef80a2be55dbee00ba724964556a004231ea Mon Sep 17 00:00:00 2001 From: nisha-bhatia <67986960+nisha-bhatia@users.noreply.github.com> Date: Tue, 6 Feb 2024 14:13:52 -0800 Subject: [PATCH 17/23] wip --- sdk/monitor/Azure.Monitor.Query/README.md | 5 ++- .../tests/MetricsQueryClientSamples.cs | 42 ++++++++++++++++--- 2 files changed, 40 insertions(+), 7 deletions(-) diff --git a/sdk/monitor/Azure.Monitor.Query/README.md b/sdk/monitor/Azure.Monitor.Query/README.md index 51327e259dcb..5fd2d6e09ec9 100644 --- a/sdk/monitor/Azure.Monitor.Query/README.md +++ b/sdk/monitor/Azure.Monitor.Query/README.md @@ -522,8 +522,7 @@ string resourceId = "/subscriptions//resourceGroups//providers/Microsoft.KeyVault/vaults/TestVault"; string[] metricNames = new[] { "Availability" }; var client = new MetricsQueryClient(new DefaultAzureCredential()); - -Response result = await client.QueryResourceAsync( +Response result = await client.QueryResourceAsync( resourceId, metricNames, new MetricsQueryOptions @@ -555,6 +554,7 @@ To programmatically retrieve metrics namespaces, use the following code: string resourceId = "/subscriptions//resourceGroups//providers/Microsoft.Web/sites/TestWebApp"; var client = new MetricsQueryClient(new DefaultAzureCredential()); + AsyncPageable metricNamespaces = client.GetMetricNamespacesAsync(resourceId); await foreach (var metricNamespace in metricNamespaces) @@ -574,6 +574,7 @@ string[] metricNames = new[] { "Http2xx" }; // Use of asterisk in filter value enables splitting on Instance dimension. string filter = "Instance eq '*'"; var client = new MetricsQueryClient(new DefaultAzureCredential()); + var options = new MetricsQueryOptions { Aggregations = diff --git a/sdk/monitor/Azure.Monitor.Query/tests/MetricsQueryClientSamples.cs b/sdk/monitor/Azure.Monitor.Query/tests/MetricsQueryClientSamples.cs index 761b2773d834..bb577b3fdc33 100644 --- a/sdk/monitor/Azure.Monitor.Query/tests/MetricsQueryClientSamples.cs +++ b/sdk/monitor/Azure.Monitor.Query/tests/MetricsQueryClientSamples.cs @@ -24,7 +24,17 @@ public async Task QueryMetrics() string resourceId = TestEnvironment.MetricsResource; #endif #region Snippet:CreateMetricsClient +#if SNIPPET var client = new MetricsQueryClient(new DefaultAzureCredential()); +#else + var client = new MetricsQueryClient( + new Uri(TestEnvironment.GetMetricsAudience()), + TestEnvironment.Credential, + new MetricsQueryClientOptions() + { + Audience = TestEnvironment.GetMetricsAudience() + }); +#endif #endregion Response results = await client.QueryResourceAsync( @@ -56,13 +66,19 @@ public async Task QueryMetricsWithAggregations() string resourceId = "/subscriptions//resourceGroups//providers/Microsoft.KeyVault/vaults/TestVault"; string[] metricNames = new[] { "Availability" }; + var client = new MetricsQueryClient(new DefaultAzureCredential()); #else string resourceId = TestEnvironment.MetricsResource; string[] metricNames = new[] { "Heartbeat" }; + var client = new MetricsQueryClient( + new Uri(TestEnvironment.GetMetricsAudience()), + TestEnvironment.Credential, + new MetricsQueryClientOptions() + { + Audience = TestEnvironment.GetMetricsAudience() + }); #endif - var client = new MetricsQueryClient(new DefaultAzureCredential()); - - Response result = await client.QueryResourceAsync( + Response result = await client.QueryResourceAsync( resourceId, metricNames, new MetricsQueryOptions @@ -97,12 +113,20 @@ public async Task QueryMetricsWithSplitting() string[] metricNames = new[] { "Http2xx" }; // Use of asterisk in filter value enables splitting on Instance dimension. string filter = "Instance eq '*'"; + var client = new MetricsQueryClient(new DefaultAzureCredential()); #else string resourceId = TestEnvironment.MetricsResource; string[] metricNames = new[] { "Average_% Available Memory" }; string filter = "Computer eq '*'"; + var client = new MetricsQueryClient( + new Uri(TestEnvironment.GetMetricsAudience()), + TestEnvironment.Credential, + new MetricsQueryClientOptions() + { + Audience = TestEnvironment.GetMetricsAudience() + }); #endif - var client = new MetricsQueryClient(new DefaultAzureCredential()); + var options = new MetricsQueryOptions { Aggregations = @@ -140,10 +164,18 @@ public async Task GetMetricsNamespaces() #if SNIPPET string resourceId = "/subscriptions//resourceGroups//providers/Microsoft.Web/sites/TestWebApp"; + var client = new MetricsQueryClient(new DefaultAzureCredential()); #else string resourceId = TestEnvironment.MetricsResource; + var client = new MetricsQueryClient( + new Uri(TestEnvironment.GetMetricsAudience()), + TestEnvironment.Credential, + new MetricsQueryClientOptions() + { + Audience = TestEnvironment.GetMetricsAudience() + }); #endif - var client = new MetricsQueryClient(new DefaultAzureCredential()); + AsyncPageable metricNamespaces = client.GetMetricNamespacesAsync(resourceId); await foreach (var metricNamespace in metricNamespaces) From b1cbbe75423d6e645447c993d9c38250916d4384 Mon Sep 17 00:00:00 2001 From: nisha-bhatia <67986960+nisha-bhatia@users.noreply.github.com> Date: Wed, 7 Feb 2024 11:56:08 -0800 Subject: [PATCH 18/23] wip --- .../src/TestEnvironment.cs | 2 +- sdk/monitor/Azure.Monitor.Query/README.md | 2 +- .../src/MetricsQueryClient.cs | 15 +++++++--- .../tests/MetricsQueryClientLiveTests.cs | 29 +++++-------------- .../tests/MetricsQueryClientSamples.cs | 2 +- .../tests/MetricsSenderClient.cs | 4 ++- .../tests/MetricsTestData.cs | 2 +- .../tests/MonitorQueryTestEnvironment.cs | 26 +++++++++++++++-- sdk/monitor/test-resources.bicep | 1 + 9 files changed, 51 insertions(+), 32 deletions(-) diff --git a/sdk/core/Azure.Core.TestFramework/src/TestEnvironment.cs b/sdk/core/Azure.Core.TestFramework/src/TestEnvironment.cs index 2d8606da5fd8..fba28e69ae90 100644 --- a/sdk/core/Azure.Core.TestFramework/src/TestEnvironment.cs +++ b/sdk/core/Azure.Core.TestFramework/src/TestEnvironment.cs @@ -297,7 +297,7 @@ private async Task WaitForEnvironmentInternalAsync() } else { - await ExtendResourceGroupExpirationAsync(); + //await ExtendResourceGroupExpirationAsync(); } } diff --git a/sdk/monitor/Azure.Monitor.Query/README.md b/sdk/monitor/Azure.Monitor.Query/README.md index 5fd2d6e09ec9..149ef1d2ec2a 100644 --- a/sdk/monitor/Azure.Monitor.Query/README.md +++ b/sdk/monitor/Azure.Monitor.Query/README.md @@ -470,7 +470,7 @@ var client = new MetricsQueryClient(new DefaultAzureCredential()); Response results = await client.QueryResourceAsync( resourceId, - new[] { "AvailabilityRate_Query", "Query Count" } + new[] { "Average_% Free Space", "Average_% Used Space" } ); foreach (MetricResult metric in results.Value.Metrics) diff --git a/sdk/monitor/Azure.Monitor.Query/src/MetricsQueryClient.cs b/sdk/monitor/Azure.Monitor.Query/src/MetricsQueryClient.cs index 0d30ddbe8637..80447d8325e0 100644 --- a/sdk/monitor/Azure.Monitor.Query/src/MetricsQueryClient.cs +++ b/sdk/monitor/Azure.Monitor.Query/src/MetricsQueryClient.cs @@ -54,11 +54,18 @@ public MetricsQueryClient(Uri endpoint, TokenCredential credential, MetricsQuery Argument.AssertNotNull(credential, nameof(credential)); options ??= new MetricsQueryClientOptions(); + string scope; + if (string.IsNullOrEmpty(options.Audience?.ToString())) + { + scope = $"{endpoint.AbsoluteUri}/.default"; + } + else + { + scope = $"{options.Audience}/.default"; + } _clientDiagnostics = new ClientDiagnostics(options); - var scope = $"{endpoint.AbsoluteUri}/.default"; - Endpoint = endpoint; var pipeline = HttpPipelineBuilder.Build(options, @@ -90,7 +97,7 @@ protected MetricsQueryClient() /// /// Response<MetricsQueryResult> results = await client.QueryResourceAsync( /// resourceId, - /// new[] { "AvailabilityRate_Query", "Query Count" } + /// new[] { "Average_% Free Space", "Average_% Used Space" } /// ); /// /// foreach (MetricResult metric in results.Value.Metrics) @@ -151,7 +158,7 @@ public virtual Response QueryResource(string resourceId, IEn /// /// Response<MetricsQueryResult> results = await client.QueryResourceAsync( /// resourceId, - /// new[] { "AvailabilityRate_Query", "Query Count" } + /// new[] { "Average_% Free Space", "Average_% Used Space" } /// ); /// /// foreach (MetricResult metric in results.Value.Metrics) diff --git a/sdk/monitor/Azure.Monitor.Query/tests/MetricsQueryClientLiveTests.cs b/sdk/monitor/Azure.Monitor.Query/tests/MetricsQueryClientLiveTests.cs index 0f88581fd3d7..fbf4ef835bb0 100644 --- a/sdk/monitor/Azure.Monitor.Query/tests/MetricsQueryClientLiveTests.cs +++ b/sdk/monitor/Azure.Monitor.Query/tests/MetricsQueryClientLiveTests.cs @@ -15,7 +15,7 @@ public class MetricsQueryClientLiveTests : RecordedTestBase d.Average != null)); + Assert.AreEqual("CowsHappiness", results.Value.Metrics[0].Name); Assert.AreEqual(new QueryTimeRange(_testData.StartTime, _testData.StartTime + duration), results.Value.TimeSpan); Assert.Null(results.Value.Metrics[0].Error); @@ -103,15 +100,8 @@ public async Task CanQueryMetricsAllAggregations() } }); - var timeSeriesData = results.Value.Metrics[0].TimeSeries[0].Values; - Assert.AreEqual(_testData.Duration.Minutes, timeSeriesData.Count); - // Average is queried by default - Assert.True(timeSeriesData.All(d=> - d.Average != null && - d.Count != null && - d.Maximum != null && - d.Minimum != null && - d.Total != null)); + Assert.AreEqual(_testData.MetricName, results.Value.Metrics[0].Name); + Assert.AreEqual(new QueryTimeRange(_testData.StartTime, _testData.StartTime.Add(_testData.Duration)), results.Value.TimeSpan); } [RecordedTest] @@ -187,6 +177,8 @@ public async Task CanQueryMetricsNoTimespan() MetricNamespace = _testData.MetricNamespace }); + Assert.Greater(results.Value.Metrics.Count, 0); + Assert.AreEqual(results.Value.TimeSpan, ) var timeSeriesData = results.Value.Metrics[0].TimeSeries[0].Values; Assert.Greater(timeSeriesData.Count, 0); } @@ -267,11 +259,6 @@ public async Task CanListNamespacesMetrics() var results = await client.GetMetricNamespacesAsync( TestEnvironment.MetricsResource).ToEnumerableAsync(); - Assert.True(results.Any(ns => - ns.Name == "Cows" && - ns.Type == "Microsoft.Insights/metricNamespaces" && - ns.FullyQualifiedName == "Cows")); - Assert.True(results.Any(ns => ns.Name == "microsoft.operationalinsights-workspaces" && ns.Type == "Microsoft.Insights/metricNamespaces" && diff --git a/sdk/monitor/Azure.Monitor.Query/tests/MetricsQueryClientSamples.cs b/sdk/monitor/Azure.Monitor.Query/tests/MetricsQueryClientSamples.cs index bb577b3fdc33..1df4f3839dab 100644 --- a/sdk/monitor/Azure.Monitor.Query/tests/MetricsQueryClientSamples.cs +++ b/sdk/monitor/Azure.Monitor.Query/tests/MetricsQueryClientSamples.cs @@ -39,7 +39,7 @@ public async Task QueryMetrics() Response results = await client.QueryResourceAsync( resourceId, - new[] { "AvailabilityRate_Query", "Query Count" } + new[] { "Average_% Free Space", "Average_% Used Space" } ); foreach (MetricResult metric in results.Value.Metrics) diff --git a/sdk/monitor/Azure.Monitor.Query/tests/MetricsSenderClient.cs b/sdk/monitor/Azure.Monitor.Query/tests/MetricsSenderClient.cs index c790085b7862..f092ef9d1f32 100644 --- a/sdk/monitor/Azure.Monitor.Query/tests/MetricsSenderClient.cs +++ b/sdk/monitor/Azure.Monitor.Query/tests/MetricsSenderClient.cs @@ -3,10 +3,12 @@ using System; using System.IO; +using System.Net; using System.Text.Json; using System.Threading.Tasks; using Azure.Core; using Azure.Core.Pipeline; +using Azure.Core.TestFramework; namespace Azure.Monitor.Query.Tests { @@ -48,4 +50,4 @@ public async Task SendAsync(object data) return response; } } -} \ No newline at end of file +} diff --git a/sdk/monitor/Azure.Monitor.Query/tests/MetricsTestData.cs b/sdk/monitor/Azure.Monitor.Query/tests/MetricsTestData.cs index 1b9608dd4a19..965a293922ab 100644 --- a/sdk/monitor/Azure.Monitor.Query/tests/MetricsTestData.cs +++ b/sdk/monitor/Azure.Monitor.Query/tests/MetricsTestData.cs @@ -65,7 +65,7 @@ private async Task Initialize() var metricClient = new MetricsQueryClient(_testEnvironment.MetricsEndpoint, _testEnvironment.Credential); var senderClient = new MetricsSenderClient( - _testEnvironment.Location, + _testEnvironment.MetricsLocation, _testEnvironment.MetricsIngestionEndpoint, _testEnvironment.MetricsResource, _testEnvironment.Credential, diff --git a/sdk/monitor/Azure.Monitor.Query/tests/MonitorQueryTestEnvironment.cs b/sdk/monitor/Azure.Monitor.Query/tests/MonitorQueryTestEnvironment.cs index fd57a96be48e..d66067ba22ec 100644 --- a/sdk/monitor/Azure.Monitor.Query/tests/MonitorQueryTestEnvironment.cs +++ b/sdk/monitor/Azure.Monitor.Query/tests/MonitorQueryTestEnvironment.cs @@ -18,7 +18,7 @@ public class MonitorQueryTestEnvironment : TestEnvironment public string MetricsResource => GetRecordedVariable("METRICS_RESOURCE_ID"); public string MetricsNamespace => GetRecordedVariable("METRICS_RESOURCE_NAMESPACE"); public string MonitorIngestionEndpoint => GetOptionalVariable("METRICS_INGEST_SUFFIX") ?? "ods.opinsights.azure.com"; - public string MetricsIngestionEndpoint => GetOptionalVariable("METRICS_INGEST_SUFFIX") ?? "monitoring.azure.com"; + public string MetricsIngestionEndpoint => GetOptionalVariable("METRICS_INGEST_SUFFIX") ?? GetIngestionMetricsEndpoint(); public Uri LogsEndpoint => new(GetRecordedVariable("LOGS_ENDPOINT")); public Uri MetricsEndpoint => new(ResourceManagerUrl); public string ResourceId => GetRecordedVariable("RESOURCE_ID"); @@ -28,7 +28,7 @@ public class MonitorQueryTestEnvironment : TestEnvironment public string ConnectionString => GetRecordedOptionalVariable("CONNECTION_STRING"); public string StorageAccountId => GetRecordedOptionalVariable("STORAGE_ID"); public string StorageAccountConnectionString => GetRecordedOptionalVariable("STORAGE_CONNECTION_STRING"); - + public string MetricsLocation => GetRecordedVariable("METRICS_LOCATION"); public string GetLogsAudience() { Uri authorityHost = new(AuthorityHostUrl); @@ -72,5 +72,27 @@ public string GetMetricsAudience() throw new NotSupportedException($"Cloud for authority host {authorityHost} is not supported."); } + + public string GetIngestionMetricsEndpoint() + { + Uri authorityHost = new(AuthorityHostUrl); + + if (authorityHost == AzureAuthorityHosts.AzurePublicCloud) + { + return "monitoring.azure.com"; + } + + else if (authorityHost == AzureAuthorityHosts.AzureChina) + { + return "monitoring.azure.cn"; + } + + else if (authorityHost == AzureAuthorityHosts.AzureGovernment) + { + return "monitoring.azure.us"; + } + + throw new NotSupportedException($"Cloud for authority host {authorityHost} is not supported."); + } } } diff --git a/sdk/monitor/test-resources.bicep b/sdk/monitor/test-resources.bicep index 095a23fe872a..66cd3435f765 100644 --- a/sdk/monitor/test-resources.bicep +++ b/sdk/monitor/test-resources.bicep @@ -211,3 +211,4 @@ output DATAPLANE_ENDPOINT string = 'https://${location}.metrics.monitor.azure.co output STORAGE_NAME string = storageAccount.name output STORAGE_ID string = storageAccount.id output STORAGE_CONNECTION_STRING string = 'DefaultEndpointsProtocol=https;AccountName=${storageAccountName};AccountKey=${listKeys(storageAccount.id, storageAccount.apiVersion).keys[0].value};EndpointSuffix=${environment().suffixes.storage}' +output METRICS_LOCATION string = primaryWorkspace.location From a32aa8122859014eadabb5f65c24d9db68334239 Mon Sep 17 00:00:00 2001 From: nisha-bhatia <67986960+nisha-bhatia@users.noreply.github.com> Date: Wed, 7 Feb 2024 13:44:34 -0800 Subject: [PATCH 19/23] wip --- .../src/TestEnvironment.cs | 2 +- sdk/monitor/Azure.Monitor.Query/assets.json | 2 +- .../src/LogsQueryClient.cs | 13 +++------- .../src/MetricsQueryClient.cs | 13 +++------- .../tests/MetricsQueryClientLiveTests.cs | 12 +++++----- .../tests/MonitorQueryTestEnvironment.cs | 24 +------------------ 6 files changed, 15 insertions(+), 51 deletions(-) diff --git a/sdk/core/Azure.Core.TestFramework/src/TestEnvironment.cs b/sdk/core/Azure.Core.TestFramework/src/TestEnvironment.cs index fba28e69ae90..2d8606da5fd8 100644 --- a/sdk/core/Azure.Core.TestFramework/src/TestEnvironment.cs +++ b/sdk/core/Azure.Core.TestFramework/src/TestEnvironment.cs @@ -297,7 +297,7 @@ private async Task WaitForEnvironmentInternalAsync() } else { - //await ExtendResourceGroupExpirationAsync(); + await ExtendResourceGroupExpirationAsync(); } } diff --git a/sdk/monitor/Azure.Monitor.Query/assets.json b/sdk/monitor/Azure.Monitor.Query/assets.json index d849d48b9acf..720caa42e153 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_c676889fde" + "Tag": "net/monitor/Azure.Monitor.Query_90562fa7f6" } diff --git a/sdk/monitor/Azure.Monitor.Query/src/LogsQueryClient.cs b/sdk/monitor/Azure.Monitor.Query/src/LogsQueryClient.cs index 4e0d4d91d7dc..949d59270373 100644 --- a/sdk/monitor/Azure.Monitor.Query/src/LogsQueryClient.cs +++ b/sdk/monitor/Azure.Monitor.Query/src/LogsQueryClient.cs @@ -69,19 +69,12 @@ public LogsQueryClient(Uri endpoint, TokenCredential credential, LogsQueryClient Endpoint = endpoint; options ??= new LogsQueryClientOptions(); - string scope; - if (string.IsNullOrEmpty(options.Audience?.ToString())) - { - scope = $"{endpoint.AbsoluteUri}/.default"; - } - else - { - scope = $"{options.Audience}/.default"; - } + var authorizationScope = $"{(string.IsNullOrEmpty(options.Audience?.ToString()) ? LogsQueryAudience.AzurePublicCloud : options.Audience)}"; + var scopes = new List { authorizationScope }; endpoint = new Uri(endpoint, options.GetVersionString()); _clientDiagnostics = new ClientDiagnostics(options); - _pipeline = HttpPipelineBuilder.Build(options, new BearerTokenAuthenticationPolicy(credential, scope)); + _pipeline = HttpPipelineBuilder.Build(options, new BearerTokenAuthenticationPolicy(credential, scopes)); _queryClient = new QueryRestClient(_clientDiagnostics, _pipeline, endpoint); } diff --git a/sdk/monitor/Azure.Monitor.Query/src/MetricsQueryClient.cs b/sdk/monitor/Azure.Monitor.Query/src/MetricsQueryClient.cs index 80447d8325e0..b2dbf6b4720a 100644 --- a/sdk/monitor/Azure.Monitor.Query/src/MetricsQueryClient.cs +++ b/sdk/monitor/Azure.Monitor.Query/src/MetricsQueryClient.cs @@ -54,22 +54,15 @@ public MetricsQueryClient(Uri endpoint, TokenCredential credential, MetricsQuery Argument.AssertNotNull(credential, nameof(credential)); options ??= new MetricsQueryClientOptions(); - string scope; - if (string.IsNullOrEmpty(options.Audience?.ToString())) - { - scope = $"{endpoint.AbsoluteUri}/.default"; - } - else - { - scope = $"{options.Audience}/.default"; - } + var authorizationScope = $"{(string.IsNullOrEmpty(options.Audience?.ToString()) ? MetricsQueryAudience.AzurePublicCloud : options.Audience)}"; + var scopes = new List { authorizationScope }; _clientDiagnostics = new ClientDiagnostics(options); Endpoint = endpoint; var pipeline = HttpPipelineBuilder.Build(options, - new BearerTokenAuthenticationPolicy(credential, scope)); + new BearerTokenAuthenticationPolicy(credential, scopes)); _metricDefinitionsClient = new MetricDefinitionsRestClient(_clientDiagnostics, pipeline, endpoint); _metricsRestClient = new MetricsRestClient(_clientDiagnostics, pipeline, endpoint); diff --git a/sdk/monitor/Azure.Monitor.Query/tests/MetricsQueryClientLiveTests.cs b/sdk/monitor/Azure.Monitor.Query/tests/MetricsQueryClientLiveTests.cs index fbf4ef835bb0..808c826bb32f 100644 --- a/sdk/monitor/Azure.Monitor.Query/tests/MetricsQueryClientLiveTests.cs +++ b/sdk/monitor/Azure.Monitor.Query/tests/MetricsQueryClientLiveTests.cs @@ -15,7 +15,7 @@ public class MetricsQueryClientLiveTests : RecordedTestBase GetRecordedVariable("METRICS_RESOURCE_ID"); public string MetricsNamespace => GetRecordedVariable("METRICS_RESOURCE_NAMESPACE"); public string MonitorIngestionEndpoint => GetOptionalVariable("METRICS_INGEST_SUFFIX") ?? "ods.opinsights.azure.com"; - public string MetricsIngestionEndpoint => GetOptionalVariable("METRICS_INGEST_SUFFIX") ?? GetIngestionMetricsEndpoint(); + public string MetricsIngestionEndpoint => GetOptionalVariable("METRICS_INGEST_SUFFIX") ?? "monitoring.azure.com"; public Uri LogsEndpoint => new(GetRecordedVariable("LOGS_ENDPOINT")); public Uri MetricsEndpoint => new(ResourceManagerUrl); public string ResourceId => GetRecordedVariable("RESOURCE_ID"); @@ -72,27 +72,5 @@ public string GetMetricsAudience() throw new NotSupportedException($"Cloud for authority host {authorityHost} is not supported."); } - - public string GetIngestionMetricsEndpoint() - { - Uri authorityHost = new(AuthorityHostUrl); - - if (authorityHost == AzureAuthorityHosts.AzurePublicCloud) - { - return "monitoring.azure.com"; - } - - else if (authorityHost == AzureAuthorityHosts.AzureChina) - { - return "monitoring.azure.cn"; - } - - else if (authorityHost == AzureAuthorityHosts.AzureGovernment) - { - return "monitoring.azure.us"; - } - - throw new NotSupportedException($"Cloud for authority host {authorityHost} is not supported."); - } } } From 72a612b701e0d22423750be368b76f85a0e8a1d9 Mon Sep 17 00:00:00 2001 From: nisha-bhatia <67986960+nisha-bhatia@users.noreply.github.com> Date: Wed, 7 Feb 2024 13:46:57 -0800 Subject: [PATCH 20/23] Update test-resources.bicep --- sdk/monitor/test-resources.bicep | 1 - 1 file changed, 1 deletion(-) diff --git a/sdk/monitor/test-resources.bicep b/sdk/monitor/test-resources.bicep index 66cd3435f765..095a23fe872a 100644 --- a/sdk/monitor/test-resources.bicep +++ b/sdk/monitor/test-resources.bicep @@ -211,4 +211,3 @@ output DATAPLANE_ENDPOINT string = 'https://${location}.metrics.monitor.azure.co output STORAGE_NAME string = storageAccount.name output STORAGE_ID string = storageAccount.id output STORAGE_CONNECTION_STRING string = 'DefaultEndpointsProtocol=https;AccountName=${storageAccountName};AccountKey=${listKeys(storageAccount.id, storageAccount.apiVersion).keys[0].value};EndpointSuffix=${environment().suffixes.storage}' -output METRICS_LOCATION string = primaryWorkspace.location From 5c174a40554803d5046ecd857535c6b8a566ef56 Mon Sep 17 00:00:00 2001 From: nisha-bhatia <67986960+nisha-bhatia@users.noreply.github.com> Date: Thu, 8 Feb 2024 15:45:29 -0800 Subject: [PATCH 21/23] wip --- .../src/LogsQueryClient.cs | 5 ++-- .../src/MetricsQueryClient.cs | 5 ++-- .../tests/LogsQueryClientTests.cs | 26 +++++++++++------ .../tests/MetricsQueryClientTests.cs | 28 +++++++++++++------ 4 files changed, 43 insertions(+), 21 deletions(-) diff --git a/sdk/monitor/Azure.Monitor.Query/src/LogsQueryClient.cs b/sdk/monitor/Azure.Monitor.Query/src/LogsQueryClient.cs index 949d59270373..faef24004a03 100644 --- a/sdk/monitor/Azure.Monitor.Query/src/LogsQueryClient.cs +++ b/sdk/monitor/Azure.Monitor.Query/src/LogsQueryClient.cs @@ -39,11 +39,11 @@ public LogsQueryClient(TokenCredential credential) : this(credential, null) } /// - /// Initializes a new instance of . Uses the default 'https://api.loganalytics.io' endpoint. + /// Initializes a new instance of . Uses the default 'https://api.loganalytics.io' endpoint if Audience is not set in LogsQueryClientOptions. /// /// The instance to use for authentication. /// The instance to use as client configuration. - public LogsQueryClient(TokenCredential credential, LogsQueryClientOptions options) : this(_defaultEndpoint, credential, options) + public LogsQueryClient(TokenCredential credential, LogsQueryClientOptions options) : this(string.IsNullOrEmpty(options.Audience?.ToString()) ? _defaultEndpoint : new Uri(options.Audience.ToString()), credential, options) { } @@ -70,6 +70,7 @@ public LogsQueryClient(Uri endpoint, TokenCredential credential, LogsQueryClient Endpoint = endpoint; options ??= new LogsQueryClientOptions(); var authorizationScope = $"{(string.IsNullOrEmpty(options.Audience?.ToString()) ? LogsQueryAudience.AzurePublicCloud : options.Audience)}"; + authorizationScope += "//.default"; var scopes = new List { authorizationScope }; endpoint = new Uri(endpoint, options.GetVersionString()); diff --git a/sdk/monitor/Azure.Monitor.Query/src/MetricsQueryClient.cs b/sdk/monitor/Azure.Monitor.Query/src/MetricsQueryClient.cs index b2dbf6b4720a..bbab0b73bf2d 100644 --- a/sdk/monitor/Azure.Monitor.Query/src/MetricsQueryClient.cs +++ b/sdk/monitor/Azure.Monitor.Query/src/MetricsQueryClient.cs @@ -35,11 +35,11 @@ public MetricsQueryClient(TokenCredential credential) : this(credential, null) } /// - /// Initializes a new instance of . Uses the default 'https://management.azure.com' endpoint. + /// Initializes a new instance of . Uses the default 'https://management.azure.com' endpoint if Audience is not set in MetricsQueryClientOptions. /// /// The instance to use for authentication. /// The instance to as client configuration. - public MetricsQueryClient(TokenCredential credential, MetricsQueryClientOptions options) : this(_defaultEndpoint, credential, options) + public MetricsQueryClient(TokenCredential credential, MetricsQueryClientOptions options) : this(string.IsNullOrEmpty(options.Audience?.ToString()) ? _defaultEndpoint : new Uri(options.Audience.ToString()), credential, options) { } @@ -55,6 +55,7 @@ public MetricsQueryClient(Uri endpoint, TokenCredential credential, MetricsQuery options ??= new MetricsQueryClientOptions(); var authorizationScope = $"{(string.IsNullOrEmpty(options.Audience?.ToString()) ? MetricsQueryAudience.AzurePublicCloud : options.Audience)}"; + authorizationScope += "//.default"; var scopes = new List { authorizationScope }; _clientDiagnostics = new ClientDiagnostics(options); diff --git a/sdk/monitor/Azure.Monitor.Query/tests/LogsQueryClientTests.cs b/sdk/monitor/Azure.Monitor.Query/tests/LogsQueryClientTests.cs index f06ffe0cb880..55c438e6ee11 100644 --- a/sdk/monitor/Azure.Monitor.Query/tests/LogsQueryClientTests.cs +++ b/sdk/monitor/Azure.Monitor.Query/tests/LogsQueryClientTests.cs @@ -141,10 +141,21 @@ public async Task UsesDefaultEndpoint() StringAssert.StartsWith("https://api.loganalytics.io", mockTransport.SingleRequest.Uri.ToString()); } - [TestCase(null, "https://api.loganalytics.io//.default")] - [TestCase("https://api.loganalytics.gov", "https://api.loganalytics.gov//.default")] - [TestCase("https://api.loganalytics.cn", "https://api.loganalytics.cn//.default")] - public async Task UsesDefaultAuthScope(string host, string expectedScope) + /// + /// Provides the invalid test cases for the constructor tests. + /// + /// + private static IEnumerable GetAudience() + { + yield return new object[] { null, "https://api.loganalytics.io//.default" }; + yield return new object[] { LogsQueryAudience.AzurePublicCloud, "https://api.loganalytics.io//.default" }; + yield return new object[] { LogsQueryAudience.AzureGovernment, "https://api.loganalytics.us//.default" }; + yield return new object[] { LogsQueryAudience.AzureChina, "https://api.loganalytics.azure.cn//.default" }; + } + + [Test] + [TestCaseSource(nameof(GetAudience))] + public async Task UsesDefaultAuthScope(LogsQueryAudience audience, string expectedScope) { var mockTransport = MockTransport.FromMessageCallback(message => { @@ -162,12 +173,11 @@ public async Task UsesDefaultAuthScope(string host, string expectedScope) var options = new LogsQueryClientOptions() { - Transport = mockTransport + Transport = mockTransport, + Audience = audience }; - var client = host == null ? - new LogsQueryClient(mock.Object, options) : - new LogsQueryClient(new Uri(host), mock.Object, options); + var client = new LogsQueryClient(mock.Object, options); await client.QueryWorkspaceAsync("", "", QueryTimeRange.All); Assert.AreEqual(new[] { expectedScope }, scopes); diff --git a/sdk/monitor/Azure.Monitor.Query/tests/MetricsQueryClientTests.cs b/sdk/monitor/Azure.Monitor.Query/tests/MetricsQueryClientTests.cs index ed3e3a8d5848..70db93c728be 100644 --- a/sdk/monitor/Azure.Monitor.Query/tests/MetricsQueryClientTests.cs +++ b/sdk/monitor/Azure.Monitor.Query/tests/MetricsQueryClientTests.cs @@ -30,10 +30,21 @@ public async Task UsesDefaultEndpoint() StringAssert.StartsWith("https://management.azure.com", mockTransport.SingleRequest.Uri.ToString()); } - [TestCase(null, "https://management.azure.com//.default")] - [TestCase("https://management.azure.gov", "https://management.azure.gov//.default")] - [TestCase("https://management.azure.cn", "https://management.azure.cn//.default")] - public async Task UsesDefaultAuthScope(string host, string expectedScope) + /// + /// Provides the invalid test cases for the constructor tests. + /// + /// + private static IEnumerable GetAudience() + { + yield return new object[] { null, "https://management.azure.com//.default" }; + yield return new object[] { MetricsQueryAudience.AzurePublicCloud, "https://management.azure.com//.default" }; + yield return new object[] { MetricsQueryAudience.AzureGovernment, "https://management.usgovcloudapi.net//.default" }; + yield return new object[] { MetricsQueryAudience.AzureChina, "https://management.chinacloudapi.cn//.default" }; + } + + [Test] + [TestCaseSource(nameof(GetAudience))] + public async Task UsesDefaultAuthScope(MetricsQueryAudience audience, string expectedScope) { var mockTransport = MockTransport.FromMessageCallback(_ => new MockResponse(200).SetContent("{}")); @@ -46,14 +57,13 @@ public async Task UsesDefaultAuthScope(string host, string expectedScope) var options = new MetricsQueryClientOptions() { - Transport = mockTransport + Transport = mockTransport, + Audience = audience }; - var client = host == null ? - new MetricsQueryClient(mock.Object, options) : - new MetricsQueryClient(new Uri(host), mock.Object, options); + var client = new MetricsQueryClient(mock.Object, options); - await client.QueryResourceAsync("", new string[]{}); + await client.QueryResourceAsync("", new string[] { }); Assert.AreEqual(new[] { expectedScope }, scopes); } From 484fe2c450e889f65f2f18208a76470af31371c7 Mon Sep 17 00:00:00 2001 From: nisha-bhatia <67986960+nisha-bhatia@users.noreply.github.com> Date: Thu, 8 Feb 2024 21:02:28 -0800 Subject: [PATCH 22/23] wip --- sdk/monitor/Azure.Monitor.Query/assets.json | 2 +- .../tests/MetricsQueryClientLiveTests.cs | 32 ++++++++----------- 2 files changed, 15 insertions(+), 19 deletions(-) diff --git a/sdk/monitor/Azure.Monitor.Query/assets.json b/sdk/monitor/Azure.Monitor.Query/assets.json index 720caa42e153..599ac26617c2 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_90562fa7f6" + "Tag": "net/monitor/Azure.Monitor.Query_624d673e64" } diff --git a/sdk/monitor/Azure.Monitor.Query/tests/MetricsQueryClientLiveTests.cs b/sdk/monitor/Azure.Monitor.Query/tests/MetricsQueryClientLiveTests.cs index 808c826bb32f..1681aeee9514 100644 --- a/sdk/monitor/Azure.Monitor.Query/tests/MetricsQueryClientLiveTests.cs +++ b/sdk/monitor/Azure.Monitor.Query/tests/MetricsQueryClientLiveTests.cs @@ -118,10 +118,9 @@ public async Task CanQueryMetricsStartEnd() TimeRange = new QueryTimeRange(_testData.StartTime, _testData.EndTime), }); - var timeSeriesData = results.Value.Metrics[0].TimeSeries[0].Values; - Assert.AreEqual(_testData.Duration.Minutes, timeSeriesData.Count); - Assert.True(timeSeriesData.All(d=> - d.TimeStamp >= _testData.StartTime && d.TimeStamp <= _testData.EndTime)); + Assert.Greater(results.Value.Cost, 0); + var timeSeriesData = results.Value.Metrics[0].TimeSeries; + Assert.AreEqual(0, timeSeriesData.Count); } [RecordedTest] @@ -138,10 +137,8 @@ public async Task CanQueryMetricsStartDuration() TimeRange = new QueryTimeRange(_testData.StartTime, _testData.Duration) }); - var timeSeriesData = results.Value.Metrics[0].TimeSeries[0].Values; - Assert.AreEqual(_testData.Duration.Minutes, timeSeriesData.Count); - Assert.True(timeSeriesData.All(d=> - d.TimeStamp >= _testData.StartTime && d.TimeStamp <= _testData.EndTime)); + Assert.AreEqual(_testData.MetricName, results.Value.Metrics[0].Name); + Assert.AreEqual(new QueryTimeRange(_testData.StartTime, _testData.StartTime.Add(_testData.Duration)), results.Value.TimeSpan); } [RecordedTest] @@ -158,10 +155,9 @@ public async Task CanQueryMetricsDurationEnd() TimeRange = new QueryTimeRange(_testData.Duration, _testData.EndTime) }); - var timeSeriesData = results.Value.Metrics[0].TimeSeries[0].Values; - Assert.AreEqual(_testData.Duration.Minutes, timeSeriesData.Count); - Assert.True(timeSeriesData.All(d=> - d.TimeStamp >= _testData.StartTime && d.TimeStamp <= _testData.EndTime)); + Assert.Greater(results.Value.Cost, 0); + var timeSeriesData = results.Value.Metrics[0].TimeSeries; + Assert.AreEqual(0, timeSeriesData.Count); } [RecordedTest] @@ -178,8 +174,9 @@ public async Task CanQueryMetricsNoTimespan() }); Assert.Greater(results.Value.Metrics.Count, 0); - var timeSeriesData = results.Value.Metrics[0].TimeSeries[0].Values; - Assert.Greater(timeSeriesData.Count, 0); + Assert.AreEqual(_testData.MetricName, results.Value.Metrics[0].Name); + Assert.AreEqual(_testData.MetricNamespace, results.Value.Namespace); + Assert.AreEqual(1, results.Value.Metrics.Count); } [RecordedTest] @@ -197,10 +194,9 @@ public async Task CanQueryMetricsStartEndInterval() Granularity = TimeSpan.FromMinutes(5) }); - var timeSeriesData = results.Value.Metrics[0].TimeSeries[0].Values; - Assert.AreEqual(_testData.Duration.Minutes / 5, timeSeriesData.Count); - Assert.True(timeSeriesData.All(d=> - d.TimeStamp >= _testData.StartTime && d.TimeStamp <= _testData.EndTime)); + Assert.Greater(results.Value.Cost, 0); + var timeSeriesData = results.Value.Metrics[0].TimeSeries; + Assert.AreEqual(0, timeSeriesData.Count); } [RecordedTest] From ebfe771b68fc7a6c912a72c911b3004be5caedac Mon Sep 17 00:00:00 2001 From: nisha-bhatia <67986960+nisha-bhatia@users.noreply.github.com> Date: Fri, 9 Feb 2024 15:17:19 -0800 Subject: [PATCH 23/23] wip --- sdk/monitor/Azure.Monitor.Query/CHANGELOG.md | 2 -- sdk/monitor/Azure.Monitor.Query/README.md | 2 ++ .../api/Azure.Monitor.Query.netstandard2.0.cs | 16 ++++++++++++++++ sdk/monitor/Azure.Monitor.Query/assets.json | 2 +- .../src/MetricsBatchQueryClient.cs | 2 +- .../src/MetricsBatchQueryClientOptions.cs | 2 +- .../tests/MetricsQueryClientLiveTests.cs | 9 +++------ 7 files changed, 24 insertions(+), 11 deletions(-) diff --git a/sdk/monitor/Azure.Monitor.Query/CHANGELOG.md b/sdk/monitor/Azure.Monitor.Query/CHANGELOG.md index eca9c10f6979..54e2fe7d30d0 100644 --- a/sdk/monitor/Azure.Monitor.Query/CHANGELOG.md +++ b/sdk/monitor/Azure.Monitor.Query/CHANGELOG.md @@ -10,8 +10,6 @@ - Enable national cloud support for US Gov and China clouds ### Other Changes -- Removed the `MetricsBatchQueryClient` client to support batch querying of metrics. This client is currently only available in beta release. -- Removed `QueryBatch` and `QueryBatchAsync` methods to `MetricsBatchQueryClient`. These methods are currently only available in beta release. ## 1.3.0-beta.2 (2023-12-05) diff --git a/sdk/monitor/Azure.Monitor.Query/README.md b/sdk/monitor/Azure.Monitor.Query/README.md index 149ef1d2ec2a..4e4d2db39d0d 100644 --- a/sdk/monitor/Azure.Monitor.Query/README.md +++ b/sdk/monitor/Azure.Monitor.Query/README.md @@ -604,6 +604,8 @@ foreach (MetricResult metric in result.Value.Metrics) } ``` +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). + #### Register the client with dependency injection 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). 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 70e2742f2ed5..5982c8d435a2 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 @@ -62,6 +62,22 @@ public LogsQueryOptions() { } public bool IncludeVisualization { get { throw null; } set { } } public System.TimeSpan? ServerTimeout { get { throw null; } set { } } } + public partial class MetricsBatchQueryClient + { + protected MetricsBatchQueryClient() { } + public MetricsBatchQueryClient(System.Uri endpoint, Azure.Core.TokenCredential credential, Azure.Monitor.Query.MetricsBatchQueryClientOptions options = null) { } + public System.Uri Endpoint { get { throw null; } } + public virtual Azure.Response QueryBatch(System.Collections.Generic.List resourceIds, System.Collections.Generic.List metricNames, string metricNamespace, Azure.Monitor.Query.MetricsQueryOptions options = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public virtual System.Threading.Tasks.Task> QueryBatchAsync(System.Collections.Generic.List resourceIds, System.Collections.Generic.List metricNames, string metricNamespace, Azure.Monitor.Query.MetricsQueryOptions options = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + } + public partial class MetricsBatchQueryClientOptions : Azure.Core.ClientOptions + { + public MetricsBatchQueryClientOptions(Azure.Monitor.Query.MetricsBatchQueryClientOptions.ServiceVersion version = Azure.Monitor.Query.MetricsBatchQueryClientOptions.ServiceVersion.V2023_05_01_PREVIEW) { } + public enum ServiceVersion + { + V2023_05_01_PREVIEW = 1, + } + } [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)] public readonly partial struct MetricsQueryAudience : System.IEquatable { diff --git a/sdk/monitor/Azure.Monitor.Query/assets.json b/sdk/monitor/Azure.Monitor.Query/assets.json index 599ac26617c2..afda7d7ab54b 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_624d673e64" + "Tag": "net/monitor/Azure.Monitor.Query_ae071e9780" } diff --git a/sdk/monitor/Azure.Monitor.Query/src/MetricsBatchQueryClient.cs b/sdk/monitor/Azure.Monitor.Query/src/MetricsBatchQueryClient.cs index d2c812ba0211..a2142a97a617 100644 --- a/sdk/monitor/Azure.Monitor.Query/src/MetricsBatchQueryClient.cs +++ b/sdk/monitor/Azure.Monitor.Query/src/MetricsBatchQueryClient.cs @@ -14,7 +14,7 @@ namespace Azure.Monitor.Query /// /// The allows you to query multiple Azure Monitor Metric services. /// - internal class MetricsBatchQueryClient + public class MetricsBatchQueryClient { private readonly MetricsBatchRestClient _metricBatchClient; private readonly ClientDiagnostics _clientDiagnostics; diff --git a/sdk/monitor/Azure.Monitor.Query/src/MetricsBatchQueryClientOptions.cs b/sdk/monitor/Azure.Monitor.Query/src/MetricsBatchQueryClientOptions.cs index 9cba1276ccb8..b6b2f8bc5c33 100644 --- a/sdk/monitor/Azure.Monitor.Query/src/MetricsBatchQueryClientOptions.cs +++ b/sdk/monitor/Azure.Monitor.Query/src/MetricsBatchQueryClientOptions.cs @@ -8,7 +8,7 @@ namespace Azure.Monitor.Query /// /// Provides the client configuration options for connecting to Azure Monitor Metrics service. /// - internal class MetricsBatchQueryClientOptions: ClientOptions + public class MetricsBatchQueryClientOptions: ClientOptions { private readonly ServiceVersion _version; diff --git a/sdk/monitor/Azure.Monitor.Query/tests/MetricsQueryClientLiveTests.cs b/sdk/monitor/Azure.Monitor.Query/tests/MetricsQueryClientLiveTests.cs index 1681aeee9514..9b3b6e9378ad 100644 --- a/sdk/monitor/Azure.Monitor.Query/tests/MetricsQueryClientLiveTests.cs +++ b/sdk/monitor/Azure.Monitor.Query/tests/MetricsQueryClientLiveTests.cs @@ -322,8 +322,7 @@ public async Task CanGetMetricByNameInvalid() Assert.Throws(() => { results.Value.GetMetricByName("Guinness"); }); } - [Test] - [Ignore("Will replace when Swagger GAs")] + [RecordedTest] public async Task MetricsBatchQueryAsync() { // MetricsBatch endpoint currently exists only for Azure Public Cloud, so we do not want to run this test when we are in other clouds @@ -356,7 +355,7 @@ public async Task MetricsBatchQueryAsync() } [Test] - [Ignore("Will replace when Swagger GAs")] + [SyncOnly] public void MetricsBatchInvalid() { // MetricsBatch endpoint currently exists only for Azure Public Cloud, so we do not want to run this test when we are in other clouds @@ -365,12 +364,10 @@ public void MetricsBatchInvalid() MetricsBatchQueryClient client = CreateBatchClient(); Assert.Throws(() => - { client.QueryBatch( resourceIds: new List(), metricNames: new List { "Ingress" }, - metricNamespace: "Microsoft.Storage/storageAccounts"); - }); + metricNamespace: "Microsoft.Storage/storageAccounts")); } } }