简体   繁体   中英

How to Trigger Event When Serilog Logs File is Written to?

I am trying to display the contents of the Serilog "logs.txt" file in my UWP app. I have it successfully displayed, but now I want it to auto refresh as new log events are created.

So far I tried making a ContentsChanged event listener that subscribes to changes in .txt files in the local files drive.

private async void CreateFileUpdater()
{
    List<string> fileTypeFilter = new List<string>();
    fileTypeFilter.Add(".txt");
    var options = new Windows.Storage.Search.QueryOptions(Windows.Storage.Search.CommonFileQuery.OrderByName, fileTypeFilter);
    var query = ApplicationData.Current.LocalFolder.CreateFileQueryWithOptions(options);
            //subscribe on query's ContentsChanged event
    query.ContentsChanged += Query_ContentsChanged;
    var files = await query.GetFilesAsync();
}

private void Query_ContentsChanged(Windows.Storage.Search.IStorageQueryResultBase sender, object args)
{
    ReadFileAsync(); //This updates the bound variable to display in UI
}

However, It doesn't seem to trigger properly when new log events are added to the logs file. So I was wondering if Serilog itself has an event I am just not seeing in the documentation or if there is a better way to detect changes in files or when things are added to files. I just want some sort of event to be called so that I can trigger my ReadFilesAsync() function to update the variable that is bound to my UI.

Thanks for any help!

The best way I think to do this, is to create your own custom Sink for Serilog. It will catch any log generated, and then you can filter and output these logs anywhere you want. In my case, I output them to my UI.

Create a sinks class:

    public class LogsSink : ILogEventSink
    {
        /// <summary>
        /// Format of the output log
        /// </summary>
        readonly string Format = "{0} {1} {2}";

        /// <summary>
        /// Emit the provided log event to the sink.
        /// </summary>
        /// <param name="logEvent">The log event to write</param>
        public void Emit(LogEvent logEvent)
        {
            var t = logEvent.Timestamp;
            LogMsg msg = new LogMsg()
            {
                Text = logEvent.RenderMessage(),
                Lvl = LevelToSeverity(logEvent),
                TimeStamp = DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss.fff") + " -" + t.Offset.ToString(@"hh\:mm"),
            };
            if (LogsViewModel.logFile != null)
                LogsViewModel.logFile.AllText.Add(string.Format(Format, msg.TimeStamp, msg.Lvl, msg.Text));
            LogsViewModel.logFile.AppendText();
        }

        static string LevelToSeverity(LogEvent logEvent)
        {
            switch (logEvent.Level)
            {
                case LogEventLevel.Debug:
                    return "[DBG]";
                case LogEventLevel.Error:
                    MainPageViewModel.statusBar.AddError();
                    return "[ERR]";
                case LogEventLevel.Fatal:
                    return "[FTL]";
                case LogEventLevel.Verbose:
                    return "VERBOSE";
                case LogEventLevel.Warning:
                    MainPageViewModel.statusBar.AddWarning();
                    return "WARNING";
                default:
                    return "[INF]";
            }
        }
    }

    struct LogMsg
    {
        public string Lvl;
        public string Text;
        public string TimeStamp;
    }

Register your sink when you instantiate the logger

public LogsSink sink;
sink = new LogsSink();
Log.Logger = new LoggerConfiguration().MinimumLevel.Debug()
                .WriteTo.Sink(sink)
                .CreateLogger();

Let me know if you have any questions!

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