From c9c7316b7d59d8b78d0e13de3529e84b94b22a3c Mon Sep 17 00:00:00 2001 From: Andrew Camilleri Date: Wed, 7 Nov 2018 14:29:35 +0100 Subject: [PATCH] Logs UI in Server Admin (#374) * add in ui * add in logging viewer * Revert "add in ui" This reverts commit 9614721fa8a439f7097adca69772b5d41f6585d6. * finish basic feature * clean up * improve and fix build * add in debug log level command option * use paging for log file list, use extension to select log files, show message for setting up logging * make paging a little better * add very basic UT for logs * Update ServerController.cs --- BTCPayServer.Tests/UnitTest1.cs | 18 ++++++ .../Configuration/BTCPayServerOptions.cs | 24 ++++++++ .../Configuration/DefaultConfiguration.cs | 1 + BTCPayServer/Controllers/ServerController.cs | 57 +++++++++++++++++++ .../Models/ServerViewModels/LogsViewModel.cs | 19 +++++++ .../ServerViewModels/ServicesViewModel.cs | 1 + BTCPayServer/Program.cs | 13 ++--- BTCPayServer/Views/Server/Logs.cshtml | 40 +++++++++++++ BTCPayServer/Views/Server/ServerNavPages.cs | 2 +- BTCPayServer/Views/Server/_Nav.cshtml | 1 + 10 files changed, 167 insertions(+), 9 deletions(-) create mode 100644 BTCPayServer/Models/ServerViewModels/LogsViewModel.cs create mode 100644 BTCPayServer/Views/Server/Logs.cshtml diff --git a/BTCPayServer.Tests/UnitTest1.cs b/BTCPayServer.Tests/UnitTest1.cs index a73c07135..fea752023 100644 --- a/BTCPayServer.Tests/UnitTest1.cs +++ b/BTCPayServer.Tests/UnitTest1.cs @@ -43,8 +43,10 @@ using System.Security.Cryptography.X509Certificates; using BTCPayServer.Lightning; using BTCPayServer.Models.WalletViewModels; using System.Security.Claims; +using BTCPayServer.Models.ServerViewModels; using BTCPayServer.Security; using NBXplorer.Models; +using RatesViewModel = BTCPayServer.Models.StoreViewModels.RatesViewModel; namespace BTCPayServer.Tests { @@ -1772,6 +1774,22 @@ namespace BTCPayServer.Tests } } + [Fact] + [Trait("Integration", "Integration")] + public async Task CheckLogsRoute() + { + using (var tester = ServerTester.Create()) + { + tester.Start(); + var user = tester.NewAccount(); + user.GrantAccess(); + user.RegisterDerivationScheme("BTC"); + + var serverController = user.GetController(); + var vm = Assert.IsType(Assert.IsType(await serverController.LogsView()).Model); + } + } + [Fact] [Trait("Fast", "Fast")] public void CheckRatesProvider() diff --git a/BTCPayServer/Configuration/BTCPayServerOptions.cs b/BTCPayServer/Configuration/BTCPayServerOptions.cs index 51febf179..e477a200b 100644 --- a/BTCPayServer/Configuration/BTCPayServerOptions.cs +++ b/BTCPayServer/Configuration/BTCPayServerOptions.cs @@ -16,6 +16,7 @@ using NBitcoin.DataEncoders; using BTCPayServer.SSH; using BTCPayServer.Lightning; using BTCPayServer.Configuration.External; +using Serilog.Events; namespace BTCPayServer.Configuration { @@ -33,6 +34,12 @@ namespace BTCPayServer.Configuration get; set; } public string ConfigurationFile + { + get; + private set; + } + + public string LogFile { get; private set; @@ -54,6 +61,16 @@ namespace BTCPayServer.Configuration set; } = new List(); + public static string GetDebugLog(IConfiguration configuration) + { + return configuration.GetValue("debuglog", null); + } + public static LogEventLevel GetDebugLogLevel(IConfiguration configuration) + { + var raw = configuration.GetValue("debugloglevel", nameof(LogEventLevel.Debug)); + return (LogEventLevel)Enum.Parse(typeof(LogEventLevel), raw, true); + } + public void LoadArgs(IConfiguration conf) { NetworkType = DefaultConfiguration.GetNetworkType(conf); @@ -174,6 +191,13 @@ namespace BTCPayServer.Configuration var old = conf.GetOrDefault("internallightningnode", null); if (old != null) throw new ConfigException($"internallightningnode should not be used anymore, use btclightning instead"); + + LogFile = GetDebugLog(conf); + if (!string.IsNullOrEmpty(LogFile)) + { + Logs.Configuration.LogInformation("LogFile: " + LogFile); + Logs.Configuration.LogInformation("Log Level: " + GetDebugLogLevel(conf)); + } } private SSHSettings ParseSSHConfiguration(IConfiguration conf) diff --git a/BTCPayServer/Configuration/DefaultConfiguration.cs b/BTCPayServer/Configuration/DefaultConfiguration.cs index a59d513f5..ef8511db3 100644 --- a/BTCPayServer/Configuration/DefaultConfiguration.cs +++ b/BTCPayServer/Configuration/DefaultConfiguration.cs @@ -41,6 +41,7 @@ namespace BTCPayServer.Configuration app.Option("--sshkeyfilepassword", "Password of the SSH keyfile (default: empty)", CommandOptionType.SingleValue); app.Option("--sshtrustedfingerprints", "SSH Host public key fingerprint or sha256 (default: empty, it will allow untrusted connections)", CommandOptionType.SingleValue); app.Option("--debuglog", "A rolling log file for debug messages.", CommandOptionType.SingleValue); + app.Option("--debugloglevel", "The severity you log (default:information)", CommandOptionType.SingleValue); foreach (var network in provider.GetAll()) { var crypto = network.CryptoCode.ToLowerInvariant(); diff --git a/BTCPayServer/Controllers/ServerController.cs b/BTCPayServer/Controllers/ServerController.cs index 30ae7e53c..ae75cafc8 100644 --- a/BTCPayServer/Controllers/ServerController.cs +++ b/BTCPayServer/Controllers/ServerController.cs @@ -17,6 +17,7 @@ using NBitcoin.DataEncoders; using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; +using System.IO; using System.Linq; using System.Net; using System.Net.Http; @@ -167,6 +168,7 @@ namespace BTCPayServer.Controllers vm.DNSDomain = null; return View(vm); } + [Route("server/maintenance")] [HttpPost] public async Task Maintenance(MaintenanceViewModel vm, string command) @@ -625,5 +627,60 @@ namespace BTCPayServer.Controllers return View(model); } } + + [Route("server/logs/{file?}")] + public async Task LogsView(string file = null, int offset = 0) + { + if (offset < 0) + { + offset = 0; + } + + var vm = new LogsViewModel(); + + if (string.IsNullOrEmpty(_Options.LogFile)) + { + vm.StatusMessage = "Error: File Logging Option not specified. " + + "You need to set debuglog and optionally " + + "debugloglevel in the configuration or through runtime arguments"; + } + else + { + var di = Directory.GetParent(_Options.LogFile); + if (di == null) + { + vm.StatusMessage = "Error: Could not load log files"; + } + + var fileNameWithoutExtension = Path.GetFileNameWithoutExtension(_Options.LogFile); + var fileExtension = Path.GetExtension(_Options.LogFile) ?? string.Empty; + var logFiles = di.GetFiles($"{fileNameWithoutExtension}*{fileExtension}"); + vm.LogFileCount = logFiles.Length; + vm.LogFiles = logFiles + .OrderBy(info => info.LastWriteTime) + .Skip(offset) + .Take(5) + .ToList(); + vm.LogFileOffset = offset; + + if (string.IsNullOrEmpty(file)) return View("Logs", vm); + vm.Log = ""; + var path = Path.Combine(di.FullName, file); + + using (var fileStream = new FileStream( + path, + FileMode.Open, + FileAccess.Read, + FileShare.ReadWrite)) + { + using (var reader = new StreamReader(fileStream)) + { + vm.Log = await reader.ReadToEndAsync(); + } + } + } + + return View("Logs", vm); + } } } diff --git a/BTCPayServer/Models/ServerViewModels/LogsViewModel.cs b/BTCPayServer/Models/ServerViewModels/LogsViewModel.cs new file mode 100644 index 000000000..9a05c142f --- /dev/null +++ b/BTCPayServer/Models/ServerViewModels/LogsViewModel.cs @@ -0,0 +1,19 @@ +using System.Collections.Generic; +using System.IO; + +namespace BTCPayServer.Models.ServerViewModels +{ + public class LogsViewModel + { + + public string StatusMessage + { + get; set; + } + + public List LogFiles { get; set; } = new List(); + public string Log { get; set; } + public int LogFileCount { get; set; } + public int LogFileOffset{ get; set; } + } +} diff --git a/BTCPayServer/Models/ServerViewModels/ServicesViewModel.cs b/BTCPayServer/Models/ServerViewModels/ServicesViewModel.cs index 23e9b2911..e103bd6bf 100644 --- a/BTCPayServer/Models/ServerViewModels/ServicesViewModel.cs +++ b/BTCPayServer/Models/ServerViewModels/ServicesViewModel.cs @@ -14,6 +14,7 @@ namespace BTCPayServer.Models.ServerViewModels public LndTypes Type { get; set; } public int Index { get; set; } } + public List LNDServices { get; set; } = new List(); public bool HasSSH { get; set; } } diff --git a/BTCPayServer/Program.cs b/BTCPayServer/Program.cs index 2b1916c9e..0722f8c36 100644 --- a/BTCPayServer/Program.cs +++ b/BTCPayServer/Program.cs @@ -55,18 +55,15 @@ namespace BTCPayServer l.AddProvider(new CustomConsoleLogProvider(processor)); // Use Serilog for debug log file. - string debugLogFile = conf.GetOrDefault("debuglog", null); - if (String.IsNullOrEmpty(debugLogFile) == false) - { - Serilog.Log.Logger = new LoggerConfiguration() + var debugLogFile = BTCPayServerOptions.GetDebugLog(conf); + if (string.IsNullOrEmpty(debugLogFile) != false) return; + Serilog.Log.Logger = new LoggerConfiguration() .Enrich.FromLogContext() - .MinimumLevel.Debug() + .MinimumLevel.Is(BTCPayServerOptions.GetDebugLogLevel(conf)) .WriteTo.File(debugLogFile, rollingInterval: RollingInterval.Day, fileSizeLimitBytes: MAX_DEBUG_LOG_FILE_SIZE, rollOnFileSizeLimit: true, retainedFileCountLimit: 1) .CreateLogger(); - l.AddSerilog(Serilog.Log.Logger); - logger.LogDebug($"Debug log file configured for {debugLogFile}."); - } + l.AddSerilog(Serilog.Log.Logger); }) .UseStartup() .Build(); diff --git a/BTCPayServer/Views/Server/Logs.cshtml b/BTCPayServer/Views/Server/Logs.cshtml new file mode 100644 index 000000000..1771d9d54 --- /dev/null +++ b/BTCPayServer/Views/Server/Logs.cshtml @@ -0,0 +1,40 @@ +@model BTCPayServer.Models.ServerViewModels.LogsViewModel +@{ + ViewData.SetActivePageAndTitle(ServerNavPages.Logs); +} + +

@ViewData["Title"]

+ + +
+
    + @foreach (var file in Model.LogFiles) + { +
  • + @file.Name +
  • + } +
  • + @if (Model.LogFileOffset > 0) + { + << + } + Showing @Model.LogFileOffset - (@Model.LogFileOffset+@Model.LogFiles.Count) of @Model.LogFileCount + @if ((Model.LogFileOffset+ Model.LogFiles.Count) < Model.LogFileCount) + { + >> + } +
  • +
+ @if (!string.IsNullOrEmpty(Model.Log)) + { +
+@Model.Log
+
+ } + +
+ +@section Scripts { + @await Html.PartialAsync("_ValidationScriptsPartial") +} diff --git a/BTCPayServer/Views/Server/ServerNavPages.cs b/BTCPayServer/Views/Server/ServerNavPages.cs index 23d870922..2772c9572 100644 --- a/BTCPayServer/Views/Server/ServerNavPages.cs +++ b/BTCPayServer/Views/Server/ServerNavPages.cs @@ -7,6 +7,6 @@ namespace BTCPayServer.Views.Server { public enum ServerNavPages { - Index, Users, Rates, Emails, Policies, Theme, Hangfire, Services, Maintenance + Index, Users, Rates, Emails, Policies, Theme, Hangfire, Services, Maintenance, Logs } } diff --git a/BTCPayServer/Views/Server/_Nav.cshtml b/BTCPayServer/Views/Server/_Nav.cshtml index 393160976..87a0ca29a 100644 --- a/BTCPayServer/Views/Server/_Nav.cshtml +++ b/BTCPayServer/Views/Server/_Nav.cshtml @@ -6,6 +6,7 @@ Services Theme Maintenance + Logs Hangfire