Plugins: Improve crash detection on startup and hint at disabled plugins (#5514)

This commit is contained in:
d11n 2023-11-28 15:19:47 +01:00 committed by GitHub
parent bac9ab08d1
commit 4023b24209
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 47 additions and 44 deletions

View File

@ -7,6 +7,7 @@
@using BTCPayServer.Client
@using BTCPayServer.Components.ThemeSwitch
@using BTCPayServer.Components.UIExtensionPoint
@using BTCPayServer.Plugins
@using BTCPayServer.Services
@using BTCPayServer.Views.Apps
@using BTCPayServer.Views.CustodianAccounts
@ -15,6 +16,7 @@
@inject SignInManager<ApplicationUser> SignInManager
@inject PoliciesSettings PoliciesSettings
@inject ThemeSettings Theme
@inject PluginService PluginService
@model BTCPayServer.Components.MainNav.MainNavViewModel
@ -185,7 +187,14 @@
<ul class="navbar-nav">
<li class="nav-item" permission="@Policies.CanModifyServerSettings">
<a asp-area="" asp-controller="UIServer" asp-action="ListPlugins" class="nav-link @ViewData.IsActivePage(ServerNavPages.Plugins)" id="Nav-ManagePlugins">
<vc:icon symbol="manage-plugins"/>
@if (PluginService.GetDisabledPlugins().Any())
{
<span class="me-2 btcpay-status btcpay-status--disabled"></span>
}
else
{
<vc:icon symbol="manage-plugins" />
}
<span>Manage Plugins</span>
</a>
</li>

View File

@ -7,6 +7,7 @@ using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Reflection;
using System.Text.RegularExpressions;
using BTCPayServer.Abstractions.Contracts;
using BTCPayServer.Configuration;
using McMaster.NETCore.Plugins;
@ -27,12 +28,16 @@ namespace BTCPayServer.Plugins
public static bool IsExceptionByPlugin(Exception exception, [MaybeNullWhen(false)] out string pluginName)
{
var fromAssembly = exception is TypeLoadException
? Regex.Match(exception.Message, "from assembly '(.*?),").Groups[1].Value
: null;
foreach (var assembly in _pluginAssemblies)
{
var assemblyName = assembly.GetName().Name;
if (assemblyName is null)
continue;
// Comparison is case sensitive as it is theorically possible to have a different plugin
// Comparison is case sensitive as it is theoretically possible to have a different plugin
// with same name but different casing.
if (exception.Source is not null &&
assemblyName.Equals(exception.Source, StringComparison.Ordinal))
@ -45,6 +50,12 @@ namespace BTCPayServer.Plugins
pluginName = assemblyName;
return true;
}
// For TypeLoadException, check if it might come from areferenced assembly
if (!string.IsNullOrEmpty(fromAssembly) && assembly.GetReferencedAssemblies().Select(a => a.Name).Contains(fromAssembly))
{
pluginName = assemblyName;
return true;
}
}
pluginName = null;
return false;

View File

@ -4,6 +4,7 @@ using System.Linq;
using System.Net;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using BTCPayServer.Configuration;
using BTCPayServer.Hosting;
using BTCPayServer.Logging;
@ -19,7 +20,7 @@ namespace BTCPayServer
{
class Program
{
static void Main(string[] args)
static async Task Main(string[] args)
{
if (args.Length > 0 && args[0] == "run")
args = args.Skip(1).ToArray(); // Hack to make dotnet watch work
@ -27,11 +28,11 @@ namespace BTCPayServer
ServicePointManager.DefaultConnectionLimit = 100;
IWebHost host = null;
var processor = new ConsoleLoggerProcessor();
CustomConsoleLogProvider loggerProvider = new CustomConsoleLogProvider(processor);
var loggerProvider = new CustomConsoleLogProvider(processor);
using var loggerFactory = new LoggerFactory();
loggerFactory.AddProvider(loggerProvider);
var logger = loggerFactory.CreateLogger("Configuration");
Logs logs = new Logs();
var logs = new Logs();
logs.Configure(loggerFactory);
IConfiguration conf = null;
try
@ -43,8 +44,6 @@ namespace BTCPayServer
confBuilder.AddJsonFile("appsettings.dev.json", true, false);
#endif
conf = confBuilder.Build();
if (conf == null)
return;
var builder = new WebHostBuilder()
.UseKestrel()
@ -74,14 +73,14 @@ namespace BTCPayServer
builder.UseContentRoot(Directory.GetCurrentDirectory());
}
host = builder.Build();
host.StartWithTasksAsync().GetAwaiter().GetResult();
await host.StartWithTasksAsync();
var urls = host.ServerFeatures.Get<IServerAddressesFeature>().Addresses;
foreach (var url in urls)
{
// Some tools such as dotnet watch parse this exact log to open the browser
logger.LogInformation("Now listening on: " + url);
}
host.WaitForShutdown();
await host.WaitForShutdownAsync();
}
catch (ConfigException ex)
{
@ -99,9 +98,8 @@ namespace BTCPayServer
processor.Dispose();
if (host == null)
logs.Configuration.LogError("Configuration error");
if (host != null)
host.Dispose();
Serilog.Log.CloseAndFlush();
host?.Dispose();
await Serilog.Log.CloseAndFlushAsync();
loggerProvider.Dispose();
}
}

View File

@ -117,9 +117,25 @@
{
<div class="alert alert-danger mb-4 d-flex align-items-center justify-content-between">
Some plugins were disabled due to fatal errors. They may be incompatible with this version of BTCPay Server.
<button class="btn btn-danger" data-bs-toggle="collapse" data-bs-target="#disabled-plugins">View disabled plugins</button>
</div>
<div class="mb-5">
<h3 class="mb-4">Disabled Plugins</h3>
<ul class="list-group list-group-flush d-inline-block">
@foreach (var d in Model.Disabled)
{
<li class="list-group-item px-0">
<div class="d-flex flex-wrap align-items-center justify-content-between gap-3">
<span>@d</span>
<form asp-action="UnInstallPlugin" asp-route-plugin="@d">
<button type="submit" class="btn btn-sm btn-outline-danger">Uninstall</button>
</form>
</div>
</li>
}
</ul>
</div>
}
@if (Model.Commands.Any())
{
<div class="alert alert-info mb-4 d-flex align-items-center justify-content-between">
@ -477,34 +493,3 @@
</div>
</div>
}
@if (Model.Disabled.Any())
{
<div class="mb-4">
<h3 class="mb-4">Disabled Plugins</h3>
<button class="btn btn-secondary mb-4" type="button" data-bs-toggle="collapse" data-bs-target="#disabled-plugins">
Disabled Plugins
</button>
<div class="row collapse" id="disabled-plugins">
<div class="col col-12 col-lg-6 mb-4">
<div class="card">
<div class="card-body">
<h4 class="card-title">Disabled plugins</h4>
<ul class="list-group list-group-flush">
@foreach (var d in Model.Disabled)
{
<li class="list-group-item px-0">
<div class="d-flex flex-wrap align-items-center justify-content-between mx-3">
<span class="my-2 me-3">@d</span>
<form asp-action="UnInstallPlugin" asp-route-plugin="@d">
<button type="submit" class="btn btn-outline-secondary">Uninstall</button>
</form>
</div>
</li>
}
</ul>
</div>
</div>
</div>
</div>
</div>
}