initial commit

This commit is contained in:
Matthias Heil
2026-04-04 13:30:13 +02:00
commit 6bed9b284c
186 changed files with 10650 additions and 0 deletions
@@ -0,0 +1,94 @@
using Serilog.Events;
using LogViewer.Core;
using Microsoft.Extensions.Logging;
using Serilog.Core;
namespace Serilog.Sinks.LogView.Core;
public class DataStoreLoggerSink : ILogEventSink
{
protected readonly Func<ILogDataStore> _dataStoreProvider;
private readonly IFormatProvider? _formatProvider;
private readonly Func<DataStoreLoggerConfiguration>? _getCurrentConfig;
public DataStoreLoggerSink(Func<ILogDataStore> dataStoreProvider,
Func<DataStoreLoggerConfiguration>? getCurrentConfig = null,
IFormatProvider? formatProvider = null)
{
_formatProvider = formatProvider;
_dataStoreProvider = dataStoreProvider;
_getCurrentConfig = getCurrentConfig;
}
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
};
DataStoreLoggerConfiguration config = _getCurrentConfig?.Invoke() ?? new DataStoreLoggerConfiguration();
EventId eventId = EventIdFactory(logEvent);
if (eventId.Id == 0 && config.EventId != 0)
eventId = config.EventId;
string message = logEvent.RenderMessage(_formatProvider);
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)
{
ILogDataStore? dataStore = _dataStoreProvider.Invoke();
// 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;
LogEventProperty? idProperty = value!.Properties.FirstOrDefault(x => x.Name.Equals("Id"));
if (idProperty is not null)
id = int.Parse(idProperty.Value.ToString());
LogEventProperty? nameProperty = value.Properties.FirstOrDefault(x => x.Name.Equals("Name"));
if (nameProperty is not null)
eventName = nameProperty.Value.ToString().Trim('"');
eventId = new EventId(id ?? 0, eventName ?? string.Empty);
return eventId;
}
}
@@ -0,0 +1,24 @@
using Serilog.Configuration;
using LogViewer.Core;
namespace Serilog.Sinks.LogView.Core;
public static class DataStoreLoggerSinkExtensions
{
public static LoggerConfiguration DataStoreLoggerSink
(
this LoggerSinkConfiguration loggerConfiguration,
Func<ILogDataStore> dataStoreProvider,
Action<DataStoreLoggerConfiguration>? configuration = null,
IFormatProvider formatProvider = null!
)
=> loggerConfiguration.Sink(new DataStoreLoggerSink(dataStoreProvider, GetConfig(configuration), formatProvider));
private static Func<DataStoreLoggerConfiguration> GetConfig(Action<DataStoreLoggerConfiguration>? configuration)
{
// convert from Action to Func delegate to pass data
DataStoreLoggerConfiguration data = new();
configuration?.Invoke(data);
return () => data;
}
}
@@ -0,0 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Serilog" Version="2.12.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\LogViewer.Core\LogViewer.Core.csproj" />
</ItemGroup>
</Project>