Skip to content

Commit

Permalink
Introduce InstanceName and use it in telemetry (#1392)
Browse files Browse the repository at this point in the history
  • Loading branch information
martintmk committed Jul 10, 2023
1 parent 44ec049 commit 472e961
Show file tree
Hide file tree
Showing 23 changed files with 115 additions and 110 deletions.
8 changes: 4 additions & 4 deletions src/Polly.Core/Registry/ConfigureBuilderContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ namespace Polly.Registry;
public class ConfigureBuilderContext<TKey>
where TKey : notnull
{
internal ConfigureBuilderContext(TKey strategyKey, string builderName, string strategyKeyString)
internal ConfigureBuilderContext(TKey strategyKey, string builderName, string? builderInstanceName)
{
StrategyKey = strategyKey;
BuilderName = builderName;
StrategyKeyString = strategyKeyString;
BuilderInstanceName = builderInstanceName;
}

/// <summary>
Expand All @@ -27,9 +27,9 @@ internal ConfigureBuilderContext(TKey strategyKey, string builderName, string st
public string BuilderName { get; }

/// <summary>
/// Gets the string representation of strategy key for the strategy being created.
/// Gets the instance name for the builder being used to create the strategy.
/// </summary>
public string StrategyKeyString { get; }
public string? BuilderInstanceName { get; }

internal Func<Func<CancellationToken>>? ReloadTokenProducer { get; private set; }

Expand Down
10 changes: 5 additions & 5 deletions src/Polly.Core/Registry/ResilienceStrategyRegistry.TResult.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,21 @@ private sealed class GenericRegistry<TResult>
private readonly ConcurrentDictionary<TKey, Action<ResilienceStrategyBuilder<TResult>, ConfigureBuilderContext<TKey>>> _builders;
private readonly ConcurrentDictionary<TKey, ResilienceStrategy<TResult>> _strategies;

private readonly Func<TKey, string> _strategyKeyFormatter;
private readonly Func<TKey, string> _builderNameFormatter;
private readonly Func<TKey, string>? _instanceNameFormatter;

public GenericRegistry(
Func<ResilienceStrategyBuilder<TResult>> activator,
IEqualityComparer<TKey> builderComparer,
IEqualityComparer<TKey> strategyComparer,
Func<TKey, string> strategyKeyFormatter,
Func<TKey, string> builderNameFormatter)
Func<TKey, string> builderNameFormatter,
Func<TKey, string>? instanceNameFormatter)
{
_activator = activator;
_builders = new ConcurrentDictionary<TKey, Action<ResilienceStrategyBuilder<TResult>, ConfigureBuilderContext<TKey>>>(builderComparer);
_strategies = new ConcurrentDictionary<TKey, ResilienceStrategy<TResult>>(strategyComparer);
_strategyKeyFormatter = strategyKeyFormatter;
_builderNameFormatter = builderNameFormatter;
_instanceNameFormatter = instanceNameFormatter;
}

public bool TryAdd(TKey key, ResilienceStrategy<TResult> strategy) => _strategies.TryAdd(key, strategy);
Expand All @@ -51,7 +51,7 @@ public bool TryGet(TKey key, [NotNullWhen(true)] out ResilienceStrategy<TResult>

public ResilienceStrategy<TResult> GetOrAdd(TKey key, Action<ResilienceStrategyBuilder<TResult>, ConfigureBuilderContext<TKey>> configure)
{
var context = new ConfigureBuilderContext<TKey>(key, _builderNameFormatter(key), _strategyKeyFormatter(key));
var context = new ConfigureBuilderContext<TKey>(key, _builderNameFormatter(key), _instanceNameFormatter?.Invoke(key));

#if NETCOREAPP3_0_OR_GREATER
return _strategies.GetOrAdd(key, static (_, factory) =>
Expand Down
13 changes: 7 additions & 6 deletions src/Polly.Core/Registry/ResilienceStrategyRegistry.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public sealed partial class ResilienceStrategyRegistry<TKey> : ResilienceStrateg
private readonly ConcurrentDictionary<TKey, ResilienceStrategy> _strategies;
private readonly ConcurrentDictionary<Type, object> _genericRegistry = new();

private readonly Func<TKey, string> _strategyKeyFormatter;
private readonly Func<TKey, string>? _instanceNameFormatter;
private readonly Func<TKey, string> _builderNameFormatter;
private readonly IEqualityComparer<TKey> _builderComparer;
private readonly IEqualityComparer<TKey> _strategyComparer;
Expand Down Expand Up @@ -52,7 +52,7 @@ public ResilienceStrategyRegistry(ResilienceStrategyRegistryOptions<TKey> option
_activator = options.BuilderFactory;
_builders = new ConcurrentDictionary<TKey, Action<ResilienceStrategyBuilder, ConfigureBuilderContext<TKey>>>(options.BuilderComparer);
_strategies = new ConcurrentDictionary<TKey, ResilienceStrategy>(options.StrategyComparer);
_strategyKeyFormatter = options.StrategyKeyFormatter;
_instanceNameFormatter = options.InstanceNameFormatter;
_builderNameFormatter = options.BuilderNameFormatter;
_builderComparer = options.BuilderComparer;
_strategyComparer = options.StrategyComparer;
Expand Down Expand Up @@ -154,7 +154,7 @@ public ResilienceStrategy GetOrAddStrategy(TKey key, Action<ResilienceStrategyBu
return strategy;
}

var context = new ConfigureBuilderContext<TKey>(key, _builderNameFormatter(key), _strategyKeyFormatter(key));
var context = new ConfigureBuilderContext<TKey>(key, _builderNameFormatter(key), _instanceNameFormatter?.Invoke(key));

#if NETCOREAPP3_0_OR_GREATER
return _strategies.GetOrAdd(key, static (_, factory) =>
Expand Down Expand Up @@ -272,7 +272,7 @@ public bool TryAddBuilder<TResult>(TKey key, Action<ResilienceStrategyBuilder<TR
{
var builder = activator();
builder.BuilderName = context.BuilderName;
builder.Properties.Set(TelemetryUtil.StrategyKey, context.StrategyKeyString);
builder.InstanceName = context.BuilderInstanceName;
configure(builder, context);
return builder;
Expand All @@ -294,6 +294,7 @@ public bool TryAddBuilder<TResult>(TKey key, Action<ResilienceStrategyBuilder<TR
TelemetryUtil.CreateTelemetry(
diagnosticSource,
context.BuilderName,
context.BuilderInstanceName,
builder.Properties,
ReloadableResilienceStrategy.StrategyName,
ReloadableResilienceStrategy.StrategyType));
Expand All @@ -312,8 +313,8 @@ private GenericRegistry<TResult> GetGenericRegistry<TResult>()
() => new ResilienceStrategyBuilder<TResult>(_activator()),
_builderComparer,
_strategyComparer,
_strategyKeyFormatter,
_builderNameFormatter);
_builderNameFormatter,
_instanceNameFormatter);
});
}
}
11 changes: 5 additions & 6 deletions src/Polly.Core/Registry/ResilienceStrategyRegistryOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,17 +37,16 @@ public class ResilienceStrategyRegistryOptions<TKey>

/// <summary>
/// Gets or sets the formatter that is used by the registry to format the <typeparamref name="TKey"/> to a string that
/// represents the strategy key.
/// represents the instance name of the builder.
/// </summary>
/// <remarks>
/// By default, the formatter uses the <see cref="object.ToString"/> method.
/// Defaults to <see langword="null"/>.
/// <para>
/// Use custom formatter for composite keys in case you want to have different metric values for a builder and strategy key.
/// In general, strategies can have the same builder name and different strategy keys.
/// Use custom formatter for composite keys in case you want to have different metric values for a builder and instance key.
/// In general, strategies can have the same builder name and different instance names.
/// </para>
/// </remarks>
[Required]
public Func<TKey, string> StrategyKeyFormatter { get; set; } = (key) => key?.ToString() ?? string.Empty;
public Func<TKey, string>? InstanceNameFormatter { get; set; }

/// <summary>
/// Gets or sets the formatter that is used by the registry to format the <typeparamref name="TKey"/> to a string that
Expand Down
11 changes: 11 additions & 0 deletions src/Polly.Core/ResilienceStrategyBuilderBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,16 @@ private protected ResilienceStrategyBuilderBase(ResilienceStrategyBuilderBase ot
/// </remarks>
public string? BuilderName { get; set; }

/// <summary>
/// Gets or sets the instance name of the builder.
/// </summary>
/// <remarks>
/// This property is also included in the telemetry that is produced by the individual resilience strategies.
/// The instance name can be used to differentiate between multiple builder instances with the same <see cref="BuilderName"/>.
/// Defaults to <see langword="null"/>.
/// </remarks>
public string? InstanceName { get; set; }

/// <summary>
/// Gets the custom properties attached to builder options.
/// </summary>
Expand Down Expand Up @@ -125,6 +135,7 @@ private ResilienceStrategy CreateResilienceStrategy(Entry entry)
{
var context = new ResilienceStrategyBuilderContext(
builderName: BuilderName,
builderInstanceName: InstanceName,
builderProperties: Properties,
strategyName: entry.Properties.StrategyName,
strategyType: entry.Properties.StrategyType,
Expand Down
9 changes: 8 additions & 1 deletion src/Polly.Core/ResilienceStrategyBuilderContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ public sealed class ResilienceStrategyBuilderContext
{
internal ResilienceStrategyBuilderContext(
string? builderName,
string? builderInstanceName,
ResilienceProperties builderProperties,
string? strategyName,
string strategyType,
Expand All @@ -20,12 +21,13 @@ public sealed class ResilienceStrategyBuilderContext
Func<double> randomizer)
{
BuilderName = builderName;
BuilderInstanceName = builderInstanceName;
BuilderProperties = builderProperties;
StrategyName = strategyName;
StrategyType = strategyType;
TimeProvider = timeProvider;
IsGenericBuilder = isGenericBuilder;
Telemetry = TelemetryUtil.CreateTelemetry(diagnosticSource, builderName, builderProperties, strategyName, strategyType);
Telemetry = TelemetryUtil.CreateTelemetry(diagnosticSource, builderName, builderInstanceName, builderProperties, strategyName, strategyType);
Randomizer = randomizer;
}

Expand All @@ -34,6 +36,11 @@ public sealed class ResilienceStrategyBuilderContext
/// </summary>
public string? BuilderName { get; }

/// <summary>
/// Gets the instance name of the builder.
/// </summary>
public string? BuilderInstanceName { get; }

/// <summary>
/// Gets the custom properties attached to the builder.
/// </summary>
Expand Down
2 changes: 2 additions & 0 deletions src/Polly.Core/Telemetry/ResilienceTelemetrySource.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ namespace Polly.Telemetry;
/// The source of resilience telemetry events.
/// </summary>
/// <param name="BuilderName">The builder name.</param>
/// <param name="BuilderInstanceName">The builder instance name.</param>
/// <param name="BuilderProperties">The builder properties.</param>
/// <param name="StrategyName">The strategy name. </param>
/// <param name="StrategyType">The strategy type.</param>
Expand All @@ -12,6 +13,7 @@ namespace Polly.Telemetry;
/// </remarks>
public sealed record class ResilienceTelemetrySource(
string? BuilderName,
string? BuilderInstanceName,
ResilienceProperties BuilderProperties,
string? StrategyName,
string StrategyType);
Expand Down
5 changes: 2 additions & 3 deletions src/Polly.Core/Telemetry/TelemetryUtil.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,15 @@ internal static class TelemetryUtil

internal const string ExecutionAttempt = "ExecutionAttempt";

internal static readonly ResiliencePropertyKey<string> StrategyKey = new("Polly.StrategyKey");

public static ResilienceStrategyTelemetry CreateTelemetry(
DiagnosticSource? diagnosticSource,
string? builderName,
string? builderInstanceName,
ResilienceProperties builderProperties,
string? strategyName,
string strategyType)
{
var telemetrySource = new ResilienceTelemetrySource(builderName, builderProperties, strategyName, strategyType);
var telemetrySource = new ResilienceTelemetrySource(builderName, builderInstanceName, builderProperties, strategyName, strategyType);

return new ResilienceStrategyTelemetry(telemetrySource, diagnosticSource);
}
Expand Down
24 changes: 8 additions & 16 deletions src/Polly.Extensions/Telemetry/Log.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,7 @@ internal static partial class Log
EventId = 0,
Message = "Resilience event occurred. " +
"EventName: '{EventName}', " +
"Builder Name: '{BuilderName}', " +
"Strategy Name: '{StrategyName}', " +
"Strategy Type: '{StrategyType}', " +
"Strategy Key: '{StrategyKey}', " +
"Source: '{BuilderName}[{BuilderInstance}]/{StrategyType}[{StrategyName}]', " +
"Operation Key: '{OperationKey}', " +
"Result: '{Result}'",
EventName = "ResilienceEvent")]
Expand All @@ -24,9 +21,9 @@ internal static partial class Log
LogLevel logLevel,
string eventName,
string? builderName,
string? builderInstance,
string? strategyName,
string strategyType,
string? strategyKey,
string? operationKey,
object? result,
Exception? exception);
Expand All @@ -35,23 +32,21 @@ internal static partial class Log
1,
LogLevel.Debug,
"Resilience strategy executing. " +
"Builder Name: '{BuilderName}', " +
"Strategy Key: '{StrategyKey}', " +
"Source: '{BuilderName}[{BuilderInstance}]', " +
"Operation Key: '{OperationKey}', " +
"Result Type: '{ResultType}'",
EventName = "StrategyExecuting")]
public static partial void ExecutingStrategy(
this ILogger logger,
string? builderName,
string? strategyKey,
string? builderInstance,
string? operationKey,
string resultType);

[LoggerMessage(
EventId = 2,
Message = "Resilience strategy executed. " +
"Builder Name: '{BuilderName}', " +
"Strategy Key: '{StrategyKey}', " +
"Source: '{BuilderName}[{BuilderInstance}]', " +
"Operation Key: '{OperationKey}', " +
"Result Type: '{ResultType}', " +
"Result: '{Result}', " +
Expand All @@ -62,7 +57,7 @@ internal static partial class Log
this ILogger logger,
LogLevel logLevel,
string? builderName,
string? strategyKey,
string? builderInstance,
string? operationKey,
string resultType,
object? result,
Expand All @@ -73,10 +68,7 @@ internal static partial class Log
[LoggerMessage(
EventId = 3,
Message = "Execution attempt. " +
"Builder Name: '{BuilderName}', " +
"Strategy Name: '{StrategyName}', " +
"Strategy Type: '{StrategyType}', " +
"Strategy Key: '{StrategyKey}', " +
"Source: '{BuilderName}[{BuilderInstance}]/{StrategyType}[{StrategyName}]', " +
"Operation Key: '{OperationKey}', " +
"Result: '{Result}', " +
"Handled: '{Handled}', " +
Expand All @@ -88,9 +80,9 @@ internal static partial class Log
this ILogger logger,
LogLevel level,
string? builderName,
string? builderInstance,
string? strategyName,
string strategyType,
string? strategyKey,
string? operationKey,
object? result,
bool handled,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,9 @@ private static void AddCommonTags(TelemetryEventArguments args, ResilienceTeleme
enrichmentContext.Tags.Add(new(ResilienceTelemetryTags.EventName, args.Event.EventName));
enrichmentContext.Tags.Add(new(ResilienceTelemetryTags.EventSeverity, args.Event.Severity.AsString()));
enrichmentContext.Tags.Add(new(ResilienceTelemetryTags.BuilderName, source.BuilderName));
enrichmentContext.Tags.Add(new(ResilienceTelemetryTags.BuilderInstance, source.BuilderInstanceName));
enrichmentContext.Tags.Add(new(ResilienceTelemetryTags.StrategyName, source.StrategyName));
enrichmentContext.Tags.Add(new(ResilienceTelemetryTags.StrategyType, source.StrategyType));
enrichmentContext.Tags.Add(new(ResilienceTelemetryTags.StrategyKey, source.BuilderProperties.GetValue(TelemetryUtil.StrategyKey, null!)));
enrichmentContext.Tags.Add(new(ResilienceTelemetryTags.OperationKey, enrichmentContext.Context.OperationKey));
enrichmentContext.Tags.Add(new(ResilienceTelemetryTags.ResultType, args.Context.GetResultType()));
enrichmentContext.Tags.Add(new(ResilienceTelemetryTags.ExceptionName, args.Outcome?.Exception?.GetType().FullName));
Expand Down Expand Up @@ -93,7 +93,6 @@ private void MeterEvent(TelemetryEventArguments args)

private void LogEvent(TelemetryEventArguments args)
{
var strategyKey = args.Source.BuilderProperties.GetValue(TelemetryUtil.StrategyKey, null!);
var result = args.Outcome?.Result;
if (result is not null)
{
Expand All @@ -114,9 +113,9 @@ private void LogEvent(TelemetryEventArguments args)
_logger,
level,
args.Source.BuilderName,
args.Source.BuilderInstanceName,
args.Source.StrategyName,
args.Source.StrategyType,
strategyKey,
args.Context.OperationKey,
result,
executionAttempt.Handled,
Expand All @@ -132,9 +131,9 @@ private void LogEvent(TelemetryEventArguments args)
level,
args.Event.EventName,
args.Source.BuilderName,
args.Source.BuilderInstanceName,
args.Source.StrategyName,
args.Source.StrategyType,
strategyKey,
args.Context.OperationKey,
result,
args.Outcome?.Exception);
Expand Down
4 changes: 2 additions & 2 deletions src/Polly.Extensions/Telemetry/ResilienceTelemetryTags.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@ internal class ResilienceTelemetryTags

public const string BuilderName = "builder-name";

public const string BuilderInstance = "builder-instance";

public const string StrategyName = "strategy-name";

public const string StrategyType = "strategy-type";

public const string StrategyKey = "strategy-key";

public const string ResultType = "result-type";

public const string OperationKey = "operation-key";
Expand Down
Loading

0 comments on commit 472e961

Please sign in to comment.