Replacing your application stack with Azure services

I've been thinking recently what would be the cost of Azure services, if I'd like to replace my VM with this particular cloud solutions. Please do have in mind, that in this post I'm not taking into account multiple third-party applications(like TeamCity or YouTrack), which I run on the VM along with my projects. Only technology stack matters.

What do we have?

My VM is a very basic machine:

  • Windows Server 2012
  • 1 Core AMD Opteron Processor 6386 SE 2,80 GHz
  • 50 GBs HDD storage
  • 4 GBs RAM

It's perfectly fine to run a simple SPA application, SQL server and EventStore to aggregate events from multiple devices. It's far from optimal solution but serves well since many months. Cost - about 18 EUR. 

If I had a chance to start from scratch, I'd select following stack on Azure:

  • EventHub for 10M events for 9,65 EUR
  • App Service shared infrastructure for 8,16 EUR
  • Table Storage with 50 GBs of storage and 100 transaction units for 3,26EUR

It gives total of 21,06 EUR.

Pros and cons?

While having a VM gives you great flexibility, it also complicates many things when it comes to update all software, deploy and configure it. It's also a bit more difficult to integrate all together. The biggest disadvantage of a VM is the lack of scalability - if an application will meet its higher requirements, it will cost us much more to migrate to the higher stack.

The downside of a stack built on Azure is having shared infrastructure for our web application which can(but doesn't have to be) problematic from time to time. What I like about this solution is having it all in once place and integrating it all with ease. What is more I can add Azure B2C for free and have a widely used access control solution for my application. Who knows, maybe I'll migrate to the cloud in the future?

Monitoring available threads for an application in Azure

Recently I've been thinking how can I track amount of threads available for an application hosted in Azure cloud. It was due to early discovered performance issues, which should be addressed sooner than later. Since we've decided to be async-heavy and made many possible breaking changes, solid metrics related to different application domains should be introduced and implemented.

Since we're taking advantage of Application Insights when measuring performance, finding a way to utilize it and measure threads available for our web app seems natural and uncomplicated. Fortunately Microsoft.ApplicationInsights NuGet package contains ITelemetryInitializer, which looks like this:

using Microsoft.ApplicationInsights.Channel;

namespace Microsoft.ApplicationInsights.Extensibility
{
  /// <summary>
  /// Represents an object that initializes <see cref="T:Microsoft.ApplicationInsights.Channel.ITelemetry" /> objects.
  /// </summary>
  /// <remarks>
  /// The <see cref="T:Microsoft.ApplicationInsights.DataContracts.TelemetryContext" /> instances use <see cref="T:Microsoft.ApplicationInsights.Extensibility.ITelemetryInitializer" /> objects to
  /// automatically initialize properties of the <see cref="T:Microsoft.ApplicationInsights.Channel.ITelemetry" /> objects.
  /// </remarks>
  public interface ITelemetryInitializer
  {
    /// <summary>
    /// Initializes properties of the specified <see cref="T:Microsoft.ApplicationInsights.Channel.ITelemetry" /> object.
    /// </summary>
    void Initialize(ITelemetry telemetry);
  }
}

All it needs is to implement Initialize() method.

Worth noting is the fact, that such initializer will be hit by all traces so don't go crazy when using it to log data from external resources etc.

With such interface, creating a custom initializer, which will log information about threads is a piece of cake:

//
public class AvailableThreadsInitializer : ITelemetryInitializer
{
	public void Initialize(ITelemetry telemetry)
	{
		int workerThreadsMax;
		int completionPortThreadsMax;
		int workerThreadsAvailable;
		int completionPortThreadsMaxAvailable;

		ThreadPool.GetMaxThreads(out workerThreadsMax, out completionPortThreadsMax);
		ThreadPool.GetAvailableThreads(out workerThreadsAvailable, out completionPortThreadsMaxAvailable);

		telemetry.Context.Properties["Max. threads"] = workerThreadsMax.ToString();
		telemetry.Context.Properties["Max. threads(async I/O)"] = completionPortThreadsMax.ToString();
		telemetry.Context.Properties["Available threads"] = workerThreadsAvailable.ToString();
		telemetry.Context.Properties["Available threads(async I/O)"] = completionPortThreadsMaxAvailable.ToString();
	}
}

All what is left to do is to add this initializer to the collection of already defined initializers:

//
TelemetryConfiguration.Active.TelemetryInitializers.Add(new AvailableThreadsInitializer());

Thanks to this change, each trace will have an information about threads available for your application - for sure it will ease diagnosis when something is wrong with your web application.

Thanks to @marekgrabarz for revealing this feature to me!