@@ -29,6 +29,8 @@ public class AzureQuery(ILogger<AzureQuery> logger, TimeProvider timeProvider, T
2929 MetricsQueryClient ? client ;
3030 ArmClient ? armClient ;
3131 string ? resourceId ;
32+ ArmEnvironment armEnvironment ;
33+ MetricsQueryAudience metricsQueryAudience ;
3234
3335 protected override void InitializeCore ( ReadOnlyDictionary < string , string > settings )
3436 {
@@ -101,11 +103,11 @@ protected override void InitializeCore(ReadOnlyDictionary<string, string> settin
101103 Diagnostics . AppendLine ( "Client secret set" ) ;
102104 }
103105
104- ( ArmEnvironment armEnvironment , MetricsQueryAudience metricsQueryAudience ) environment = GetEnvironment ( ) ;
106+ ( armEnvironment , metricsQueryAudience ) = GetEnvironment ( ) ;
105107
106108 if ( managementUrl == null )
107109 {
108- Diagnostics . AppendLine ( $ "Management Url not set, defaulted to \" { environment . armEnvironment . Endpoint } \" ") ;
110+ Diagnostics . AppendLine ( $ "Management Url not set, defaulted to \" { armEnvironment . Endpoint } \" ") ;
109111 }
110112 else
111113 {
@@ -128,10 +130,10 @@ protected override void InitializeCore(ReadOnlyDictionary<string, string> settin
128130 clientCredentials = new ClientSecretCredential ( tenantId , clientId , clientSecret ) ;
129131 }
130132
131- client = new MetricsQueryClient ( environment . armEnvironment . Endpoint , clientCredentials ,
133+ client = new MetricsQueryClient ( armEnvironment . Endpoint , clientCredentials ,
132134 new MetricsQueryClientOptions
133135 {
134- Audience = environment . metricsQueryAudience ,
136+ Audience = metricsQueryAudience ,
135137 Transport = new HttpClientTransport (
136138 new HttpClient ( new SocketsHttpHandler
137139 {
@@ -141,7 +143,7 @@ protected override void InitializeCore(ReadOnlyDictionary<string, string> settin
141143 armClient = new ArmClient ( clientCredentials , subscriptionId ,
142144 new ArmClientOptions
143145 {
144- Environment = environment . armEnvironment ,
146+ Environment = armEnvironment ,
145147 Transport = new HttpClientTransport (
146148 new HttpClient ( new SocketsHttpHandler
147149 {
@@ -265,16 +267,7 @@ async Task<IReadOnlyList<MetricValue>> GetMetrics(string queueName, DateOnly sta
265267 public override async IAsyncEnumerable < IBrokerQueue > GetQueueNames (
266268 [ EnumeratorCancellation ] CancellationToken cancellationToken = default )
267269 {
268- var validNamespaces = new HashSet < string > ( StringComparer . OrdinalIgnoreCase ) { serviceBusName } ;
269-
270- var dnsLookup = new LookupClient ( ) ;
271- var dnsResult = await dnsLookup . QueryAsync ( $ "{ serviceBusName } .servicebus.windows.net", QueryType . CNAME , cancellationToken : cancellationToken ) ;
272- var domain = ( dnsResult . Answers . FirstOrDefault ( ) as CNameRecord ) ? . CanonicalName . Value ;
273- if ( domain is not null && domain . EndsWith ( ".servicebus.windows.net." ) )
274- {
275- var otherName = domain . Split ( '.' ) . First ( ) ;
276- validNamespaces . Add ( otherName ) ;
277- }
270+ var validNamespaces = await GetValidNamespaceNames ( cancellationToken ) ;
278271
279272 SubscriptionResource ? subscription = await armClient ! . GetDefaultSubscriptionAsync ( cancellationToken ) ;
280273 var namespaces =
@@ -299,6 +292,37 @@ public override async IAsyncEnumerable<IBrokerQueue> GetQueueNames(
299292 throw new Exception ( $ "Could not find a ServiceBus named \" { serviceBusName } \" ") ;
300293 }
301294
295+ async Task < HashSet < string > > GetValidNamespaceNames ( CancellationToken cancellationToken = default )
296+ {
297+ var validNamespaces = new HashSet < string > ( StringComparer . OrdinalIgnoreCase ) { serviceBusName } ;
298+
299+ // ArmEnvironment Audience Values: https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/resourcemanager/Azure.ResourceManager/src/ArmEnvironment.cs
300+ // Service Bus Domains: https://learn.microsoft.com/en-us/rest/api/servicebus/
301+ var serviceBusCloudDomain = armEnvironment . Audience switch
302+ {
303+ "https://management.usgovcloudapi.net" => "servicebus.usgovcloudapi.net" ,
304+ "https://management.microsoftazure.de" => "servicebus.cloudapi.de" ,
305+ "https://management.chinacloudapi.cn" => "servicebus.chinacloudapi.cn" ,
306+ _ => "servicebus.windows.net"
307+ } ;
308+
309+ var queryDomain = $ "{ serviceBusName } .{ serviceBusCloudDomain } ";
310+ var validDomainTail = $ ".{ serviceBusCloudDomain } .";
311+
312+ var dnsLookup = new LookupClient ( ) ;
313+ var dnsResult = await dnsLookup . QueryAsync ( queryDomain , QueryType . CNAME , cancellationToken : cancellationToken ) ;
314+ var domain = ( dnsResult . Answers . FirstOrDefault ( ) as CNameRecord ) ? . CanonicalName . Value ;
315+ if ( domain is not null && domain . EndsWith ( validDomainTail ) )
316+ {
317+ // In some cases, like private networking access, result might be something like `namespacename.private` with a dot in the middle
318+ // which is not a big deal because that will not actually match a namespace name in metrics
319+ var otherName = domain [ ..^ validDomainTail . Length ] ;
320+ validNamespaces . Add ( otherName ) ;
321+ }
322+
323+ return validNamespaces ;
324+ }
325+
302326 public override string SanitizedEndpointNameCleanser ( string endpointName ) => endpointName . ToLower ( ) ;
303327
304328 public override KeyDescriptionPair [ ] Settings =>
0 commit comments