Retrieving the number of messages of a Service Bus Queue in .NET Core
Connection String approach
Starting from version 3.1.0
(which is still in preview at the time of writing this post) Service Bus Management library offers a smooth way to access a queue information by only using the connection string.
Install Microsoft.Azure.ServiceBus
NuGet package in your project. Be sure that the version installed is higher or equal than 3.1.0
.
Open the Service Bus namespace from your Azure Portal, select Shared access policies and copy your connection string.
Only 3 lines of codes are necessary for message count retrieval:
var managementClient = new ManagementClient("CONNECTION_STRING");
var queue = await managementClient.GetQueueRuntimeInfoAsync("QUEUE_NAME");
var messageCount = queue.MessageCount;
Pretty straight-forward if you ask me :).
Service Principal approach
This was the main way to go before the 3.1.0
version of the Microsoft.Azure.ServiceBus
library.
Creating the Azure Service Principal
Azure CLI
A painless way to create a Service Principal is by using Azure CLI 2.0. After installing, open your command prompt and type:
az login
After you successfully logged-in, a response containing your subscriptions details is shown. A response example can be seen below, but it may be different based on how many subscriptions your account has:
[
{
"cloudName": "AzureCloud",
"id": "id",
"isDefault": true,
"name": "Azure Pass",
"state": "Enabled",
"tenantId": "tenantId",
"user": {
"name": "your-email-address",
"type": "user"
}
}]
We must mark an important value in this response. The id
property in fact a subscriptionId
, which we will use later.
The next step is the creation of the Service Principal:
az ad sp create-for-rbac --name SERVICE_PRINCIPAL_NAME --password SERVICE_PRINCIPAL_PASSWORD --role Reader --scopes /subscriptions/SUBSCRIPTION_ID/resourceGroups/SERVICE_BUS_RESOURCE_GROUP_NAME
Let's break-down the command:
az ad sp create-for-rbac
-> create Service Principal for role-based access control- --name SERVICE_PRINCIPAL_NAME -> the name we assign to the Service Principal.
- --password SERVICE_PRINCIPAL_PASSWORD -> (optional) the password we want to use in order to log-in with the Service Principal. In case this argument is not given, Azure will generate a strong password for you.
- --role Reader -> we specify that the SP has a Reader role, meaning that he can view, but cannot make any changes to the specified resources. More information can be found here.
- --scopes -> where the SP has access to. In our case, we want our Service Principal to have a Reader role only for the resource group containing our Service Bus.
Replace SERVICE_PRINCIPAL_NAME
and SERVICE_PRINCIPAL_PASSWORD
as you wish, but take care to use correct SUBSCRIPTION_ID
and SERVICE_BUS_RESOURCE_GROUP_NAME
.
After a short period a response similar to this will be shown:
{
"appId": "CLIENT_ID",
"displayName": "SERVICE_PRINCIPAL_NAME",
"name": "http://SERVICE_PRINCIPAL_NAME",
"password": "SERVICE_PRINCIPAL_PASSWORD",
"tenant": "TENANT_ID"
}
Please note down the following information:
clientId
(appId)clientSecret
(password)tenantId
(tenant)subscriptionId
(subscriptionId from the--scopes
argument)
We now have all the information needed in order to connect to Azure Resource Manager.
Azure Resource Manager
It's an easy task to see the number of messages inside a Service Bus Queue using Azure Portal, but the real question is how can we do it programatically? That's where Azure Resource Manager comes into play.
We can use Azure Powershell, Azure CLI, Azure REST APIs and client SDKs to access all capabilities that are available in the Azure portal. Sounds cool, right? For more information, you can check out this page.
Coding part
Start by defining 4 variables that we will use later:
var clientId = "...";
var clientSecret = "...";
var tenantId = "...";
var subscriptionId = "...";
We have two possibilities to continue and you can choose the one that fits you better.
Using Specific Service Bus Management Library
Install Microsoft.Azure.Management.ServiceBus.Fluent NuGet package.
- Acquire the Bearer Token that we will use to call
Azure Resource Manager
:
var authenticationContext = new AuthenticationContext($"https://login.windows.net/{tenantId}");
var clientCredentials = new ClientCredential(clientId, clientSecret);
var authenticationResult = await authenticationContext.AcquireTokenAsync("https://management.core.windows.net/", clientCredentials);
- Create a
ServiceBusManagementClient
instance using your token:
var tokenCredentials = new TokenCredentials(authenticationResult.AccessToken);
var serviceBusClient = new ServiceBusManagementClient(tokenCredentials)
{
SubscriptionId = subscriptionId
};
- Get the Service Bus Queue
var serviceBusQueue = await serviceBusClient.Queues.GetAsync("RESOURCE_GROUP_SERVICE_BUS", "SERVICE_BUS_NAMESPACE_NAME", "SERVICE_BUS_QUEUE_NAME");
- Access
MessageCount
property.
Using Resource Manager Libraries.
In order to proceed, two NuGet packages must be installed:
After you have successfully installed the packages, it's time to write the actual code that will retrieve the number of messages from the Service Bus Queue.
- Create an AzureCredentials object:
var azureCredentials = SdkContext
.AzureCredentialsFactory
.FromServicePrincipal(clientId, clientSecret, tenantId, AzureEnvironment.AzureGlobalCloud);
Note: Change your AzureEnvironment in case you are not using Azure Global Cloud.
- Authenticate using the previously created Azure Credentials.
var azure = Azure.Configure()
.WithLogLevel(HttpLoggingDelegatingHandler.Level.BodyAndHeaders)
.Authenticate(azureCredentials)
.WithSubscription(subscriptionId);
Note: In case you don't have multiple subscriptions in your Azure account, then WithDefaultSubscription()
can be used instead.
- The next thing we must do is to retrieve the service bus namespace, and after that, we select the queue by name:
var serviceBus = azure.ServiceBusNamespaces.GetByResourceGroup("SERVICE_BUS_RESOURCE_GROUP_NAME", "SERVICE_BUS_NAMESPACE");
var queue = serviceBus.Queues.GetByName("SERVICE_BUS_QUEUE_NAME");
var activeMessageCount = queue.ActiveMessageCount;
- And we are done :).