Logo

dev-resources.site

for different kinds of informations.

Deploying Azure Functions with Application Insights via ARM

Published at
4/24/2019
Categories
azureresourcemanager
microsoftazure
applicationinsights
arm
Author
aloneguid
Author
9 person written this
aloneguid
open
Deploying Azure Functions with Application Insights via ARM

Recently I've started playing with Azure Function for real, end-to-end, pushing it to the limits, but that's another conversation. My last mile in mastering them was automatically creating necessary resources in Microsoft Azure via ARM templates. Functions in essence need 4 resources:

  • Azure Functions resource itself, where you are deploying your function app to.
  • A hosting plan, either web hosting or consumption. Web hosting plan is a classy one that websites use - you are pre-allocating certain resources to use and pay for them regardless whether you are using them or not. Consumption plan is the real deal, because it will charge you per execution time, so if you're not using anything you're not paying anything either. I'd generally recommend consumption plan for all function apps.
  • A storage account, which is required by azure functions to store internal state.
  • Azure Application Insights for monitoring, unless you are using another monitoring solution.
Application Insights

Creating AI resource is easy:

{
      "apiVersion": "2014-04-01",
      "name": "[variables('appInsightsName')]",
      "type": "Microsoft.Insights/components",
      "location": "[resourceGroup().location]",
      "properties": {
        "applicationId": "[variables('appInsightsName')]"
      }
    }
Consumption Plan

As well as creating a consumption plan in ARM:

{
      "comments": "consumption plan for functions",
      "type": "Microsoft.Web/serverfarms",
      "sku": {
        "name": "Y1",
        "tier": "Dynamic",
        "size": "Y1",
        "family": "Y",
        "capacity": 0
      },
      "kind": "functionapp",
      "name": "[variables('functionsWebFarmName')]",
      "apiVersion": "2016-09-01",
      "location": "[resourceGroup().location]",
      "scale": null,
      "properties": {
        "name": "[variables('functionsWebFarmName')]",
        "perSiteScaling": false,
        "reserved": false,
        "targetWorkerCount": 0,
        "targetWorkerSizeId": 0
      },
      "dependsOn": []
    }
Storage Account

No surprises in storage account either:

{
      "type": "Microsoft.Storage/storageAccounts",
      "sku": {
        "name": "Standard_LRS",
        "tier": "Standard"
      },
      "kind": "Storage",
      "name": "[variables('storageAccountName')]",
      "apiVersion": "2018-07-01",
      "location": "[resourceGroup().location]",
      "properties": {
        "networkAcls": {
          "bypass": "AzureServices",
          "virtualNetworkRules": [],
          "ipRules": [],
          "defaultAction": "Allow"
        },
        "supportsHttpsTrafficOnly": false
      }
    }
Linking it all together

The last part, the function app itself, is a bit more tricky, especially if you want to automatically integrate azure functions with application insights. The full template is here, and I'll explain the bits as well.

{
      "type": "Microsoft.Web/sites",
      "kind": "functionapp",
      "name": "[variables('functionsAppName')]",
      "apiVersion": "2016-08-01",
      "location": "[resourceGroup().location]",
      "properties": {
        "serverFarmId": "[resourceId('Microsoft.Web/serverfarms', variables('functionsWebFarmName'))]",
        "siteConfig": {
          "appSettings": [
            {
              "name": "AzureWebJobsStorage",
              "value": "[concat('DefaultEndpointsProtocol=https;AccountName=', variables('storageAccountName'), ';AccountKey=', listKeys(resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName')), providers('Microsoft.Storage', 'storageAccounts').apiVersions[0]).keys[0].value)]"
            },
            {
              "name": "AzureWebJobsDashboard",
              "value": "[concat('DefaultEndpointsProtocol=https;AccountName=', variables('storageAccountName'), ';AccountKey=', listKeys(resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName')), providers('Microsoft.Storage', 'storageAccounts').apiVersions[0]).keys[0].value)]"
            },
            {
              "name": "WEBSITE_CONTENTAZUREFILECONNECTIONSTRING",
              "value": "[concat('DefaultEndpointsProtocol=https;AccountName=', variables('storageAccountName'), ';AccountKey=', listKeys(resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName')), providers('Microsoft.Storage', 'storageAccounts').apiVersions[0]).keys[0].value)]"
            },
            {
              "name": "WEBSITE_CONTENTSHARE",
              "value": "[toLower(variables('functionsAppName'))]"
            },
            {
              "name": "FUNCTIONS_EXTENSION_VERSION",
              "value": "~2"
            },
            {
              "name": "APPINSIGHTS_INSTRUMENTATIONKEY",
              "value": "[reference(concat('microsoft.insights/components/', variables('appInsightsName'))).InstrumentationKey]"
            }          ]
        }
      },
      "dependsOn": [
        "[resourceId('Microsoft.Web/serverfarms', variables('functionsWebFarmName'))]",
        "[resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName'))]"
      ]
    }

You'll notice that function app ARM resource is not a special resource type after all, it's just a normal web app ("type": "Microsoft.Web/sites"), so how do you bind AI resource, and storage to it? And this is done via application properties, weirdly enough!

  • AzureWebJobsDashboard is some sort of thing i'm not sure about, something related to logging, it's set by Azure Portal, therefore I've left it here for consistence.
  • AzureWebJobsStorage binds storage account to the function app. The value must be a connection string, just like the previous parameter, therefore I'm generating it here. As you can see i'm using built-in string concatenation functions and also getting storage key via ARM functions on the fly, because they are part of the same template
  • I'm also not quite sure about WEBSITE_CONTENTAZUREFILECONNECTIONSTRING but again it's present in the resource generated by Azure Portal so I've added it here for consistence as well. If you know what it does, please comment here.
  • Same goes for WEBSITE_CONTENTSHARE - it was set to the application name, which I'm also generating.
  • FUNCTIONS_EXTENSION_VERSION is responsible for setting which functions runtime you are using. ~1 is old Functions v1 runtime, but i'm using new shiny .net core v2, therefore it's set to ~2.
  • APPINSIGHTS_INSTRUMENTATIONKEY is an important key which sets off integration with Application Insights. This means that every function execution will be logged and you will see it in Azure Portal nicely as well. Through trial and error I've discovered that this parameter name must be capitalised, otherwise it won't work. I'm declaring AI resource in the same ARM file, therefore I can get AI key by referencing it. *

Once deployed, there is no difference between function app created manually via the portal and via arm template.

This article was originally published on isolineltd.com on February 15, 2019

applicationinsights Article's
30 articles in total
Favicon
Optimize and Monitor Power Apps Like a Pro with Application Insights
Favicon
Application Insights - 5 Tips to Improve Your Observability
Favicon
Announcing the Tracetest Integration with Azure App Insights
Favicon
Application Insights: Display Heatmap of Page Views per calendar week
Favicon
Using Application Insights with Bicep to monitor Azure Static Web Apps and Azure Functions
Favicon
Using Application Insights For Better Application Logging
Favicon
kusto & concat string array
Favicon
Week 12 2021 - Tips I learned this week
Favicon
Application Insights for Worker Service using Serilog
Favicon
Expose data from Application Insights
Favicon
Using Fiddler for Application Insights codeless java agent with docker on WSL2
Favicon
A quick intro: Application Insights for your Angular Java stack
Favicon
Monitorando uma aplicação VueJS com o Application Insights
Favicon
Cell CMS — Criando logs robustos e monitorando uma API
Favicon
Global Error Handler in Angular + Application Insights
Favicon
Monitor application via Application Insights and send alert: Part 4 Offline Scenario?
Favicon
Monitor application via Application Insights and send alert: Part 2 Understand Telemetry Types and use advanced monitoring
Favicon
Monitor application via Application Insights and send alert: Part 1 Set Rule and Action in Unified Alert
Favicon
Web App Monitoring with Application Insights
Favicon
Application Insights SDK for Node.js part 5 : Out of box telemetries - Exception, Performance and Live Metrics Stream
Favicon
Application Insights SDK for Node.js part 4 : Out of box telemetries - Basics and Console
Favicon
Application Insights SDK for Node.js part 3 : Application Map
Favicon
Application Insights SDK for Node.js part 1 : Basic usage
Favicon
Application Insights SDK for Node.js part 2 : Track events
Favicon
Bulk add Application Insights Availability Test IPs to Azure App Service Access Restrictions using Az PowerShell
Favicon
Deploying Azure Functions with Application Insights via ARM
Favicon
Gated Release
Favicon
Adding Application Insights to Azure Functions
Favicon
What the heck is Business Intelligence?
Favicon
Monitor application via Application Insights and send alert: Part 3 Optimize telemetry and alerts

Featured ones: