I know there is a way to determine the number of messages (or approximate number) in the Azure Queue (Store Account); however is there a way to query for the number of pending messages on an Azure Service Bus queue?
var nsmgr = Microsoft.ServiceBus.NamespaceManager.CreateFromConnectionString(connectionString);
long count = nsmgr.GetQueue(queueName).MessageCount;
It is called MessagesCountDetails.ActiveMessageCount.
It returns the number of the Active Messages in the Queue. You probably have some Dead letter messages:
var msg = Microsoft.ServiceBus.NamespaceManager.CreateFromConnectionString(Settings.Default.ConnectionString);
numofmessages.Text = msg.GetQueue(QueueName).MessageCountDetails.ActiveMessageCount.ToString();
Correct answer as of 2020+
Use of new packages as follows:
<PackageReference Include="Azure.Messaging.ServiceBus" Version="x.x.x" />
also two namespaces in the same package
using Azure.Messaging.ServiceBus;
using Azure.Messaging.ServiceBus.Administration;
and then you can use the new class ServiceBusAdministrationClient
var administrationClient = new ServiceBusAdministrationClient("connectionString");
var props = await administrationClient.GetQueueRuntimePropertiesAsync("queue");
var messageCount = props.Value.ActiveMessageCount;
have you looked at the Queue Description API? There's a property called MessageCount.
Here's the .NET SDK reference documentation page as well.
Based off what Joseph had as an answer I came up with, but for Topics and Subscriptions.
public async Task<long> GetCounterMessages()
{
var client = new ManagementClient(ServiceBusConnectionString);
var subs = await client.GetSubscriptionRuntimeInfoAsync(TopicName, SubscriptionName);
var countForThisSubscription = subs.MessageCount; //// (Comes back as a Long.)
return countForThisSubscription;
}
I ran into this same problem trying to get the count from the dead letter queue. It looks like the deadletterqueue doesn't allow you to get a count directly, you get it from the MessageCountDetails of the normal Queue.
string connectionString = ConfigurationManager.AppSettings["Microsoft.ServiceBus.Connstr"].ToString();
NamespaceManager nsmgr = Microsoft.ServiceBus.NamespaceManager.CreateFromConnectionString(connectionString);
return nsmgr.GetQueue(QueueName).MessageCountDetails.DeadLetterMessageCount;
Here's a PowerShell example to continually eyeball the queue length as used in Azure Portal Cloud Shell
cd "Azure:\<MySubscription>\"
while (1) {(Get-AzureRmServiceBusQueue -ResourceGroup <myRG> -NamespaceName <myNS> -QueueName <myQueueName>).CountDetails | Select -expand ActiveMessageCount}
I've spent good 2 hours digging through docs to get that and for people using .net core and Microsoft.Azure.ServiceBus nuget package, code looks like that:
var managementClient = new ManagementClient("queue connection string"));
var runtimeInfo = await managementClient.GetQueueRuntimeInfoAsync("queueName");
var messagesInQueueCount = runtimeInfo.MessageCountDetails.ActiveMessageCount;
Aparently you get the information about all Counts(including deadletter, active, etc.) from QueueRuntimeInfo object instead of old QueueDescription object.
As per the recommendation by Microsoft, it is recommended to use Microsoft.Azure.ServiceBus in which you can easily fetch the message count by
var managementClient = new ManagementClient("connection string for queue");
var queue = await managementClient.GetQueueRuntimeInfoAsync("queue name");
var messages = queue.MessageCount;
Also..you can check the pending messages on Azure Management Portal...on the dashboard for service bus queue...under quick glance...you can see the queue length...this is the number of current/pending messages in length at the time of dashboard page load.
Related
I'm creating a ping function using azure functions that needs to check if a service bus in another region is operating so it can update the status of the whole system (two regions). What is the best way to check the status of the other service bus \ topics in the other service bus?
I found this code which I could adapt to GetTopic() instead of the Queue:
string connectionString = "connection string";
var namespaceManager = NamespaceManager.CreateFromConnectionString(connectionString);
var queueDescription = namespaceManager.GetQueue("queue name");
var status = queueDescription.Status;
However, it has been recommended that this library (WindowsAzure.ServiceBus) has been updated to Azure.Messaging.ServiceBus and I can't find a similar way to do this in the newer library.
Please point me in the right direction?
ServiceBusAdministrationClient from Package 'Azure.Messaging.ServiceBus v7.8.1' can be used.
ServiceBusAdministrationClient.GetQueueAsync returns the QueueProperties incl. Status:
https://learn.microsoft.com/en-us/dotnet/api/azure.messaging.servicebus.administration.queueproperties.status?view=azure-dotnet#azure-messaging-servicebus-administration-queueproperties-status
public Azure.Messaging.ServiceBus.Administration.EntityStatus Status { get; set; }
The current status of the queue (Enabled / Disabled).
ServiceBusAdministrationClient serviceBusAdministrationClient = new ServiceBusAdministrationClient();
var status = await serviceBusAdministrationClient.GetQueueAsync("myQueue").Status;
I am following the example in the link https://github.com/microsoftgraph/msgraph-training-changenotifications and creating and updating the notification subscription using a timer class.
[HttpGet]
public ActionResult<string> Get()
{
var graphServiceClient = GetGraphClient();
var sub = new Microsoft.Graph.Subscription();
sub.ChangeType = "updated";
sub.NotificationUrl = config.Ngrok + "/api/notifications";
sub.Resource = "/users";
sub.ExpirationDateTime = DateTime.UtcNow.AddMinutes(5);
sub.ClientState = "SecretClientState";
var newSubscription = graphServiceClient
.Subscriptions
.Request()
.AddAsync(sub).Result;
Subscriptions[newSubscription.Id] = newSubscription;
if(subscriptionTimer == null)
{
subscriptionTimer = new Timer(CheckSubscriptions, null, 5000, 15000);
}
return $"Subscribed. Id: {newSubscription.Id}, Expiration: {newSubscription.ExpirationDateTime}";
}
But I have noticed the timer does not always get triggered(eg: network related issue/ after a fresh deployment of the code).
Is there a better way to replace this timer?
I have heard about webjobs in azure, is it possible to replace this timer with azure webjobs? If so can someone point me to some documentation on how?
I noticed you're using ASPNET, if you're using the ASPNETCORE version, since 2.x, you can have background services that you could run every X hours to resubscribe (update) the subscriptions. That's what we're using (and we're on Azure). I would guess webjobs could do the trick, but I have not used them yet. You could also have an external service that calls one of your endpoints every X hours (like a CRON job) .
hope this helps!
JS
I have a listen access on Topic/Subscription for Azure Service Bus. Is there a way to verify if a subscription has a message and how many messages are there. I don't have manage connection string and I think I cannot run Service Bus Explorer. I don't intent to read the message out of the subscription.
The count of the messages in a Topic Subscription can be retrieved only using Manage Connection string. With the Listen Connection string, you cannot read the properties or count of messages.
But, you can peek the messages in the Subscription using Listen Connection string. Peeking the messages will not lock or remove the messages from the Subscription. You can peek the messages as many times as you need.
Thus, with the help of Listen Connection string, you can find the number of messages in a Subscription by peeking the messages one by one inside a while loop and add a counter inside the loop. The counter value is the number of messages inside the Subscription.
I don't intent to read the message out of the subscription.
The short answer is no. Manage access is required to get the topic or subscription message information.
If you want to get the subscription message count, you could have a try following 2 ways:
1.You have manage access, you could use the following demo code to do that.
var topicName = "topic1";
var subscriptionName = "subscription";
var address = "sb://xxx.servicebus.windows.net/"; //base address of namespace you are connecting to.
MessagingFactorySettings MsgFactorySettings = new MessagingFactorySettings
{
TokenProvider = TokenProvider.CreateSharedAccessSignatureTokenProvider("SharedAccessKeyName", "xxxxxx"),
};
MessagingFactory msgFactory = MessagingFactory.Create(address, MsgFactorySettings);
NamespaceManager manager = new NamespaceManager(msgFactory.Address,msgFactory.GetSettings().TokenProvider);
var subscriptioncDescription = manager.GetSubscription(topicName, subscriptionName);
var count = subscriptioncDescription.MessageCountDetails.ActiveMessageCount;
2.Use Azure Microsoft.Azure.Management.ServiceBus.Fluent sdk. You need to registry Azure AD application and assign corresponding role it. For more information please refer to another SO thread.
var subscriptionId = "Azure subscriptionId";
var resourceGroupName = "rgName";
var nameSpace = "tomtestsb";
var topicName = "topic1";
var subscriptionName = "subscription";
var credentials = SdkContext.AzureCredentialsFactory.FromFile(#"D:\Tom\Documents\azureCred.txt");
var client = new ServiceBusManagementClient(credentials);
client.SubscriptionId = subscriptionId;
var topic = client.Topics.GetAsync(resourceGroupName, nameSpace, topicName).Result;
var topicMessagecount = topic.CountDetails.ActiveMessageCount;
var subscription = client.Subscriptions.GetAsync(resourceGroupName, nameSpace, topicName, subscriptionName).Result;
var subscriptionMessagecount = subscription.CountDetails.ActiveMessageCount;
What's the equivalent of NamespaceManager in the new NET Standard Microsoft.Azure.ServiceBus?
I've used WindowsAzure.ServiceBus to do things like count messages in a queue ...
var namespaceManager = NamespaceManager.CreateFromConnectionString(SbConnectionString);
var count = namespaceManager.GetQueue(queueName).MessageCount;
Moving over to the new Microsoft.Azure.ServiceBus .NET Standard library, but whilst it's got classes like QueueClient and TopicClient, it's not got any NamespaceManager
How can you could do message counts in the new .NET Standard library?
To provide an update:
This is now implemented and available under the Microsoft.Azure.ServiceBus.Management; namespace.
NamespaceManager is now called ManagementClient and has (roughly) the same endpoints available.
Here's the class itself as part of the pull request to merge it into the main repository.
You can't.
The new API doesn't support reading message counts. You'd have to use Azure Monitor API to get them.
Read why that's that case and how to work with Azure Monitor in Reading Azure Service Bus Metrics.
You CAN read the queue message count:
var managementClient = new ManagementClient(connectionString);
(await managementClient.GetQueueRuntimeInfoAsync("name")).MessageCount;
using Azure.Messaging.ServiceBus.Administration;
private readonly ServiceBusAdministrationClient _serviceBusAdministrationClient;
_serviceBusAdministrationClient = new ServiceBusAdministrationClient(connectionString);
Response<QueueRuntimeProperties> queueRuntimePropertiesAsync = await _serviceBusAdministrationClient.GetQueueRuntimePropertiesAsync(name);
ActiveMessageCount = queueRuntimeProperties.ActiveMessageCount,
DeadLetterMessageCount = queueRuntimeProperties.DeadLetterMessageCount,
ScheduledMessageCount = queueRuntimeProperties.ScheduledMessageCount,
TotalMessageCount = queueRuntimeProperties.TotalMessageCount,
We have a job hosted in an azure website, the job reads entries from a topic subscription. Everything works fine when we only have one instance to host the website. Once we scale out to more than one instance we observe the message is processed as many times as instances we have. Each instance points to the same subscription. From what we read, once the item is read, it won't be available for any other process. The duplicated processing is happening inside the same instance, meaning that if we have two instances, the item is processed twice in one of the instances, it is not splitted.
What can be possible be wrong in the way we are doing things?
This is how we proceed to configure the connection to the queue, if the subscription does not exists, it is created:
var serviceBusConfig = new ServiceBusConfiguration
{
ConnectionString = transactionsBusConnectionString
};
config.UseServiceBus(serviceBusConfig);
var allRule1 = new RuleDescription
{
Name = "All",
Filter = new TrueFilter()
};
SetupSubscription(transactionsBusConnectionString,"topic1", "subscription1", allRule1);
private static void SetupSubscription(string busConnectionString, string topicNameKey, string subscriptionNameKey, RuleDescription newRule)
{
var namespaceManager =
NamespaceManager.CreateFromConnectionString(busConnectionString);
var topicName = ConfigurationManager.AppSettings[topicNameKey];
var subscriptionName = ConfigurationManager.AppSettings[subscriptionNameKey];
if (!namespaceManager.SubscriptionExists(topicName, subscriptionName))
{
namespaceManager.CreateSubscription(topicName, subscriptionName);
}
var subscriptionClient = SubscriptionClient.CreateFromConnectionString(busConnectionString, topicName, subscriptionName);
var rules = namespaceManager.GetRules(topicName, subscriptionName);
foreach (var rule in rules)
{
subscriptionClient.RemoveRule(rule.Name);
}
subscriptionClient.AddRule(newRule);
rules = namespaceManager.GetRules(topicName, subscriptionName);
rules.ToString();
}
Example of the code that process the topic item:
public void SendInAppNotification(
[ServiceBusTrigger("%eventsTopicName%", "%SubsInAppNotifications%"), ServiceBusAccount("OutputServiceBus")] Notification message)
{
this.valueCalculator.AddInAppNotification(message);
}
This method is inside a Function static class, I'm using azure web job sdk.
Whenever the azure web site is scaled to more than one instance, all the instances share the same configuration.
It sounds like you're creating a new subscription each time your new instance runs, rather than hooking into an existing one. Topics are designed to allow multiple subscribers to attach in that way as well - usually though each subscriber has a different purpose, so they each see a copy of the message.
I cant verify this from your code snippet but that's my guess - are the config files identical? You should add some trace output to see if your processes are calling CreateSubscription() each time they run.
I think I can access the message id, I'm using azure web job sdk but I think I can find a way to get it. Let me check it and will let you know.