Here is the PowerShell script:
Param(
[string]$counterFile
)
Function ParseCounterXMLFile
{
[xml]$counters = Get-Content $counterFile
foreach ($category in $counters.counters.category)
{
$categoryName = $category.Name;
# Delete category if it already exists.
$exists = [System.Diagnostics.PerformanceCounterCategory]::Exists($categoryName)
if ($exists)
{
[System.Diagnostics.PerformanceCounterCategory]::Delete($categoryName)
}
$counterData = new-object System.Diagnostics.CounterCreationDataCollection
# For each counter in the category, add it to the new category collection.
foreach ($counterElement in $category.counter)
{
$name = $counterElement.Attributes.ItemOf("name").Value
$type = $counterElement.Attributes.ItemOf("type").Value
AddCounter $counterData $name $type
$baseType = ""
switch ($type)
{
"AverageTimer32" { $baseType = "AverageBase" }
"AverageCount64" { $baseType = "AverageBase" }
"CounterMultiTimer" { $baseType = "CounterMultiBase" }
"CounterMultiTimerInverse" { $baseType = "CounterMultiBase" }
"CounterMultiTimer100Ns" { $baseType = "CounterMultiBase" }
"CounterMultiTimer100NsInverse" { $baseType = "CounterMultiBase" }
"RawFraction" { $baseType = "RawBase" }
"SampleFraction" { $baseType = "SampleBase" }
default { }
}
if ($baseType)
{
AddCounter $counterData "$name Base" $baseType
}
}
# Create the counters in this category.
[System.Diagnostics.PerformanceCounterCategory]::Create($categoryName, $categoryName, [System.Diagnostics.PerformanceCounterCategoryType]::SingleInstance, $counterData)
}
}
Function AddCounter($counterData, $name, $type)
{
$counter = new-object System.Diagnostics.CounterCreationData
$counter.CounterType = [System.Diagnostics.PerformanceCounterType] $type;
$counter.CounterName = $name
$counterData.Add($counter)
write $name $type
}
ParseCounterXMLFile
And here is an example XML file:
<counters>
<category name="My Test Performance Counters">
<counter type="AverageTimer32" name="Avg Timer Test" />
<counter type="NumberOfItems32" name="Counter Test 1" />
</category>
<category name="My Test Performance Counters Cat 2">
<counter type="NumberOfItems32" name="Counter Test 2" />
</category>
</counters>
You can use this in Azure by adding a StartupTask that calls a .cmd file that issues this command:
powershell -ExecutionPolicy Unrestricted -File .\loadperformancecounters.ps1 .\PerfCounters.xml
Update: This was working in the Compute Emulator, but failed on Azure. Upon troubleshooting I discovered something very strange... Using the bracket operator on an XmlAttributeCollection does not work in whatever version of .NET or Powershell being used in Azure instances. In the end, all I had to do was replace two lines of code:
$name = $counterElement.Attributes["name"].Value
$type = $counterElement.Attributes["type"].Value
was changed to:
$name = $counterElement.Attributes.ItemOf("name").Value
$type = $counterElement.Attributes.ItemOf("type").Value
This change is reflected in the code up above. I have absolutely no idea why this would make a difference