How to do health checks for Azure functions and Web Apps.

With Azure Monitor and IaaS via C#.

Stas(Stanislav) Lebedenko
Microsoft Azure

--

This article is a part of the https://www.azurespringclean.com/ #AzureFamily community event.

There were two reasons to write this article, the first one is that basic health checks usually not added in the early stages of projects and not deployed with infrastructure. The second one is the awesome Microsoft Extensions.Diagnostics.HealthChecks is not supported by Azure Functions for a good reason, but there is a native health monitor configuration and walkaround from the community on GitHub.

So I decided to share several approaches that can be used together or independently, but all approaches are super easy to repeat for any project(Azure Portal setup is not an easily repeatable solution). This article is a part of the #AzureSpringClean #AzureFamily community event.

TL;DR; I will cover Azure Monitor health checks that can be deployed along the main infrastructure written via C#(Pulumi), then provide anoverview of Azure Functions health monitor configuration which I`m using and provide usage example of Health checks package for WebApps and link to workaround for Azure Functions

Azure Monitor health checks with infrastructure.

Let’s start with a simple approach that is not related to changes in a solution code, but still needs to be written with C# :).

For this purpose, we can use the Pulumi framework, which I started to adopt recently to increase the adoption of the IaaS approach within developers teams. Writing JSON and YAML file is not fun and usually meet a lot of backpressure from developer teams g the classic response is “we will ask DevOps engineer to do a task”. And the ability to do this task with strongly typed language is usually met with curiosity.

Short introduction Pulumi/C# video below, if you prefer video format.

Short introduction — Pulumi for developers

The first step is to install Pulumi, generate a new project, apply your C# infrastructure code and deploy it to Azure.

  1. Install Pulumi from https://www.pulumi.com/docs/get-started/install/
  2. Run in the CMD az login command to get an auth token for a subscription.
  3. Run pulumi login (you will be prompted to register a new account)
  4. Run pulumi new azure-csharp to create the new C# app for your infrastructure.
  5. You can open this project both in VS Code or Visual Studio 2019, I prefer the latter for better IntelliSense support :).

Now let's have a look at our project, Program.cs is a classic entry point for application start, and Stack.cs will contain our infrastructure.

Pulumi project structure.

Let's write some infrastructure, I cannot express how cool it is to write a C# code for my Azure infrastructure. Let's examine basic infrastructure with my example.

There a few things to note, at the moment Pulumi has two providers for Azure, the old one based on Terraform and the new one based on Azure Resource Manager API. I will use the new one - Pulumi.AzureNative v0.7 and version 1.0 are due at the end of April.

And another important thing is that Pulumi is not free for teams, but the great news that it is free for personal usage and only 50$ per month for small teams. Which is cheaper than dedicated DevOps engineer hours :). I will also not do the deep dive into why “desired state configuration” is great.

The infrastructure code below contains Azure Functions, Azure SQL.

Basic infrastructure code via C#

The only thing is needed to open cmd and run command pulumi up.

There is an option to avoid the command line and make deployments with a C# code, also Pulumi can be integrated with Azure DevOps or GitHub, the command line in this article used for the sake of brevity.

Preview of resources that will be deployed.

And after selection of the yes option, my resources are online.

Deployment results.

And now to the fun part, let's add a basic availability test. While most of the infrastructure is covered by Pulumi, some exotic cases still require XML stuff to work, such as fields in this availability test. And moreover, current documentation sometimes doesn't reflect all needed changes for exotic cases like this alert. But they will improve WebTestPropertiesConfigurationArgs class to handle all configuration fields.

Let's add this test to our infrastructure.

Azure availability Alert.

But before I will share the successful deployment screen, let me share what will happen if you misspell something in the XML string above. Not very informative.

Internal exception during deployment

But in other cases, linking internal fields of Pulumi objects inside concatenated string can produce meaningful errors :).

Mention of exact error during infrastructure deployment.

So after a few fixes, I deployed the alert and then updated it.

Successful update of Alert configuration.

One of many benefits of writing infrastructure via Pulumi/C# is

Azure Functions host health monitor.

In this section, I will cover the magic of the Azure Functions host.json file. If there is a need to configure ingest, scalability of monitoring is a place to go. So configuring the application this way is also a repeatable option, though it can be changed at any time.

I will not repeat official documentation in this article but provide my configuration and few important takeaways from usage. You need to monitor additional parameters of function app host like connection limits and track these errors in connected Application Insights Instance. The Azure Functions runtime in Azure is not aware of any additional logic like HealthCheck middleware outside of functions execution context.

So in order to have proper health checks, you should create a special alert rule(with IaaS code) in Application Insights so it can be triggered with a specific type of event, that contains “Host thresholds exceeded - message”

This solution is only for applications deployed to Consumption Plan.

{
"healthMonitor": {
"enabled": true,
"healthCheckInterval": "00:05:00",
"healthCheckWindow": "00:10:00",
"healthCheckThreshold": 6,
"counterThreshold": 0.80
}
}

Host Health Monitor · Azure/azure-functions-host Wiki (github.com)

An alternative workaround(or if you use Premium functions plan) is to use a guide and code from Keith Smith, his approach will use classic NuGet packages from Microsoft along with a custom code wrapper and Azure Function to expose health checkpoint of application.

Microsoft.Extensions.Diagnostics.HealthChecks
Microsoft.Extensions.Diagnostics.HealthChecks

Adding Health Checks to your Azure Functions (keithmsmith.com)

Azure Web Apps health monitoring.

.NET Core is providing middleware for health checks and reporting of the health of a variety of standard components such as Entity Core Framework DB context, underlying databases, and its super easy to customize health checks for any of your components.

Let's cover this functionality briefly, everything starts with the standard Startup class and health monitoring of standard components. Take for example package:

Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore

All you need is to add a health check to services and configure the monitoring endpoint, so you can visit it via the application.

Sample of basic health check configuration.

One important notice, this health endpoint can be also configured from the App Service via Azure Portal since August 2020.

Sample with an underlying service error.

The summary.

Sometimes basic scenarios are enough and if you can create them via easily configurable code and repeating of this code for all you project can be a first major milestone.

But there is more, you might need to monitor the health of your database in Azure, receive additional alerts via different Azure Monitor alerts. In order to write less code you can create a set of alerts for different types in Azure Portal, then export the ARM template and convert them to C# Pulumi via an online converter https://www.pulumi.com/arm2pulumi/.

Or you can embrace the native .NET Core approach via code provided by Microsoft. My take is to go with the infrastructure approach for cloud component and try to delegate this work to developers(not DevOps engineers)

That’s it, thanks for reading. Cheers!

--

--

Stas(Stanislav) Lebedenko
Microsoft Azure

Azure MVP | MCT | Software/Cloud Architect | Dev | https://github.com/staslebedenko | Odesa MS .NET/Azure group | Serverless fan 🙃| IT2School/AtomSpace