serilog/serilog-sinks-map

Memory leak when 'sinkMapCountLimit' is set in WriteTo.Map

LachlanCoote opened this issue · 1 comments

Description
When sinkMapCountLimit is set lower than the possible amount of sinks being created, evicted sinks are still being referenced by LoggerConfiguration's _logEventSinks. The GC is unable to reclaim the resources of those sinks.

Reproduction

private const int FILE_COUNT = 5;

private static readonly Random _random = new Random();

private static readonly string _path = System.IO.Path.Combine(Environment.GetFolderPath(
	Environment.SpecialFolder.CommonApplicationData), "Serilog-Memleak-Test");

static async Task Main(string[] args)
{
	Log.Logger = new LoggerConfiguration()
		.WriteTo.Map("Number", "",
			     (number, wt) => wt.File($"{_path}/logs-{number}.txt"),
			     sinkMapCountLimit: FILE_COUNT - 1)
		.CreateLogger();

	do
	{
		while (!Console.KeyAvailable)
		{
			Log.Information("Test log entry for {Number}", _random.Next(0, FILE_COUNT).ToString());
			await Task.Delay(100).ConfigureAwait(false);
		}
	} while (Console.ReadKey(true).Key != ConsoleKey.Escape);
}

Expected behavior
When a wrapped sink is evicted from MappedSink, its resources are reclaimed by the GC.

Relevant package, tooling and runtime versions

First Discovered Reproduced
.NET Framework 4.6.1 .NET Core 3.1
Serilog v2.9.0 Serilog v2.10.0
Sinks.Map v1.0.0 Sinks.Map v1.0.1
Sink.File v4.1.0 Sinks.File v4.1.0

Nice spotting - thanks! PR on its way.