C# Log4Net:如何将程序内部的日志记录结果输出到变量中?
我正在努力学习使用Log4Net来改进我程序中的日志记录技术。 我已经阅读了Log4Net网站上提供的文档,但是我有这些问题 这是由C# Log4Net:如何将程序内部的日志记录结果输出到变量中?,c#,wpf,log4net,log4net-appender,C#,Wpf,Log4net,Log4net Appender,我正在努力学习使用Log4Net来改进我程序中的日志记录技术。 我已经阅读了Log4Net网站上提供的文档,但是我有这些问题 这是由BasicConfigurator.Configure()生成的Log4Net网站上的示例程序中显示的最简单的输出 我的程序已经有一个窗格(在调试模式下)来显示程序的流程,该流程在多次异步尝试中循环。因此,当我运行它时,我可以看到程序的流程(典型的批量调试方法) 在这个级别,据我所知,通过使用Log4Net,我可以在这些时刻收集日志,这些日志可以附加到许多不同的输出
BasicConfigurator.Configure()
生成的Log4Net网站上的示例程序中显示的最简单的输出
我的程序已经有一个窗格(在调试模式下)来显示程序的流程,该流程在多次异步尝试中循环。因此,当我运行它时,我可以看到程序的流程(典型的批量调试方法)
在这个级别,据我所知,通过使用Log4Net,我可以在这些时刻收集日志,这些日志可以附加到许多不同的输出方法中,如控制台、外部文件、数据库等。这导致代码中出现双ups。在每个测试点中,一行用于将日志输出到UI,另一行用于记录Log4Net
是否有任何方法可以将其中一个附加器的内容(如上图所示)输出到字符串或类似类型的变量,以便在运行时显示它?
我不确定您如何在WPF应用程序中看到控制台的输出。将Log4Net输出到一个文件中,然后将它的竞赛结果打印回一个字符串,这似乎很有趣
更新
当ShowOutput from:下拉菜单设置为“Debug”时,可以在Visual Studio的“输出”窗口中看到控制台附加程序的输出。非常感谢@Aron指出这一点。Log4net附带了
udpapender
,这是一种低调的方式,可以将日志内容传输给网络上的任何侦听器。我建议使用它将日志推送到UI
<appender name="UdpAppender" type="log4net.Appender.UdpAppender">
<remoteAddress value="127.0.0.1" /> <!-- local for the demo on my machine -->
<remotePort value="10000" />
<layout type="log4net.Layout.PatternLayout" value="%-5level %logger [%ndc] - %message%newline" />
</appender>
有趣的是,这是许多log4net“仪表盘”用来监视应用程序的一种方法,因此,如果您愿意,可以在应用程序的发布版本中删除该窗格,并从网络上的另一台机器上查看您的应用程序
编辑:在程序的任何应用程序中写入控制台,您可以通过管道将其导入其他进程;例如,启动使用以下语法写入控制台的wpf应用程序会将消息记录到log.txt文件中
myApp.exe > log.txt
(下面的例子要归功于@Aron)作为一个更有用的示例,Visual studio将附加到的程序的标准输出导入其输出窗口,因此发送到ConsolePender的任何内容都将显示在输出窗口中
因此,如果您重用程序的默认输出,控制台附加程序可能会很有用,但没有什么强迫您使用它。可能有点离题,但我在尝试将日志写入应用程序中的文件和消息栏时发现了这个主题。我设法找到了一个更优雅的解决方案 因此,我们将在2020年推出.Net Core和Microsoft.Extensions.Logging及其通用记录器工厂和接口:
var messageBar = new MessageBar();
using var loggerFactory = LoggerFactory.Create(builder => builder
.AddLog4Net()
.AddProvider(new MessageBarLoggerProvider(messageBar))
.SetMinimumLevel(LogLevel.Debug));
ILogger programLogger = loggerFactory.CreateLogger(nameof(App));
programLogger.LogDebug("hello world!");
“hello world!”文本出现在log4net.config日志文件和消息栏的配置中。实现ILogger提供程序
和ILogger
并不难,以下是概念:
internal sealed class MessageBarLoggerProvider : ILoggerProvider
{
private readonly MessageBar _messageBar;
public MessageBarLoggerProvider(MessageBar messageBar) => _messageBar = messageBar;
public ILogger CreateLogger(string categoryName) => new MessageBarLogger(_messageBar);
public void Dispose() { }
}
internal class MessageBarLogger : ILogger
{
private readonly MessageBar _messageBar;
public MessageBarLogger(MessageBar messageBar) => _messageBar = messageBar;
public IDisposable BeginScope<TState>(TState state) => throw new NotImplementedException();
public bool IsEnabled(LogLevel logLevel) => true;
public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception,
Func<TState, Exception, string> formatter)
{
_messageBar.MessagesList.Add(new Message(formatter(state, exception)));
}
}
内部密封类MessageBarLoggerProvider:ILoggerProvider
{
私有只读消息栏_MessageBar;
public MessageBar loggerprovider(MessageBar MessageBar)=>\u MessageBar=MessageBar;
公共ILogger CreateLogger(string categoryName)=>new MessageBarLogger(_messageBar);
public void Dispose(){}
}
内部类MessageBarLogger:ILogger
{
私有只读消息栏_MessageBar;
公共MessageBarLogger(MessageBar MessageBar)=>\u MessageBar=MessageBar;
公共IDisposable BeginScope(TState状态)=>抛出新的NotImplementedException();
公共bool已启用(LogLevel LogLevel)=>true;
公共无效日志(日志级别、日志级别、事件ID、事件状态、异常、,
函数格式化程序)
{
_messageBar.MessagesList.Add(新消息(格式化程序(状态,异常));
}
}
我想你需要的是另一个log4Net appender。谢谢你的详细回复,朋友。我会试试的。在我看来很有可能。但是,我仍然想知道在WPF应用程序中使用控制台追加器的目的是什么?我的意思是,如果我为CLI
开发,我可以推理,但一般来说,我需要在我的WPF中有一个console
appender吗?@Mehrad我添加了一点关于控制台在任何类型的apps@Mehrad控制台appender对于WPF应用程序来说非常棒。Visual Studio在连接时将能够在“控制台”上显示输出,但在正常操作期间,它不会执行任何操作。@Aron我不确定“连接时在控制台上显示日志”的确切含义。据我所知,如果您没有手动为WPF创建控制台,您将看不到任何控制台,甚至可以使用console.write()为其输出@阿隆现在我知道了。。。您是指visual studio中的“输出”窗口。我的通常设置为Build
,而不是Debug
,一旦我更改了它,我就可以看到Log4Netconsole appender
结果。你提到的一点很有趣。谢谢:)
var messageBar = new MessageBar();
using var loggerFactory = LoggerFactory.Create(builder => builder
.AddLog4Net()
.AddProvider(new MessageBarLoggerProvider(messageBar))
.SetMinimumLevel(LogLevel.Debug));
ILogger programLogger = loggerFactory.CreateLogger(nameof(App));
programLogger.LogDebug("hello world!");
internal sealed class MessageBarLoggerProvider : ILoggerProvider
{
private readonly MessageBar _messageBar;
public MessageBarLoggerProvider(MessageBar messageBar) => _messageBar = messageBar;
public ILogger CreateLogger(string categoryName) => new MessageBarLogger(_messageBar);
public void Dispose() { }
}
internal class MessageBarLogger : ILogger
{
private readonly MessageBar _messageBar;
public MessageBarLogger(MessageBar messageBar) => _messageBar = messageBar;
public IDisposable BeginScope<TState>(TState state) => throw new NotImplementedException();
public bool IsEnabled(LogLevel logLevel) => true;
public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception,
Func<TState, Exception, string> formatter)
{
_messageBar.MessagesList.Add(new Message(formatter(state, exception)));
}
}