简体   繁体   中英

How to output logs with Serilog to a textbox in Winform?

Help!

I can not figure it out how to implement Serilog to output my logs in real time into a textbox from Winforms. I have an application written in.Net C# that was written a long time ago and had the logging framework log4net. I had different appenders and one was created in my code:

public class ExAppender : AppenderSkeleton{
       private IExAppender control = null;
       public void AttachControl(IExAppender obj)
       { this.control = obj;}
       protected override void Append(LoggingEvent loggingEvent)
       {
           try
           {
               string message = RenderLoggingEvent(loggingEvent);
               if (this.control != null)
               {
                   this.control.LogMessage(message, loggingEvent.Level.Name);
               }
           }catch{// ignore}
       }

And after that I had another class defined ExLogger:

public static class ExLogger
    { private static readonly ILog LoggerObj = null;
      public static bool AttachControl(IExAppender obj)
        {
            IAppender[] appenders = LoggerObj.Logger.Repository.GetAppenders();
            (appender as ExAppender).AttachControl(obj);
            return true;
            }
            return false;}

I defined my serilog loggers in app.config, I want to read them from there because i have multiple loggers, I think that I need to use public class ExAppender: ILogEventSink , I replaced the old code to be suitable for Serilog, it writes to files, to eventLog, console etc, BUT I could not found a way to attach a windows to the logger and to write there. After my modification I obtaind something like this:

  public class ExAppender : ILogEventSink
    {
        public ExAppender control = null;
        public ConcurrentQueue<string> Events { get; } = new ConcurrentQueue<string>();
        public void AttachControl(IExAppender  obj)
        {
            this.control = obj;
        }
        public void Emit(LogEvent logEvent)
        {
            if (logEvent == null) throw new ArgumentNullException(nameof(logEvent));
            var renderSpace = new ExAppender();
            Events.Enqueue(renderSpace.ToString());
            try
            {   string message = logEvent.RenderMessage();
                if (this.control != null)
                {
                    this.control.LogMessage(message, logEvent.Level.ToString());
                }
            }catch { }
        }

And for the ExLogger class:

public static bool AttachControl( IExAppender obj)
        {try
            {               
                ILogger test = new LoggerConfiguration()
                          .ReadFrom.AppSettings(settingPrefix: "ExAppender")
                          .WriteTo.ExAppender(restrictedToMinimumLevel: LogEventLevel.Information)
                          .CreateLogger();
                 return true;
            }catch
            {
                return false;
            }}

Can someone guide me? Does someone has an example or maybe explain what am I missing?

Maybe I am a bit too late to help you, but this is how I implemented it:

Custom logger sink, which has EventHandler:

    public class TbsLoggerSink : ILogEventSink
    {
        public event EventHandler NewLogHandler;

        public TbsLoggerSink() { }

        public void Emit(LogEvent logEvent)
        {
#if DEBUG
            Console.WriteLine($"{logEvent.Timestamp}] {logEvent.MessageTemplate}");
#endif
            NewLogHandler?.Invoke(typeof(TbsCore.Helpers.TbsLoggerSink), new LogEventArgs() { Log = logEvent });
        }
    }

    public class LogEventArgs : EventArgs
    {
        public LogEvent Log { get; set; }
    }

When creating the Serilog logger, add your custom sink. I use static sink/logger so I can access it from anywhere.

public static TbsLoggerSink LoggerSink = new TbsLoggerSink();

public static readonly Serilog.Core.Logger Log = new LoggerConfiguration()
            .WriteTo.Sink(LoggerSink)
            .CreateLogger();

Than in your view/form, where you have TextBox/RichTextBox (in my case this.logTextBox), add event handler:

public partial class MyUserControl : UserControl
{
    public MyUserControl()
    {
        InitializeComponent();
        Utils.LoggerSink.NewLogHandler += LogHandler;
    }

    private void LogHandler(object sender, EventArgs e)
    {
        var log = ((LogEventArgs)e).Log;
        this.logTextBox.Text = $"{log.Timestamp.DateTime.ToString("HH:mm:ss")}: {log.MessageTemplate}\n{this.logTextBox.Text}";
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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