Reading metric data from Azure using the Azure Insights library

A couple of months ago I published a post on how to get metrics from the Azure API Management service in order to integrate it into existing monitoring tools and/or dashboards.

One of my customers is building a solution with a significant use of Document DB at the heart of it and asked how we could do the same for Document DB.

In this blog post I will walk through the steps required to obtain the metrics for Document DB using the preview release of the Microsoft Azure Insights Library (I’ve used version 0.6.0) to obtain metric data for Document DB using Azure Active Directory (AAD) for authentication but the same approach should work for any of the services that are accessible via the Azure Resource Manager (and the Azure Preview Portal)

There are three steps required to obtain metrics through Azure Insights –

  1. 1. [One time] access control configuration
  2. 2. Authenticating using Azure Active Directory
  3. 3. Requesting the metrics from Azure Insights

Configuring Access Control

Access to resources through the Azure Resource Manager (ARM) is governed by AAD and so the first step is to have an identity, configured with the right permissions to our desired resource (a Document DB account, in this case), which we could use to authenticate to Azure AD and obtain a token.

The token would then be used  in subsequent requests to ARM for authentication and authorisation.

Naturally, we need our solution to work programmatically, without an interactive user, and so we need to have a service principal with the right permissions.

Service Principals exist in AAD through web Applications – every configured web application is also a service principal in AAD and its client Id and client secret can be used to authenticate to AAD and obtain a token on the apps behalf.

this documentation article shows how to create such application using Powershell, configure it with permissions to use the ARM API as well as how to obtain an authentication token for it

the following steps can be used to configure this through the protal –

In the Management portal open the directory’s application tab and clicked on the Add button at the bottom toolbar.

In the popup window, enter a name for the application ( I used ‘monitoring’, as I plan to use it to monitor my services) and keep the web application radio button selected

clip_image002

In the next screen enter a sign-on URL and application URI.
The values do not really matte as long as they are unique, as this application isn’t really going to be used by interactive users and so does not perform any browser redirection

clip_image004

As I’ve mentioned – the application represents a service principal in the directory.
To be able to authenticate using this service principal need three pieces of information – the client Id (essentially – the username of the principal), the client secret (the equivalent to the password) and the tenant Id (which is the authentication authority).

Once the application is created, within the application page in AAD, generate an application secret and note that as well as the client Id.

clip_image006

The tenant Id can be extracted using the View Endpoints button at the bottom toolbar and noting the GUID part of any of the endpoints shown –

clip_image008

With the application created,  the service principal is ready and the next step is to configure role-based-access-control to provide permissions to the relevant resources to the principal.

At the moment this needs to be done via PowerShell

To see all existing service principles –

  1. Open Azure PowerShell console
  2. Use Azure-AddAccount and sign-in with an account that has permissions to the directory
  3. Switch to AzureResourceManager mode using the Switch-AzureMode AzureResourceManager command
  4. Ensure you’re using the correct subscription using Select-AzureSubscription
  5. Use the Get-AzureADServicePrincipal command to see a list of the service principals in the active directory.

Doing so also reveals the service principal’s Object Id which is needed in order to assign permissions to the newly created principal to the relevant resource. This is done using the New-AzureRoleAsignment cmdlet.

The following example assigns a service principal the Contributor role for a specific resource group.

The scope can be expanded, of course, to more specific elements such as the document db account or even a specific database –

New-AzureRoleAssignment -ObjectId {service principal’s objectId} -RoleDefinitionName {role i.e Contributor} -Scope /subscriptions/{subscription id}/resourceGroups/{resource group name}

Authenticating using Azure Active Directory

With a principal in place and the right permissions set, the next step is to authenticate to Azure AD using the service principal’s credentials (the client id and client secret).

In .net this can be done using the Active Directory Authentication Library, here’s a brief code sample-

private static string GetAuthorizationHeader (string tenantId, string clientId, string clientSecret)
{
	var context = new AuthenticationContext("https://login.windows.net/" + tenantId);
	ClientCredential creds = new ClientCredential(clientId, clientSecret);
	AuthenticationResult result = 
		context.AcquireToken("https://management.core.windows.net/", creds);
	return result.AccessToken;
}

This code snippet returns an authorization token from AAD for the service principal which can subsequently be used in requests to the Azure Resource Management to authenticate and authorise these requests.

As an aside – obtaing a token can also be done in PowerShell as follows –

$password = ConvertTo-SecureString {client secret} -AsPlainText –Force

$creds = New-Object System.Management.Automation.PSCredential ({client id}, $password) 
Add-AzureAccount -ServicePrincipal -Tenant {tenant id} -Credential $creds

David Ebbo has a great blog post title Automating Azure on your CI server using a Service Principal which walks through this in detail.

Requesting metrics from Azure Insights

Now that authentication has been completed and we’ve obtained a token for the principal, we’re ready to call the Azure Resource Manager API and retrieve the metrics required. The best way to do so is to use the aforementioned Microsoft Azure Insights Library.

The first step is to instantiate an InsightsClient with the right credentials, here’s a code snippet that does that (and uses the GetAuthorizationHeader method described earlier) –

private static InsightsClient getInsightsClient(string subscriptionId, string tenantId, string clientId, string clientSecret)
{
	Uri baseUri = new Uri("https://management.azure.com");
	string token = GetAuthorizationHeader(tenantId, clientId,clientSecret);
	SubscriptionCloudCredentials credentials = new 
		TokenCloudCredentials(subscriptionId, token);
	InsightsClient client = new InsightsClient(credentials, baseUri);
	return client;
}

With an instance of the insights client obtained, reading metrics is a simple case of creating a Urli pointing at the required resource and a filter string describing the required metrics and time frame before calling the GetMetricsAsync method of the MetricsOperations property in the client –

 

The result of this call is a MetricListResponse containing the metrics requested for the period grouped

InsightsClient client = getInsightsClient(subscriptionId,tenantId , clientId, clientSecret);

string start = DateTime.UtcNow.AddHours(-1).ToString("yyyy-MM-ddTHH:mmZ");
string end = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mmZ");

string resourceUri = string.Format("/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.DocumentDB/databaseAccounts/{2}/", subscriptionId, resourceGroupName, documentDbName);
string filterString = string.Format("(name.value eq 'Total Requests' or name.value eq 'Average Requests per Second' or name.value eq 'Throttled Requests' or name.value eq 'Internal Server Error') and startTime eq {0} and endTime eq {1} and timeGrain eq duration'PT5M'", start, end);

CancellationToken ct = new CancellationToken();

Task<MetricListResponse> result = client.MetricOperations.GetMetricsAsync(resourceUri, filterString, ct);

return result.Result;

according to the time-grain value supplied

image

Two things worth noting, as they caught me out initially –

  1. MetricValues only contains records for time slots for which there is data. If you consider the request above – I’ve asked for data for the last hour aggregated as groups of 5 minutes. the result will not necessarily contain 12 values under MetricValues groups. it will only contain records form time aggregation windows in which there was activity
  2. In addition – there is some latency in getting the data, at the moment of about 20 minutes, but this is likely to be reduced.
    The combination of these meant that for a while I thought this my  code was not working  because during my tests  I was only running load against my Document DB account for a short whilst at a time and then immediately requested the metrics.
    Because of the latency – data was not yet available, which meant MetricValues was always empty.

Once the above was pointed out to me it all made perfect sense, of course.

About Yossi Dahan
I work as a cloud solutions architect in the Azure team at Microsoft UK. I spend my days working with customers helping be successful in the cloud with Microsoft Azure.

One Response to Reading metric data from Azure using the Azure Insights library

  1. Pingback: Retrieving Resource Metrics via the Azure Insights API | Michael S. Collier's Blog

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: