Skip to content

Commit 40bd549

Browse files
aradalvandKielek
andauthored
[StackExchangeRedis] Pass ParentActivity to Filter and Enrich to compensate for Activity.Current always being null (#2977)
Co-authored-by: Piotr Kiełkowicz <[email protected]>
1 parent ed28ca7 commit 40bd549

File tree

7 files changed

+60
-15
lines changed

7 files changed

+60
-15
lines changed
Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,31 @@
1+
OpenTelemetry.Instrumentation.StackExchangeRedis.RedisInstrumentationContext
2+
OpenTelemetry.Instrumentation.StackExchangeRedis.RedisInstrumentationContext.Deconstruct(out System.Diagnostics.Activity? ParentActivity, out StackExchange.Redis.Profiling.IProfiledCommand! ProfiledCommand) -> void
3+
OpenTelemetry.Instrumentation.StackExchangeRedis.RedisInstrumentationContext.ParentActivity.get -> System.Diagnostics.Activity?
4+
OpenTelemetry.Instrumentation.StackExchangeRedis.RedisInstrumentationContext.ParentActivity.init -> void
5+
OpenTelemetry.Instrumentation.StackExchangeRedis.RedisInstrumentationContext.ProfiledCommand.get -> StackExchange.Redis.Profiling.IProfiledCommand!
6+
OpenTelemetry.Instrumentation.StackExchangeRedis.RedisInstrumentationContext.ProfiledCommand.init -> void
7+
OpenTelemetry.Instrumentation.StackExchangeRedis.RedisInstrumentationContext.RedisInstrumentationContext() -> void
8+
OpenTelemetry.Instrumentation.StackExchangeRedis.RedisInstrumentationContext.RedisInstrumentationContext(System.Diagnostics.Activity? ParentActivity, StackExchange.Redis.Profiling.IProfiledCommand! ProfiledCommand) -> void
19
OpenTelemetry.Instrumentation.StackExchangeRedis.StackExchangeRedisInstrumentation
210
OpenTelemetry.Instrumentation.StackExchangeRedis.StackExchangeRedisInstrumentation.AddConnection(StackExchange.Redis.IConnectionMultiplexer! connection) -> System.IDisposable!
311
OpenTelemetry.Instrumentation.StackExchangeRedis.StackExchangeRedisInstrumentation.AddConnection(string! name, StackExchange.Redis.IConnectionMultiplexer! connection) -> System.IDisposable!
412
OpenTelemetry.Instrumentation.StackExchangeRedis.StackExchangeRedisInstrumentation.Dispose() -> void
513
OpenTelemetry.Instrumentation.StackExchangeRedis.StackExchangeRedisInstrumentationOptions
6-
OpenTelemetry.Instrumentation.StackExchangeRedis.StackExchangeRedisInstrumentationOptions.Enrich.get -> System.Action<System.Diagnostics.Activity!, StackExchange.Redis.Profiling.IProfiledCommand!>?
14+
OpenTelemetry.Instrumentation.StackExchangeRedis.StackExchangeRedisInstrumentationOptions.Enrich.get -> System.Action<System.Diagnostics.Activity!, OpenTelemetry.Instrumentation.StackExchangeRedis.RedisInstrumentationContext>?
715
OpenTelemetry.Instrumentation.StackExchangeRedis.StackExchangeRedisInstrumentationOptions.Enrich.set -> void
816
OpenTelemetry.Instrumentation.StackExchangeRedis.StackExchangeRedisInstrumentationOptions.EnrichActivityWithTimingEvents.get -> bool
917
OpenTelemetry.Instrumentation.StackExchangeRedis.StackExchangeRedisInstrumentationOptions.EnrichActivityWithTimingEvents.set -> void
10-
OpenTelemetry.Instrumentation.StackExchangeRedis.StackExchangeRedisInstrumentationOptions.Filter.get -> System.Func<StackExchange.Redis.Profiling.IProfiledCommand!, bool>?
18+
OpenTelemetry.Instrumentation.StackExchangeRedis.StackExchangeRedisInstrumentationOptions.Filter.get -> System.Func<OpenTelemetry.Instrumentation.StackExchangeRedis.RedisInstrumentationContext, bool>?
1119
OpenTelemetry.Instrumentation.StackExchangeRedis.StackExchangeRedisInstrumentationOptions.Filter.set -> void
1220
OpenTelemetry.Instrumentation.StackExchangeRedis.StackExchangeRedisInstrumentationOptions.FlushInterval.get -> System.TimeSpan
1321
OpenTelemetry.Instrumentation.StackExchangeRedis.StackExchangeRedisInstrumentationOptions.FlushInterval.set -> void
1422
OpenTelemetry.Instrumentation.StackExchangeRedis.StackExchangeRedisInstrumentationOptions.SetVerboseDatabaseStatements.get -> bool
1523
OpenTelemetry.Instrumentation.StackExchangeRedis.StackExchangeRedisInstrumentationOptions.SetVerboseDatabaseStatements.set -> void
1624
OpenTelemetry.Instrumentation.StackExchangeRedis.StackExchangeRedisInstrumentationOptions.StackExchangeRedisInstrumentationOptions() -> void
1725
OpenTelemetry.Trace.TracerProviderBuilderExtensions
26+
override OpenTelemetry.Instrumentation.StackExchangeRedis.RedisInstrumentationContext.GetHashCode() -> int
27+
static OpenTelemetry.Instrumentation.StackExchangeRedis.RedisInstrumentationContext.operator ==(OpenTelemetry.Instrumentation.StackExchangeRedis.RedisInstrumentationContext left, OpenTelemetry.Instrumentation.StackExchangeRedis.RedisInstrumentationContext right) -> bool
28+
static OpenTelemetry.Instrumentation.StackExchangeRedis.RedisInstrumentationContext.operator !=(OpenTelemetry.Instrumentation.StackExchangeRedis.RedisInstrumentationContext left, OpenTelemetry.Instrumentation.StackExchangeRedis.RedisInstrumentationContext right) -> bool
1829
static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddRedisInstrumentation(this OpenTelemetry.Trace.TracerProviderBuilder! builder) -> OpenTelemetry.Trace.TracerProviderBuilder!
1930
static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddRedisInstrumentation(this OpenTelemetry.Trace.TracerProviderBuilder! builder, object! serviceKey) -> OpenTelemetry.Trace.TracerProviderBuilder!
2031
static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddRedisInstrumentation(this OpenTelemetry.Trace.TracerProviderBuilder! builder, StackExchange.Redis.IConnectionMultiplexer! connection) -> OpenTelemetry.Trace.TracerProviderBuilder!
@@ -24,3 +35,6 @@ static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddRedisInstrumentati
2435
static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddRedisInstrumentation(this OpenTelemetry.Trace.TracerProviderBuilder! builder, System.Action<OpenTelemetry.Instrumentation.StackExchangeRedis.StackExchangeRedisInstrumentationOptions!>! configure) -> OpenTelemetry.Trace.TracerProviderBuilder!
2536
static OpenTelemetry.Trace.TracerProviderBuilderExtensions.ConfigureRedisInstrumentation(this OpenTelemetry.Trace.TracerProviderBuilder! builder, System.Action<OpenTelemetry.Instrumentation.StackExchangeRedis.StackExchangeRedisInstrumentation!>! configure) -> OpenTelemetry.Trace.TracerProviderBuilder!
2637
static OpenTelemetry.Trace.TracerProviderBuilderExtensions.ConfigureRedisInstrumentation(this OpenTelemetry.Trace.TracerProviderBuilder! builder, System.Action<System.IServiceProvider!, OpenTelemetry.Instrumentation.StackExchangeRedis.StackExchangeRedisInstrumentation!>! configure) -> OpenTelemetry.Trace.TracerProviderBuilder!
38+
~override OpenTelemetry.Instrumentation.StackExchangeRedis.RedisInstrumentationContext.ToString() -> string
39+
~override OpenTelemetry.Instrumentation.StackExchangeRedis.RedisInstrumentationContext.Equals(object obj) -> bool
40+
OpenTelemetry.Instrumentation.StackExchangeRedis.RedisInstrumentationContext.Equals(OpenTelemetry.Instrumentation.StackExchangeRedis.RedisInstrumentationContext other) -> bool

src/OpenTelemetry.Instrumentation.StackExchangeRedis/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
## Unreleased
44

5+
* **Breaking change** Introduce `RedisInstrumentationContext` and use it
6+
as context for `Filter`
7+
([#2977](https://github.com/open-telemetry/opentelemetry-dotnet-contrib/pull/2977))
8+
59
* Removed the `db.redis.flags` attribute from the implementation
610
as it is not part of the Semantic Conventions for Database Client Calls.
711
([#2982](https://github.com/open-telemetry/opentelemetry-dotnet-contrib/pull/2982))

src/OpenTelemetry.Instrumentation.StackExchangeRedis/Implementation/RedisProfilerEntryToActivityConverter.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ static bool GetCommandAndKey(
7575
{
7676
try
7777
{
78-
if (options.Filter != null && !options.Filter(command))
78+
if (options.Filter != null && !options.Filter(new(parentActivity, command)))
7979
{
8080
return null;
8181
}
@@ -184,7 +184,7 @@ static bool GetCommandAndKey(
184184
activity.AddEvent(new ActivityEvent("ResponseReceived", response));
185185
}
186186

187-
options.Enrich?.Invoke(activity, command);
187+
options.Enrich?.Invoke(activity, new(parentActivity, command));
188188
}
189189

190190
activity.Stop();
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// Copyright The OpenTelemetry Authors
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
namespace System.Runtime.CompilerServices;
5+
6+
// NOTE: Needed for C# 9 record types in projects that target frameworks prior to .NET 5. See https://stackoverflow.com/a/64749403
7+
internal static class IsExternalInit;
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// Copyright The OpenTelemetry Authors
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
using System.Diagnostics;
5+
using StackExchange.Redis.Profiling;
6+
7+
namespace OpenTelemetry.Instrumentation.StackExchangeRedis;
8+
9+
/// <summary>
10+
/// Represents contextual information about a profiled Redis command off of which an <see cref="Activity"/> can be created.
11+
/// </summary>
12+
/// <param name="ParentActivity">
13+
/// The parent activity associated with the profiled command.
14+
/// <see cref="Activity.Current"/> is not guaranteed to be the parent activity since commands are profiled asynchronously.
15+
/// </param>
16+
/// <param name="ProfiledCommand">
17+
/// The profiled Redis command.
18+
/// </param>
19+
public readonly record struct RedisInstrumentationContext(
20+
Activity? ParentActivity,
21+
IProfiledCommand ProfiledCommand);

src/OpenTelemetry.Instrumentation.StackExchangeRedis/StackExchangeRedisInstrumentationOptions.cs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33

44
using System.Diagnostics;
55
using OpenTelemetry.Trace;
6-
using StackExchange.Redis.Profiling;
76

87
namespace OpenTelemetry.Instrumentation.StackExchangeRedis;
98

@@ -23,26 +22,26 @@ public class StackExchangeRedisInstrumentationOptions
2322
public bool SetVerboseDatabaseStatements { get; set; }
2423

2524
/// <summary>
26-
/// Gets or sets a callback method allowing to filter out particular <see cref="IProfiledCommand"/> instances.
25+
/// Gets or sets a callback method allowing to filter out particular <see cref="RedisInstrumentationContext"/> instances.
2726
/// </summary>
2827
/// <remarks>
29-
/// The filter callback receives the <see cref="IProfiledCommand"/> for the
28+
/// The filter callback receives the <see cref="RedisInstrumentationContext"/> for the
3029
/// processed profiled command and returns a boolean indicating whether it should be filtered out.
3130
/// <list type="bullet">
3231
/// <item>If filter returns <see langword="true"/> the event is collected.</item>
3332
/// <item>If filter returns <see langword="false"/> or throws an exception the event is filtered out (NOT collected).</item>
3433
/// </list>
3534
/// </remarks>
36-
public Func<IProfiledCommand, bool>? Filter { get; set; }
35+
public Func<RedisInstrumentationContext, bool>? Filter { get; set; }
3736

3837
/// <summary>
3938
/// Gets or sets an action to enrich an Activity.
4039
/// </summary>
4140
/// <remarks>
4241
/// <para><see cref="Activity"/>: the activity being enriched.</para>
43-
/// <para><see cref="IProfiledCommand"/>: the profiled redis command from which additional information can be extracted to enrich the activity.</para>
42+
/// <para><see cref="RedisInstrumentationContext"/>: the profiled redis command from which additional information can be extracted to enrich the activity.</para>
4443
/// </remarks>
45-
public Action<Activity, IProfiledCommand>? Enrich { get; set; }
44+
public Action<Activity, RedisInstrumentationContext>? Enrich { get; set; }
4645

4746
/// <summary>
4847
/// Gets or sets a value indicating whether the <see cref="StackExchangeRedisConnectionInstrumentation"/> should enrich Activity with <see cref="ActivityEvent"/> entries about the Redis command processing/lifetime. Defaults to <see langword="true"/>.

test/OpenTelemetry.Instrumentation.StackExchangeRedis.Tests/StackExchangeRedisCallsInstrumentationTests.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -184,9 +184,9 @@ public void CanEnrichActivityFromCommand(string value)
184184
var builder = Sdk.CreateTracerProviderBuilder()
185185
.AddInMemoryExporter(exportedItems)
186186
.SetSampler(sampler)
187-
.AddRedisInstrumentation(c => c.Enrich = (activity, command) =>
187+
.AddRedisInstrumentation(c => c.Enrich = (activity, context) =>
188188
{
189-
if (command.ElapsedTime < TimeSpan.FromMilliseconds(100))
189+
if (context.ProfiledCommand.ElapsedTime < TimeSpan.FromMilliseconds(100))
190190
{
191191
activity.AddTag("is_fast", true);
192192
}
@@ -367,9 +367,9 @@ public void StackExchangeRedis_StackExchangeRedisInstrumentation_Test()
367367

368368
var builder = Sdk.CreateTracerProviderBuilder()
369369
.SetSampler(sampler)
370-
.AddRedisInstrumentation(c => c.Enrich = (activity, command) =>
370+
.AddRedisInstrumentation(c => c.Enrich = (activity, context) =>
371371
{
372-
if (command.ElapsedTime < TimeSpan.FromMilliseconds(100))
372+
if (context.ProfiledCommand.ElapsedTime < TimeSpan.FromMilliseconds(100))
373373
{
374374
activity.AddTag("is_fast", true);
375375
}
@@ -414,7 +414,7 @@ public void FilterOption_FiltersOutSpecifiedCommands(string value)
414414
.AddInMemoryExporter(exportedItems)
415415
.AddRedisInstrumentation(connection, options =>
416416
{
417-
options.Filter = command => !string.Equals(command.Command, "GET", StringComparison.OrdinalIgnoreCase);
417+
options.Filter = context => !string.Equals(context.ProfiledCommand.Command, "GET", StringComparison.OrdinalIgnoreCase);
418418
})
419419
.Build())
420420
{

0 commit comments

Comments
 (0)