Skip to content

Commit e30acf6

Browse files
authored
Porting Reactive Scanning and Smart Categorization to All DLQ Commands (#9)
* Ported the reactive and smart categorization into the dump DLQ * Ported the reactive and smart categorization into the purge DLQ * Ported the reactive and smart categorization into the diagnose DLQ * Combine shared code * Extract common code into base class * Fixed integration tests * Added confirmation for purge DLQ * Added test infra * Telemetry fixes * Increase the batch size * Fixed diagnosing * Updated the docs
1 parent bf8ea07 commit e30acf6

71 files changed

Lines changed: 4274 additions & 1064 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

ServiceBusToolset.slnx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
<Folder Name="/src/">
1414
<Project Path="src/ServiceBusToolset.Application/ServiceBusToolset.Application.csproj"/>
1515
<Project Path="src/ServiceBusToolset.CLI/ServiceBusToolset.CLI.csproj"/>
16+
<Project Path="src/ServiceBusToolset.TestHarness/ServiceBusToolset.TestHarness.csproj"/>
1617
</Folder>
1718
<Folder Name="/tests/">
1819
<Project Path="tests/ServiceBusToolset.Application.Tests/ServiceBusToolset.Application.Tests.csproj"/>

docs/articles/port-improvements-to-all-commands.md

Lines changed: 324 additions & 0 deletions
Large diffs are not rendered by default.

docs/diagnose-dlq.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,9 @@ dotnet run -- diagnose-dlq -n <namespace> (-q <queue> | -t <topic> -s <subscript
1919
| `--app-insights` | `-a` | **(Required)** Application Insights resource ID |
2020
| `--output` | `-o` | Output JSON file path (optional, prints summary to console) |
2121
| `--before` | | Only include messages enqueued before this UTC datetime (ISO 8601) |
22-
| `--max-messages` | | Maximum number of messages to diagnose (default: 100) |
22+
| `--max-messages` | | Maximum number of messages to diagnose (default: 1000) |
2323
| `--interactive` | `-i` | Interactive mode: view and select categories to diagnose |
24+
| `--merge-similar` | | Merge similar DLQ categories using LCS-based clustering (interactive mode only) |
2425
| `--verbose` | `-v` | Enable verbose output |
2526

2627
## Getting the App Insights Resource ID

docs/dump-dlq.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ dotnet run -- dump-dlq -n <namespace> (-q <queue> | -t <topic> -s <subscription>
2020
| `--before` | | Only include messages enqueued before this UTC datetime (ISO 8601) |
2121
| `--dry-run` | | Preview message count without writing to file |
2222
| `--interactive` | `-i` | Interactive mode: view and select categories to dump |
23+
| `--merge-similar` | | Merge similar DLQ categories using LCS-based clustering (interactive mode only) |
2324
| `--verbose` | `-v` | Enable verbose output |
2425

2526
## Examples

docs/purge-dlq.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ dotnet run -- purge-dlq -n <namespace> (-q <queue> | -t <topic> -s <subscription
1919
| `--before` | | Only purge messages enqueued before this UTC datetime (ISO 8601) |
2020
| `--dry-run` | | Preview message count without purging |
2121
| `--interactive` | `-i` | Interactive mode: view and select categories to purge |
22+
| `--merge-similar` | | Merge similar DLQ categories using LCS-based clustering (interactive mode only) |
2223
| `--verbose` | `-v` | Enable verbose output |
2324

2425
## Examples

docs/resubmit-dlq.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ dotnet run -- resubmit-dlq -n <namespace> (-q <queue> | -t <topic> -s <subscript
2121
| `--before` | | Only resubmit messages enqueued before this UTC datetime (ISO 8601) |
2222
| `--dry-run` | | Preview message count without resubmitting |
2323
| `--interactive` | `-i` | Interactive mode: view and select categories to resubmit |
24+
| `--merge-similar` | | Merge similar categories by replacing parameterized values (GUIDs, numbers) with wildcards |
2425
| `--verbose` | `-v` | Enable verbose output |
2526

2627
## Examples

infra/test/main.bicep

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
@description('Resource name prefix')
2+
param prefix string
3+
4+
@description('Azure region')
5+
param location string
6+
7+
@description('Service Bus SKU')
8+
@allowed(['Standard', 'Premium'])
9+
param serviceBusSku string
10+
11+
var logAnalyticsName = '${prefix}-law'
12+
var appInsightsName = '${prefix}-ai'
13+
var serviceBusName = '${prefix}-sbns'
14+
var queueName = 'test-dlq-queue'
15+
16+
resource logAnalytics 'Microsoft.OperationalInsights/workspaces@2023-09-01' = {
17+
name: logAnalyticsName
18+
location: location
19+
properties: {
20+
sku: {
21+
name: 'PerGB2018'
22+
}
23+
retentionInDays: 30
24+
}
25+
}
26+
27+
resource appInsights 'Microsoft.Insights/components@2020-02-02' = {
28+
name: appInsightsName
29+
location: location
30+
kind: 'web'
31+
properties: {
32+
Application_Type: 'web'
33+
WorkspaceResourceId: logAnalytics.id
34+
}
35+
}
36+
37+
resource serviceBusNamespace 'Microsoft.ServiceBus/namespaces@2024-01-01' = {
38+
name: serviceBusName
39+
location: location
40+
sku: {
41+
name: serviceBusSku
42+
tier: serviceBusSku
43+
}
44+
}
45+
46+
resource testQueue 'Microsoft.ServiceBus/namespaces/queues@2024-01-01' = {
47+
parent: serviceBusNamespace
48+
name: queueName
49+
properties: {
50+
maxDeliveryCount: 1
51+
deadLetteringOnMessageExpiration: true
52+
}
53+
}
54+
55+
@description('Fully qualified Service Bus namespace')
56+
output serviceBusFqdn string = '${serviceBusNamespace.name}.servicebus.windows.net'
57+
58+
@description('Test queue name')
59+
output queueName string = testQueue.name
60+
61+
@description('Application Insights resource ID')
62+
output appInsightsResourceId string = appInsights.id
63+
64+
@description('Application Insights connection string')
65+
output appInsightsConnectionString string = appInsights.properties.ConnectionString

infra/test/main.bicepparam

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
using 'main.bicep'
2+
3+
param prefix = 'sbtools-test'
4+
param location = 'eastus2'
5+
param serviceBusSku = 'Standard'

infra/test/setup.ps1

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
[CmdletBinding()]
2+
param(
3+
[Parameter()]
4+
[string]$Prefix = 'sbtools-test',
5+
6+
[Parameter()]
7+
[string]$Location = 'eastus2',
8+
9+
[Parameter()]
10+
[string]$SubscriptionId
11+
)
12+
13+
$ErrorActionPreference = 'Stop'
14+
15+
$resourceGroup = "$Prefix-rg"
16+
17+
# Set subscription if provided
18+
if ($SubscriptionId) {
19+
Write-Host "Setting subscription to $SubscriptionId..."
20+
az account set --subscription $SubscriptionId
21+
}
22+
23+
# Create resource group
24+
Write-Host "Creating resource group '$resourceGroup' in '$Location'..."
25+
az group create --name $resourceGroup --location $Location --output none
26+
27+
# Deploy Bicep template
28+
Write-Host "Deploying infrastructure..."
29+
$deployment = az deployment group create `
30+
--resource-group $resourceGroup `
31+
--template-file "$PSScriptRoot/main.bicep" `
32+
--parameters "$PSScriptRoot/main.bicepparam" `
33+
--parameters prefix=$Prefix location=$Location `
34+
--output json | ConvertFrom-Json
35+
36+
$fqdn = $deployment.properties.outputs.serviceBusFqdn.value
37+
$queueName = $deployment.properties.outputs.queueName.value
38+
$appInsightsConnectionString = $deployment.properties.outputs.appInsightsConnectionString.value
39+
$appInsightsResourceId = $deployment.properties.outputs.appInsightsResourceId.value
40+
41+
# Assign Service Bus Data Owner role to current user
42+
Write-Host "Assigning 'Azure Service Bus Data Owner' role..."
43+
$currentUser = az ad signed-in-user show --query id --output tsv
44+
$serviceBusId = az servicebus namespace show --resource-group $resourceGroup --name "$Prefix-sbns" --query id --output tsv
45+
46+
az role assignment create `
47+
--assignee $currentUser `
48+
--role "Azure Service Bus Data Owner" `
49+
--scope $serviceBusId `
50+
--output none 2>$null
51+
52+
Write-Host ""
53+
Write-Host "======================================" -ForegroundColor Green
54+
Write-Host " Infrastructure deployed successfully" -ForegroundColor Green
55+
Write-Host "======================================" -ForegroundColor Green
56+
Write-Host ""
57+
Write-Host "Service Bus FQDN : $fqdn"
58+
Write-Host "Queue Name : $queueName"
59+
Write-Host "App Insights Connection String: $appInsightsConnectionString"
60+
Write-Host "App Insights Resource ID : $appInsightsResourceId"
61+
Write-Host ""
62+
Write-Host "Example commands:" -ForegroundColor Cyan
63+
Write-Host " # Generate DLQ messages with correlated App Insights telemetry:"
64+
Write-Host " dotnet run --project src/ServiceBusToolset.TestHarness -- generate-dlq -n $fqdn -q $queueName -c 100 --app-insights-connection-string `"$appInsightsConnectionString`""
65+
Write-Host ""
66+
Write-Host " # Generate DLQ messages without telemetry:"
67+
Write-Host " dotnet run --project src/ServiceBusToolset.TestHarness -- generate-dlq -n $fqdn -q $queueName -c 100"
68+
Write-Host ""
69+
Write-Host " # Diagnose DLQ messages (wait 2-5 min after generate-dlq for telemetry ingestion):"
70+
Write-Host " dotnet run --project src/ServiceBusToolset.CLI -- diagnose-dlq -n $fqdn -q $queueName -a $appInsightsResourceId"
71+
Write-Host ""
72+
Write-Host " # Dump DLQ messages:"
73+
Write-Host " dotnet run --project src/ServiceBusToolset.CLI -- dump-dlq -n $fqdn -q $queueName -i --merge-similar -o dump.json"

infra/test/teardown.ps1

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
[CmdletBinding()]
2+
param(
3+
[Parameter()]
4+
[string]$Prefix = 'sbtools-test',
5+
6+
[Parameter()]
7+
[string]$SubscriptionId
8+
)
9+
10+
$ErrorActionPreference = 'Stop'
11+
12+
$resourceGroup = "$Prefix-rg"
13+
14+
# Set subscription if provided
15+
if ($SubscriptionId) {
16+
Write-Host "Setting subscription to $SubscriptionId..."
17+
az account set --subscription $SubscriptionId
18+
}
19+
20+
# Confirm deletion
21+
$confirm = Read-Host "Are you sure you want to delete resource group '$resourceGroup'? (y/N)"
22+
if ($confirm -ne 'y') {
23+
Write-Host "Cancelled."
24+
return
25+
}
26+
27+
# Delete resource group
28+
Write-Host "Deleting resource group '$resourceGroup' (no-wait)..."
29+
az group delete --name $resourceGroup --yes --no-wait
30+
31+
Write-Host "Resource group deletion initiated. It may take a few minutes to complete." -ForegroundColor Yellow

0 commit comments

Comments
 (0)