forked from bit/DotRecastNetSim
add log message broker sink
This commit is contained in:
parent
6300a24a81
commit
188b9e619e
|
@ -0,0 +1,26 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using Serilog.Core;
|
||||
using Serilog.Events;
|
||||
using Serilog.Formatting;
|
||||
|
||||
namespace DotRecast.Recast.Demo.Logging.Sinks;
|
||||
|
||||
public class LogMessageBrokerSink : ILogEventSink
|
||||
{
|
||||
public static event Action<int, string> OnEmitted;
|
||||
|
||||
private readonly ITextFormatter _formatter;
|
||||
|
||||
public LogMessageBrokerSink(ITextFormatter formatter)
|
||||
{
|
||||
_formatter = formatter;
|
||||
}
|
||||
|
||||
public void Emit(LogEvent logEvent)
|
||||
{
|
||||
using var writer = new StringWriter();
|
||||
_formatter.Format(logEvent, writer);
|
||||
OnEmitted?.Invoke((int)logEvent.Level, writer.ToString());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
using Serilog;
|
||||
using Serilog.Configuration;
|
||||
using Serilog.Events;
|
||||
using Serilog.Formatting.Display;
|
||||
|
||||
namespace DotRecast.Recast.Demo.Logging.Sinks;
|
||||
|
||||
public static class SerilogSinkExtensions
|
||||
{
|
||||
public static LoggerConfiguration LogMessageBroker(
|
||||
this LoggerSinkConfiguration sinkConfiguration,
|
||||
LogEventLevel restrictedToMinimumLevel = LogEventLevel.Verbose,
|
||||
string outputTemplate = "[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj}{NewLine}{Exception}")
|
||||
{
|
||||
var formatter = new MessageTemplateTextFormatter(outputTemplate);
|
||||
return sinkConfiguration.Sink(new LogMessageBrokerSink(formatter));
|
||||
}
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
using System.IO;
|
||||
using DotRecast.Core;
|
||||
using DotRecast.Recast.Demo.Logging.Sinks;
|
||||
using Serilog;
|
||||
using Serilog.Enrichers;
|
||||
|
||||
|
@ -9,7 +10,6 @@ public static class Program
|
|||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
|
||||
var path = Loader.ToRPath("dungeon.obj");
|
||||
path = Path.GetDirectoryName(path);
|
||||
if (!string.IsNullOrEmpty(path))
|
||||
|
@ -25,6 +25,7 @@ public static class Program
|
|||
.Enrich.WithThreadId()
|
||||
.Enrich.WithThreadName()
|
||||
.Enrich.WithProperty(ThreadNameEnricher.ThreadNamePropertyName, "main")
|
||||
.WriteTo.LogMessageBroker(outputTemplate: format)
|
||||
.WriteTo.Console(outputTemplate: format)
|
||||
.WriteTo.File(
|
||||
"logs/log.log",
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using System.Text;
|
||||
using DotRecast.Recast.Demo.Logging.Sinks;
|
||||
using DotRecast.Recast.Demo.Tools;
|
||||
using DotRecast.Recast.Demo.UI.ViewModels;
|
||||
using ImGuiNET;
|
||||
|
||||
namespace DotRecast.Recast.Demo.UI;
|
||||
|
@ -13,29 +16,25 @@ public class RcLogView : IRcView
|
|||
private RecastDemoCanvas _canvas;
|
||||
private bool _mouseInside;
|
||||
|
||||
private List<string> _lines = new();
|
||||
private readonly ConcurrentQueue<string> _output = new();
|
||||
private readonly StringBuilder _outputStringBuilder = new();
|
||||
|
||||
private readonly ConcurrentQueue<string> _error = new();
|
||||
private readonly StringBuilder _errorStringBuilder = new();
|
||||
|
||||
private readonly List<LogMessageItem> _lines;
|
||||
private readonly ConcurrentQueue<LogMessageItem> _queues;
|
||||
|
||||
|
||||
public RcLogView()
|
||||
{
|
||||
Console.SetOut(new ConsoleTextWriterHook(OnOut));
|
||||
Console.SetError(new ConsoleTextWriterHook(OnError));
|
||||
_lines = new();
|
||||
_queues = new();
|
||||
|
||||
LogMessageBrokerSink.OnEmitted += OnOut;
|
||||
}
|
||||
|
||||
private void OnOut(string log)
|
||||
private void OnOut(int level, string message)
|
||||
{
|
||||
_output.Enqueue(log);
|
||||
}
|
||||
|
||||
private void OnError(string log)
|
||||
{
|
||||
_error.Enqueue(log);
|
||||
var lines = message
|
||||
.Split(Environment.NewLine, StringSplitOptions.RemoveEmptyEntries)
|
||||
.Select(x => new LogMessageItem { Level = level, Message = x });
|
||||
|
||||
_lines.AddRange(lines);
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
|
@ -43,23 +42,6 @@ public class RcLogView : IRcView
|
|||
_lines.Clear();
|
||||
}
|
||||
|
||||
private void MergeLines(ConcurrentQueue<string> queue, StringBuilder builder)
|
||||
{
|
||||
while (queue.TryDequeue(out var s))
|
||||
{
|
||||
if (s != "\r\n")
|
||||
{
|
||||
builder.Append(s);
|
||||
}
|
||||
else
|
||||
{
|
||||
_lines.Add(builder.ToString());
|
||||
builder.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void Bind(RecastDemoCanvas canvas)
|
||||
{
|
||||
_canvas = canvas;
|
||||
|
@ -67,16 +49,16 @@ public class RcLogView : IRcView
|
|||
|
||||
public void Update(double dt)
|
||||
{
|
||||
MergeLines(_output, _outputStringBuilder);
|
||||
MergeLines(_error, _errorStringBuilder);
|
||||
|
||||
while (_queues.TryDequeue(out var item))
|
||||
_lines.Add(item);
|
||||
|
||||
// buffer
|
||||
if (10240 < _lines.Count)
|
||||
{
|
||||
_lines.RemoveRange(0, _lines.Count - 8196);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public bool IsMouseInside() => _mouseInside;
|
||||
|
||||
public void Draw(double dt)
|
||||
|
@ -97,7 +79,7 @@ public class RcLogView : IRcView
|
|||
if (ImGui.BeginChild("scrolling", Vector2.Zero, false, ImGuiWindowFlags.HorizontalScrollbar))
|
||||
{
|
||||
_mouseInside = ImGui.IsWindowHovered();
|
||||
|
||||
|
||||
ImGui.PushStyleVar(ImGuiStyleVar.ItemSpacing, Vector2.Zero);
|
||||
|
||||
unsafe
|
||||
|
@ -108,7 +90,7 @@ public class RcLogView : IRcView
|
|||
{
|
||||
for (int lineNo = clipper.DisplayStart; lineNo < clipper.DisplayEnd; lineNo++)
|
||||
{
|
||||
ImGui.TextUnformatted(_lines[lineNo]);
|
||||
ImGui.TextUnformatted(_lines[lineNo].Message);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
namespace DotRecast.Recast.Demo.UI.ViewModels;
|
||||
|
||||
public class LogMessageItem
|
||||
{
|
||||
public required int Level { get; init; }
|
||||
public required string Message { get; init; }
|
||||
}
|
Loading…
Reference in New Issue