Skip to content

Commit 48b7f06

Browse files
Merge pull request #21 from Stravaig-Projects/#19/internal-replay-limit
(#19) Enforce replay log limit
2 parents d5660de + 2882566 commit 48b7f06

File tree

5 files changed

+84
-28
lines changed

5 files changed

+84
-28
lines changed

release-notes/wip-release-notes.md

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

55
Date: ???
66

7+
### Features
8+
9+
- #19: Limit the number of replayed logs.
10+
711
### Miscellaneous
812

913
- #18: Use compile time logging source generation.
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
using Microsoft.Extensions.Logging;
2+
using NUnit.Framework;
3+
using Shouldly;
4+
using Stravaig.Configuration.SqlServer.Glue;
5+
using Stravaig.Extensions.Logging.Diagnostics;
6+
using Stravaig.Extensions.Logging.Diagnostics.Render;
7+
8+
namespace Stravaig.Configuration.SqlServer.Tests;
9+
10+
[TestFixture]
11+
public class ReplayLoggerTests
12+
{
13+
[Test]
14+
public void LogsThatReplayLimitWasReached()
15+
{
16+
ReplayLogger replayLogger = new ();
17+
for (int counter = 0; counter < 30; counter++)
18+
{
19+
replayLogger.LogInformation("This is log number {Counter}", counter);
20+
}
21+
22+
TestCaptureLogger<ReplayLoggerTests> captureLogger = new ();
23+
replayLogger.Replay(captureLogger);
24+
25+
var logs = captureLogger.GetLogs();
26+
logs.RenderLogs(Formatter.SimpleBySequence, Sink.Console);
27+
28+
logs.Count.ShouldBe(28);
29+
30+
logs[0].OriginalMessage.ShouldBe("Replaying {Count} delayed logs. NOTE: Some replayed logs may not emit if filters prevent them.");
31+
logs[0].PropertyDictionary["Count"].ShouldBe(25);
32+
33+
logs[^2].OriginalMessage.ShouldBe("The replay limit was reached. There are {excessCount} logs that cannot be replayed.");
34+
logs[^2].PropertyDictionary["excessCount"].ShouldBe(5);
35+
36+
logs[^1].OriginalMessage.ShouldBe("End of replay.");
37+
}
38+
39+
[Test]
40+
public void ReplayLogsHappyPath()
41+
{
42+
ReplayLogger replayLogger = new ();
43+
for (int counter = 0; counter < 10; counter++)
44+
{
45+
replayLogger.LogInformation("This is log number {Counter}", counter);
46+
}
47+
48+
TestCaptureLogger<ReplayLoggerTests> captureLogger = new ();
49+
replayLogger.Replay(captureLogger);
50+
51+
var logs = captureLogger.GetLogs();
52+
logs.RenderLogs(Formatter.SimpleBySequence, Sink.Console);
53+
54+
logs.Count.ShouldBe(12);
55+
56+
logs[0].OriginalMessage.ShouldBe("Replaying {Count} delayed logs. NOTE: Some replayed logs may not emit if filters prevent them.");
57+
logs[0].PropertyDictionary["Count"].ShouldBe(10);
58+
59+
logs[^1].OriginalMessage.ShouldBe("End of replay.");
60+
}
61+
}

src/Stravaig.Configuration.SqlServer/Glue/Log.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,4 +52,10 @@ public static partial class Log
5252
Level = LogLevel.Debug,
5353
Message = "Starting SQL Server Configuration DB Polling every {frequency} seconds.")]
5454
public static partial void StartingDbPolling(this ILogger logger, double frequency);
55+
56+
[LoggerMessage(
57+
EventId = 9,
58+
Level = LogLevel.Warning,
59+
Message = "The replay limit was reached. There are {excessCount} logs that cannot be replayed.")]
60+
public static partial void ReplayLimitExceeded(this ILogger logger, int excessCount);
5561
}

src/Stravaig.Configuration.SqlServer/Glue/ReplayLogger.cs

Lines changed: 12 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,12 @@ internal class ReplayLogger : ILogger
1515

1616
private readonly object _lock = new ();
1717
private readonly Queue<Action<ILogger>> _logs;
18-
private readonly Stack<IDisposable> _scopes;
1918
private readonly int _limit = 25;
19+
private int _limitExcess;
2020

21-
public ReplayLogger()
21+
internal ReplayLogger()
2222
{
23-
this._logs = new Queue<Action<ILogger>>();
24-
this._scopes = new Stack<IDisposable>();
23+
_logs = new Queue<Action<ILogger>>();
2524
}
2625

2726
public void Log<TState>(
@@ -39,7 +38,10 @@ void ReplayLog(ILogger logger)
3938
lock (_lock)
4039
{
4140
if (_logs.Count >= _limit)
42-
_logs.Dequeue();
41+
{
42+
_limitExcess++;
43+
return;
44+
}
4345
_logs.Enqueue(ReplayLog);
4446
}
4547
}
@@ -48,17 +50,7 @@ void ReplayLog(ILogger logger)
4850

4951
public IDisposable BeginScope<TState>(TState state)
5052
{
51-
lock (_lock)
52-
{
53-
_logs.Enqueue(logger =>
54-
{
55-
IDisposable scope = logger.BeginScope(state);
56-
57-
_scopes.Push(scope);
58-
});
59-
60-
return new Scope(this);
61-
}
53+
return new Scope();
6254
}
6355

6456
public void Replay(ILogger logger)
@@ -76,26 +68,19 @@ public void Replay(ILogger logger)
7668
replayTo(logger);
7769
}
7870

71+
if (_limitExcess > 0)
72+
logger.ReplayLimitExceeded(_limitExcess);
73+
7974
_logs.Clear();
75+
_limitExcess = 0;
8076
}
8177
logger.ReplayEnd();
8278
}
8379

8480
private class Scope : IDisposable
8581
{
86-
private readonly ReplayLogger _logger;
87-
88-
public Scope(ReplayLogger logger)
89-
{
90-
_logger = logger;
91-
}
92-
9382
public void Dispose()
9483
{
95-
lock (_logger._lock)
96-
{
97-
_logger._logs.Enqueue(_ => this._logger._scopes.Pop());
98-
}
9984
}
10085
}
10186
}

version.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
0.2.1
1+
0.3.0

0 commit comments

Comments
 (0)