Month: November 2022

Azure DiagnosticSettings and Bicep

This is not the explain everything article, but something I wrote as a guide to how I usually solve the issue of DiagnosticSettings.

The basics

I will assume you know what Diagnostics are within Azure and that you know how to create and deploy Bicep. This post aims at showing you how you can solve how to connect Azure Diagnostigs to your resources, using Bicep.

The Scenario

In this scenario I will use something very specific but it will work just as well for your scenario. I am using autoscaling for an Azure Function environment (or Service Plan if you prefer). If the function gets a lot of traffic, the autoscaler will add an additional instance and then remove instances if the traffic goes down.

The autoscaler can alert users whenever it fires. Either by sending emails or using a webhook. However you also need a record of when the autoscaler triggered. That is very useful when you want to analyze traffic and response times.

Bicep and DiagnosticSettings

A diagnostic setting is different compared to, lets say an Azure Storage. Normally, a resource can be deployed by itself but diagnosticsettings need to be connected to an existing resource. This is called Extension Resource.

When deploying an extension resource you simply need to tell it which other resource it is connected to. You do this using the scope property.

Here is an example from my Bicep file:

resource LogAnalyticsConnection 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = {
  name: 'scaling'
  scope: FunctionplanElastic_Autoscale
  properties: {...}
}

The FunctionplanElastic_Autoscale is the autoscale I have created for my function.

The problem

When deploying a diagnostic setting you might not always know which metrics are available to you, and in some cases the metrics differ between the portal and the APIs used by Azure for deployment. So using the portal is not the best way, because you get strange errors complaining about different metrics not being available.

Another problem is that diagnostic settings are not exported as a part of the resource, so finding the settings can be really tricky.

A solution

This is in two parts: Finding what resource to scope, and finding what metrics and logs are available to you.

Finding the scope

This is the easy part. When you navigate the Azure Portal you connect diagnostic settings to a resource. That is the scope you are looking for. If you need it for an Azure Storage, that storage is the scope. In my case, I needed it for an autoscaling resource which in turn is connected to an Azure function. In this case, the diagnostic settings should be connected to the autoscaler.

Finding the Logs and Metrics

There is an API for this called Diagnostic Settings – List!
If you call the API you will get the possible diagnostic settings for that particular resource, including syntax. Using the API is a little tricky but here goes:

Authenticating the API

The caller needs to have read access to the resource. I recommend you use my “Login as yourself” post to manage the API authorization.

Setting up the URI

This is the tricky part. Here is the documentation version GET https://management.azure.com/{resourceUri}/providers/Microsoft.Insights/diagnosticSettings?api-version=2021-05-01-preview.

The tricky part is the resourceUri. Here is my version from Postman.

https://management.azure.com/subscriptions/:subscriptionId/resourcegroups/:resourcegroupName/providers/:provider/:resourceName/providers/Microsoft.Insights/diagnosticSettings?api-version=2021-05-01-preview

The resourceUri has 4 different parts:
– The subscriptionId: I think you know what this is.
– The resourceGroupName: Yeah, you know this too.
Provider this is the provider name of the resource type you are trying to access.
The easiest way to find this is to look in the URL when you access the resource in the Azure Portal. This always contains a /, for instance Microsoft.DataFactory/factories.
ResourceName: This is simply the name of the resource you are trying to access.

In my scenario: https://management.azure.com/subscriptions/XXXX-YYYY-zzzz-eeee-wuertweuygfdu/resourcegroups/SYS001-Identifier-RG/providers/microsoft.insights/autoscalesettings/MyAutoscaler/providers/Microsoft.Insights/diagnosticSettings?api-version=2021-05-01-preview

This replies back with this body:

{
    "value": [
        {
            ...
                "metrics": [
                    {
                        "category": "AllMetrics",
                        "enabled": false,
                        "retentionPolicy": {
                            "enabled": false,
                            "days": 0
                        }
                    }
                ],
                "logs": [
                    {
                        "category": "AutoscaleEvaluations",
                        "categoryGroup": null,
                        "enabled": false,
                        "retentionPolicy": {
                            "enabled": false,
                            "days": 0
                        }
                    },
                    {
                        "category": "AutoscaleScaleActions",
                        "categoryGroup": null,
                        "enabled": true,
                        "retentionPolicy": {
                            "enabled": false,
                            "days": 0
                        }
                    }
                ],
                "logAnalyticsDestinationType": null
            },
            "identity": null
        }
    ]
}

Note! There is two small issues here.
1. If you have selected any logging, then that is the configuration that will show up. To know which features are available, the option has to be unconfigured.
2. If you have not added any diagnostic settings before, the APIs returns an empty list.

So now I know which features are available. I need both logging options, so I will add allLogs to my Bicep.

Updating the Bicep file

My finished Bicep looks like this:

param logAnalyticsResourceId string
...
resource LogAnalyticsConnection 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = {
  name: 'scaling'
  scope: FunctionplanElastic_Autoscale
  properties: {
    workspaceId: logAnalyticsResourceId
    logs: [
      { 
        enabled: true
        categoryGroup: 'allLogs'
        retentionPolicy: {
          days: 30
          enabled:true 
        }
      }
    ]
  }
}

Conclusion

Adding diagnostic settings needs to be done using another process since they cannot be downloaded. You can access and API to get the settings available to you.

If you need the files used in this scenario you can find them in my GitHub Repo.