All scripts
Azure AI 274

Get-AzureCosmosDbThroughputReport

Reports RU/s throughput settings across every Cosmos DB account, SQL API database, and container in a subscription, flagging containers that rely on shared database throughput instead of their own dedicated setting, and exports the results to CSV.

Get-AzureCosmosDbThroughputReport.ps1
<#
.SYNOPSIS
    Reports throughput (RU/s) settings across Azure Cosmos DB accounts, databases, and containers in a subscription.

.DESCRIPTION
    Connects to Azure using an existing Az session and enumerates every Cosmos DB account in the
    current subscription (or a single resource group if you pass one in). For each account it walks
    every SQL API database and container, records whether throughput is set at the database level or
    the container level, whether it is manual or autoscale, and flags containers with no dedicated
    throughput setting so you can see where you are relying on shared database throughput. The report
    is written to the pipeline as objects and also exported to a CSV file so you can hand it to someone
    who does not have Azure access.

.PARAMETER ResourceGroupName
    Optional. Limits the report to Cosmos DB accounts in a single resource group. If you leave this out,
    every account in the current subscription is checked.

.PARAMETER OutputPath
    Optional. Path for the CSV export. Defaults to CosmosDbThroughputReport.csv in the current folder.

.EXAMPLE
    .\Get-AzureCosmosDbThroughputReport.ps1

    Reports on every Cosmos DB account in the current subscription and writes CosmosDbThroughputReport.csv.

.EXAMPLE
    .\Get-AzureCosmosDbThroughputReport.ps1 -ResourceGroupName "rg-prod-data" -OutputPath "C:\Reports\cosmos-ru.csv"

    Reports on Cosmos DB accounts in a single resource group only, and writes the CSV to a specific path.

.AUTHOR
    Shehryar Hassan
#>

[CmdletBinding()]
param(
    [Parameter(Mandatory = $false)]
    [string]$ResourceGroupName,

    [Parameter(Mandatory = $false)]
    [string]$OutputPath = ".\CosmosDbThroughputReport.csv"
)

if (-not (Get-AzContext)) {
    Write-Host "No active Azure session found, connecting now." -ForegroundColor Yellow
    Connect-AzAccount | Out-Null
}

$results = New-Object System.Collections.Generic.List[Object]

if ($ResourceGroupName) {
    $accounts = Get-AzCosmosDBAccount -ResourceGroupName $ResourceGroupName
} else {
    $accounts = Get-AzCosmosDBAccount
}

if (-not $accounts) {
    Write-Warning "No Cosmos DB accounts found for the given scope."
    return
}

foreach ($account in $accounts) {
    Write-Host "Checking account: $($account.Name)" -ForegroundColor Cyan

    $databases = Get-AzCosmosDBSqlDatabase -ResourceGroupName $account.ResourceGroupName -AccountName $account.Name

    foreach ($db in $databases) {

        $dbThroughput = $null
        try {
            $dbThroughput = Get-AzCosmosDBSqlDatabaseThroughput -ResourceGroupName $account.ResourceGroupName -AccountName $account.Name -Name $db.Name -ErrorAction Stop
        } catch {
            $dbThroughput = $null
        }

        $containers = Get-AzCosmosDBSqlContainer -ResourceGroupName $account.ResourceGroupName -AccountName $account.Name -DatabaseName $db.Name

        if (-not $containers) {
            $results.Add([PSCustomObject]@{
                AccountName        = $account.Name
                ResourceGroup      = $account.ResourceGroupName
                DatabaseName       = $db.Name
                ContainerName      = "(no containers)"
                ThroughputScope    = if ($dbThroughput) { "Database" } else { "None" }
                ThroughputMode     = if ($dbThroughput -and $dbThroughput.AutoscaleMaxThroughput) { "Autoscale" } elseif ($dbThroughput) { "Manual" } else { "N/A" }
                ProvisionedRUs     = if ($dbThroughput.AutoscaleMaxThroughput) { $dbThroughput.AutoscaleMaxThroughput } elseif ($dbThroughput.Throughput) { $dbThroughput.Throughput } else { $null }
            })
            continue
        }

        foreach ($container in $containers) {

            $containerThroughput = $null
            try {
                $containerThroughput = Get-AzCosmosDBSqlContainerThroughput -ResourceGroupName $account.ResourceGroupName -AccountName $account.Name -DatabaseName $db.Name -Name $container.Name -ErrorAction Stop
            } catch {
                $containerThroughput = $null
            }

            if ($containerThroughput) {
                $scope = "Container"
                $mode = if ($containerThroughput.AutoscaleMaxThroughput) { "Autoscale" } else { "Manual" }
                $rus = if ($containerThroughput.AutoscaleMaxThroughput) { $containerThroughput.AutoscaleMaxThroughput } else { $containerThroughput.Throughput }
            } elseif ($dbThroughput) {
                $scope = "Database (shared)"
                $mode = if ($dbThroughput.AutoscaleMaxThroughput) { "Autoscale" } else { "Manual" }
                $rus = if ($dbThroughput.AutoscaleMaxThroughput) { $dbThroughput.AutoscaleMaxThroughput } else { $dbThroughput.Throughput }
            } else {
                $scope = "None found"
                $mode = "N/A"
                $rus = $null
            }

            $results.Add([PSCustomObject]@{
                AccountName        = $account.Name
                ResourceGroup      = $account.ResourceGroupName
                DatabaseName       = $db.Name
                ContainerName      = $container.Name
                ThroughputScope    = $scope
                ThroughputMode     = $mode
                ProvisionedRUs     = $rus
            })
        }
    }
}

$results | Sort-Object AccountName, DatabaseName, ContainerName | Format-Table -AutoSize

$results | Export-Csv -Path $OutputPath -NoTypeInformation
Write-Host "`nReport exported to $OutputPath" -ForegroundColor Green

$sharedCount = ($results | Where-Object { $_.ThroughputScope -eq "Database (shared)" }).Count
if ($sharedCount -gt 0) {
    Write-Host "$sharedCount container(s) are relying on shared database throughput instead of their own dedicated setting. Review these if you have containers with very different workloads sharing one database." -ForegroundColor Yellow
}

Read it before you run it, and test in a safe tenant first.