Azure Service Bus - Message Peek on Subscription - azure

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;

Related

How to Get Azure Event Hub Connection String in C#?

Given a Event Hub Name, how can I get connection string in C#?
I googled a bit, but nothing useful found so far.
Thanks
Using AAD authentication for an EventHub
var credential = new DefaultAzureCredential();
// or use
// var credential = new Azure.Identity.ClientSecretCredential("tenantId", "clientId", "clientSecret");
EventHubProducerClient producerClient = new EventHubProducerClient(txtNamespace.Text, txtEventHub.Text, credential
var consumerClient = new EventHubConsumerClient(EventHubConsumerClient.DefaultConsumerGroupName, txtNamespace.Text, txtEventHub.Text, credential)
Full example and docs
Acquiring the Connection Strings of configured Access Policies
You can use these two Nuget packages:
Azure.ResourceManager.EventHubs
Azure.Identity
Then you can use the resource group name and the eventhub name to retrieve the connection string. You will need to iterate the subscriptions and resource groups if you don't have this information.
using Azure.Identity;
using Azure.ResourceManager;
using Azure.ResourceManager.EventHubs;
ArmClient client = new ArmClient(new DefaultAzureCredential());
// Or use
// ArmClient client = new ArmClient(new Azure.Identity.ClientSecretCredential("tenantId", "clientId", "clientSecret"));
var subscription = await client.GetDefaultSubscriptionAsync();
var resourceGroup = await subscription.GetResourceGroupAsync("myresourcegroup");
var eventhubNamespace = await resourceGroup.Value.GetEventHubsNamespaceAsync("namespacename");
var rules = eventhubNamespace.Value.GetEventHubsNamespaceAuthorizationRules();
foreach (var rule in rules)
{
var keys = await rule.GetKeysAsync();
Console.WriteLine(keys.Value.PrimaryConnectionString);
Console.WriteLine(keys.Value.SecondaryConnectionString);
}
Not sure if this is what you mean, but if you want to access an Event Hub through C# you need to provide the EH connection string into your code. This can be retrieved by adding a Shared access policy for the Event hub that you are trying to access.
Edit: If you are trying to actually create the connection string yourself you could follow this sample where you create the SAS-token yourself. But you would still need to provide the Primary key that is set on the policy from Azure.

Azure: How to create an Event subscription programmatically

I have many storage accounts that are created programmatically, and I'd like to create an event subscription in each to listen to BlobCreated events with an existing Azure Function endpoint. Right now, I'm doing this manually by going to the portal, but it's been time-consuming to say the least.
Are there any C# code examples that would create an event subscription using Azure credentials?
Please find an example in GitHub
static async Task CreateEventGridEventSubscriptionAsync(string azureSubscriptionId, string eventSubscriptionName, EventGridManagementClient eventGridMgmtClient)
{
Console.WriteLine($"Creating an event subscription to Azure subscription {azureSubscriptionId} with destination as queue {QueueName} under storage account {StorageAccountId}");
string scope = $"/subscriptions/{azureSubscriptionId}";
EventSubscription eventSubscription = new EventSubscription()
{
Destination = new StorageQueueEventSubscriptionDestination()
{
ResourceId = StorageAccountId,
QueueName = QueueName
},
// The below are all optional settings
EventDeliverySchema = EventDeliverySchema.EventGridSchema,
Filter = new EventSubscriptionFilter()
{
IsSubjectCaseSensitive = false,
SubjectBeginsWith = "",
SubjectEndsWith = ""
}
};
EventSubscription createdEventSubscription = await eventGridMgmtClient.EventSubscriptions.CreateOrUpdateAsync(scope, eventSubscriptionName, eventSubscription);
Console.WriteLine("EventGrid event subscription created with name " + createdEventSubscription.Name);
}
Please find the official documentation in MS Docs - IEventSubscriptionsOperations Interface
MS Docs - EventSubscriptionsOperationsExtensions.CreateOrUpdateAsync(IEventSubscriptionsOperations, String, String, EventSubscription, CancellationToken) Method

Azure service bus - how to add metadata to the message

I am using .net core web app as the publisher and .net core console app as subscriber.
I am able to successfully pass messages between these two systems using Managed Identities - set up in Azure portal.
My question is I need to add metadata to the the message that is being sent. How do I do that ?
Below is my publisher code :
string data = JsonConvert.SerializeObject(payloadEvents);
Message message = new Message(Encoding.UTF8.GetBytes(data));
var tokenProvider = TokenProvider.CreateManagedIdentityTokenProvider();
TopicClient sendClient = new TopicClient(_serviceBusNamespace, _topicName, tokenProvider, retryPolicy: null);
await sendClient.SendAsync(message);
Message object has a property called UserProperties that can be used to set custom metadata for that message.
Something like:
string data = JsonConvert.SerializeObject(payloadEvents);
Message message = new Message(Encoding.UTF8.GetBytes(data));
message.UserProperties.Add("key1", "value1");
message.UserProperties.Add("key2", "value2");
var tokenProvider = TokenProvider.CreateManagedIdentityTokenProvider();
TopicClient sendClient = new TopicClient(_serviceBusNamespace, _topicName, tokenProvider, retryPolicy: null);
await sendClient.SendAsync(message);

Sending message to a specific group of subscriber in azure service bus topic with masstransit

I'm new to azure service bus and masstransit. I'm looking for a solution to a specific situation.
I have a azure service bus topic with multiple subscribers. Subscriber will receive message based on filters. I've created the topic and subscriber with code below
class Program
{
static void Main(string[] args)
{
string connectionString = "Endpoint connection string";
// the names of topics and subscriptions we'll be working with
const string topicName = "MyTestTopic";
const string allMessagesSubName = "AllMessages";
const string filteredSubName1 = "Filtered1";
const string filteredSubName2 = "Filtered2";
// let's create the topic if it doesn't already exist...
var namespaceManager = NamespaceManager.CreateFromConnectionString(connectionString);
if (!namespaceManager.TopicExists(topicName))
{
var td = new TopicDescription(topicName);
namespaceManager.CreateTopic(td.Path);
}
if (!namespaceManager.SubscriptionExists(topicName, allMessagesSubName))
{
namespaceManager.CreateSubscription(topicName, allMessagesSubName);
}
if (!namespaceManager.SubscriptionExists(topicName, filteredSubName1))
{
namespaceManager.CreateSubscription(
new SubscriptionDescription(topicName, filteredSubName1),
new Microsoft.ServiceBus.Messaging.SqlFilter("From LIKE '%Smith'"));
}
if (!namespaceManager.SubscriptionExists(topicName, filteredSubName2))
{
namespaceManager.CreateSubscription(
new SubscriptionDescription(topicName, filteredSubName2),
new Microsoft.ServiceBus.Messaging.SqlFilter("sys.Label='important'"));
}
var message1 = new BrokeredMessage("Hello World");
var message2 = new BrokeredMessage("Second message");
message2.Label = "important";
var message3 = new BrokeredMessage("Third message");
message3.Properties["From"] = "Kelly Smith";
message3.Label = "information";
var client = TopicClient.CreateFromConnectionString(connectionString, topicName);
client.Send(message1);
client.Send(message2);
client.Send(message3);
client.Close();
}
}
Here in the code we're adding Message custom properties like From.
Now I want to send such message using masstransit. In masstransit I cannot find any option of adding Message custom properties using the Publish() method. Is there any way that I can send these messages using masstransit where these filters can be used?
NB: I've read the answer of this question But the anwer here tells us to filter the messages in subscriber side. What I want is that this filtering will occur before reaching the subscriber.
When using Azure Service Bus with MassTransit, you can add subscription endpoints in additional to regular endpoints. When configuring a subscription endpoint, you should be able to specify rules and/or filters as part of the subscription. Which is exactly what you're doing above, so that is handled.
The other part, adding properties to the message, can be done by adding text headers to the SendContext. Those headers are copied to the message Properties collection, which I believe can be used to filter messages using a "SQL" filter (which is configured on the subscription endpoint, or the topic subscription on a receive endpoint).

Determining how many messages are on the Azure Service Bus Queue

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.

Resources