英文:
How to ensure a logging file is flushed/closed within a DLL (C# and Serilog)
问题
我目前正在尝试使用Serilog来记录文件和控制台的日志,主要用于调试我正在开发的小型C# DLL。
我不确定如何刷新/关闭日志文件,即:
Log.CloseAndFlush()
我可以在析构函数中执行这个操作,但其他Stack Overflow文章建议这样做是不明智的,因为它的执行不能保证。
其他要点:
- Serilog日志未在DLL类中公开。
- 如果该类是静态的会怎么样?(虽然它不是静态的,但我对其影响很感兴趣)。
英文:
I am currently experimenting with Serilog for logging to file and console, primarily for debugging purposes of a small C# DLL I am working on.
I am unsure how to go about Flushing/Closing the log file, i.e.:
Log.CloseAndFlush()
I could do it in the destructor, but other Stack Overflow articles suggest this is unwise as its execution is not guaranteed.
Other points:
- The Serilog Log is not publically exposed by the DLL class.
- What if the class is static ? (It is not but I am curious about the implications).
答案1
得分: 1
你的DLL不应该决定使用哪个日志实现库,而应该将这个决定留给你库的使用者。只需坚持使用抽象,很可能是Microsoft.Extensions.Logging及其接口。
一般来说,如果你需要使用者执行与你的库相关的任何清理工作,你应该暴露一个显式的API来实现。就像Serilog已经做的那样,通过首先暴露Log.CloseAndFlush()
方法。Serilog(当前/可以争论)只是不知道在所有情况下何时调用它,所以“简单地”将这个任务留给使用者(最终是应用程序/可执行文件)。
考虑:
namespace YourLibrary
{
public static class Util
{
public static void Shutdown()
{
// 可能还有其他内容...
// 清理日志
Log.CloseAndFlush();
}
}
}
然后,你要求你的使用者执行类似于这样的操作(示例):
public static void Main()
{
try
{
// ... 其他操作 ...
}
finally
{
YourLibrary.Util.Shutdown();
}
}
从使用的角度来看,这种设计不是最佳的,但至少它使事情变得明确。
然而,最终总会有一些情况,你不能保证会调用你的清理方法(崩溃等),所以我建议按照Hans在他的评论中所说的做:寻找一个不同的日志框架实现(或选择一个始终隐式刷新的Serilog Sink)。
英文:
Your DLL shouldn't make the choice of logging implementation library to use, but leave that up to the consumer of your library. Simply stick with an abstraction, most likely Microsoft.Extensions.Logging, and its interfaces.
Generally, if you need the consumer to do any cleanup work related to your library, you should expose an explicit API to do so. Much like Serilog already does by exposing the Log.CloseAndFlush()
method in the first place. Serilog (currently/arguably) simply doesn't know when to call it under all circumstances and so "simply" leaves that task for the consumer (ultimately an application/executable).
Consider:
namespace YourLibrary
{
public static class Util
{
public static void Shutdown()
{
// Potentially other stuff...
// Cleanup logging
Log.CloseAndFlush();
}
}
}
Then in you require your consumers to do something like this (example):
public static void Main()
{
try
{
// ... whatever ...
}
finally
{
YourLibrary.Util.Shutdown();
}
}
This design is not optimal from a usage point of view, but at least it makes things explicit.
In the end, however, there will always be situations when you cannot have your cleanup method being called (crashes, etc.), so I would suggest what Hans said in his comment: look for a different logging framework implementation (or choose a Serilog Sink that always flushes implicitly).
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论