I’ve been working with Azure Diagnositc logs recently, and part of the data that comes out of them is something azure calls a “ResourceId”. This is used to uniquely identify the resource in Azure. It’s a slash separated value that includes a hierarchal list of values.
The issue is that they’re not always the same number of values as the different types of resources have different numbers of hierarchal elements. We could create a regex for this, however, the Azure Core nuget packages have a pre-built way to do this.
A Diagnostic log entry looks like this
{
"records": [
{
"category": "AppServiceHTTPLogs",
"time": "2022-05-08T20:14:15.0000000",
"resourceId": "/SUBSCRIPTIONS/9BDCA8E0-C38E-49E2-BD4F-313DD91C8DF5/RESOURCEGROUPS/HONEYCOMB/PROVIDERS/MICROSOFT.WEB/SITES/EXPORT-TEST",
"properties": "{\"UserAgent\":\"Mozilla\\/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit\\/537.36 (KHTML, like Gecko) Chrome\\/101.0.4951.54 Safari\\/537.36 Edg\\/101.0.1210.39\",\"Cookie\":\"--\",\"ScStatus\":\"200\",\"CsUsername\":\"-\",\"Result\":\"Success\",\"CsHost\":\"export-test.scm.azurewebsites.net\",\"CsMethod\":\"GET\",\"CsBytes\":\"1635\",\"CsUriQuery\":\"_=1652036313179\",\"CIp\":\"217.155.15.125\",\"SPort\":\"80\",\"Referer\":\"-\",\"CsUriStem\":\"\\/api\\/vfs\\/site\\/wwwroot\\/\",\"TimeTaken\":19619,\"ScBytes\":\"494\",\"ComputerName\":\"10-30-0-173\"}",
"EventStampType": "Stamp",
"EventPrimaryStampName": "waws-prod-ln1-093",
"EventStampName": "waws-prod-ln1-093",
"Host": "10-30-0-173",
"EventIpAddress": "10.30.0.173"
}
]
}
As you can see, this has a ResourceId that looks like this:
/SUBSCRIPTIONS/9BDCA8E0-C38E-49E2-BD4F-313DD91C8DF5/RESOURCEGROUPS/HONEYCOMB/PROVIDERS/MICROSOFT.WEB/SITES/EXPORT-TEST
This shows a resource with the following characteristics.
- Azure AppService with the Name “export-test”
- Resource Group with the name “honeycomb”
- In the subscription “9BDCA8E0-C38E-49E2-BD4F-313DD91C8DF5”
So we could do a fairly simple string split like this:
var resourceIdSplit = resourceId.Split("/");
Console.WriteLine($"SubscriptionId: {resourceIdSplit[2]}");
Console.WriteLine($"Resource Group: {resourceIdSplit[4]}");
Console.WriteLine($"Site Name: {resourceIdSplit[8]}");
The issue here is that the subscription and resource group are static, but the position of the name of the resource isn’t. Different resources have different hierarchy, so it’s not really portable. This is where the Azure ResourceId class helps.
The ResourceIdentifier class is part of Azure.Core nuget package and provides a supported way to parse the resource Identifier. With this we can have the following code.
var resourceIdClass = new ResourceIdentifier(resourceId);
Console.WriteLine($"Subscription: {resourceIdClass.SubscriptionId}");
Console.WriteLine($"Resource Group: {resourceIdClass.ResourceGroupName}");
Console.WriteLine($"Site Name: {resourceIdClass.Name}");
Console.WriteLine($"ResourceType: {resourceIdClass.ResourceType}");
This means we don’t need to care about the structure of the ResourceID, and we can extract the things we need pretty easily.
Conclusion
The ResourceIdentifier is pretty cool if you’re working with Resource Ids. The class has some other functions such as “Root”, “Parent” and “Child” relationships if the resource you’re looking has a parent. This is useful for things like Slots in Azure AppService or Subscriptions in Azure ServiceBus.
Leave a Reply