Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Instrumentation.StackExchangeRedis] Connection registration changes #1139

Closed
10 changes: 6 additions & 4 deletions examples/redis/Examples.StackExchangeRedis/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,19 +28,21 @@ public static void Main()
* docker run --name opentelemetry-redis-test -d -p 6379:6379 redis
*/

// connect to the redis server. The default port 6379 will be used.
var connection = ConnectionMultiplexer.Connect("localhost");

// Configure exporter to export traces to Zipkin
using var tracerProvider = Sdk.CreateTracerProviderBuilder()
.AddConsoleExporter()
.AddRedisInstrumentation(connection, options =>
.AddRedisInstrumentation(out var registry, options =>
{
// changing flush interval from 10s to 5s
options.FlushInterval = TimeSpan.FromSeconds(5);
})
.Build();

// Connect to the Redis server. The default port 6379 will be used.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: remove blank line

var connection = ConnectionMultiplexer.Connect("localhost");
registry.Register(connection);

// select a database (by default, DB = 0)
var db = connection.GetDatabase();
db.StringSet("key", "value " + DateTime.Now.ToLongDateString());
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
OpenTelemetry.Instrumentation.StackExchangeRedis.ConnectionRegistry
OpenTelemetry.Instrumentation.StackExchangeRedis.ConnectionRegistry.ConnectionRegistry() -> void
OpenTelemetry.Instrumentation.StackExchangeRedis.ConnectionRegistry.Register(StackExchange.Redis.IConnectionMultiplexer connectionMultiplexer) -> void
OpenTelemetry.Instrumentation.StackExchangeRedis.IConnectionRegistry
OpenTelemetry.Instrumentation.StackExchangeRedis.IConnectionRegistry.Register(StackExchange.Redis.IConnectionMultiplexer connectionMultiplexer) -> void
OpenTelemetry.Instrumentation.StackExchangeRedis.StackExchangeRedisCallsInstrumentationOptions
OpenTelemetry.Instrumentation.StackExchangeRedis.StackExchangeRedisCallsInstrumentationOptions.Enrich.get -> System.Action<System.Diagnostics.Activity, StackExchange.Redis.Profiling.IProfiledCommand>
OpenTelemetry.Instrumentation.StackExchangeRedis.StackExchangeRedisCallsInstrumentationOptions.Enrich.set -> void
Expand All @@ -9,4 +14,7 @@ OpenTelemetry.Instrumentation.StackExchangeRedis.StackExchangeRedisCallsInstrume
OpenTelemetry.Instrumentation.StackExchangeRedis.StackExchangeRedisCallsInstrumentationOptions.EnrichActivityWithTimingEvents.get -> bool
OpenTelemetry.Instrumentation.StackExchangeRedis.StackExchangeRedisCallsInstrumentationOptions.EnrichActivityWithTimingEvents.set -> void
OpenTelemetry.Trace.TracerProviderBuilderExtensions
static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddRedisInstrumentation(this OpenTelemetry.Trace.TracerProviderBuilder builder, StackExchange.Redis.IConnectionMultiplexer connection = null, System.Action<OpenTelemetry.Instrumentation.StackExchangeRedis.StackExchangeRedisCallsInstrumentationOptions> configure = null) -> OpenTelemetry.Trace.TracerProviderBuilder
static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddRedisInstrumentation(this OpenTelemetry.Trace.TracerProviderBuilder builder) -> OpenTelemetry.Trace.TracerProviderBuilder
static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddRedisInstrumentation(this OpenTelemetry.Trace.TracerProviderBuilder builder, out OpenTelemetry.Instrumentation.StackExchangeRedis.IConnectionRegistry connectionRegistry) -> OpenTelemetry.Trace.TracerProviderBuilder
static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddRedisInstrumentation(this OpenTelemetry.Trace.TracerProviderBuilder builder, out OpenTelemetry.Instrumentation.StackExchangeRedis.IConnectionRegistry connectionRegistry, System.Action<OpenTelemetry.Instrumentation.StackExchangeRedis.StackExchangeRedisCallsInstrumentationOptions> configure) -> OpenTelemetry.Trace.TracerProviderBuilder
static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddRedisInstrumentation(this OpenTelemetry.Trace.TracerProviderBuilder builder, StackExchange.Redis.IConnectionMultiplexer connection, System.Action<OpenTelemetry.Instrumentation.StackExchangeRedis.StackExchangeRedisCallsInstrumentationOptions> configure) -> OpenTelemetry.Trace.TracerProviderBuilder
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
OpenTelemetry.Instrumentation.StackExchangeRedis.ConnectionRegistry
OpenTelemetry.Instrumentation.StackExchangeRedis.ConnectionRegistry.ConnectionRegistry() -> void
OpenTelemetry.Instrumentation.StackExchangeRedis.ConnectionRegistry.Register(StackExchange.Redis.IConnectionMultiplexer connectionMultiplexer) -> void
OpenTelemetry.Instrumentation.StackExchangeRedis.IConnectionRegistry
OpenTelemetry.Instrumentation.StackExchangeRedis.IConnectionRegistry.Register(StackExchange.Redis.IConnectionMultiplexer connectionMultiplexer) -> void
OpenTelemetry.Instrumentation.StackExchangeRedis.StackExchangeRedisCallsInstrumentationOptions
OpenTelemetry.Instrumentation.StackExchangeRedis.StackExchangeRedisCallsInstrumentationOptions.Enrich.get -> System.Action<System.Diagnostics.Activity, StackExchange.Redis.Profiling.IProfiledCommand>
OpenTelemetry.Instrumentation.StackExchangeRedis.StackExchangeRedisCallsInstrumentationOptions.Enrich.set -> void
Expand All @@ -9,4 +14,7 @@ OpenTelemetry.Instrumentation.StackExchangeRedis.StackExchangeRedisCallsInstrume
OpenTelemetry.Instrumentation.StackExchangeRedis.StackExchangeRedisCallsInstrumentationOptions.EnrichActivityWithTimingEvents.get -> bool
OpenTelemetry.Instrumentation.StackExchangeRedis.StackExchangeRedisCallsInstrumentationOptions.EnrichActivityWithTimingEvents.set -> void
OpenTelemetry.Trace.TracerProviderBuilderExtensions
static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddRedisInstrumentation(this OpenTelemetry.Trace.TracerProviderBuilder builder, StackExchange.Redis.IConnectionMultiplexer connection = null, System.Action<OpenTelemetry.Instrumentation.StackExchangeRedis.StackExchangeRedisCallsInstrumentationOptions> configure = null) -> OpenTelemetry.Trace.TracerProviderBuilder
static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddRedisInstrumentation(this OpenTelemetry.Trace.TracerProviderBuilder builder) -> OpenTelemetry.Trace.TracerProviderBuilder
static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddRedisInstrumentation(this OpenTelemetry.Trace.TracerProviderBuilder builder, out OpenTelemetry.Instrumentation.StackExchangeRedis.IConnectionRegistry connectionRegistry) -> OpenTelemetry.Trace.TracerProviderBuilder
static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddRedisInstrumentation(this OpenTelemetry.Trace.TracerProviderBuilder builder, out OpenTelemetry.Instrumentation.StackExchangeRedis.IConnectionRegistry connectionRegistry, System.Action<OpenTelemetry.Instrumentation.StackExchangeRedis.StackExchangeRedisCallsInstrumentationOptions> configure) -> OpenTelemetry.Trace.TracerProviderBuilder
static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddRedisInstrumentation(this OpenTelemetry.Trace.TracerProviderBuilder builder, StackExchange.Redis.IConnectionMultiplexer connection, System.Action<OpenTelemetry.Instrumentation.StackExchangeRedis.StackExchangeRedisCallsInstrumentationOptions> configure) -> OpenTelemetry.Trace.TracerProviderBuilder
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

## Unreleased

* Add an ability to track connections created after tracer is initialized.
([#1139](https://github.com/open-telemetry/opentelemetry-dotnet-contrib/pull/1139))

## 1.0.0-rc9.8

Released 2023-Feb-27
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// <copyright file="ConnectionRegistry.cs" company="OpenTelemetry Authors">
// Copyright The OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>

using System;
using StackExchange.Redis;

namespace OpenTelemetry.Instrumentation.StackExchangeRedis;

/// <inheritdoc />
public class ConnectionRegistry : IConnectionRegistry
{
private Action<IConnectionMultiplexer> registrationCallback;

/// <inheritdoc />
public void Register(IConnectionMultiplexer connectionMultiplexer)
{
this.registrationCallback?.Invoke(connectionMultiplexer);
}

internal void Initialize(Action<IConnectionMultiplexer> callback)
{
this.registrationCallback = callback;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// <copyright file="IConnectionRegistry.cs" company="OpenTelemetry Authors">
// Copyright The OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>

using StackExchange.Redis;

namespace OpenTelemetry.Instrumentation.StackExchangeRedis;

/// <summary>
/// Registers connection for instrumentation purposes.
/// </summary>
public interface IConnectionRegistry
{
/// <summary>
/// Registers connection with current instrumentation instance.
/// </summary>
/// <param name="connectionMultiplexer">Connection to be tracked by instrumentation.</param>
void Register(IConnectionMultiplexer connectionMultiplexer);
}
15 changes: 8 additions & 7 deletions src/OpenTelemetry.Instrumentation.StackExchangeRedis/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,9 @@ dotnet add package OpenTelemetry.Instrumentation.StackExchangeRedis

StackExchange.Redis instrumentation must be enabled at application startup.
`AddRedisInstrumentation` method on `TracerProviderBuilder` must be called to
enable Redis instrumentation, passing the `IConnectionMultiplexer` instance used
to make Redis calls. Only those Redis calls made using the same instance of the
`IConnectionMultiplexer` will be instrumented.
enable Redis instrumentation. `AddRedisInstrumentation` returns
`ConnectionRegistry` instance, that allows to register new connections with
instrumentation instance.

The following example demonstrates adding StackExchange.Redis instrumentation to
a console application. This example also sets up the OpenTelemetry Console
Expand All @@ -53,13 +53,14 @@ public class Program
{
public static void Main(string[] args)
{
// Connect to the server.
using var connection = ConnectionMultiplexer.Connect("localhost:6379");

using var tracerProvider = Sdk.CreateTracerProviderBuilder()
.AddRedisInstrumentation(connection)
.AddRedisInstrumentation(out var connectionRegistry)
.AddConsoleExporter()
.Build();

// Connect to the server.
using var connection = ConnectionMultiplexer.Connect("localhost:6379");
connectionRegistry.Register(connection);
}
}
```
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,7 @@
using System.Diagnostics;
using System.Threading;
using OpenTelemetry.Instrumentation.StackExchangeRedis.Implementation;
using OpenTelemetry.Internal;
using OpenTelemetry.Trace;
using StackExchange.Redis;
using StackExchange.Redis.Profiling;

namespace OpenTelemetry.Instrumentation.StackExchangeRedis;
Expand Down Expand Up @@ -55,12 +53,9 @@ internal class StackExchangeRedisCallsInstrumentation : IDisposable
/// <summary>
/// Initializes a new instance of the <see cref="StackExchangeRedisCallsInstrumentation"/> class.
/// </summary>
/// <param name="connection"><see cref="IConnectionMultiplexer"/> to instrument.</param>
/// <param name="options">Configuration options for redis instrumentation.</param>
public StackExchangeRedisCallsInstrumentation(IConnectionMultiplexer connection, StackExchangeRedisCallsInstrumentationOptions options)
public StackExchangeRedisCallsInstrumentation(StackExchangeRedisCallsInstrumentationOptions options)
{
Guard.ThrowIfNull(connection);

this.options = options ?? new StackExchangeRedisCallsInstrumentationOptions();

this.drainThread = new Thread(this.DrainEntries)
Expand All @@ -69,8 +64,6 @@ public StackExchangeRedisCallsInstrumentation(IConnectionMultiplexer connection,
IsBackground = true,
};
this.drainThread.Start();

connection.RegisterProfiler(this.GetProfilerSessionsFactory());
}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,13 @@ namespace OpenTelemetry.Trace;
/// </summary>
public static class TracerProviderBuilderExtensions
{
/// <summary>
/// Enables automatic data collection of outgoing requests to Redis.
/// </summary>
/// <param name="builder"><see cref="TracerProviderBuilder"/> being configured.</param>
/// <returns>The instance of <see cref="TracerProviderBuilder"/> to chain the calls.</returns>
public static TracerProviderBuilder AddRedisInstrumentation(this TracerProviderBuilder builder) => AddRedisInstrumentation(builder, null, null);

/// <summary>
/// Enables automatic data collection of outgoing requests to Redis.
/// </summary>
Expand All @@ -40,8 +47,8 @@ public static class TracerProviderBuilderExtensions
/// <returns>The instance of <see cref="TracerProviderBuilder"/> to chain the calls.</returns>
public static TracerProviderBuilder AddRedisInstrumentation(
this TracerProviderBuilder builder,
IConnectionMultiplexer connection = null,
Action<StackExchangeRedisCallsInstrumentationOptions> configure = null)
IConnectionMultiplexer connection,
Action<StackExchangeRedisCallsInstrumentationOptions> configure)
{
Guard.ThrowIfNull(builder);

Expand All @@ -52,7 +59,7 @@ public static TracerProviderBuilder AddRedisInstrumentation(
throw new NotSupportedException($"StackExchange.Redis {nameof(IConnectionMultiplexer)} must be supplied when dependency injection is unavailable - to enable dependency injection use the OpenTelemetry.Extensions.Hosting package");
}

return AddRedisInstrumentation(builder, connection, new StackExchangeRedisCallsInstrumentationOptions(), configure);
return AddRedisInstrumentation(builder, new StackExchangeRedisCallsInstrumentationOptions(), configure, null, connection);
}

return deferredTracerProviderBuilder.Configure((sp, builder) =>
Expand All @@ -68,22 +75,77 @@ public static TracerProviderBuilder AddRedisInstrumentation(

AddRedisInstrumentation(
builder,
connection,
sp.GetOptions<StackExchangeRedisCallsInstrumentationOptions>(),
configure);
configure,
null,
connection);
});
}

/// <summary>
/// Enables automatic data collection of outgoing requests to Redis.
/// </summary>
/// <param name="builder"><see cref="TracerProviderBuilder"/> being configured.</param>
/// <param name="connectionRegistry">Registry to register connections with.</param>
/// <returns>The instance of <see cref="TracerProviderBuilder"/> to chain the calls.</returns>
public static TracerProviderBuilder AddRedisInstrumentation(
this TracerProviderBuilder builder,
out IConnectionRegistry connectionRegistry) => AddRedisInstrumentation(builder, out connectionRegistry, null);

/// <summary>
/// Enables automatic data collection of outgoing requests to Redis.
/// </summary>
/// <param name="builder"><see cref="TracerProviderBuilder"/> being configured.</param>
/// <param name="connectionRegistry">Registry to register connections with.</param>
/// <param name="configure">Optional callback to configure options.</param>
/// <returns>The instance of <see cref="TracerProviderBuilder"/> to chain the calls.</returns>
public static TracerProviderBuilder AddRedisInstrumentation(
this TracerProviderBuilder builder,
out IConnectionRegistry connectionRegistry,
Action<StackExchangeRedisCallsInstrumentationOptions> configure)
{
Guard.ThrowIfNull(builder);

var defaultRegistry = new ConnectionRegistry();
connectionRegistry = defaultRegistry;

if (builder is not IDeferredTracerProviderBuilder deferredTracerProviderBuilder)
{
return AddRedisInstrumentation(builder, new StackExchangeRedisCallsInstrumentationOptions(), configure, defaultRegistry);
}

return deferredTracerProviderBuilder.Configure((sp, builder) =>
{
AddRedisInstrumentation(
builder,
sp.GetOptions<StackExchangeRedisCallsInstrumentationOptions>(),
configure,
defaultRegistry);
});
}

private static TracerProviderBuilder AddRedisInstrumentation(
TracerProviderBuilder builder,
IConnectionMultiplexer connection,
StackExchangeRedisCallsInstrumentationOptions options,
Action<StackExchangeRedisCallsInstrumentationOptions> configure)
Action<StackExchangeRedisCallsInstrumentationOptions> configure,
ConnectionRegistry registry,
IConnectionMultiplexer connection = null)
{
configure?.Invoke(options);

return builder
.AddInstrumentation(() => new StackExchangeRedisCallsInstrumentation(connection, options))
StackExchangeRedisCallsInstrumentation stackExchangeRedisCallsInstrumentation = null;

var redisInstrumentation = builder
.AddInstrumentation(() =>
{
stackExchangeRedisCallsInstrumentation = new StackExchangeRedisCallsInstrumentation(options);
connection?.RegisterProfiler(stackExchangeRedisCallsInstrumentation?.GetProfilerSessionsFactory());

return stackExchangeRedisCallsInstrumentation;
})
.AddSource(StackExchangeRedisCallsInstrumentation.ActivitySourceName);

registry?.Initialize(connectionMultiplexer => connectionMultiplexer.RegisterProfiler(stackExchangeRedisCallsInstrumentation?.GetProfilerSessionsFactory()));
return redisInstrumentation;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,9 @@ public RedisProfilerEntryToActivityConverterTests()
this.connection = ConnectionMultiplexer.Connect(connectionOptions);

this.tracerProvider = Sdk.CreateTracerProviderBuilder()
.AddRedisInstrumentation(this.connection)
.AddRedisInstrumentation(out var connectionRegistry)
.Build();
connectionRegistry.Register(this.connection);
}

public void Dispose()
Expand Down
Loading