3

我正在尝试学习使用Log4Net来改进我的程序中的日志记录技术。我已经阅读了 Log4Net 网站上提供的文档,但是我有这些问题。

这是Log4Net网站上的示例程序中显示的最简单的输出,由BasicConfigurator.Configure().

0    [main] INFO  MyApp        - Entering application.
36   [main] DEBUG Com.Foo.Bar  - Did it again!
51   [main] INFO  MyApp        - Exiting application.

我的程序已经有一个窗格(在调试模式下)来显示程序的流程,该流程在许多异步尝试中循环。所以当我运行它时,我可以看到程序的流程(典型的批量调试方法)。

在这个级别,据我所知,通过使用 Log4Net,我可以在那些时刻收集日志,这些日志可以附加到许多不同的输出方法中,例如控制台外部文件、数据库等。这导致代码加倍. 在每个测试点中,一行用于将日志输出到 UI,另一行用于 Log4Net 的日志。

是否有任何方法可以将其中一个附加程序的内容(例如上面显示的那个)输出到字符串类型的变量或类似的变量,以便能够在运行时显示它?

我不确定您如何在 WPF 应用程序中看到控制台的输出将Log4Net输出到一个文件中,然后将它的比赛打印回一个字符串,这似乎很有趣。


更新

Show output from:下拉菜单设置为“Debug”时,Console Appender可以在Visual Studio的“输出”窗口中看到输出。非常感谢@Aron 指出这一点。

4

2 回答 2

5

Log4net 带有UDPAppender,这是一种将日志内容传输到网络上任何侦听器的低调方式。我建议使用它作为将日志推送到 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>

在 UI 中,将 WPF 应用程序的后台线程中的侦听器与这些消息挂钩,您可以随意显示它们,例如作为 x 最新日志上的滑动窗口,或将所有日志推送到您在问题。

// launch this in a background thread
private static void UDPListen()
{
    IPEndPoint remoteEndPoint = new IPEndPoint(IPAddress.Any, 0);
    var udpClient = new UdpClient(10000);

    while (true)
    {
        var buffer = udpClient.Receive(ref remoteEndPoint);
        var loggingEvent = System.Text.Encoding.Unicode.GetString(buffer);
        // write the log to your pane
    }
}

有趣的是,这是许多用于 log4net 的“仪表板”以监视应用程序的方法,因此,如果您愿意,可以在应用程序的发布版本中删除窗格并从网络上的另一台机器查看您的应用程序。


编辑:在任何应用程序中写入控制台都会写入程序的标准输出流,您可以将其通过管道传输到其他进程;例如,使用以下语法启动写入控制台的 wpf 应用程序会将消息记录到 log.txt 文件中

myApp.exe > log.txt

(以下示例向@Aron 致敬)作为一个更有用的示例,Visual Studio 将您附加到的程序的标准输出通过管道传输到其输出窗口中,因此发送到 ConsoleAppender 的任何内容都将出现在输出窗口中。

因此,如果您重用程序的默认输出,控制台附加程序可能会很有用,但没有什么强迫您使用它。

于 2014-05-27T09:16:03.117 回答
0

也许有点离题,但是当我试图找到一种将日志写入应用程序中的文件和消息栏的方法时,我发现了这个主题。我设法找到了一个更优雅的解决方案。

所以,我们在 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!");

“你好世界!” 文本出现在 log4net.config 日志文件和消息栏中的配置中。ILoggerProvider实现起来并不难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)));
    }
}
于 2020-08-18T18:55:38.497 回答