是否可以在程序的 GUI 中显示 Serilog 日志?
Is it possible to display Serilog log in the program's GUI?
使用日志系统 Serilog 是否可以在文本框、列表视图或其他一些 GUI 控件中显示日志?到达那里的机制是什么?
Serilog 为此提供了 ILogEventSink
扩展点。您可以使用它将日志事件添加到列表中,或将它们呈现到某个地方的 TextWriter
。
根据您的需要,可以有不同程度的复杂性。这个(基于 ConsoleSink
)应该让你继续:
class InMemorySink : ILogEventSink
{
readonly ITextFormatter _textFormatter = new MessageTemplateTextFormatter("{Timestamp} [{Level}] {Message}{Exception}");
public ConcurrentQueue<string> Events { get; } = new ConcurrentQueue<string>();
public void Emit(LogEvent logEvent)
{
if (logEvent == null) throw new ArgumentNullException(nameof(logEvent));
var renderSpace = new StringWriter();
_textFormatter.Format(logEvent, renderSpace);
Events.Enqueue(renderSpace.ToString());
}
}
然后连接它意味着创建一个实例:
var sink = new InMemorySink();
Log.Logger = new LoggerConfiguration()
.WriteTo.Sink(sink)
.CreateLogger();
然后,由您的应用决定如何在显示时将 sink.Events
加载到文本框中。
在 Emit()
中添加一些代码来限制队列的大小是个好主意。
您可以像下面这样在多行文本框中显示日志;
namespace SerilogSample
{
public partial class Form1 : Form
{
private StringWriter _messages;
ILogger _logger;
public Form1()
{
InitializeComponent();
_messages = new StringWriter();
_logger = new LoggerConfiguration()
.WriteTo.TextWriter(_messages)
.CreateLogger();
}
private void button1_Click(object sender, EventArgs e)
{
_logger.Information("Clicked!");
textBox1.Text = _messages.ToString();
}
}
}
结果;
您可能想查看 Serilog.Sinks.RichTextBox
接收器,它可以将日志写入带有颜色、格式等的 RichTextBox
控件,类似于您在控制台应用程序中所期望的(您有通过主题完全控制颜色)。
接收器最初是为 WPF 应用程序构建的,但也可以很容易地与 Windows Forms 应用程序一起使用,并且有一个 example in the repository that shows how to use it with Windows Forms。
免责声明:我是 Serilog.Sinks.RichTextBox
接收器的作者。
我还没试过,但是这个包看起来很有希望 Windows 表格:
我也从 开始,想出了我自己的准系统 Windows 表格 TextBox
接收器:
自定义接收器
public class TextBoxSink : ILogEventSink
{
private readonly TextBox textBox;
private readonly LogEventLevel minLevel;
private readonly ITextFormatter formatter;
public TextBoxSink(
TextBox textBox,
LogEventLevel restrictedToMinimumLevel = LogEventLevel.Verbose,
string outputTemplate = "{Timestamp:yyyy-MM-dd HH:mm:ss} {Level:u5}: {Message:lj}{NewLine}")
{
this.textBox = textBox;
minLevel = restrictedToMinimumLevel;
formatter = new MessageTemplateTextFormatter(outputTemplate);
}
public void Emit(LogEvent logEvent)
{
if (logEvent == null) throw new ArgumentNullException(nameof(logEvent));
if (logEvent.Level < minLevel) return;
var sw = new StringWriter();
formatter.Format(logEvent, sw);
textBox.InvokeIfRequired(() => textBox.AppendText(sw.ToString()));
}
}
扩展方法(上面用于从任何线程操作文本框;source)
public static class WinFormsControlExtensions
{
public static void InvokeIfRequired(this Control c, MethodInvoker action)
{
if (c.InvokeRequired)
{
c.Invoke(action);
}
else
{
action();
}
}
}
用法
public partial class Form1 : Form
{
public System.Windows.Forms.TextBox LogTextBox;
private void Form1_Shown(object sender, EventArgs e)
{
Logger.Log = new LoggerConfiguration()
.WriteTo.Sink(new TextBoxSink(LogTextBox))
.CreateLogger();
}
}
使用日志系统 Serilog 是否可以在文本框、列表视图或其他一些 GUI 控件中显示日志?到达那里的机制是什么?
Serilog 为此提供了 ILogEventSink
扩展点。您可以使用它将日志事件添加到列表中,或将它们呈现到某个地方的 TextWriter
。
根据您的需要,可以有不同程度的复杂性。这个(基于 ConsoleSink
)应该让你继续:
class InMemorySink : ILogEventSink
{
readonly ITextFormatter _textFormatter = new MessageTemplateTextFormatter("{Timestamp} [{Level}] {Message}{Exception}");
public ConcurrentQueue<string> Events { get; } = new ConcurrentQueue<string>();
public void Emit(LogEvent logEvent)
{
if (logEvent == null) throw new ArgumentNullException(nameof(logEvent));
var renderSpace = new StringWriter();
_textFormatter.Format(logEvent, renderSpace);
Events.Enqueue(renderSpace.ToString());
}
}
然后连接它意味着创建一个实例:
var sink = new InMemorySink();
Log.Logger = new LoggerConfiguration()
.WriteTo.Sink(sink)
.CreateLogger();
然后,由您的应用决定如何在显示时将 sink.Events
加载到文本框中。
在 Emit()
中添加一些代码来限制队列的大小是个好主意。
您可以像下面这样在多行文本框中显示日志;
namespace SerilogSample
{
public partial class Form1 : Form
{
private StringWriter _messages;
ILogger _logger;
public Form1()
{
InitializeComponent();
_messages = new StringWriter();
_logger = new LoggerConfiguration()
.WriteTo.TextWriter(_messages)
.CreateLogger();
}
private void button1_Click(object sender, EventArgs e)
{
_logger.Information("Clicked!");
textBox1.Text = _messages.ToString();
}
}
}
结果;
您可能想查看 Serilog.Sinks.RichTextBox
接收器,它可以将日志写入带有颜色、格式等的 RichTextBox
控件,类似于您在控制台应用程序中所期望的(您有通过主题完全控制颜色)。
接收器最初是为 WPF 应用程序构建的,但也可以很容易地与 Windows Forms 应用程序一起使用,并且有一个 example in the repository that shows how to use it with Windows Forms。
免责声明:我是 Serilog.Sinks.RichTextBox
接收器的作者。
我还没试过,但是这个包看起来很有希望 Windows 表格:
我也从 TextBox
接收器:
自定义接收器
public class TextBoxSink : ILogEventSink
{
private readonly TextBox textBox;
private readonly LogEventLevel minLevel;
private readonly ITextFormatter formatter;
public TextBoxSink(
TextBox textBox,
LogEventLevel restrictedToMinimumLevel = LogEventLevel.Verbose,
string outputTemplate = "{Timestamp:yyyy-MM-dd HH:mm:ss} {Level:u5}: {Message:lj}{NewLine}")
{
this.textBox = textBox;
minLevel = restrictedToMinimumLevel;
formatter = new MessageTemplateTextFormatter(outputTemplate);
}
public void Emit(LogEvent logEvent)
{
if (logEvent == null) throw new ArgumentNullException(nameof(logEvent));
if (logEvent.Level < minLevel) return;
var sw = new StringWriter();
formatter.Format(logEvent, sw);
textBox.InvokeIfRequired(() => textBox.AppendText(sw.ToString()));
}
}
扩展方法(上面用于从任何线程操作文本框;source)
public static class WinFormsControlExtensions
{
public static void InvokeIfRequired(this Control c, MethodInvoker action)
{
if (c.InvokeRequired)
{
c.Invoke(action);
}
else
{
action();
}
}
}
用法
public partial class Form1 : Form
{
public System.Windows.Forms.TextBox LogTextBox;
private void Form1_Shown(object sender, EventArgs e)
{
Logger.Log = new LoggerConfiguration()
.WriteTo.Sink(new TextBoxSink(LogTextBox))
.CreateLogger();
}
}