In the backend services team at SATS, we extensively use Azure Application Insights for logging, performance metrics, and perhaps most crucially, tracing requests across services. This allows us to trace requests from apps/websites throughout our platform, observe the performance impact of various services, and pinpoint where in the stack any errors occur.

We also frequently utilize Redis in our event-based architecture to cache read models close to our apps. Contrary to most services (like HTTP requests, Azure SQL, etc.), calls to Redis, made using the StackExchange.Redis Nuget package, aren’t automatically tracked in Application Insights.

However, integrating your custom dependency tracking into Application Insights is relatively straightforward:

var startTime = DateTime.UtcNow;
var timer = System.Diagnostics.Stopwatch.StartNew();
try
{
    // making dependency call
    success = dependency.Call();
}
finally
{
    timer.Stop();
    telemetryClient.TrackDependency(
        "myDependencyType",
        "myDependencyCall",
        "myDependencyData", 
        startTime,
        timer.Elapsed,
        success);
}

The challenge lies in embedding that tracking into StackExchange.Redis. To achive this we’ve used AspectCore, which is described as:

[…] an Aspect-Oriented Programming based cross platform framework for .NET Core and .NET Framework.

While Aspect-Oriented programming covers a broad spectrum, our focus is on intercepting any calls through the IRedisDatabase interface, allowing us to integrate dependency tracking. It’s worth noting that the same could be achieved by wrapping the IRedisDatabase interface. But since this interface has a lot of methods, that would be tedious, error prone and not future-proof.

Creating a dynamic proxy with AspectCore and embedding your desired interceptor is a breeze:

var generator = new ProxyGeneratorBuilder()
    .Configure(c =>
    {
        c.Interceptors.Add(
            new TypeInterceptorFactory(
                typeof(TelemetryInterceptor),
                new object[]
                {
                    _telemetryClient,
                    "Redis",
                    target,
                }));
    })
    .Build();

var proxyRedisDatabase = generator.CreateInterfaceProxy(actual);

In the above code snippet, we’re creating an interface proxy for IRedisDatabase with an interceptor dubbed TelemetryInterceptor. This interceptor activates whenever a method is invoked on the proxyRedisDatabase object.

An interceptor possesses the capability to execute tasks both prior to and following the call to the actual object. In our scenario, we aspire to initiate a timer beforehand and dispatch a dependency tracking event to Application Insights subsequently.

public override async Task Invoke(AspectContext context, AspectDelegate next)
{
    var startTime = DateTime.UtcNow;
    var timer = System.Diagnostics.Stopwatch.StartNew();
    try
    {
        await next(context);
    }
    finally
    {
        timer.Stop();
        var parameters = string.Join(", ", context.Parameters);
        _telemetryClient.TrackDependency(
            _type,
            _target,
            context.ProxyMethod.Name,
            parameters,
            startTime,
            timer.Elapsed,
            "0",
            true);
    }
}

The above method activates whenever a method on the proxied object is called. As evident, we have access to data on the proxied method, which allows us to include relevant information in Application Insights.

Application Insight

From the above, it’s clear that we can now view the duration of requests to Redis and the type of request. The dependency entry’s details also includes information regarding the parameters relayed to the monitored Redis request. Here, it’s evident that a GetAsync call is made, in addtion the details includes the key that was requested.

Take note of the nice Redis icon. Provided by Application Insight out-of-the-box, simply because we set the dependency type to Redis.

At SATS, Azure Application Insights is an indispensable tool for our backend services. By seamlessly integrating Redis tracking, we’ve supercharged our monitoring capabilities. Now, we can also gain granular insights into our extensive Redis operations. This enhancement elevates our operational transparency, allowing us to better understand, optimize, and troubleshoot our systems, making Application Insights even more valuable to SATS’ infrastructure.