diff --git a/src/ModSink.CLI/ModSink.CLI.csproj b/src/ModSink.CLI/ModSink.CLI.csproj index 9876b966..f9ee1f3d 100644 --- a/src/ModSink.CLI/ModSink.CLI.csproj +++ b/src/ModSink.CLI/ModSink.CLI.csproj @@ -6,9 +6,14 @@ - + + + + + + diff --git a/src/ModSink.CLI/Program.cs b/src/ModSink.CLI/Program.cs index fbe4fbbe..18ebd39c 100644 --- a/src/ModSink.CLI/Program.cs +++ b/src/ModSink.CLI/Program.cs @@ -14,6 +14,8 @@ using ModSink.Common.Models.Group; using ModSink.Common.Models.Repo; using Serilog; +using Serilog.Formatting.Compact; +using Serilog.Sinks.SystemConsole.Themes; namespace ModSink.CLI { @@ -83,7 +85,7 @@ private static void AddColCheck(this CommandLineApplication app) var path = Path.Combine(Directory.GetCurrentDirectory(), pathStr); IHashFunction xxhash = new XXHash64(); var hashing = new HashingService(xxhash); - hashing.GetFiles(new DirectoryInfo(path)) + foreach (var g in hashing.GetFiles(new DirectoryInfo(path)) .Select(f => { var hash = hashing.GetFileHash(f, CancellationToken.None).GetAwaiter().GetResult(); @@ -91,14 +93,13 @@ private static void AddColCheck(this CommandLineApplication app) return new {f, hash}; }) .GroupBy(a => a.hash.ToString()) - .Where(g => g.Count() > 1) - .ForEach(g => - { - Console.WriteLine(g.Key); - foreach (var i in g) - Console.WriteLine($" {i.f.FullName}"); - Console.WriteLine(); - }); + .Where(g => g.Count() > 1)) + { + Console.WriteLine(g.Key); + foreach (var i in g) + Console.WriteLine($" {i.f.FullName}"); + Console.WriteLine(); + } Console.WriteLine("Done."); return 0; @@ -347,10 +348,18 @@ private static void DumpRepo(Repo repo) public static void Main(string[] args) { Log.Logger = new LoggerConfiguration() - .WriteTo.Console(outputTemplate: - "{Timestamp:HH:mm:ss} {Level:u3} [{SourceContext}] {Properties} {Message:lj}{NewLine}{Exception}") + .WriteTo.Console( + theme: AnsiConsoleTheme.Code, + outputTemplate: + "{Timestamp:HH:mm:ss} {Level:u3} {SourceContext} {Message:lj} {Properties} {NewLine}{Exception}") + .WriteTo.File(new CompactJsonFormatter(), "log.txt", fileSizeLimitBytes: 10 * 1024 * 1024, + buffered: true, flushToDiskInterval: 10.Seconds(), rollingInterval: RollingInterval.Day, + rollOnFileSizeLimit: true) .MinimumLevel.Verbose() .Enrich.FromLogContext() + .Enrich.WithDemystifiedStackTraces() + .Enrich.WithMemoryUsage() + .Enrich.WithThreadId() .CreateLogger(); var app = new CommandLineApplication diff --git a/src/ModSink.Common.Tests/ModSink.Common.Tests.csproj b/src/ModSink.Common.Tests/ModSink.Common.Tests.csproj index e9e7c4b0..5f70d4e9 100644 --- a/src/ModSink.Common.Tests/ModSink.Common.Tests.csproj +++ b/src/ModSink.Common.Tests/ModSink.Common.Tests.csproj @@ -5,17 +5,19 @@ - - + + + all + runtime; build; native; contentfiles; analyzers + - - + + - diff --git a/src/ModSink.Common/Client/ActiveDownload.cs b/src/ModSink.Common/Client/ActiveDownload.cs index a879d34b..f4a108fa 100644 --- a/src/ModSink.Common/Client/ActiveDownload.cs +++ b/src/ModSink.Common/Client/ActiveDownload.cs @@ -1,15 +1,15 @@ using System; -using System.IO; +using System.ComponentModel; using System.Reactive.Disposables; using System.Reactive.Linq; using System.Reactive.Subjects; +using System.Runtime.CompilerServices; using Anotar.Serilog; using Humanizer.Bytes; -using ReactiveUI; namespace ModSink.Common.Client { - public class ActiveDownload : ReactiveObject, IDisposable + public class ActiveDownload : IDisposable { private readonly CompositeDisposable disposable = new CompositeDisposable(); @@ -21,11 +21,11 @@ public ActiveDownload(IConnectableObservable downloadProgress, { Name = name; LogTo.Verbose("[{download}] Created ActiveDownload", Name); - downloadProgress.Subscribe(progress).DisposeWith(disposable); - downloadProgress.Connect().DisposeWith(disposable); - progress.DistinctUntilChanged(dp => dp.State).Subscribe(dp => - LogTo.Verbose("[{download}] State changed to {state}", Name, dp.State)).DisposeWith(disposable); - progress.Subscribe(_ => { }, completed).DisposeWith(disposable); + disposable.Add(downloadProgress.Subscribe(progress)); + disposable.Add(downloadProgress.Connect()); + disposable.Add(progress.DistinctUntilChanged(dp => dp.State).Subscribe(dp => + LogTo.Verbose("[{download}] State changed to {state}", Name, dp.State))); + disposable.Add(progress.Subscribe(_ => { }, completed)); } public string Name { get; } diff --git a/src/ModSink.Common/Client/ClientService.cs b/src/ModSink.Common/Client/ClientService.cs index f0a29795..938891a4 100644 --- a/src/ModSink.Common/Client/ClientService.cs +++ b/src/ModSink.Common/Client/ClientService.cs @@ -14,13 +14,12 @@ using ModSink.Common.Models.Client; using ModSink.Common.Models.Group; using ModSink.Common.Models.Repo; -using ReactiveUI; namespace ModSink.Common.Client { public class ClientService : IDisposable { - private readonly CompositeDisposable disposable = new CompositeDisposable(); + private readonly CompositeDisposable d = new CompositeDisposable(); private readonly IDownloader downloader; private readonly IFileAccessService fileAccessService; @@ -36,16 +35,13 @@ public ClientService(IDownloader downloader, IFormatter serializationFormatter, this.serializationFormatter = serializationFormatter; filesAvailable.Edit(l => { l.AddOrUpdate(fileAccessService.FilesAvailable()); }); LogTo.Warning("Creating pipeline"); - Repos = DynamicDataChain.GetReposFromGroups(GroupUrls.Connect(), Load, Load).AsObservableCache().DisposeWith(disposable); - OnlineFiles = DynamicDataChain.GetOnlineFileFromRepos(Repos.Connect()) - .AsObservableCache() - .DisposeWith(disposable); - Modpacks = DynamicDataChain.GetModpacksFromRepos(Repos.Connect()).AsObservableCache() - .DisposeWith(disposable); + Repos = DynamicDataChain.GetReposFromGroups(GroupUrls.Connect(),Load,Load).AsObservableCache(); + d.Add(Repos); + OnlineFiles = DynamicDataChain.GetOnlineFileFromRepos(Repos.Connect()).AsObservableCache(); + d.Add(OnlineFiles); + Modpacks = DynamicDataChain.GetModpacksFromRepos(Repos.Connect()).AsObservableCache(); + d.Add(Modpacks); QueuedDownloads = DynamicDataChain.GetDownloadsFromModpacks(Modpacks.Connect()) - .AsObservableCache() - .DisposeWith(disposable) - .Connect() .LeftJoin(filesAvailable.Connect(), f => f, (required, available) => !available.HasValue ? Optional.Create(required) @@ -54,8 +50,8 @@ public ClientService(IDownloader downloader, IFormatter serializationFormatter, .Transform(opt => opt.Value) .InnerJoin(OnlineFiles.Connect(), of => of.FileSignature, (fs, of) => new QueuedDownload(fs, of.Uri)) - .AsObservableCache() - .DisposeWith(disposable); + .AsObservableCache(); + d.Add(QueuedDownloads); ActiveDownloads = QueuedDownloads.Connect() .Sort(Comparer.Create((_, __) => 0)) .Top(5) @@ -74,8 +70,8 @@ public ClientService(IDownloader downloader, IFormatter serializationFormatter, }, qd.FileSignature.ToString()); }) .LogVerbose("activeDownloads") - .AsObservableCache() - .DisposeWith(disposable); + .AsObservableCache(); + d.Add(ActiveDownloads); } public IObservableCache ActiveDownloads { get; } @@ -87,7 +83,7 @@ public ClientService(IDownloader downloader, IFormatter serializationFormatter, public void Dispose() { - disposable.Dispose(); + d.Dispose(); } private void AddNewFile(FileSignature fileSignature) diff --git a/src/ModSink.Common/Client/DynamicDataChain.cs b/src/ModSink.Common/Client/DynamicDataChain.cs index 152d08fa..4f101d52 100644 --- a/src/ModSink.Common/Client/DynamicDataChain.cs +++ b/src/ModSink.Common/Client/DynamicDataChain.cs @@ -6,7 +6,6 @@ using ModSink.Common.Models.Client; using ModSink.Common.Models.Group; using ModSink.Common.Models.Repo; -using ReactiveUI; namespace ModSink.Common.Client { @@ -16,7 +15,7 @@ public static IObservable> GetDownloads IObservable> modpacks) { return modpacks - .AutoRefresh(m => m.Selected, scheduler: RxApp.TaskpoolScheduler) + .AutoRefresh(m => m.Selected) .Filter(m => m.Selected) .TransformMany(m => m.Mods, m => m.Mod.Id) .TransformMany(m => m.Mod.Files.Values, fs => fs); diff --git a/src/ModSink.Common/Client/FileAccessService.cs b/src/ModSink.Common/Client/FileAccessService.cs index da664373..9b1c8eb6 100644 --- a/src/ModSink.Common/Client/FileAccessService.cs +++ b/src/ModSink.Common/Client/FileAccessService.cs @@ -27,10 +27,13 @@ IEnumerable IFileAccessService.FilesAvailable() ) fileInfo.Delete(); - return localDir.EnumerateFiles() + foreach (var file in localDir.EnumerateFiles() .Where(f => !f.Name.EndsWith(".tmp")) - .Select(f => new FileSignature(new HashValue(f.Name), f.Length)) - .Do(file => LogTo.Verbose("File {file} has been discovered", file.Hash)); + .Select(f => new FileSignature(new HashValue(f.Name), f.Length))) + { + LogTo.Verbose("File {file} has been discovered", file.Hash); + yield return file; + } } Stream IFileAccessService.Read(FileSignature fileSignature, bool temporary) diff --git a/src/ModSink.Common/DynamicDataExtensions.cs b/src/ModSink.Common/DynamicDataExtensions.cs index 254a2d35..5bf3fa75 100644 --- a/src/ModSink.Common/DynamicDataExtensions.cs +++ b/src/ModSink.Common/DynamicDataExtensions.cs @@ -5,35 +5,11 @@ using System.Reactive.Linq; using Anotar.Serilog; using DynamicData; -using ReactiveUI; namespace ModSink.Common { public static class DynamicDataExtensions { - public static IObservableCache DisposeWithThrowExceptions( - this IObservableCache o, - CompositeDisposable disposable) - { - o.DisposeWith(disposable); - o.Connect().Subscribe().DisposeWith(disposable); - o.Connect().Subscribe(_ => { }, - ex => RxApp.MainThreadScheduler.Schedule(() => RxApp.DefaultExceptionHandler.OnNext(ex))); - o.Connect().Subscribe(_ => { }, _ => Debugger.Break()); - return o; - } - - public static IObservableList DisposeWithThrowExceptions(this IObservableList o, - CompositeDisposable disposable) - { - o.DisposeWith(disposable); - o.Connect().Subscribe().DisposeWith(disposable); - o.Connect().Subscribe(_ => { }, - ex => RxApp.MainThreadScheduler.Schedule(() => RxApp.DefaultExceptionHandler.OnNext(ex))); - o.Connect().Subscribe(_ => { }, _ => Debugger.Break()); - return o; - } - public static IObservable> LogVerbose(this IObservable> source, string prefix) { return source.Do(changeSet => diff --git a/src/ModSink.Common/HashingService.cs b/src/ModSink.Common/HashingService.cs index 1316b674..b8e32af0 100644 --- a/src/ModSink.Common/HashingService.cs +++ b/src/ModSink.Common/HashingService.cs @@ -54,7 +54,10 @@ public IEnumerable GetFiles(DirectoryInfo directory) while (directoryStack.Count > 0) { var dir = directoryStack.Pop(); - dir.EnumerateDirectories().ForEach(directoryStack.Push); + foreach (var d in dir.EnumerateDirectories()) + { + directoryStack.Push(d); + } foreach (var file in dir.EnumerateFiles()) yield return file; } } diff --git a/src/ModSink.Common/HttpClientDownloader.cs b/src/ModSink.Common/HttpClientDownloader.cs index 20150422..f3490ed3 100644 --- a/src/ModSink.Common/HttpClientDownloader.cs +++ b/src/ModSink.Common/HttpClientDownloader.cs @@ -11,7 +11,6 @@ using ModSink.Common.Client; using Polly; using Polly.Extensions.Http; -using ReactiveUI; using static ModSink.Common.Client.DownloadProgress; namespace ModSink.Common @@ -85,7 +84,7 @@ public IConnectableObservable Download(Uri source, Lazy - + - + + all + runtime; build; native; contentfiles; analyzers + + - - + + - - diff --git a/src/ModSink.WPF.Tests/ModSink.WPF.Tests.csproj b/src/ModSink.WPF.Tests/ModSink.WPF.Tests.csproj index 3b15e308..63d39eb5 100644 --- a/src/ModSink.WPF.Tests/ModSink.WPF.Tests.csproj +++ b/src/ModSink.WPF.Tests/ModSink.WPF.Tests.csproj @@ -7,10 +7,13 @@ - + + all + runtime; build; native; contentfiles; analyzers + - + diff --git a/src/ModSink.WPF/App.xaml.cs b/src/ModSink.WPF/App.xaml.cs index a5b375b2..5ec63506 100644 --- a/src/ModSink.WPF/App.xaml.cs +++ b/src/ModSink.WPF/App.xaml.cs @@ -9,11 +9,14 @@ using System.Windows.Media; using Anotar.Serilog; using CountlySDK; +using Humanizer; using ModSink.WPF.Helpers; using ModSink.WPF.ViewModel; using ReactiveUI; using Serilog; using Serilog.Debugging; +using Serilog.Formatting.Compact; +using Serilog.Sinks.SystemConsole.Themes; using Splat; using Splat.Serilog; using ILogger = Splat.ILogger; @@ -33,6 +36,18 @@ public App() private static string FullVersion => typeof(App).GetTypeInfo().Assembly .GetCustomAttribute()?.InformationalVersion; + private void FatalException(Exception e, Type source) + { + ConsoleManager.Show(); + Log.ForContext(source).Fatal(e, "{exceptionText}", e.ToStringDemystified()); + Countly.RecordException(e.Message, e.ToStringDemystified(), null, true); + if (Debugger.IsAttached == false) + { + Console.WriteLine(WPF.Properties.Resources.FatalExceptionPressAnyKeyToContinue); + Console.ReadKey(); + } + } + private void InitializeDependencyInjection() { //TODO: FIX: @@ -49,18 +64,6 @@ private void InitializeDependencyInjection() } - private void FatalException(Exception e, Type source) - { - ConsoleManager.Show(); - Log.ForContext(source).Fatal(e, "{exceptionText}", e.ToStringDemystified()); - Countly.RecordException(e.Message, e.ToStringDemystified(), null, true); - if (Debugger.IsAttached == false) - { - Console.WriteLine(WPF.Properties.Resources.FatalExceptionPressAnyKeyToContinue); - Console.ReadKey(); - } - } - protected override void OnExit(ExitEventArgs e) { Countly.EndSession().ContinueWith(_ => LogTo.Information("Shutdown finished.")); @@ -85,15 +88,22 @@ private void SetupLogging() Log.Logger = new LoggerConfiguration() .WriteTo.Debug( outputTemplate: "{Level:u3} [{SourceContext}] {Message:lj}{NewLine}{Exception}") - .WriteTo.LiterateConsole( - outputTemplate: - "{Timestamp:HH:mm:ss} {Level:u3} [{SourceContext}-{ThreadId}] {Message:lj}{NewLine}{Exception}") - .WriteTo.RollingFile( - Path.Combine(PathProvider.Logs.FullName, "{Date}.log"), + .WriteTo.Trace() + .WriteTo.Console(theme: AnsiConsoleTheme.Code, outputTemplate: - "{Timestamp:o} {Level:u3} [{SourceContext}-{ThreadId}] {Message} {Properties}{NewLine}{Exception}") + "{Timestamp:HH:mm:ss} {Level:u3} {SourceContext} {ThreadId} {Message:lj}{Properties:j}{NewLine}{Exception}") + .WriteTo.File( + new CompactJsonFormatter(), + Path.Combine(PathProvider.Logs.FullName, "Log.txt"), + buffered: true, + fileSizeLimitBytes: 10 * 1024 * 1024, + flushToDiskInterval: 10.Seconds(), + rollingInterval: RollingInterval.Day, + rollOnFileSizeLimit: true) .Enrich.FromLogContext() .Enrich.WithThreadId() + .Enrich.WithDemystifiedStackTraces() + .Enrich.WithMemoryUsage() .MinimumLevel.Verbose() .CreateLogger(); diff --git a/src/ModSink.WPF/ModSink.WPF.csproj b/src/ModSink.WPF/ModSink.WPF.csproj index acc05eb9..ae815825 100644 --- a/src/ModSink.WPF/ModSink.WPF.csproj +++ b/src/ModSink.WPF/ModSink.WPF.csproj @@ -36,23 +36,28 @@ - - - + + + all + runtime; build; native; contentfiles; analyzers + - - - + + + - + + + + - - + +