From 42dc15e1af2ce14c315fbe9e1818fc8925fb26c2 Mon Sep 17 00:00:00 2001 From: Mike Minutillo Date: Mon, 15 Jun 2026 17:22:23 +0800 Subject: [PATCH] Switch to Azure.ResourceManager.Monitor package --- src/Directory.Packages.props | 2 +- .../AzureQuery.cs | 106 ++++-------------- .../ServiceControl.Transports.ASBS.csproj | 2 +- 3 files changed, 25 insertions(+), 85 deletions(-) diff --git a/src/Directory.Packages.props b/src/Directory.Packages.props index 7bece8037e..7bfe5365ae 100644 --- a/src/Directory.Packages.props +++ b/src/Directory.Packages.props @@ -7,7 +7,7 @@ - + diff --git a/src/ServiceControl.Transports.ASBS/AzureQuery.cs b/src/ServiceControl.Transports.ASBS/AzureQuery.cs index a8c436a725..8c57afd421 100644 --- a/src/ServiceControl.Transports.ASBS/AzureQuery.cs +++ b/src/ServiceControl.Transports.ASBS/AzureQuery.cs @@ -12,9 +12,9 @@ namespace ServiceControl.Transports.ASBS; using Azure.Core; using Azure.Core.Pipeline; using Azure.Identity; -using Azure.Monitor.Query.Metrics; -using Azure.Monitor.Query.Metrics.Models; using Azure.ResourceManager; +using Azure.ResourceManager.Monitor; +using Azure.ResourceManager.Monitor.Models; using Azure.ResourceManager.Resources; using Azure.ResourceManager.ServiceBus; using BrokerThroughput; @@ -33,8 +33,6 @@ public class AzureQuery(ILogger logger, TimeProvider timeProvider, T TokenCredential? credential; ResourceIdentifier? resourceId; ArmEnvironment armEnvironment; - MetricsClientAudience metricsClientAudience; - MetricsClient? metricsClient; protected override void InitializeCore(ReadOnlyDictionary settings) { @@ -107,7 +105,7 @@ protected override void InitializeCore(ReadOnlyDictionary settin Diagnostics.AppendLine("Client secret set"); } - (armEnvironment, metricsClientAudience) = GetEnvironment(); + armEnvironment = GetEnvironment(); if (managementUrl == null) { @@ -146,26 +144,26 @@ protected override void InitializeCore(ReadOnlyDictionary settin return; - (ArmEnvironment armEnvironment, MetricsClientAudience metricsClientAudience) GetEnvironment() + ArmEnvironment GetEnvironment() { if (managementUrlParsed == null || managementUrlParsed == ArmEnvironment.AzurePublicCloud.Endpoint) { - return (ArmEnvironment.AzurePublicCloud, MetricsClientAudience.AzurePublicCloud); + return ArmEnvironment.AzurePublicCloud; } if (managementUrlParsed == ArmEnvironment.AzureChina.Endpoint) { - return (ArmEnvironment.AzureChina, MetricsClientAudience.AzureChina); + return ArmEnvironment.AzureChina; } if (managementUrlParsed == ArmEnvironment.AzureGermany.Endpoint) { - return (ArmEnvironment.AzureGermany, MetricsClientAudience.AzurePublicCloud); + return ArmEnvironment.AzureGermany; } if (managementUrlParsed == ArmEnvironment.AzureGovernment.Endpoint) { - return (ArmEnvironment.AzureGovernment, MetricsClientAudience.AzureGovernment); + return ArmEnvironment.AzureGovernment; } string options = string.Join(", ", @@ -175,7 +173,7 @@ protected override void InitializeCore(ReadOnlyDictionary settin }.Select(environment => $"\"{environment.Endpoint}\"")); InitialiseErrors.Add($"Management url configuration is invalid, available options are {options}"); - return (ArmEnvironment.AzurePublicCloud, MetricsClientAudience.AzurePublicCloud); + return ArmEnvironment.AzurePublicCloud; } } @@ -235,85 +233,27 @@ public override async IAsyncEnumerable GetThroughputPerDay(IBro } } - async Task InitializeMetricsClient(CancellationToken cancellationToken = default) - { - if (resourceId is null || armClient is null || credential is null) - { - throw new InvalidOperationException("AzureQuery has not been initialized correctly."); - } - - var serviceBusNamespaceResource = await armClient - .GetServiceBusNamespaceResource(resourceId).GetAsync(cancellationToken) - ?? throw new Exception($"Could not find an Azure Service Bus namespace with resource Id: \"{resourceId}\""); - - // Determine the region of the namespace - var regionName = serviceBusNamespaceResource.Value.Data.Location.Name; - - // Build the regional Azure Monitor Metrics endpoint from the audience - var metricsEndpoint = BuildMetricsEndpoint(metricsClientAudience, regionName); - - // CreateNewOnMetadataUpdateAttribute the MetricsClient for this namespace - return new MetricsClient( - metricsEndpoint, - credential!, - new MetricsClientOptions - { - Audience = metricsClientAudience, - Transport = new HttpClientTransport( - new HttpClient(new SocketsHttpHandler - { - PooledConnectionIdleTimeout = TimeSpan.FromMinutes(2) - })) - }); - } - - static Uri BuildMetricsEndpoint(MetricsClientAudience audience, string regionName) - { - var region = regionName.ToLowerInvariant(); - var builder = new UriBuilder(audience.ToString()); - builder.Host = $"{region}.{builder.Host}"; - return builder.Uri; - } - - async Task> GetMetrics(string queueName, DateOnly startTime, DateOnly endTime, + async Task> GetMetrics(string queueName, DateOnly startTime, DateOnly endTime, CancellationToken cancellationToken = default) { - metricsClient ??= await InitializeMetricsClient(cancellationToken); - - var response = await metricsClient.QueryResourcesAsync( - [resourceId!], - [CompleteMessageMetricName], - MicrosoftServicebusNamespacesMetricsNamespace, - new MetricsQueryResourcesOptions - { - Filter = $"EntityName eq '{queueName}'", - TimeRange = new MetricsQueryTimeRange(startTime.ToDateTime(TimeOnly.MinValue, DateTimeKind.Utc), endTime.ToDateTime(TimeOnly.MaxValue, DateTimeKind.Utc)), - Granularity = TimeSpan.FromDays(1) - }, - cancellationToken); - - var metricQueryResult = response.Value.Values.SingleOrDefault(mr => mr.Namespace == MicrosoftServicebusNamespacesMetricsNamespace); - - if (metricQueryResult is null) + var options = new ArmResourceGetMonitorMetricsOptions() { - throw new Exception($"No metrics query results returned for {MicrosoftServicebusNamespacesMetricsNamespace}"); - } + Metricnames = CompleteMessageMetricName, + Timespan = $"{startTime.ToDateTime(TimeOnly.MinValue, DateTimeKind.Utc):o}/{endTime.ToDateTime(TimeOnly.MaxValue, DateTimeKind.Utc):o}", + Filter = $"EntityName eq '{queueName}'", + Interval = TimeSpan.FromDays(1), + Metricnamespace = MicrosoftServicebusNamespacesMetricsNamespace + }; - var metricResult = metricQueryResult.GetMetricByName(CompleteMessageMetricName); + var response = armClient.GetMonitorMetricsAsync(resourceId, options, cancellationToken); - if (metricResult.Error.Message is not null) - { - throw new Exception($"Metrics query result for '{metricResult.Name}' failed: {metricResult.Error.Message}"); - } + var metric = await response.SingleOrDefaultAsync(m => m.Name.Value == CompleteMessageMetricName, cancellationToken) + ?? throw new Exception($"Metric {CompleteMessageMetricName} not found for {queueName}"); - var timeSeries = metricResult.TimeSeries.SingleOrDefault(); - - if (timeSeries is null) - { - throw new Exception($"Metrics query result for '{metricResult.Name}' contained no time series"); - } + var timeSeries = metric.Timeseries.SingleOrDefault() + ?? throw new Exception($"Metric {metric.Name.Value} for {queueName} contains no time series"); - return timeSeries.Values.AsReadOnly(); + return timeSeries.Data; } public override async IAsyncEnumerable GetQueueNames( diff --git a/src/ServiceControl.Transports.ASBS/ServiceControl.Transports.ASBS.csproj b/src/ServiceControl.Transports.ASBS/ServiceControl.Transports.ASBS.csproj index a0404ac4a0..bd61cf9af1 100644 --- a/src/ServiceControl.Transports.ASBS/ServiceControl.Transports.ASBS.csproj +++ b/src/ServiceControl.Transports.ASBS/ServiceControl.Transports.ASBS.csproj @@ -12,7 +12,7 @@ - +