Skip to content

Commit 43c01c9

Browse files
authored
Merge pull request #40 from nblumhardt/reloadable-logger-fixes
Fix freezing of CachingReloadableLoggers
2 parents 5540199 + 8abbc70 commit 43c01c9

File tree

4 files changed

+37
-21
lines changed

4 files changed

+37
-21
lines changed

samples/SimpleServiceSample/Program.cs

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,25 +7,14 @@
77

88
namespace SimpleServiceSample
99
{
10-
public class Program
10+
public static class Program
1111
{
12-
public static Action<IConfigurationBuilder> BuildConfiguration =
13-
builder => builder
14-
.SetBasePath(Directory.GetCurrentDirectory())
15-
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
16-
.AddJsonFile($"appsettings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? "Production"}.json", optional: true)
17-
.AddEnvironmentVariables();
18-
1912
public static int Main(string[] args)
2013
{
21-
var builder = new ConfigurationBuilder();
22-
BuildConfiguration(builder);
23-
2414
Log.Logger = new LoggerConfiguration()
25-
.ReadFrom.Configuration(builder.Build())
2615
.Enrich.FromLogContext()
2716
.WriteTo.Console()
28-
.CreateLogger();
17+
.CreateBootstrapLogger();
2918

3019
try
3120
{
@@ -47,6 +36,9 @@ public static int Main(string[] args)
4736
public static IHostBuilder CreateHostBuilder(string[] args) =>
4837
Host.CreateDefaultBuilder(args)
4938
.ConfigureServices(services => services.AddHostedService<PrintTimeService>())
50-
.UseSerilog();
39+
.UseSerilog((context, services, loggerConfiguration) => loggerConfiguration
40+
.ReadFrom.Configuration(context.Configuration)
41+
.Enrich.FromLogContext()
42+
.WriteTo.Console());
5143
}
5244
}

src/Serilog.Extensions.Hosting/Extensions/Hosting/CachingReloadableLogger.cs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -128,8 +128,7 @@ public ILogger ForContext<TSource>()
128128
{
129129
if (_frozen)
130130
return _cached.ForContext<TSource>();
131-
132-
131+
133132
if (_reloadableLogger.CreateChild(
134133
_root,
135134
this,
@@ -171,12 +170,15 @@ void Update(ILogger newRoot, ILogger newCached, bool frozen)
171170
{
172171
_root = newRoot;
173172
_cached = newCached;
174-
_frozen = frozen;
175173

176174
// https://github.com/dotnet/runtime/issues/20500#issuecomment-284774431
177-
// Publish `_cached` and `_frozen`. This is useful here because it means that once the logger is frozen - which
175+
// Publish `_cached` and then `_frozen`. This is useful here because it means that once the logger is frozen - which
178176
// we always expect - reads don't require any synchronization/interlocked instructions.
179177
Interlocked.MemoryBarrierProcessWide();
178+
179+
_frozen = frozen;
180+
181+
Interlocked.MemoryBarrierProcessWide();
180182
}
181183

182184
public void Write(LogEvent logEvent)

src/Serilog.Extensions.Hosting/Extensions/Hosting/ReloadableLogger.cs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ public Logger Freeze()
8080
throw new InvalidOperationException("The logger is already frozen.");
8181

8282
_frozen = true;
83-
83+
8484
// https://github.com/dotnet/runtime/issues/20500#issuecomment-284774431
8585
// Publish `_logger` and `_frozen`. This is useful here because it means that once the logger is frozen - which
8686
// we always expect - reads don't require any synchronization/interlocked instructions.
@@ -368,12 +368,21 @@ public bool BindProperty(string propertyName, object value, bool destructureObje
368368
[MethodImpl(MethodImplOptions.AggressiveInlining)]
369369
(ILogger, bool) UpdateForCaller(ILogger root, ILogger cached, IReloadableLogger caller, out ILogger newRoot, out ILogger newCached, out bool frozen)
370370
{
371+
if (_frozen)
372+
{
373+
// If we're frozen, then the caller hasn't observed this yet and should update.
374+
newRoot = _logger;
375+
newCached = caller.ReloadLogger();
376+
frozen = true;
377+
return (newCached, true);
378+
}
379+
371380
if (cached != null && root == _logger)
372381
{
373382
newRoot = default;
374383
newCached = default;
375-
frozen = _frozen;
376-
return (cached, frozen); // If we're frozen, then the caller hasn't observed this yet and should update.
384+
frozen = false;
385+
return (cached, false);
377386
}
378387

379388
newRoot = _logger;

test/Serilog.Extensions.Hosting.Tests/ReloadableLoggerTests.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,19 @@ public void AFrozenLoggerYieldsSerilogLoggers()
2020
nested = contextual.ForContext("test", "test");
2121
Assert.IsType<Core.Logger>(nested);
2222
}
23+
24+
[Fact]
25+
public void CachingReloadableLoggerRemainsUsableAfterFreezing()
26+
{
27+
var logger = new LoggerConfiguration().CreateBootstrapLogger();
28+
var contextual = logger.ForContext<ReloadableLoggerTests>();
29+
contextual.Information("First");
30+
logger.Reload(c => c);
31+
logger.Freeze();
32+
contextual.Information("Second");
33+
contextual.Information("Third");
34+
contextual.Information("Fourth"); // No crash :-)
35+
}
2336
}
2437
}
2538

0 commit comments

Comments
 (0)