Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@

### Other Changes

- Replaced scaling warning/error log calls with standardized `LogFunctionScaleWarning` extension method to enable Scale Controller App Insights diagnostics.

## 5.17.0 (2025-06-20)

### Other Changes
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.

using Microsoft.Azure.WebJobs.ServiceBus.Listeners;
using Microsoft.Azure.WebJobs.ServiceBus;
using System;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Azure.Messaging.ServiceBus;
using Azure.Messaging.ServiceBus.Administration;
using Microsoft.Azure.WebJobs.Extensions.ServiceBus.Config;
using Microsoft.Azure.WebJobs.Host.Scale;
using Microsoft.Azure.WebJobs.ServiceBus;
using Microsoft.Azure.WebJobs.ServiceBus.Listeners;
using Microsoft.Extensions.Logging;

namespace Microsoft.Azure.WebJobs.Extensions.ServiceBus.Listeners
{
Expand All @@ -17,6 +17,7 @@ internal class ServiceBusMetricsProvider
internal const string DeadLetterQueuePath = @"/$DeadLetterQueue";

private readonly ILogger _logger;
private readonly string _functionId;
private readonly string _entityPath;
private readonly ServiceBusEntityType _serviceBusEntityType;
private readonly Lazy<ServiceBusReceiver> _receiver;
Expand All @@ -30,12 +31,14 @@ internal class ServiceBusMetricsProvider
private DateTime _nextWarningTime;

public ServiceBusMetricsProvider(
string functionId,
string entityPath,
ServiceBusEntityType serviceBusEntityType,
Lazy<ServiceBusReceiver> receiver,
Lazy<ServiceBusAdministrationClient> administrationClient,
ILoggerFactory loggerFactory)
{
_functionId = functionId;
_serviceBusEntityType = serviceBusEntityType;
_receiver = receiver;
_entityPath = entityPath;
Expand Down Expand Up @@ -90,19 +93,20 @@ public async Task<long> GetMessageCountAsync()
catch (ServiceBusException ex)
when (ex.Reason == ServiceBusFailureReason.MessagingEntityNotFound)
{
_logger.LogWarning($"ServiceBus {entityName} '{_entityPath}' was not found.");
_logger.LogFunctionScaleWarning($"ServiceBus {entityName} '{_entityPath}' was not found.", _functionId, ex);
}
catch (UnauthorizedAccessException ex)
{
if (TimeToLogWarning())
{
_logger.LogWarning(ex, $"Connection string does not have 'Manage Claim' for {entityName} '{_entityPath}'. Unable to determine active message count.");
_logger.LogFunctionScaleWarning($"Connection string does not have 'Manage Claim' for {entityName} '{_entityPath}'. Unable to determine active message count.",
_functionId, ex);
}
throw;
}
catch (Exception e)
catch (Exception ex)
{
_logger.LogWarning(e, $"Error querying for Service Bus {entityName} scale");
_logger.LogFunctionScaleWarning($"Error querying for Service Bus {entityName} scale", _functionId, ex);
}

long totalNewMessageCount = 0;
Expand Down Expand Up @@ -163,19 +167,20 @@ public async Task<ServiceBusTriggerMetrics> GetMetricsAsync()
catch (ServiceBusException ex)
when (ex.Reason == ServiceBusFailureReason.MessagingEntityNotFound)
{
_logger.LogWarning($"ServiceBus {entityName} '{_entityPath}' was not found.");
_logger.LogFunctionScaleWarning($"ServiceBus {entityName} '{_entityPath}' was not found.", _functionId, ex);
}
catch (UnauthorizedAccessException) // When manage claim is not used on Service Bus connection string
catch (UnauthorizedAccessException ex) // When manage claim is not used on Service Bus connection string
{
if (TimeToLogWarning())
{
_logger.LogWarning($"Connection string does not have Manage claim for {entityName} '{_entityPath}'. Failed to get {entityName} description to " +
$"derive {entityName} length metrics. Falling back to using first message enqueued time.");
_logger.LogFunctionScaleWarning($"Connection string does not have Manage claim for {entityName} '{_entityPath}'. Failed to get {entityName} description to " +
$"derive {entityName} length metrics. Falling back to using first message enqueued time.",
_functionId, ex);
}
}
catch (Exception e)
catch (Exception ex)
{
_logger.LogWarning($"Error querying for Service Bus {entityName} scale status: {e.Message}");
_logger.LogFunctionScaleWarning($"Error querying for Service Bus {entityName} scale status", _functionId, ex);
}

// Path for connection strings with no manage claim
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ ILoggerFactory loggerFactory
{
_functionId = functionId;
_entityPath = entityPath;
_serviceBusMetricsProvider = new ServiceBusMetricsProvider(entityPath, entityType, receiver, administrationClient, loggerFactory);
_serviceBusMetricsProvider = new ServiceBusMetricsProvider(_functionId, entityPath, entityType, receiver, administrationClient, loggerFactory);
_scaleMonitorDescriptor = new ScaleMonitorDescriptor($"{_functionId}-ServiceBusTrigger-{_entityPath}".ToLower(CultureInfo.InvariantCulture), functionId);
_logger = loggerFactory.CreateLogger<ServiceBusScaleMonitor>();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ ILoggerFactory loggerFactory
)
{
_functionId = functionId;
_serviceBusMetricsProvider = new ServiceBusMetricsProvider(entityPath, entityType, receiver, administrationClient, loggerFactory);
_serviceBusMetricsProvider = new ServiceBusMetricsProvider(_functionId, entityPath, entityType, receiver, administrationClient, loggerFactory);
_entityPath = entityPath;
_targetScalerDescriptor = new TargetScalerDescriptor(functionId);
_logger = loggerFactory.CreateLogger<ServiceBusTargetScaler>();
Expand Down Expand Up @@ -108,7 +108,7 @@ internal TargetScalerResult GetScaleResultInternal(TargetScalerContext context,
targetWorkerCount = int.MaxValue;
}

_logger.LogInformation($"Target worker count for function '{_functionId}' is '{targetWorkerCount}' (EntityPath='{_entityPath}', MessageCount ='{messageCount}', Concurrency='{concurrency}').");
_logger.LogInformation($"Target worker count for function '{_functionId}' is '{targetWorkerCount}' (EntityPath='{_entityPath}', MessageCount='{messageCount}', Concurrency='{concurrency}').");

return new TargetScalerResult
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -471,7 +471,7 @@ public async Task GetMetrics_HandlesExceptions()
Assert.AreNotEqual(default(DateTime), metrics.Timestamp);

var warning = _loggerProvider.GetAllLogMessages().Single(p => p.Level == LogLevel.Warning);
Assert.AreEqual($"ServiceBus {_entityTypeName} '{_entityPath}' was not found.", warning.FormattedMessage);
Assert.AreEqual($"Function '{_functionId}' warning: ServiceBus {_entityTypeName} '{_entityPath}' was not found.", warning.FormattedMessage);
_loggerProvider.ClearAllLogMessages();

// UnauthorizedAccessException
Expand All @@ -488,7 +488,7 @@ public async Task GetMetrics_HandlesExceptions()
Assert.AreNotEqual(default(DateTime), metrics.Timestamp);

warning = _loggerProvider.GetAllLogMessages().Single(p => p.Level == LogLevel.Warning);
Assert.AreEqual($"Connection string does not have Manage claim for {_entityTypeName} '{_entityPath}'. Failed to get {_entityTypeName} description to derive {_entityTypeName} length metrics. " +
Assert.AreEqual($"Function '{_functionId}' warning: Connection string does not have Manage claim for {_entityTypeName} '{_entityPath}'. Failed to get {_entityTypeName} description to derive {_entityTypeName} length metrics. " +
$"Falling back to using first message enqueued time.",
warning.FormattedMessage);
_loggerProvider.ClearAllLogMessages();
Expand All @@ -507,7 +507,7 @@ public async Task GetMetrics_HandlesExceptions()
Assert.AreNotEqual(default(DateTime), metrics.Timestamp);

warning = _loggerProvider.GetAllLogMessages().Single(p => p.Level == LogLevel.Warning);
Assert.AreEqual($"Error querying for Service Bus {_entityTypeName} scale status: Uh oh", warning.FormattedMessage);
Assert.AreEqual($"Function '{_functionId}' warning: Error querying for Service Bus {_entityTypeName} scale status", warning.FormattedMessage);
}

private ServiceBusListener CreateListener(bool useDeadletterQueue = false)
Expand Down