Creating a solution with multiple small services is great of course. It provides you with a lot of flexibility and scalability.

There are however a couple of things you have to think about when designing and developing a solution with multiple services. One of the things you need to figure out is how to implement proper logging. For an actual production system you need to have this in place in order to monitor and debug the overall solution.

We, developers using Azure Functions, are already blessed with some logging mechanisms and tools provided out of the box! The out of the box stuff is pretty basic, but it gets the job done and will make your life much easier when the need arises to analyze a production issue.

Logging in your function

When first creating your Azure Function you will probably see a parameter being passed in your `Run` method called `log`.

public static class Function1
    public static async Task<HttpResponseMessage> Start(
        [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = null)]
        HttpRequestMessage req, 
        TraceWriter log)
        log.Info("C# HTTP trigger function processed a request.");

        // Logic

This `log`-parameter can be used to do some simple logging inside your Azure Function. When invoking this function you’ll be able to see the specified log entry in your console.

[10-4-2018 19:12:12] Function started (Id=a669fc9a-b15b-44b9-a863-47a303aca6b6)
[10-4-2018 19:12:13] Executing 'Function1' (Reason='This function was programmatically called via the host APIs.', Id=a669fc9a-b15b-44b9-a863-47a303aca6b6)
[10-4-2018 19:12:13] C# HTTP trigger function processed a request.

All of the other common logging levels, like `Error`, `Warning` and `Verbose`, are also implemented in the TraceWriter.

After having deployed the Azure Function to Azure you will also be able to see the log messages in the Portal.

2018-04-10T19:30:09.112 [Info] Function started (Id=71cead2b-3f90-4c04-8c82-42f6a885491a)
2018-04-10T19:30:09.127 [Info] C# HTTP trigger function processed a request.
2018-04-10T19:30:09.205 [Info] Function completed (Success, Id=71cead2b-3f90-4c04-8c82-42f6a885491a, Duration=87ms)

Checking out the log messages inside the log monitor is nice and all, but the best thing over here is the (automatic) integration with Application Insights! If you have activated this feature you will be able to see all logs in the Application Insights Search blade.


I totally recommend using Application Insights to monitor your application, along with all of the logging, as it’s an awesome piece of technology with endless possibilities for your DevOps teams. I’ll share more of my experience with Application Insights in a later post, because it’s too much to share in a single post.

Using the `TraceWriter` is a nice way to get you started with logging, but it’s probably not something you want to use in an actual application.

Introducing the `ILogger`

A different way to start logging is by using the `ILogger` from the `Microsoft.Extensions.Logging` namespace. You can just replace the earlier mentioned `TraceWriter` with the `ILogger`, change the logging methods and be done with it. The Azure Functions runtime will make sure some concrete implementation is being injected which will act similarly to the `TraceWriter`.
The main benefit will be the improved testability of your Azure Function as this parameter is much easier to mock.

One thing I did notice though is the `ILogger` doesn’t output any logging to the Azure Functions console application when running locally. There appears to be an (now open) issue on GitHub which mentions this bug. But don’t worry, you can see all the expected logging in the available tooling of the Azure Portal.

As mentioned, the `ILogger` is a better solution if you want to use Azure Functions in your actual project, because it offers better testability. However, the functionality is quite limited and you can’t extend much on the `ILogger` at this time. If you already have some kind of logging mechanism or framework elsewhere in your solution your probably don’t want to introduce this new logging implementation. My go-to logging framework is log4net and I'd like to use it for the logging inside my Azure Functions also. In order to do so you need to configure a thing or two when setting up log4net. It isn’t very complicated, but something to keep in mind when setting up the Azure Functions.
I’ll describe the necessary steps in a later post.

For now my main advice is just to use the `ILogger` instead of the `TraceWriter`. Both work very well, but `ILogger` offers some advantages compared to the `TraceWriter`.

So you might remember me posting about using the Let’s Encrypt site extension for Azure App Services, called Azure Let’s Encrypt, created by SJKP.

This has quite well for over a year now and even works for Function Apps.

However, last month I got notified my SSL certificate was expired on one of my sites. Strange, as an automated job should just handle this for me. I thought the job probably didn’t execute because of some glitch in the matrix. Therefore I logged in manually, started the site extension wizard again and was stuck on this screen.


The reason I was stuck was because the ClientId and ClientSecret didn’t work anymore. As these settings hadn’t changed since I started using this extension I found it quite strange.

Apparently, the Server Principal, which I had created last year, somehow had changed and I didn’t know how to change it back. Lucky for me, managing the AAD isn’t very hard to do nowadays. With a bit of trial and error I was able to create a new SNP and use these details on the Let’s Encrypt site extension.

Creating a new application in AAD

First thing you need to do is add a new Appliction to your AAD. Be sure to pick the option App registrations over here and press the New application registration.


When creating an application you have to specify a name, I chose `LetsEncrypt` and which type it is. Just choose the `Web app/ API` option over here. The other mandatory field called `Sign-on URL` isn’t used in our scenario so you can use any URL you like.

When your application is created you’ll see be navigated to the overview page of this application. Be sure to copy the Application ID from over here as you need it later on. This value has to be used as the ClientId in the site extension.


Next thing we need to do is add a Key to this application. You can add new keys by Settings link and choose the Keys option. This key will be used as the Client Secret. Be sure to copy the value after saving as this is the only time you’ll be able to see it.


Also note the Expires option.

The default expiration date is set to 1 year from now. This has led me to believe the ClientSecret of my earlier SNP is probably expired. In hindsight I could probably have updated the value in my old SNP and be done with it.

We now have everything we need from our application, so the next thing is to set up the resource group.

Set up your resource group

We need the newly created application to do stuff inside our resource group. Therefore we need to add some permission to it.

To do so, head down to the resource group which contains your app service(s) and pick the Access control (IAM) option.


From over here you can select your newly created application and grant it the Contributor role.


If everything goes well you’ll see the application is added to the list of contributors of this resource.


Running the wizard again

Everything should be set up correctly now so you can head back to the wizard of the site extension. Be sure to fill out the ClientId and ClientSecret with the newly retrieved values from the application.

After doing so and trying to proceed to the next screen I was prompted with the message `The ClientId registered under application settings [guid] does not match the ClientId you entered here [guid]` as you can see in the screenshot below.


The first time I ran this wizard (a year ago) it was able to create and update the application settings of the App Service. Apparently this has changed and I had to change the Application Settings by myself in the App Service before I was able to continue in the Let’s Encrypt site extension.

For completeness sake, if you’re running a Function App, you can find the settings under All settings, which will navigate you to the App Service settings.


After you’ve changed these settings you should be able to proceed and continue with requesting your SSL certificates.

That’s all there is to it!

Hope it helps whenever you run into problems if your SNP doesn’t work anymore. As I already mentioned, in hindsight it would probably have been much easier by just updating the Key of my original SNP, which I’ll probably need to do in 2 years from now when this new secret will expire.

In a couple of weeks, on the 22nd of February, I’ll be talking at a free event organized by 4DotNet and SnelStart called Move Up with Azure. I’m not the only one who will be speaking over there, there’s also a great session by Henry Been (SnelStart) and an awesome talk from Christos Matskas (Microsoft).

I myself will be talking on how to create a serverless solution using Azure Functions. This of course is a very broad subject and I’d like to know what you think I should focus on or what you would like to see covered in this session?

Some areas which I’ll be covering for sure is a short introduction on the serverless paradigm, how to design and create a scalable architecture, using built-in functionality offered by Azure Functions to make your life easier, working with Visual Studio to get stuff done and of course how to test your solution.
There are a lot of other subjects which I can also cover and deep-dive into. Feel free to comment over here if you have a specific interest in something related to serverless or Azure Functions. For example Durable Functions, performance, common patterns & principles.

Hope to see you on the 22nd of February in Nieuwegein. Be sure to register on Eventbrite to get your free ticket for this event!

Warming up your web applications and websites is something which we have been doing for quite some time now and will probably be doing for the next couple of years also. This warmup is necessary to ‘spin up’ your services, like the just-in-time compiler, your database context, caches, etc.

I’ve worked in several teams where we had solved the warming up of a web application in different ways. Running smoke-tests, pinging some endpoint on a regular basis, making sure the IIS application recycle timeout is set to infinite and some more creative solutions.
Luckily you don’t need to resort to these kind of solutions anymore. There is built-in functionality inside IIS and the ASP.NET framework. Just add an `applicationInitialization`-element inside the `system.WebServer`-element in your web.config file and you are good to go! This configuration will look very similar to the following block.

    <add initializationPage="/Warmup" />

What this will do is invoke a call to the /Warmup-endpoint whenever the application is being deployed/spun up. Quite awesome, right? This way you don’t have to resort to those arcane solutions anymore and just use the functionality which is delivered out of the box.

The above works quite well most of the time.
However, we were noticing some strange behavior while using this for our Azure App Services. The App Services weren’t ‘hot’ when a new version was deployed and swapped. This probably isn’t much of a problem if you’re only deploying your application once per day, but it does become a problem when your application is being deployed multiple times per hour.

In order to investigate why the initialization of the web application wasn’t working as expected I needed to turn on some additional monitoring in the App Service.
The easiest way to do this is to turn on the Failed Request Tracing in the App Service and make sure all requests are logged inside these log files. Turning on the Failed Request Tracing is rather easy, this can be enabled inside the Azure Portal.


In order to make sure all requests are logged inside this log file, you have to make sure all HTTP status codes are stored, from all possible areas. This requires a bit of configuration in the web.config file. The trace-element will have to be added, along with the traceFailedRequests-element.

    <add path="*">
        <add provider="WWW Server" 	
		verbosity="Verbose" />
      <failureDefinitions statusCodes="200-600" />

As you can see I’ve configured this to trace all status codes from 200 to 600, which results in all possible HTTP response codes.

Once these settings were configured correctly I was able to do some tests between the several tiers and configurations in an App Service. I had read a post by Ruslan Y stating the use of slot settings might help in our problems with the warmup functionality.
In order to test this I’ve created an App Service for all of the tiers we are using, Free and Standard, in order to see what happens exactly when deploying and swapping the application.
All of the deployments have been executed via TFS Release Management, but I’ve also checked if a right-click deployment from Visual Studio resulted in different logs. I was glad to see they resulted in having the same entries in the log files.


I first tested my application in the Free App Service (F1). After the application was deployed I navigated to the Kudu site to download the trace logs.

Much to my surprise I couldn’t find anything in the logs. There were a lot of log files, but none of them contained anything which closely resembled something like a warmup event. This does validate the earlier linked post, stating we should be using slot settings.

You probably think something like “That’s all fun and games, but deployment slots aren’t available in the Free tier”. That’s a valid thought, but you can configure slot settings, even if you can’t do anything useful with it.

So I added a slot setting to see what would happen when deploying. After the deploying the application I downloaded the log files again and was happy to see the a warmup event being triggered.

  <Data Name="ContextId">{00000000-0000-0000-0000-000000000000}</Data>
  <Data Name="Headers">
    Host: localhost
    User-Agent: IIS Application Initialization Warmup

This is what you want to see, a request by a user agent called `IIS Application Initialization Warmup`.

Somewhere later in the file you should see a different EventData block with your configured endpoint(s) inside it.

  <Data Name="ContextId">{00000000-0000-0000-0000-000000000000}</Data>
  <Data Name="RequestURL">/Warmup</Data>

If you have multiple warmup endpoints you should be able to see each of them in a different EventData-block.

Well, that’s about anything for the Free tier, as you can’t do any actual swapping.


On the Standard App Service I started with a baseline test by just deploying the application without any slots and slot settings.

After deploying the application to the App Service without a slot setting, I did see a warmup event in the logs. This is quite strange, to me, as there wasn’t a warmup event in the logs for the Free tier. This means there are some differences between the Free and Standard tiers considering this warmup functionality.

After having performed the standard deployment, I also tested the other common scenario’s.
The second scenario I tried was deploying the application to the Staging slot and press the Swap VIP button on the Azure portal. Both of these environments (staging & production) didn’t have a slot setting specified.
So, I checked the log files again and couldn’t find a warmup event or anything which closely resembled this.

This means deploying directly to the Production slot DOES trigger the warmup, but deploying to the Staging slot and execute a swap DOESN’T! Strange, right?

Let’s see what happens when you add a slot setting to the application.
Well, just like the post of Ruslan Y states, if there is a slot setting the warmup is triggered after swapping your environment. This actually makes sense, as your website has to ‘restart’ after swapping environments if there is a slot setting. This restarting also triggers the warmup, like you would expect when starting a site in IIS.

How to configure this?

Based on these tests it appears you probably always want to configure a slot setting, even if you are on the Free tier, when using the warmup functionality.

Configuring slot settings is quite easy if you are using ARM templates to deploy your resources. First of all you need to add a setting which will be used as a slot setting. If you haven’t one already, just add something like `Environment` to the `properties` block in your template.

"properties": {
  "Environment": "ProductionSlot"

Now for the trickier part, actually defining a slot setting. Just paste the code block from below.

  "apiVersion": "2015-08-01",
  "name": "slotconfignames",
  "type": "config",
  "dependsOn": [
"properties": {
  "appSettingNames": [ "Environment" ]

When I added this to the template I got red squigglies underneath `slotconfignames` in Visual Studio, but you can ignore them as this is valid setting name.

What the code block above does is telling your App Service the application setting `Environment` is a slot setting.

After deploying your application with these ARM-template settings you should see this setting inside the Azure Portal with a checked checkbox.


Some considerations

If you want to use the Warmup functionality, do make sure you use it properly. Use the warmup endpoint(s) to ‘start up’ your database connection, fill your caches, etc.

Another thing to keep in mind is the swapping (or deploying) of an App Service is done after all of the Warmup endpoint(s) are finished executing. This means if you have some code which will take multiple seconds to execute it will ‘delay’ the deployment because of this.

To conclude, please use the warmup-functionality provided by IIS (and Azure) instead of those old-fashioned methods and if deploying to an App Service, just add a slot setting to make sure it always triggers.

Hope the above helps if you have experienced similar issues and don’t have the time to investigate the issue.

A new year has started, so it’s time to reflect and think of what we’ll be doing the rest of this new year.

2017 has been a great year for me, not only from a technical point of view, but also personally.
First of all, I have had the chance to be an amazing dad for our son. Being a dad is the best thing one can imagine. Seeing the joy in your child’s eyes whenever you get home and seeing him grow up so quickly is just amazing! 2017 is also the year we got blessed by being pregnant again! We are expecting our second kid any day now. Both of these things are probably the biggest highlights of the year. Of course, we also moved between houses, just in time for our baby to get born in the new house. Really looking forward to this event!

As I said, 2017 also was a great year for my professional life. First of all I’ve had to chance to speak at a 4DotNet event early in the year and a couple of months later I was picked to deliver 2 sessions at the TechDays Netherlands. Aside from these two big events I also talked a couple of times at some smaller user groups and companies.
I’ve also started at a project from an existing customer of us. This project is being developed completely with the Azure stack and most of the time we have the chance to develop our solutions with the latest and greatest technologies Azure has to offer.
My personal focus has been in the serverless space. Azure Functions are just amazing and you’ve probably seen quite a bit of blog posts on the subject over here.

Hopefully this year, 2018, will be just as amazing as the past. Of course, we are expecting our baby any day now. I’m pretty sure this will be the biggest highlight of the year.
Professionally I’ll continue to focus on the serverless technologies like Azure Functions and Cosmos DB. This means you can expect even more blog posts on these subjects. I’m also planning to do a lot more talks on these subjects. So if you have an event and are in need of speakers, or would like me to talk on serverless technologies at your company, feel free to contact me.

Well, that’s enough reflection and future-telling for me.
What are your own plans this year? I really hope all of them will come true.