Skip to content

Commit 0d8061d

Browse files
authored
Log unhealthy executions with warning level (#1306)
1 parent 5bfceb2 commit 0d8061d

File tree

6 files changed

+40
-13
lines changed

6 files changed

+40
-13
lines changed

src/Polly.Extensions/Telemetry/Log.cs

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -83,9 +83,10 @@ public static void ExecutingStrategy(
8383
#endif
8484

8585
#if NET6_0_OR_GREATER
86-
[LoggerMessage(2, LogLevel.Debug, StrategyExecutedMessage, EventName = "StrategyExecuted")]
86+
[LoggerMessage(EventId = 2, Message = StrategyExecutedMessage, EventName = "StrategyExecuted")]
8787
public static partial void StrategyExecuted(
8888
this ILogger logger,
89+
LogLevel logLevel,
8990
string? builderName,
9091
string? strategyKey,
9192
string resultType,
@@ -94,11 +95,15 @@ public static partial void StrategyExecuted(
9495
double executionTime,
9596
Exception? exception);
9697
#else
97-
private static readonly Action<ILogger, string?, string?, string, object?, string, double, Exception?> StrategyExecutedAction =
98+
private static readonly Action<ILogger, string?, string?, string, object?, string, double, Exception?> StrategyExecutedActionDebug =
9899
LoggerMessage.Define<string?, string?, string, object?, string, double>(LogLevel.Debug, new EventId(2, "StrategyExecuted"), StrategyExecutedMessage);
99100

101+
private static readonly Action<ILogger, string?, string?, string, object?, string, double, Exception?> StrategyExecutedActionWarning =
102+
LoggerMessage.Define<string?, string?, string, object?, string, double>(LogLevel.Warning, new EventId(2, "StrategyExecuted"), StrategyExecutedMessage);
103+
100104
public static void StrategyExecuted(
101105
this ILogger logger,
106+
LogLevel logLevel,
102107
string? builderName,
103108
string? strategyKey,
104109
string resultType,
@@ -107,7 +112,14 @@ public static void StrategyExecuted(
107112
double executionTime,
108113
Exception? exception)
109114
{
110-
StrategyExecutedAction(logger, builderName, strategyKey, resultType, result, executionHealth, executionTime, exception);
115+
if (logLevel == LogLevel.Warning)
116+
{
117+
StrategyExecutedActionWarning(logger, builderName, strategyKey, resultType, result, executionHealth, executionTime, exception);
118+
}
119+
else
120+
{
121+
StrategyExecutedActionDebug(logger, builderName, strategyKey, resultType, result, executionHealth, executionTime, exception);
122+
}
111123
}
112124
#endif
113125
}

src/Polly.Extensions/Telemetry/ResilienceContextExtensions.cs

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,9 @@ namespace Polly.Extensions.Telemetry;
44

55
internal static class ResilienceContextExtensions
66
{
7-
public static string GetResultType(this ResilienceContext context)
8-
{
9-
return context.IsVoid ? "void" : context.ResultType.Name.ToString(CultureInfo.InvariantCulture);
10-
}
7+
public static string GetResultType(this ResilienceContext context) => context.IsVoid ? "void" : context.ResultType.Name.ToString(CultureInfo.InvariantCulture);
118

12-
public static string GetExecutionHealth(this ResilienceContext context)
13-
{
14-
return context.ResilienceEvents.Count == 0 ? "Healthy" : "Unhealthy";
15-
}
9+
public static string GetExecutionHealth(this ResilienceContext context) => context.IsExecutionHealthy() ? "Healthy" : "Unhealthy";
10+
11+
public static bool IsExecutionHealthy(this ResilienceContext context) => context.ResilienceEvents.Count == 0;
1612
}

src/Polly.Extensions/Telemetry/TelemetryResilienceStrategy.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,11 @@ protected override async ValueTask<Outcome<TResult>> ExecuteCoreAsync<TResult, T
5858
var outcome = await callback(context, state).ConfigureAwait(context.ContinueOnCapturedContext);
5959

6060
var duration = _timeProvider.GetElapsedTime(stamp);
61+
var logLevel = context.IsExecutionHealthy() ? LogLevel.Debug : LogLevel.Warning;
62+
6163
Log.StrategyExecuted(
6264
_logger,
65+
logLevel,
6366
_builderName,
6467
_strategyKey,
6568
context.GetResultType(),

test/Polly.Extensions.Tests/Telemetry/TelemetryResilienceStrategyTests.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
using System.Collections.Generic;
2+
using FluentAssertions;
13
using Microsoft.Extensions.Logging;
24
using Polly.Extensions.Telemetry;
35
using Polly.Telemetry;
@@ -54,6 +56,20 @@ public void Execute_EnsureLogged(bool healthy)
5456
messages = _logger.GetRecords(new EventId(2, "StrategyExecuted")).ToList();
5557
messages.Should().HaveCount(1);
5658
messages[0].Message.Should().Match($"Resilience strategy executed. Builder Name: 'my-builder', Strategy Key: 'my-key', Result Type: 'void', Result: 'void', Execution Health: '{healthString}', Execution Time: *ms");
59+
messages[0].LogLevel.Should().Be(healthy ? LogLevel.Debug : LogLevel.Warning);
60+
61+
// verify reported state
62+
var coll = messages[0].State.Should().BeAssignableTo<IReadOnlyList<KeyValuePair<string, object>>>().Subject;
63+
coll.Count.Should().Be(7);
64+
coll.AsEnumerable().Should().HaveCount(7);
65+
(coll as IEnumerable).GetEnumerator().Should().NotBeNull();
66+
67+
for (int i = 0; i < coll.Count; i++)
68+
{
69+
coll[i].Value.Should().NotBeNull();
70+
}
71+
72+
coll.Invoking(c => c[coll.Count + 1]).Should().Throw<IndexOutOfRangeException>();
5773
}
5874

5975
[Fact]

test/Polly.TestUtils/FakeLogger.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,6 @@ public IDisposable BeginScope<TState>(TState state)
2020
public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func<TState, Exception?, string> formatter)
2121
where TState : notnull
2222
{
23-
_records.Add(new LogRecord(eventId, formatter(state, exception), exception));
23+
_records.Add(new LogRecord(logLevel, eventId, formatter(state, exception), exception, state));
2424
}
2525
}

test/Polly.TestUtils/LogRecord.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@
33
namespace Polly.TestUtils;
44
#pragma warning disable CS8633 // Nullability in constraints for type parameter doesn't match the constraints for type parameter in implicitly implemented interface method'.
55

6-
public record class LogRecord(EventId EventId, string Message, Exception? Exception);
6+
public record class LogRecord(LogLevel LogLevel, EventId EventId, string Message, Exception? Exception, object State);

0 commit comments

Comments
 (0)