Serilog Dispose/Close 日志文件流

Serilog Dispose/Close log file-stream

最近我专注于 Serilog 指出基于每个 LogEvent 的当前日期的模板化路径。 在弄清楚如何实现之后,我最终通过使用 Serilog.Sinks.Map 将 Date 字段动态解析为 LogEvent,如下所示:

return new LoggerConfiguration().WriteTo
    .Map(
        // Log key
        (LogEvent le) => le.Timestamp.Date,
        // Log Action
        (DateTime date, LoggerSinkConfiguration lc) =>
        {
            string path = GetFilesPath(date, logName);
            lc.File(path);
        }
    );
public string GetFilePath(DateTime date, string logName) =>
            Path.Combine("./Logs", $"{date:yyyy-MM-dd}", $"{logName}.log");

有了这个,我实现了我的目标:根据日期在子文件夹中写入日志。

问题是,由于 Serilog 不知道指向路径已更改,因此它不会按预期关闭或处理文件流。因此,我的应用程序让文件每天都打开,无休止。

如果有人遇到过这种方法,手动关闭流,或者如果 Serilog API 公开以某种方式自动关闭这些流,那就太好了。

顺便说一句,我正在使用

编辑 2020 年 5 月 6 日,供之后阅读本文的人使用。
通过 Timestamp 键入每个日志事件是一个坏主意。通过这样做,我们实际上是在为每个日志事件添加一个条目(为简单起见,假设没有同时发出任何事件)。
即使我们将 sinkMapCountLimit 指定为 0,这在理论上不会在我们的地图中保留任何事件,如果该事件配置为写入文件(特别是使用 RollingFile 接收器) ,那些水槽不会被处理掉,也不会从内存中删除。

所以,上面的代码块正在泄漏内存(而且速度非常快)。
Map.Sink documentation 确实对此发出了警告。

...but isn't suitable when the set of possible key values is open-ended.

Serilog.Sinks.Map 接受一个参数 sinkMapCountLimit 来控制它:

return new LoggerConfiguration().WriteTo
    .Map(
        // Log key
        (LogEvent le) => le.Timestamp.Date,
        // Log Action
        (DateTime date, LoggerSinkConfiguration lc) =>
        {
            string path = GetFilesPath(date, logName);
            lc.File(path);
        },
        sinkMapCountLimit: 5
    );