Image courtesy- Network Encyclopaedia

ASP is an abbreviation for Active Server Pages. The thought process from the early days in Seattle’s Redmond office was to leverage the power that is residing on the server. Server capacity and processing power has increased from the days of ASP so did the variety of client devices, and their capacity and processing power. During the past decade or so the focus shifted to client devices with pushing the processing need to them. Many javascript frameworks sprouted, to the extend that even assembly language was interfaced with javascript to accomplish some fast operations on browser.

Blazor is many ways we found takes the stance that Redmond office took in the beginning of internet revolution. Shift the compute load to server. Make it do the heavy lifting. It has been around for couple of years now. The server workload of Blazor is in Generally Available (GA) with promise of stability in production environment. Other hosting environment like WebAssembly and Mobile is still in experimental stage.

We assume a discourse into what Blazor and its capability is futile as there is plenty of good words on that in the official documentation. We rather will share our recent experience where we had to determine the number of active circuits in the Blazor’sSignalR server. This helped us explore the less explored territory of Blazor.

Background

One of the key hindrances to Blazor’s adoption is how is the concern on scalability to greater pressure of connections. As more and more clients connect the pressure on server to have active connection and maintain the state of client’s DOM among other things made us think what happens in spike of client’s connection.

For reasons beyond worth exploration in this article we did not have the option to switch to MVC or equivalent framework. Sticking with Blazor we decided to put to test in lower environment to simulate load. We then explored the metrics that we could monitor to understand the impact. We hosted the application in Azure. In Azure WebApp’s the metrics were standard ones and did not offer much insights into the circuits that were active in a Blazor server.

The approach

Our first solution to

With app insights out of our way we had to look at a bespoke solution to address the ask of getting insights on the metric. That is when we stumbled on the CircuitHandler. This class is present in the namespace Microsoft.AspNetCore.Components.Server.Circuits. As we studied this class a bit more, it came with the responsibility. By deriving this class and annexing it to our Blazor app we are taking the responsibility of managing Circuits lifecycle events. Any fatal failure here will cause the application to crash. So, responsible exception handling and graceful shutdown is very important.

Our idea was to absorb this responsibility and implement a counter that counts all the new circuits that gets created and decreases the counter when circuits are dropped. Now, this is how our circuit handler looked –

 

using Microsoft.AspNetCore.Components.Server.Circuits;

using Microsoft.ApplicationInsights;

using System.Collections.Generic;

using System.Threading;

using System.Threading.Tasks;

 

 

public class MetricCreatorHook : CircuitHandler

{

   private HashSet<Circuit> circuitsAvailable = new();

   private TelemetryClient telmetClient = new();

 

   public override Task OnConnectionUpAsync(Circuit instance, CancellationToken cancToken)

   {

       circuitsAvailable.Add(instance);

       var countMetric = new MetricTelemetry();

       countMetric.Name = “CircuitsConnected”;

       countMetric.Value = circuitsAvailable.Count;

       telmetClient.TrackMetric(countMetric);

       return Tasks.CompletedTask;

   }

 

   public override Task OnConnectionDownAsync(Circuit instance, CancellationToken cancToken)

   {

       circuitsAvailable.Remove(instance);

       var countMetric = new MetricTelemetry();

       countMetric.Name = “CircuitsConnected”;

       countMetric.Value = circuitsAvailable.Count;

       telmetClient.TrackMetric(countMetric);

       return Task.CompletedTask;

    }

 

   public int ConnectedCircuits => circuitsAvailable.Count;

}

 

 

Here we have a class that holds a list of circuits and logs the value every time a new connection is created or destroyed. The immediate next thing we need to do is to register this class as a singleton with the DI for the Blazor

 

public void ConfigureServices(IServiceCollection services)

{

   …

   services.AddSingleton<CircuitHandler, MetricCreatorHook>();

}

 

We did not talk much about the AppInsights configuration to stay focused on the CircuitHandler approach. But needless to say, registering AppInsights in the service is needed to get that working. Happy coding till next time.