【发布时间】:2019-08-04 22:41:33
【问题描述】:
我正在编写一个应用程序,其中日志记录是我实际域模型的一部分。这是一个自动化和批处理工具,最终用户将能够在实际应用程序中查看批处理作业的日志,而不仅仅是文本日志文件。
所以我的域模型包含一个LogMessage 类:
public sealed class LogMessage
{
public string Message { get; }
public DateTime TimestampUtc { get; }
public LogLevel Level { get; }
}
public enum LogLevel
{
Fatal = 5,
Error = 4,
Warn = 3,
Info = 2,
Debug = 1,
Trace = 0
}
我还有一个Result 类,它的集合属性为LogMessages。最终用户可以使用我的应用程序将结果保存到文件中并从文件中打开。
public class Result
{
public bool Succeeded {get; set;}
public string StatusMessage {get; set;}
public IList<LogMessage> LogMessages {get; set;}
}
我的应用程序还支持第三方开发人员使用插件扩展应用程序,这些插件也可以写入日志消息。所以我为插件开发者定义了一个通用的ILogger接口。
public interface ILogger
{
void Debug(string message);
void Error(string message);
void Fatal(string message);
void Info(string message);
void Log(LogLevel level, string message);
void Trace(string message);
void Warn(string message);
}
我向写入Result.LogMessages 的插件提供ILogger 的实例。
public interface IPlugIn
{
Output DoSomeThing(Input in, ILogger logger);
}
我显然也希望能够从我自己的内部代码进行日志记录,并最终希望Result.LogMessages 包含我的内部日志消息和来自插件的日志消息的混合。因此,遇到问题的最终用户可以向我发送一个结果文件,其中包含来自我的内部代码和使用的任何插件的调试日志。
目前,我有一个使用自定义 NLog 目标的解决方案。
public class LogResultTarget : NLog.Targets.Target
{
public static Result CurrentTargetResult { get; set; }
protected override void Write(NLog.LogEventInfo logEvent)
{
if (CurrentTargetResult != null)
{
//Convert NLog logEvent to LogMessage
LogLevel level = (LogLevel)Enum.Parse(typeof(LogLevel), logEvent.Level.Name);
LogMessage lm = new LogMessage(logEvent.TimeStamp.ToUniversalTime(), level, logEvent.Message);
CurrentTargetResult.LogMessages.Add(lm);
}
}
protected override void Write(NLog.Common.AsyncLogEventInfo logEvent)
{
Write(logEvent.LogEvent);
}
}
此类将消息转发到分配给静态LogResultTarget.CurrentTargetResult 属性的Result。我的内部代码记录到 NLog 记录器,并且我有一个 ILogger 的实现,它也记录到 NLog.Logger。
这是有效的,但感觉真的很脆弱。如果CurrentTargetResult 设置不正确或未设置回null,我最终可能会将日志消息存储到它们不适用的结果中。另外,因为只有一个静态CurrentTargetResult,所以我无法支持同时处理多个结果。
有没有不同/更好的方法可以解决这个问题?还是我试图做的事情根本上是错误的?
【问题讨论】:
-
我不完全理解
CurrentTargetResult属性,您当前的目标中没有使用它? (只有空检查?)Result类型到底长什么样? -
啊,我的示例代码中好像有错字,我有“Target”而不是“CurrentTargetResult”。我还添加了“结果”类的示例。这有帮助吗?
-
是的,添加了答案:)
标签: c# logging nlog error-logging