-
Notifications
You must be signed in to change notification settings - Fork 367
Description
When using a dependency injection framework, I found it took quite a bit of effort to figure out the best approach that can be implemented with the current Redis tracing API. I've discovered a good solution and have idea proposals to improve it even further.
Best Current Solution
The best way I've found to register the Redis connection with it's current API is to use a factory class that returns the connection either lazily when accessed or via a method call in the startup class (in my case, it was in the hosted service). As for tracing instrumentation, the concrete instance is registered with DI and can be called to set the connection in the factory class:
using Microsoft.Extensions.Options;
using OpenTelemetry.Instrumentation.StackExchangeRedis;
using Service.Abstractions;
using StackExchange.Redis;
namespace Service.Libraries.Redis;
internal class RedisConnection(IOptions<RedisOptions> redisOptions, StackExchangeRedisInstrumentation instrumentation) : IStartupService, IRedisConnection
{
private readonly RedisOptions redisSettings = redisOptions.Value;
public IDatabase Database { get; private set; }
public IServer Server { get; private set; }
public async Task Startup()
{
var muxer = await ConnectionMultiplexer.ConnectAsync($"{redisSettings.Host}:{redisSettings.Port}");
Database = muxer.GetDatabase();
Server = muxer.GetServer(muxer.GetEndPoints().First());
instrumentation.AddConnection(muxer);
}
}Tracing DI Registration:
services.AddOpenTelemetry()
.WithTracing(tracing => tracing.AddRedisInstrumentation());Solution Proposal 1: Short Term, Quick Win
- Add interface to
StackExchangeRedisInstrumentationand use it in DI instead of the concrete type. - Document this recommended solution when using DI.
This will make onboarding of new users of the Redis tracing library a lot easier and enable easier unit testing by being able to mock the interface for the injected instrumentation. This should also resolve the root issue of #2656
Solution Proposal 2: Long Term, But Even Better
I'm not sure exactly how they do it, but Npgsql.OpenTelemetry works magically without having the user of the library get a reference to a connection object:
public static void RegisterTelemetry(IOpenTelemetryBuilder telemetry)
{
telemetry.WithTracing(tracing => tracing.AddNpgsql());
}And that's all that needs to be done. 😕