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.

What can you do with metrics

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:

Vmcounters

These are in fact are generated by Metrics API.

So let's explore how we can call them ourselves.

Creating Service Principal

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:

App Click1

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.

App Key

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:

App Tenantid

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:

  • Client ID (Application ID)
  • Client Secret (Key)
  • Tenant ID (Directory ID)

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:

Perm1

The permission you need to grant here is Reader:

Perm2

Once that's done, you're authentication will work further.

First call to Metrics API

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:

  • Microsoft.Rest.ClientRuntime.Azure.Authentication
  • Microsoft.IdentityModel.Clients.ActiveDirectory

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.

Fetching Metrics

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:

Listasync

As you can see, you need to pass at least:

  • resourceUri which is an identifier of a resource.
  • metric displays as an optional parameter, however if you don't pass it, you'll get back a default metric for a resource, which is not that useful.
  • timespan is in a specific weird format, I guess because this SDK is autogenerated.

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.

Links


Thanks for reading. If you would like to follow up with future posts please subscribe to our rss feed.