【问题标题】:Log4Net: How to output the logging results inside the program into a variable?Log4Net:如何将程序内部的日志记录结果输出到变量中?
【发布时间】:2014-05-27 06:13:20
【问题描述】:

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

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

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

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

在这个级别,据我所知,通过使用 Log4Net,我可以收集那些时刻的日志,这些日志可以附加到许多不同的输出方法中,例如 consoleexternal file , db 等等。这会导致代码加倍。在每个测试点中,一行用于将日志输出到 UI,另一行用于 Log4Net 的日志。

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

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


更新

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

【问题讨论】:

  • 我认为你需要的是另一个 log4Net appender。

标签: c# wpf log4net log4net-appender


【解决方案1】:

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 用于监视应用程序的“仪表板”的方法,因此,如果您愿意,可以在应用程序的发布版本中删除窗格并从网络上的另一台机器查看您的应用程序。


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

myApp.exe > log.txt

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

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

【讨论】:

  • 感谢朋友的详细回复。我会试一试。在我看来很有可能。但是,我仍然想知道在 WPF 应用程序中使用 console appender 的目的是什么?我的意思是,如果我为 CLI 开发,我可以推理它,但一般来说,我需要在我的 WPF 中有一个 console 附加程序吗?
  • @Mehrad 我添加了一点关于控制台登录任何类型的应用程序
  • @Mehrad Console appender 非常适合 WPF 应用程序。附加后,Visual Studio 将能够在“控制台”上显示输出,但在正常操作期间,它什么也不做。
  • @Aron 我不确定“连接时在控制台上显示日志”到底是什么意思。据我所知,如果您没有手动为您的 WPF 创建控制台,您将看不到任何控制台,甚至可以使用 console.write() 为它输出。 !!
  • @Aron NOW I KNOWW ...您的意思是视觉工作室中的“输出”窗口。我的通常设置为Build 而不是Debug,一旦我更改它,我就可以看到 Log4Net console appender 导致它通过。你提到的一个很有趣的观点。谢谢:)
【解决方案2】:

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

所以,我们在 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 日志文件和消息栏中的配置中。实现ILoggerProviderILogger并不难,概念如下:

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)));
    }
}

【讨论】:

    猜你喜欢
    • 2012-04-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-11
    • 1970-01-01
    • 2010-12-28
    • 1970-01-01
    • 2016-02-26
    相关资源
    最近更新 更多