2026-04-04 13:30:13 +02:00
|
|
|
using Serilog.Events;
|
|
|
|
|
using LogViewer.Core;
|
|
|
|
|
using Microsoft.Extensions.Logging;
|
|
|
|
|
using Serilog.Core;
|
2026-04-05 08:00:09 +02:00
|
|
|
using System.Globalization;
|
2026-04-05 10:13:12 +02:00
|
|
|
using Serilog.Sinks.LogView.Core.Logging;
|
2026-04-04 13:30:13 +02:00
|
|
|
|
|
|
|
|
namespace Serilog.Sinks.LogView.Core;
|
|
|
|
|
|
2026-04-05 08:00:09 +02:00
|
|
|
public class DataStoreLoggerSink(
|
|
|
|
|
Func<ILogDataStore> dataStoreProvider,
|
|
|
|
|
Func<DataStoreLoggerConfiguration>? getCurrentConfig = null,
|
|
|
|
|
IFormatProvider? formatProvider = null) : ILogEventSink
|
2026-04-04 13:30:13 +02:00
|
|
|
{
|
2026-04-05 08:00:09 +02:00
|
|
|
protected Func<ILogDataStore> DataStoreProvider { get; } = dataStoreProvider;
|
|
|
|
|
private IFormatProvider? FormatProvider { get; } = formatProvider;
|
|
|
|
|
private Func<DataStoreLoggerConfiguration>? GetCurrentConfig { get; } = getCurrentConfig;
|
2026-04-04 13:30:13 +02:00
|
|
|
|
|
|
|
|
public void Emit(LogEvent logEvent)
|
|
|
|
|
{
|
|
|
|
|
LogLevel logLevel = logEvent.Level switch
|
|
|
|
|
{
|
|
|
|
|
LogEventLevel.Verbose => LogLevel.Trace,
|
|
|
|
|
LogEventLevel.Debug => LogLevel.Debug,
|
|
|
|
|
LogEventLevel.Warning => LogLevel.Warning,
|
|
|
|
|
LogEventLevel.Error => LogLevel.Error,
|
|
|
|
|
LogEventLevel.Fatal => LogLevel.Critical,
|
|
|
|
|
_ => LogLevel.Information
|
|
|
|
|
};
|
|
|
|
|
|
2026-04-05 08:00:09 +02:00
|
|
|
DataStoreLoggerConfiguration config = GetCurrentConfig?.Invoke() ?? new DataStoreLoggerConfiguration();
|
2026-04-04 13:30:13 +02:00
|
|
|
|
|
|
|
|
EventId eventId = EventIdFactory(logEvent);
|
|
|
|
|
if (eventId.Id == 0 && config.EventId != 0)
|
|
|
|
|
eventId = config.EventId;
|
|
|
|
|
|
2026-04-05 08:00:09 +02:00
|
|
|
string message = logEvent.RenderMessage(FormatProvider);
|
2026-04-04 13:30:13 +02:00
|
|
|
|
|
|
|
|
string exception = logEvent.Exception?.Message ?? (logEvent.Level >= LogEventLevel.Error ? message : string.Empty);
|
|
|
|
|
|
|
|
|
|
LogEntryColor color = config.Colors[logLevel];
|
|
|
|
|
|
|
|
|
|
AddLogEntry(logLevel, eventId, message, exception, color);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected virtual void AddLogEntry(LogLevel logLevel, EventId eventId, string message, string exception, LogEntryColor color)
|
|
|
|
|
{
|
2026-04-05 08:00:09 +02:00
|
|
|
ILogDataStore? dataStore = DataStoreProvider.Invoke();
|
2026-04-04 13:30:13 +02:00
|
|
|
|
|
|
|
|
// ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract
|
|
|
|
|
if (dataStore == null)
|
|
|
|
|
return; // app is shutting down
|
|
|
|
|
|
|
|
|
|
dataStore.AddEntry(new()
|
|
|
|
|
{
|
|
|
|
|
Timestamp = DateTime.UtcNow,
|
|
|
|
|
LogLevel = logLevel,
|
|
|
|
|
EventId = eventId,
|
|
|
|
|
State = message,
|
|
|
|
|
Exception = exception,
|
|
|
|
|
Color = color
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static EventId EventIdFactory(LogEvent logEvent)
|
|
|
|
|
{
|
|
|
|
|
EventId eventId;
|
|
|
|
|
if (!logEvent.Properties.TryGetValue("EventId", out LogEventPropertyValue? src))
|
|
|
|
|
return new();
|
|
|
|
|
|
|
|
|
|
int? id = null;
|
|
|
|
|
string? eventName = null;
|
|
|
|
|
|
|
|
|
|
// ref: https://stackoverflow.com/a/56722516
|
|
|
|
|
StructureValue? value = src as StructureValue;
|
|
|
|
|
|
2026-04-05 08:00:09 +02:00
|
|
|
LogEventProperty? idProperty = value!.Properties.FirstOrDefault(x => x.Name.Equals("Id", StringComparison.Ordinal));
|
2026-04-04 13:30:13 +02:00
|
|
|
if (idProperty is not null)
|
2026-04-05 08:00:09 +02:00
|
|
|
id = int.Parse(idProperty.Value.ToString(),CultureInfo.InvariantCulture);
|
2026-04-04 13:30:13 +02:00
|
|
|
|
2026-04-05 08:00:09 +02:00
|
|
|
LogEventProperty? nameProperty = value.Properties.FirstOrDefault(x => x.Name.Equals("Name", StringComparison.Ordinal));
|
2026-04-04 13:30:13 +02:00
|
|
|
if (nameProperty is not null)
|
|
|
|
|
eventName = nameProperty.Value.ToString().Trim('"');
|
|
|
|
|
|
|
|
|
|
eventId = new EventId(id ?? 0, eventName ?? string.Empty);
|
|
|
|
|
|
|
|
|
|
return eventId;
|
|
|
|
|
}
|
|
|
|
|
}
|