Add logging

This commit is contained in:
BlossomiShymae
2024-12-17 23:36:28 -06:00
parent f65c6f1b09
commit 9270c6d1f1
11 changed files with 88 additions and 27 deletions

View File

@@ -41,7 +41,6 @@
<PackageReference Include="Serilog" Version="4.2.0" /> <PackageReference Include="Serilog" Version="4.2.0" />
<PackageReference Include="Serilog.Extensions.Logging" Version="9.0.0" /> <PackageReference Include="Serilog.Extensions.Logging" Version="9.0.0" />
<PackageReference Include="Serilog.Sinks.File" Version="6.0.0" /> <PackageReference Include="Serilog.Sinks.File" Version="6.0.0" />
<PackageReference Include="Serilog.Sinks.ObservableCollection" Version="1.0.0" />
<PackageReference Include="TextMateSharp.Grammars" Version="1.0.65" /> <PackageReference Include="TextMateSharp.Grammars" Version="1.0.65" />
</ItemGroup> </ItemGroup>

View File

@@ -6,8 +6,10 @@ using Needlework.Net.ViewModels.MainWindow;
using Needlework.Net.ViewModels.Pages; using Needlework.Net.ViewModels.Pages;
using Projektanker.Icons.Avalonia; using Projektanker.Icons.Avalonia;
using Projektanker.Icons.Avalonia.FontAwesome; using Projektanker.Icons.Avalonia.FontAwesome;
using Serilog;
using System; using System;
using System.IO; using System.IO;
using System.Reflection;
namespace Needlework.Net; namespace Needlework.Net;
@@ -44,9 +46,16 @@ class Program
builder.AddSingleton<MainWindowViewModel>(); builder.AddSingleton<MainWindowViewModel>();
builder.AddSingleton<DialogService>(); builder.AddSingleton<DialogService>();
builder.AddSingletonsFromAssemblies<PageBase>(); builder.AddSingletonsFromAssemblies<PageBase>();
builder.AddHttpClient(); builder.AddHttpClient();
var logger = new LoggerConfiguration()
.MinimumLevel.Debug()
.WriteTo.File("Logs/NeedleworkDotNet.log", rollingInterval: RollingInterval.Day, shared: true)
.CreateLogger();
logger.Debug("NeedleworkDotNet version: {Version}", Assembly.GetEntryAssembly()?.GetName().Version?.ToString() ?? "0.0.0.0");
logger.Debug("OS description: {Description}", System.Runtime.InteropServices.RuntimeInformation.OSDescription);
builder.AddLogging(builder => builder.AddSerilog(logger));
var services = builder.BuildServiceProvider(); var services = builder.BuildServiceProvider();
return services; return services;
} }

View File

@@ -3,6 +3,7 @@ using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input; using CommunityToolkit.Mvvm.Input;
using CommunityToolkit.Mvvm.Messaging; using CommunityToolkit.Mvvm.Messaging;
using FluentAvalonia.UI.Controls; using FluentAvalonia.UI.Controls;
using Microsoft.Extensions.Logging;
using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Models;
using Needlework.Net.Messages; using Needlework.Net.Messages;
using Needlework.Net.Models; using Needlework.Net.Models;
@@ -42,8 +43,12 @@ public partial class MainWindowViewModel
[ObservableProperty] private ObservableCollection<InfoBarViewModel> _infoBarItems = []; [ObservableProperty] private ObservableCollection<InfoBarViewModel> _infoBarItems = [];
public MainWindowViewModel(IEnumerable<PageBase> pages, HttpClient httpClient, DialogService dialogService) private readonly ILogger<MainWindowViewModel> _logger;
public MainWindowViewModel(IEnumerable<PageBase> pages, HttpClient httpClient, DialogService dialogService, ILogger<MainWindowViewModel> logger)
{ {
_logger = logger;
MenuItems = new AvaloniaList<NavigationViewItem>(pages MenuItems = new AvaloniaList<NavigationViewItem>(pages
.OrderBy(p => p.Index) .OrderBy(p => p.Index)
.ThenBy(p => p.DisplayName) .ThenBy(p => p.DisplayName)
@@ -83,7 +88,11 @@ public partial class MainWindowViewModel
var response = await HttpClient.SendAsync(request); var response = await HttpClient.SendAsync(request);
var release = await response.Content.ReadFromJsonAsync<GithubRelease>(); var release = await response.Content.ReadFromJsonAsync<GithubRelease>();
if (release == null) return; if (release == null)
{
_logger.LogWarning("Release response is null");
return;
}
var currentVersion = int.Parse(Version.Replace(".", "")); var currentVersion = int.Parse(Version.Replace(".", ""));
@@ -101,10 +110,15 @@ public partial class MainWindowViewModel
}); });
} }
} }
catch (Exception) { } catch (Exception ex)
{
_logger.LogError(ex, "Failed to check for latest version");
}
} }
private async Task FetchDataAsync() private async Task FetchDataAsync()
{
try
{ {
var document = await Resources.GetOpenApiDocumentAsync(HttpClient); var document = await Resources.GetOpenApiDocumentAsync(HttpClient);
HostDocument = document; HostDocument = document;
@@ -114,6 +128,11 @@ public partial class MainWindowViewModel
WeakReferenceMessenger.Default.Send(new DataReadyMessage(handler)); WeakReferenceMessenger.Default.Send(new DataReadyMessage(handler));
IsBusy = false; IsBusy = false;
} }
catch (HttpRequestException ex)
{
_logger.LogError(ex, "Failed to fetch OpenAPI data");
}
}
public void Receive(DataRequestMessage message) public void Receive(DataRequestMessage message)
{ {

View File

@@ -2,6 +2,7 @@
using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input; using CommunityToolkit.Mvvm.Input;
using CommunityToolkit.Mvvm.Messaging; using CommunityToolkit.Mvvm.Messaging;
using Microsoft.Extensions.Logging;
using Needlework.Net.Messages; using Needlework.Net.Messages;
using Needlework.Net.ViewModels.Shared; using Needlework.Net.ViewModels.Shared;
using System.Threading.Tasks; using System.Threading.Tasks;
@@ -14,10 +15,11 @@ public partial class ConsoleViewModel : PageBase, IRecipient<DataReadyMessage>
public IAvaloniaList<string> RequestPaths { get; } = new AvaloniaList<string>(); public IAvaloniaList<string> RequestPaths { get; } = new AvaloniaList<string>();
[ObservableProperty] private bool _isBusy = true; [ObservableProperty] private bool _isBusy = true;
[ObservableProperty] private LcuRequestViewModel _lcuRequest = new(); [ObservableProperty] private LcuRequestViewModel _lcuRequest;
public ConsoleViewModel() : base("Console", "terminal", -200) public ConsoleViewModel(ILogger<LcuRequestViewModel> lcuRequestViewModelLogger) : base("Console", "terminal", -200)
{ {
_lcuRequest = new(lcuRequestViewModelLogger);
WeakReferenceMessenger.Default.Register<DataReadyMessage>(this); WeakReferenceMessenger.Default.Register<DataReadyMessage>(this);
} }

View File

@@ -1,7 +1,9 @@
using Avalonia.Collections; using Avalonia.Collections;
using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Messaging; using CommunityToolkit.Mvvm.Messaging;
using Microsoft.Extensions.Logging;
using Needlework.Net.Messages; using Needlework.Net.Messages;
using Needlework.Net.ViewModels.Shared;
using System; using System;
using System.Linq; using System.Linq;
@@ -21,12 +23,12 @@ public partial class EndpointViewModel : ObservableObject
public event EventHandler<string>? PathOperationSelected; public event EventHandler<string>? PathOperationSelected;
public EndpointViewModel(string endpoint) public EndpointViewModel(string endpoint, ILogger<LcuRequestViewModel> lcuRequestViewModelLogger)
{ {
Endpoint = endpoint; Endpoint = endpoint;
var handler = WeakReferenceMessenger.Default.Send<DataRequestMessage>().Response; var handler = WeakReferenceMessenger.Default.Send<DataRequestMessage>().Response;
PathOperations = new AvaloniaList<PathOperationViewModel>(handler.Plugins[endpoint].Select(x => new PathOperationViewModel(x))); PathOperations = new AvaloniaList<PathOperationViewModel>(handler.Plugins[endpoint].Select(x => new PathOperationViewModel(x, lcuRequestViewModelLogger)));
FilteredPathOperations = new AvaloniaList<PathOperationViewModel>(PathOperations); FilteredPathOperations = new AvaloniaList<PathOperationViewModel>(PathOperations);
} }

View File

@@ -1,6 +1,8 @@
using Avalonia.Collections; using Avalonia.Collections;
using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input; using CommunityToolkit.Mvvm.Input;
using Microsoft.Extensions.Logging;
using Needlework.Net.ViewModels.Shared;
using System; using System;
namespace Needlework.Net.ViewModels.Pages.Endpoints; namespace Needlework.Net.ViewModels.Pages.Endpoints;
@@ -15,9 +17,9 @@ public partial class EndpointsNavigationViewModel : ObservableObject
private readonly Action<string?, Guid> _onEndpointNavigation; private readonly Action<string?, Guid> _onEndpointNavigation;
public EndpointsNavigationViewModel(IAvaloniaList<string> plugins, Action<string?, Guid> onEndpointNavigation) public EndpointsNavigationViewModel(IAvaloniaList<string> plugins, Action<string?, Guid> onEndpointNavigation, ILogger<LcuRequestViewModel> lcuRequestViewModelLogger)
{ {
_activeViewModel = _endpointsViewModel = new EndpointsViewModel(plugins, OnClicked); _activeViewModel = _endpointsViewModel = new EndpointsViewModel(plugins, OnClicked, lcuRequestViewModelLogger);
_onEndpointNavigation = onEndpointNavigation; _onEndpointNavigation = onEndpointNavigation;
} }

View File

@@ -4,7 +4,9 @@ using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input; using CommunityToolkit.Mvvm.Input;
using CommunityToolkit.Mvvm.Messaging; using CommunityToolkit.Mvvm.Messaging;
using FluentAvalonia.UI.Controls; using FluentAvalonia.UI.Controls;
using Microsoft.Extensions.Logging;
using Needlework.Net.Messages; using Needlework.Net.Messages;
using Needlework.Net.ViewModels.Shared;
using System; using System;
namespace Needlework.Net.ViewModels.Pages.Endpoints; namespace Needlework.Net.ViewModels.Pages.Endpoints;
@@ -16,8 +18,11 @@ public partial class EndpointsTabViewModel : PageBase, IRecipient<DataReadyMessa
[ObservableProperty] private bool _isBusy = true; [ObservableProperty] private bool _isBusy = true;
public EndpointsTabViewModel() : base("Endpoints", "list-alt", -500) private readonly ILogger<LcuRequestViewModel> _lcuRequestViewModelLogger;
public EndpointsTabViewModel(ILogger<LcuRequestViewModel> lcuRequestViewModelLogger) : base("Endpoints", "list-alt", -500)
{ {
_lcuRequestViewModelLogger = lcuRequestViewModelLogger;
WeakReferenceMessenger.Default.RegisterAll(this); WeakReferenceMessenger.Default.RegisterAll(this);
} }
@@ -35,7 +40,7 @@ public partial class EndpointsTabViewModel : PageBase, IRecipient<DataReadyMessa
{ {
Endpoints.Add(new() Endpoints.Add(new()
{ {
Content = new EndpointsNavigationViewModel(Plugins, OnEndpointNavigation), Content = new EndpointsNavigationViewModel(Plugins, OnEndpointNavigation, _lcuRequestViewModelLogger),
Selected = true Selected = true
}); });
} }

View File

@@ -1,6 +1,8 @@
using Avalonia.Collections; using Avalonia.Collections;
using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input; using CommunityToolkit.Mvvm.Input;
using Microsoft.Extensions.Logging;
using Needlework.Net.ViewModels.Shared;
using System; using System;
using System.Linq; using System.Linq;
@@ -16,11 +18,14 @@ public partial class EndpointsViewModel : ObservableObject
public Action<ObservableObject> OnClicked { get; } public Action<ObservableObject> OnClicked { get; }
public EndpointsViewModel(IAvaloniaList<string> plugins, Action<ObservableObject> onClicked) private readonly ILogger<LcuRequestViewModel> _lcuRequestViewModelLogger;
public EndpointsViewModel(IAvaloniaList<string> plugins, Action<ObservableObject> onClicked, ILogger<LcuRequestViewModel> lcuRequestViewModelLogger)
{ {
Plugins = new AvaloniaList<string>(plugins); Plugins = new AvaloniaList<string>(plugins);
Query = new AvaloniaList<string>(plugins); Query = new AvaloniaList<string>(plugins);
OnClicked = onClicked; OnClicked = onClicked;
_lcuRequestViewModelLogger = lcuRequestViewModelLogger;
} }
partial void OnSearchChanged(string value) partial void OnSearchChanged(string value)
@@ -37,6 +42,6 @@ public partial class EndpointsViewModel : ObservableObject
{ {
if (string.IsNullOrEmpty(value)) return; if (string.IsNullOrEmpty(value)) return;
OnClicked.Invoke(new EndpointViewModel(value)); OnClicked.Invoke(new EndpointViewModel(value, _lcuRequestViewModelLogger));
} }
} }

View File

@@ -1,5 +1,6 @@
using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input; using CommunityToolkit.Mvvm.Input;
using Microsoft.Extensions.Logging;
using Needlework.Net.Models; using Needlework.Net.Models;
using Needlework.Net.ViewModels.Shared; using Needlework.Net.ViewModels.Shared;
using System; using System;
@@ -16,11 +17,11 @@ public partial class PathOperationViewModel : ObservableObject
[ObservableProperty] private bool _isBusy; [ObservableProperty] private bool _isBusy;
[ObservableProperty] private Lazy<LcuRequestViewModel> _lcuRequest; [ObservableProperty] private Lazy<LcuRequestViewModel> _lcuRequest;
public PathOperationViewModel(PathOperation pathOperation) public PathOperationViewModel(PathOperation pathOperation, ILogger<LcuRequestViewModel> lcuRequestViewModelLogger)
{ {
Path = pathOperation.Path; Path = pathOperation.Path;
Operation = new OperationViewModel(pathOperation.Operation); Operation = new OperationViewModel(pathOperation.Operation);
LcuRequest = new(() => new LcuRequestViewModel() LcuRequest = new(() => new LcuRequestViewModel(lcuRequestViewModelLogger)
{ {
Method = pathOperation.Method.ToUpper() Method = pathOperation.Method.ToUpper()
}); });

View File

@@ -3,11 +3,11 @@ using BlossomiShymae.GrrrLCU;
using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input; using CommunityToolkit.Mvvm.Input;
using CommunityToolkit.Mvvm.Messaging; using CommunityToolkit.Mvvm.Messaging;
using Microsoft.Extensions.Logging;
using Needlework.Net.Messages; using Needlework.Net.Messages;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Net.Http; using System.Net.Http;
using System.Text.Json; using System.Text.Json;
@@ -45,8 +45,11 @@ public partial class WebsocketViewModel : PageBase
public IReadOnlyList<EventViewModel> FilteredEventLog => string.IsNullOrWhiteSpace(Search) ? EventLog : [.. EventLog.Where(x => x.Key.Contains(Search, StringComparison.InvariantCultureIgnoreCase))]; public IReadOnlyList<EventViewModel> FilteredEventLog => string.IsNullOrWhiteSpace(Search) ? EventLog : [.. EventLog.Where(x => x.Key.Contains(Search, StringComparison.InvariantCultureIgnoreCase))];
public WebsocketViewModel(HttpClient httpClient) : base("Event Viewer", "plug", -100) private readonly ILogger<WebsocketViewModel> _logger;
public WebsocketViewModel(HttpClient httpClient, ILogger<WebsocketViewModel> logger) : base("Event Viewer", "plug", -100)
{ {
_logger = logger;
HttpClient = httpClient; HttpClient = httpClient;
EventLog.CollectionChanged += (s, e) => OnPropertyChanged(nameof(FilteredEventLog)); EventLog.CollectionChanged += (s, e) => OnPropertyChanged(nameof(FilteredEventLog));
Task.Run(async () => Task.Run(async () =>
@@ -66,6 +69,7 @@ public partial class WebsocketViewModel : PageBase
} }
catch (HttpRequestException ex) catch (HttpRequestException ex)
{ {
_logger.LogError(ex, "Failed to get event types");
WeakReferenceMessenger.Default.Send(new InfoBarUpdateMessage(new("Failed to get event types", true, ex.Message, FluentAvalonia.UI.Controls.InfoBarSeverity.Error, TimeSpan.FromSeconds(10)))); WeakReferenceMessenger.Default.Send(new InfoBarUpdateMessage(new("Failed to get event types", true, ex.Message, FluentAvalonia.UI.Controls.InfoBarSeverity.Error, TimeSpan.FromSeconds(10))));
} }
} }
@@ -76,6 +80,7 @@ public partial class WebsocketViewModel : PageBase
{ {
if (Client != null) if (Client != null)
{ {
_logger.LogDebug("Disposing old connection");
foreach (var disposable in ClientDisposables) foreach (var disposable in ClientDisposables)
disposable.Dispose(); disposable.Dispose();
ClientDisposables.Clear(); ClientDisposables.Clear();
@@ -105,6 +110,7 @@ public partial class WebsocketViewModel : PageBase
}) })
{ IsBackground = true }; { IsBackground = true };
thread.Start(); thread.Start();
_logger.LogDebug("Initialized new connection: {EventType}", EventType);
TokenSource = tokenSource; TokenSource = tokenSource;
} }
} }
@@ -129,12 +135,12 @@ public partial class WebsocketViewModel : PageBase
private void OnReconnection(ReconnectionInfo info) private void OnReconnection(ReconnectionInfo info)
{ {
Trace.WriteLine($"-- Reconnection --\nType{info.Type}"); _logger.LogTrace("Reconnected: {Type}", info.Type);
} }
private void OnDisconnection(DisconnectionInfo info) private void OnDisconnection(DisconnectionInfo info)
{ {
Trace.WriteLine($"-- Disconnection --\nType:{info.Type}\nSubProtocol:{info.SubProtocol}\nCloseStatus:{info.CloseStatus}\nCloseStatusDescription:{info.CloseStatusDescription}\nExceptionMessage:{info?.Exception?.Message}\n:InnerException:{info?.Exception?.InnerException}"); _logger.LogTrace("Disconnected: {Type}", info.Type);
InitializeWebsocket(); InitializeWebsocket();
} }

View File

@@ -2,6 +2,7 @@
using BlossomiShymae.GrrrLCU; using BlossomiShymae.GrrrLCU;
using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Messaging; using CommunityToolkit.Mvvm.Messaging;
using Microsoft.Extensions.Logging;
using Needlework.Net.Messages; using Needlework.Net.Messages;
using Needlework.Net.ViewModels.MainWindow; using Needlework.Net.ViewModels.MainWindow;
using System; using System;
@@ -31,6 +32,13 @@ public partial class LcuRequestViewModel : ObservableObject
public event EventHandler<LcuRequestViewModel>? RequestText; public event EventHandler<LcuRequestViewModel>? RequestText;
public event EventHandler<string>? UpdateText; public event EventHandler<string>? UpdateText;
private readonly ILogger<LcuRequestViewModel> _logger;
public LcuRequestViewModel(ILogger<LcuRequestViewModel> logger)
{
_logger = logger;
}
partial void OnMethodChanged(string? oldValue, string? newValue) partial void OnMethodChanged(string? oldValue, string? newValue)
{ {
if (newValue == null) return; if (newValue == null) return;
@@ -59,6 +67,8 @@ public partial class LcuRequestViewModel : ObservableObject
_ => throw new Exception("Method is not selected or missing."), _ => throw new Exception("Method is not selected or missing."),
}; };
_logger.LogDebug("Sending request: {Tuple}", (Method, RequestPath));
var processInfo = ProcessFinder.GetProcessInfo(); var processInfo = ProcessFinder.GetProcessInfo();
RequestText?.Invoke(this, this); RequestText?.Invoke(this, this);
var content = new StringContent(RequestBody ?? string.Empty, new System.Net.Http.Headers.MediaTypeHeaderValue("application/json")); var content = new StringContent(RequestBody ?? string.Empty, new System.Net.Http.Headers.MediaTypeHeaderValue("application/json"));
@@ -88,6 +98,7 @@ public partial class LcuRequestViewModel : ObservableObject
} }
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogError(ex, "Request failed: {Tuple}", (Method, RequestPath));
WeakReferenceMessenger.Default.Send(new InfoBarUpdateMessage(new InfoBarViewModel("Request Failed", true, ex.Message, FluentAvalonia.UI.Controls.InfoBarSeverity.Error, TimeSpan.FromSeconds(5)))); WeakReferenceMessenger.Default.Send(new InfoBarUpdateMessage(new InfoBarViewModel("Request Failed", true, ex.Message, FluentAvalonia.UI.Controls.InfoBarSeverity.Error, TimeSpan.FromSeconds(5))));
UpdateText?.Invoke(this, string.Empty); UpdateText?.Invoke(this, string.Empty);