Using Azure Monitor Programmatically
Azure Metrics enables you to gain visibility into the performance and health of your Azure workloads. Metrics (or performance counters) are emitted by most of the Azure resources and the best thing about them (IMHO) is that they don't need to be enabled explicitly, they are always available and available immediately. There is no need to opt in or switch something on. Now, this is good, because most of the issues come during integration and configuration phase and simply stop working or become a huge roadblock during deployment if you need to ask various people for a lot of permissions and become blocked.
For instance, I've created a virtual machine, all options for diagnostics are off and others are default, and I can see those nice charts in Azure Portal:
These are in fact are generated by Metrics API.
So let's explore how we can call them ourselves.
In order to access the API we need to create a Service Principal first. This is an object which will alow us to authentication to the API. The process is really simple but hard to find.
The easiest way to do this is to create an Active Directory application through the Azure Portal:
Call the application whatever you like, it doesn't really matter, specify anything for a reply url, like http://localhost or something, but we need two things from here - appilcation ID, and a key you need to generate.
Just write those down and let's move on. The next thing we need is a Tenant ID, which you can get from Active Directory Properties:
It's called a Directory ID but is know by another name as well - Tenant ID. You should write this down too as we need it later.
Eseentially those are 3 parameters we need for authentication:
We could start writing code right now, but this application still has no permissions to read monitor data. In order to do that you need to grant it access, and to do that you need access to Azure subscription. Therefore go find your subscription, and add press Add button in IAM as depicted below:
The permission you need to grant here is Reader:
Once that's done, you're authentication will work further.
To call the Monitor API you need to reference the NuGet Package. It gives you access to MonitorClient
class which is the main entry point to getting anything useful out of the API.
You need to specify ServiceClientCredentials
when creating the client, and there is a trivial way to pass them.
First of all, you need another two packages to perform authentication:
having those two in place we can write a helper method which creates the monitor instance (remember those 3 values we got from Active Directory?):
private async Task<MonitorClient> GetMonitorClientAsync()
{
if(_client == null)
{
var cc = new ClientCredential(_principalClientId, _principalSecret);
ServiceClientCredentials scc = await ApplicationTokenProvider.LoginSilentAsync(_tenantId, cc);
_client = new MonitorClient(scc);
}
return _client;
}
Successfully call to this method returns an instance of the MonitorClient, which you can now use to call any Monitor API you want.
Now, to fetch metrics you need to get it per resource. A resource is a virtual machine, or a web site, anything which you create in Portal. This is the call to fetch a resource:
As you can see, you need to pass at least:
You can get the list of metrics for a specific resourceUri by calling to client.MetricDefinitions.ListAsync(resourceUri)
which again requires a resourceUri. If you know it you're good, however what if you don't? In this case, you can enumerate all of the resources in your subscription by referencing Resource Manager Package. Authentication method for this package is identical to what we've just seen and you can you the same service principal you've used before as well.
Here is a code snippet to get the list of resources in your subscription:
public async Task<IEnumerable<AzureResource>> ListAllResourcesAsync(string subscriptionId)
{
ResourceManagementClient rmc = await GetClientAsync();
rmc.SubscriptionId = subscriptionId ?? throw new ArgumentNullException(nameof(subscriptionId));
var r = new List<AzureResource>();
IPage<GenericResource> page = await rmc.Resources.ListAsync();
r.AddRange(page.Select(ToAzureResource));
while(page.NextPageLink != null)
{
page = await rmc.Resources.ListNextAsync(page.NextPageLink);
r.AddRange(page.Select(ToAzureResource));
}
return r;
}
AzureResource
is a custom class containing just what I need from the big response class.
Having the list of resources, now you can get per-resource metrics list and actual metrics data.
Thanks for reading. If you would like to follow up with future posts please subscribe to my rss feed and/or follow me on twitter.