mirror of
https://github.com/MaSzyna-EU07/StarterNG.git
synced 2026-10-19 17:03:37 +02:00
86 lines
2.7 KiB
C#
86 lines
2.7 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Text;
|
|
using Avalonia.Logging;
|
|
|
|
namespace StarterNG.Infrastructure;
|
|
|
|
public sealed class DiagnosticsLogSink : ILogSink
|
|
{
|
|
private const int MaxDistinctMessages = 200;
|
|
|
|
private readonly LogEventLevel _minimumLevel;
|
|
private readonly HashSet<string> _seen = new(StringComparer.Ordinal);
|
|
private readonly object _gate = new();
|
|
private bool _capped;
|
|
|
|
private DiagnosticsLogSink(LogEventLevel minimumLevel) => _minimumLevel = minimumLevel;
|
|
|
|
public static void Install(LogEventLevel minimumLevel = LogEventLevel.Warning) =>
|
|
Logger.Sink = new DiagnosticsLogSink(minimumLevel);
|
|
|
|
public bool IsEnabled(LogEventLevel level, string area) => level >= _minimumLevel;
|
|
|
|
public void Log(LogEventLevel level, string area, object? source, string messageTemplate) =>
|
|
Write(level, area, source, messageTemplate, null);
|
|
|
|
public void Log(LogEventLevel level, string area, object? source, string messageTemplate,
|
|
params object?[] propertyValues) =>
|
|
Write(level, area, source, messageTemplate, propertyValues);
|
|
|
|
private void Write(LogEventLevel level, string area, object? source, string messageTemplate,
|
|
object?[]? propertyValues)
|
|
{
|
|
if (!IsEnabled(level, area))
|
|
return;
|
|
|
|
string line = $"[Avalonia/{area}/{level}] {Format(messageTemplate, propertyValues)}";
|
|
if (source is not null)
|
|
line += $" (source: {source.GetType().Name})";
|
|
|
|
lock (_gate)
|
|
{
|
|
if (_capped || !_seen.Add(line))
|
|
return;
|
|
if (_seen.Count >= MaxDistinctMessages)
|
|
{
|
|
_capped = true;
|
|
Diagnostics.Log(line);
|
|
Diagnostics.Log($"[Avalonia] {MaxDistinctMessages} distinct messages logged, muting the rest");
|
|
return;
|
|
}
|
|
}
|
|
|
|
Diagnostics.Log(line);
|
|
}
|
|
|
|
private static string Format(string template, object?[]? values)
|
|
{
|
|
if (values is null || values.Length == 0 || template.IndexOf('{') < 0)
|
|
return template;
|
|
|
|
var sb = new StringBuilder(template.Length + 32);
|
|
int next = 0;
|
|
for (int i = 0; i < template.Length; i++)
|
|
{
|
|
if (template[i] != '{')
|
|
{
|
|
sb.Append(template[i]);
|
|
continue;
|
|
}
|
|
|
|
int close = template.IndexOf('}', i);
|
|
if (close < 0)
|
|
{
|
|
sb.Append(template, i, template.Length - i);
|
|
break;
|
|
}
|
|
|
|
sb.Append(next < values.Length ? values[next]?.ToString() ?? "null" : template[i..(close + 1)]);
|
|
next++;
|
|
i = close;
|
|
}
|
|
return sb.ToString();
|
|
}
|
|
}
|