Update logging

This commit is contained in:
erri120 2022-01-21 14:54:22 +01:00
parent 92a2195ccf
commit e7b7350e76
No known key found for this signature in database
GPG Key ID: 7FA9556C936B847C
8 changed files with 42 additions and 197 deletions

View File

@ -3,11 +3,13 @@ using System.Windows;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Wabbajack.App.Blazor.Models;
using NLog;
using NLog.Extensions.Logging;
using NLog.Targets;
using Wabbajack.App.Blazor.State;
using Wabbajack.App.Blazor.Utility;
using Wabbajack.DTOs;
using Wabbajack.Services.OSIntegrated;
using LogLevel = Microsoft.Extensions.Logging.LogLevel;
namespace Wabbajack.App.Blazor;
@ -18,23 +20,41 @@ public partial class App
public App()
{
_serviceProvider = Host.CreateDefaultBuilder(Array.Empty<string>())
.ConfigureLogging(loggingBuilder =>
{
loggingBuilder.ClearProviders();
})
.ConfigureLogging(SetupLogging)
.ConfigureServices(services => ConfigureServices(services))
.Build()
.Services;
}
private static void SetupLogging(ILoggingBuilder loggingBuilder)
{
var config = new NLog.Config.LoggingConfiguration();
var fileTarget = new FileTarget("file")
{
FileName = "log.log"
};
var consoleTarget = new ConsoleTarget("console");
var uiTarget = new MemoryTarget("ui");
config.AddRuleForAllLevels(fileTarget);
config.AddRuleForAllLevels(consoleTarget);
config.AddRuleForAllLevels(uiTarget);
loggingBuilder.ClearProviders();
loggingBuilder.SetMinimumLevel(LogLevel.Trace);
loggingBuilder.AddNLog(config);
}
private static IServiceCollection ConfigureServices(IServiceCollection services)
{
services.AddOSIntegrated();
services.AddBlazorWebView();
services.AddAllSingleton<ILoggerProvider, LoggerProvider>();
services.AddTransient<MainWindow>();
services.AddSingleton<SystemParametersConstructor>();
services.AddSingleton(typeof(IStateContainer), typeof(StateContainer));
services.AddSingleton<IStateContainer, StateContainer>();
return services;
}

View File

@ -1,10 +1,10 @@
@using Wabbajack.App.Blazor.Models
@using NLog
@using NLog.Targets
@namespace Wabbajack.App.Blazor.Components
<div id="virtual-logger">
<Virtualize Items="@_consoleLog" Context="logItem" OverscanCount="3">
<span @key="logItem.MessageId">@logItem.LongMessage</span>
<Virtualize Items="@Logs" Context="logItem" OverscanCount="3">
<span @key="logItem">@logItem</span>
</Virtualize>
</div>
@ -13,16 +13,11 @@
// TODO: [Low] More parameters to customise the logger. E.g. Reverse order.
// TODO: [High] Find a way to auto-scroll. (JS interop?)
[Parameter]
public IObservable<LoggerProvider.ILogMessage> Messages { get; set; }
private MemoryTarget? _memoryTarget;
private ICollection<string> Logs => _memoryTarget?.Logs ?? Array.Empty<string>();
private List<LoggerProvider.ILogMessage> _consoleLog = new();
protected override async Task OnInitializedAsync()
{
Messages.Subscribe(_consoleLog.Add);
await base.OnInitializedAsync();
protected override void OnInitialized()
{
_memoryTarget = LogManager.Configuration.FindTargetByName<MemoryTarget>("ui");
}
}

View File

@ -1,31 +1,13 @@
using System;
using Microsoft.AspNetCore.Components;
using Microsoft.Extensions.Logging;
using Wabbajack.App.Blazor.Models;
using Wabbajack.App.Blazor.State;
using Wabbajack.App.Blazor.Utility;
using Wabbajack.Common;
using Wabbajack.Installer;
using Wabbajack.Paths.IO;
namespace Wabbajack.App.Blazor;
public partial class MainWindow
{
private readonly ILogger<MainWindow> _logger;
private readonly LoggerProvider _loggerProvider;
private readonly SystemParametersConstructor _systemParams;
private readonly IStateContainer _stateContainer;
public MainWindow(ILogger<MainWindow> logger, IServiceProvider serviceProvider, LoggerProvider loggerProvider,
SystemParametersConstructor systemParams, IStateContainer stateContainer)
public MainWindow(IServiceProvider serviceProvider, IStateContainer stateContainer)
{
_logger = logger;
_loggerProvider = loggerProvider;
_systemParams = systemParams;
_stateContainer = stateContainer;
_stateContainer.TaskBarStateObservable.Subscribe(state =>
stateContainer.TaskBarStateObservable.Subscribe(state =>
{
Dispatcher.InvokeAsync(() =>
{

View File

@ -1,3 +0,0 @@
namespace Wabbajack.App.Blazor.Models;
public class Install { }

View File

@ -1,149 +0,0 @@
using System;
using System.Collections.Immutable;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.IO;
using System.Reactive.Disposables;
using System.Reactive.Subjects;
using System.Text;
using System.Threading;
using DynamicData;
using Microsoft.Extensions.Logging;
using Wabbajack.Paths;
using Wabbajack.Paths.IO;
using Wabbajack.Services.OSIntegrated;
namespace Wabbajack.App.Blazor.Models;
public class LoggerProvider : ILoggerProvider
{
private readonly RelativePath _appName;
private readonly Configuration _configuration;
private readonly CompositeDisposable _disposables;
private readonly Stream _logFile;
private readonly StreamWriter _logStream;
public readonly ReadOnlyObservableCollection<ILogMessage> _messagesFiltered;
private readonly DateTime _startupTime;
private long _messageId;
private readonly SourceCache<ILogMessage, long> _messageLog = new(m => m.MessageId);
private readonly Subject<ILogMessage> _messages = new();
public LoggerProvider(Configuration configuration)
{
_startupTime = DateTime.UtcNow;
_configuration = configuration;
_configuration.LogLocation.CreateDirectory();
_disposables = new CompositeDisposable();
// Messages
// .ObserveOnGuiThread()
// .Subscribe(m => _messageLog.AddOrUpdate(m));
Messages.Subscribe(LogToFile);
_messageLog.Connect()
.Bind(out _messagesFiltered)
.Subscribe();
_appName = typeof(LoggerProvider).Assembly.Location.ToAbsolutePath().FileName;
LogPath = _configuration.LogLocation.Combine($"{_appName}.current.log");
_logFile = LogPath.Open(FileMode.Append, FileAccess.Write);
_logStream = new StreamWriter(_logFile, Encoding.UTF8);
}
public IObservable<ILogMessage> Messages => _messages;
public AbsolutePath LogPath { get; }
public ReadOnlyObservableCollection<ILogMessage> MessageLog => _messagesFiltered;
public void Dispose()
{
_disposables.Dispose();
}
public ILogger CreateLogger(string categoryName)
{
return new Logger(this, categoryName);
}
private void LogToFile(ILogMessage logMessage)
{
var line = $"[{logMessage.TimeStamp - _startupTime}] {logMessage.LongMessage}";
lock (_logStream)
{
_logStream.Write(line);
_logStream.Flush();
}
}
private long NextMessageId()
{
return Interlocked.Increment(ref _messageId);
}
public class Logger : ILogger
{
private readonly string _categoryName;
private readonly LoggerProvider _provider;
private ImmutableList<object> Scopes = ImmutableList<object>.Empty;
public Logger(LoggerProvider provider, string categoryName)
{
_categoryName = categoryName;
_provider = provider;
}
public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception? exception,
Func<TState, Exception?, string> formatter)
{
Debug.WriteLine($"{logLevel} - {formatter(state, exception)}");
_provider._messages.OnNext(new LogMessage<TState>(DateTime.UtcNow, _provider.NextMessageId(), logLevel,
eventId, state, exception, formatter));
}
public bool IsEnabled(LogLevel logLevel)
{
return true;
}
public IDisposable BeginScope<TState>(TState state)
{
Scopes = Scopes.Add(state);
return Disposable.Create(() => Scopes = Scopes.Remove(state));
}
}
public interface ILogMessage
{
long MessageId { get; }
string ShortMessage { get; }
DateTime TimeStamp { get; }
string LongMessage { get; }
}
private record LogMessage<TState>(DateTime TimeStamp, long MessageId, LogLevel LogLevel, EventId EventId,
TState State, Exception? Exception, Func<TState, Exception?, string> Formatter) : ILogMessage
{
public string ShortMessage => Formatter(State, Exception);
public string LongMessage
{
get
{
var sb = new StringBuilder();
sb.AppendLine(ShortMessage);
if (Exception != null)
{
sb.Append("Exception: ");
sb.Append(Exception);
}
return sb.ToString();
}
}
}
}

View File

@ -41,7 +41,7 @@
@if (InstallState == InstallState.Installing)
{
<div class="logger-container">
<VirtualLogger Messages="LoggerProvider.Messages"/>
<VirtualLogger/>
</div>
}
else

View File

@ -12,7 +12,6 @@ using Wabbajack.Services.OSIntegrated;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Microsoft.JSInterop;
using Wabbajack.App.Blazor.Models;
using Wabbajack.App.Blazor.State;
namespace Wabbajack.App.Blazor.Pages;
@ -26,7 +25,6 @@ public partial class Configure
[Inject] private SystemParametersConstructor ParametersConstructor { get; set; } = default!;
[Inject] private IGameLocator GameLocator { get; set; } = default!;
[Inject] private SettingsManager SettingsManager { get; set; } = default!;
[Inject] private LoggerProvider LoggerProvider { get; set; } = default!;
[Inject] private JSRuntime JSRuntime { get; set; } = default!;
private ModList? Modlist => StateContainer.Modlist;

View File

@ -20,6 +20,8 @@
<PackageReference Include="Microsoft.AspNetCore.Components.WebView.Wpf" Version="6.0.101-preview.11.2349" />
<PackageReference Include="Microsoft.AspNetCore.Components.Web" Version="6.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="6.0.1" />
<PackageReference Include="NLog" Version="4.7.13" />
<PackageReference Include="NLog.Extensions.Logging" Version="1.7.4" />
<PackageReference Include="PInvoke.User32" Version="0.7.104" />
<PackageReference Include="Silk.NET.DXGI" Version="2.12.0" />
<PackageReference Include="System.Reactive" Version="5.0.0" />