简体   繁体   English

Log4Net:如何将程序内部的日志结果输出到变量中?

[英]Log4Net: How to output the logging results inside the program into a variable?

I am trying to learn using Log4Net to be able to improve my logging technique in my program.我正在尝试学习使用Log4Net来改进我的程序中的日志记录技术。 I have read the documents provided in the Log4Net website, however I have these questions in mind.我已经阅读了 Log4Net 网站中提供的文档,但是我有这些问题。

This is the most simple output shown in the example program on the Log4Net website produced by BasicConfigurator.Configure() .这是由BasicConfigurator.Configure()生成的Log4Net网站上的示例程序中显示的最简单的输出。

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

My program already has a pane (in debug mode) to show the flow of the program which cycles through numerous asynchronous attempts.我的程序已经有一个窗格(在调试模式下)来显示程序的流程,该流程在多次异步尝试中循环。 So when I run it I can see the flow of the program (typical mass debugging method).所以当我运行它时,我可以看到程序的流程(典型的批量调试方法)。

In this level, as far as I know by using Log4Net I can collect logs in those moments and these logs can be appended into so many different output methods such as console , external file, db and etc. This leads to double ups in the code.在这个级别,据我所知,通过使用 Log4Net,我可以收集那些时刻的日志,这些日志可以附加到许多不同的输出方法中,例如控制台外部文件、数据库等。这导致代码加倍. One line to output the logs to the UI and the other to log for Log4Net, in each test point.在每个测试点中,一行用于将日志输出到 UI,另一行用于 Log4Net 的日志记录。

Is there any method that I can output the contents of one of the appenders, such as the one shown above, to a variable of a type string or similar to be able to show it at runtime?是否有任何方法可以将其中一个附加程序的内容(例如上面显示的附加程序)输出到字符串或类似类型的变量,以便能够在运行时显示它?

I am not sure how you can see the output of the console in the WPF application . 我不确定如何在 WPF 应用程序中看到控制台的输出 And it seems quite funny to output the Log4Net into a file and then print the contests of it back to a string.Log4Net输出到文件中,然后将它的竞赛打印回字符串似乎很有趣。


Update更新

The output of the Console Appender can be seen in the Output window of Visual Studio when Show output from: drop-down is set to "Debug".Show output from:下拉菜单设置为“Debug”时,可以在Visual Studio输出窗口中看到Console Appender输出 Many thanks to @Aron for pointing it out.非常感谢@Aron 指出。

Log4net comes with the UDPAppender , which is a low profile way of transmitting the content of your logs to any listener on the network. Log4net 带有UDPAppender ,这是一种将日志内容传输到网络上任何侦听器的低调方式。 I would recommend using it as a way to push your logs to your UI.我建议使用它作为将日志推送到 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>

In the UI, hooking a listener in a background thread of your WPF app to these messages lets you display them however you like, for example as a sliding window on the x latest logs, or pushing all the logs to the pane you mentioned in your question.在 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
    }
}

Interestingly, this is an approach many "dashboards" for log4net use in order to monitor applications, so if you want you can remove the pane in a release build of your application and look at your app from another machine on the network.有趣的是,这是许多用于 log4net 的“仪表板”用于监视应用程序的方法,因此如果您愿意,可以在应用程序的发布版本中删除该窗格,并从网络上的另一台机器查看您的应用程序。


EDIT : Writing to the console in any application writes to the standard output stream of the program, which you can pipe into other processes;编辑:在任何应用程序中写入控制台都会写入程序的标准输出流,您可以将其通过管道传输到其他进程; for example launching your wpf app that writes to the console with the following syntax would log the messages to the log.txt file例如,启动使用以下语法写入控制台的 wpf 应用程序会将消息记录到 log.txt 文件中

myApp.exe > log.txt

(kudos to @Aron for the following example) As a much more useful example Visual studio pipes the stdout of the program you are attached to into its Output window, so anything sent to the ConsoleAppender will be present in the Output window. (以下示例感谢@Aron)作为一个更有用的示例,Visual Studio 将您附加到的程序的标准输出通过管道传输到其输出窗口,因此发送到 ConsoleAppender 的任何内容都将出现在输出窗口中。

So a console appender can be useful if you reuse the default output of the program, but nothing forces you to use it.因此,如果您重用程序的默认输出,控制台 appender 会很有用,但没有什么会强迫您使用它。

Maybe offtopic a little, but I found this topic when tried to find a way to write logs both to file and to message bar in the app.也许有点偏离主题,但是当我试图找到一种将日志写入文件和应用程序中的消息栏的方法时,我发现了这个主题。 I managed to find a more elegant solution.我设法找到了一个更优雅的解决方案。

So, we're in 2020, and there is .Net Core and Microsoft.Extensions.Logging with its universal logger factory and interfaces:所以,我们在 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!");

The "hello world!" “你好世界!” text appeared both in configured in the log4net.config log file and message bar.文本出现在 log4net.config 日志文件和消息栏中的配置中。 It's not that difficult to implement ILoggerProvider and ILogger , here's the concept:实现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)));
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM