Read the Azure Storage Analytics Metrics Table with PowerShell

Another script I recently needed to read Azure Storage Analytics Metrics.

Here is the table schema if you need additional or different information.

https://msdn.microsoft.com/en-us/library/azure/hh343264.aspx

Please note that metrics are calculated when an aggregation period ends and are not available immediately.  If you run my script as-is, it will attempt to get blob metrics from the previous hour.  If you run it "early" in the hour, the data from the previous hour may not yet be ready.  You can comment out my filter line to get all data.

Please note that you are on your own to turn storage metrics on.  My script will not enable storage metrics for you.

##########################################################################
# Hard-coded Parameters
# Set $proxyAddr = '' if you don't need a proxy server
# Change $BlobOrQueueOrTable to 'Queue' or 'Table' if you like.
##########################################################################
$mgmtUri = 'https://management.core.windows.net'
$subId = '12345678-1234-1234-1234-123456789ABC'
$msApiVer = '2012-08-01'
$servName = 'asdfgh'
$tableEP = 'https://asdfgh.table.core.windows.net/'
$certPW = '<PFX Password>'
$certPath = 'C:\myCert.pfx'
$proxyAddr = 'https://proxy:80'

$HourOrMinute = 'Hour'
$PrimaryOrSecondary = 'Primary'
$BlobOrQueueOrTable = 'Blob'

##########################################################################
# Create a X509 Certificate from the byte array
##########################################################################
$flags = [System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]"MachineKeySet"
$clientCert = New-Object -TypeName System.Security.Cryptography.X509Certificates.X509Certificate2 -ArgumentList $certPath, $certPW, $flags

##########################################################################
# Call the management service to get the storage keys
##########################################################################
$keysUri = $mgmtUri + '/' + $subId + '/services/storageservices/' + $servName + '/keys'
$mgmtWebRequest = [System.Net.HttpWebRequest]::Create($keysUri)
$mgmtWebRequest.Timeout = 15000
$mgmtWebRequest.ClientCertificates.Add($clientCert)
$mgmtWebRequest.Method = "GET"
$mgmtWebRequest.Headers.Add("x-ms-version", $msApiVer)
If ($proxyAddr -eq '')
{
  $mgmtWebRequest.Proxy = $null
}
Else
{
  $myWebProxy = New-Object System.Net.WebProxy($proxyAddr)
  $mgmtWebRequest.Proxy = $myWebProxy
}

##########################################################################
# Get the storage service keys from the response
##########################################################################
$response = $mgmtWebRequest.GetResponse()
$responseReader = New-Object System.IO.StreamReader($response.GetResponseStream())
[xml]$xmlResponseBody = $responseReader.ReadToEnd()
$responseReader.Close()
$primaryKey = $xmlResponseBody.StorageService.StorageServiceKeys.Primary

##########################################################################
# Create a hasher and seed it with the storage key
##########################################################################
$sharedKey = [System.Convert]::FromBase64String($primaryKey)
$myHasher = New-Object System.Security.Cryptography.HMACSHA256
$myHasher.Key = $sharedKey

##########################################################################
# Construct the Storage Analytics Metrics Table and URI
##########################################################################
$myInvariantCulture = New-Object System.Globalization.CultureInfo("")
$strTable = '$Metrics' + $HourOrMinute + $PrimaryOrSecondary + 'Transactions' + $BlobOrQueueOrTable
$strTableUri = $tableEP + $strTable

     
     
##########################################################################
# Get the current date/time and format it properly
# The culture "" is the invariant culture
##########################################################################
$myDateObj = Get-Date
$strDate = $myDateObj.ToUniversalTime().ToString("R", $myInvariantCulture)

##########################################################################
# This will get only the metrics from the previous hour. Metrics are not
# available immediately when an hour ends. If you want to change this
# try either subtracting more than 1 hour from the current time or
# removing the filter from the URI. You can comment out the next two
# lines if you like.
##########################################################################
$strPartition = $myDateObj.AddHours(-1).ToUniversalTime().ToString("yyyyMMddTHH00")
$strTableUri = $strTableUri + '?$filter=PartitionKey%20eq%20''' + $strPartition + ''''

##########################################################################
# Preare the HttpWebRequest
##########################################################################
$tableWebRequest = [System.Net.HttpWebRequest]::Create($strTableUri)
$tableWebRequest.Timeout = 15000
$tableWebRequest.ContentType = "application/xml"
$tableWebRequest.Method = "GET"
$tableWebRequest.Headers.Add("x-ms-date", $strDate)
If ($proxyAddr -eq '')
{
  $tableWebRequest.Proxy = $null
}
Else
{
  $tableWebProxy = New-Object System.Net.WebProxy($proxyAddr)
  $tableWebRequest.Proxy = $tableWebProxy
}

##########################################################################
# Create the Authorization header
##########################################################################
$strToSign = $tableWebRequest.Method + "`n" `
           + $tableWebRequest.Headers.Get("Content-MD5") + "`n" `
           + $tableWebRequest.Headers.Get("Content-Type") + "`n" `
           + $tableWebRequest.Headers.Get("x-ms-date") + "`n" `
           + '/' + $servName + '/' + $strTable
$bytesToSign = [System.Text.Encoding]::UTF8.GetBytes($strToSign)
$strSignedStr = [System.Convert]::ToBase64String($myHasher.ComputeHash($bytesToSign))
$strAuthHeader = "SharedKey " + $servName + ":" + $strSignedStr
$tableWebRequest.Headers.Add("Authorization", $strAuthHeader)

##########################################################################
# Read the results
##########################################################################
$tableResponse = $tableWebRequest.GetResponse()
$tableResponseReader = New-Object System.IO.StreamReader($tableResponse.GetResponseStream())
[xml]$xmlMetricsData = $tableResponseReader.ReadToEnd()
$entries = $xmlMetricsData.feed.entry

Foreach ($entry in $entries)
{
  Write-Host 'Row Key:' $entry.content.properties.RowKey
  Write-Host 'Partition Key:' $entry.content.properties.PartitionKey
  Write-Host 'Total Requests:' $entry.content.properties.TotalRequests.innertext
  Write-Host 'Total Ingress:' $entry.content.properties.TotalIngress.innertext
  Write-Host 'Total Egress:' $entry.content.properties.TotalEgress.innertext
  Write-Host '---------------------'
}

$tableResponseReader.Close()

GetMetricsData.zip