mirror of
https://github.com/Sonarr/Sonarr.git
synced 2026-03-05 13:20:20 -05:00
Optionally show mini profiler
This commit is contained in:
@@ -58,6 +58,8 @@
|
||||
};
|
||||
</script>
|
||||
|
||||
__MINI_PROFILER__
|
||||
|
||||
<% for (key in htmlWebpackPlugin.files.js) { %><script type="text/javascript" src="<%= htmlWebpackPlugin.files.js[key] %>" data-no-hash></script><% } %>
|
||||
<% for (key in htmlWebpackPlugin.files.css) { %><link href="<%= htmlWebpackPlugin.files.css[key] %>" rel="stylesheet"></link><% } %>
|
||||
|
||||
|
||||
@@ -5,4 +5,6 @@ public class AppOptions
|
||||
public string InstanceName { get; set; }
|
||||
public string Theme { get; set; }
|
||||
public bool? LaunchBrowser { get; set; }
|
||||
public bool? ProfilerEnabled { get; set; }
|
||||
public string ProfilerPosition { get; set; }
|
||||
}
|
||||
|
||||
@@ -69,6 +69,8 @@ namespace NzbDrone.Core.Configuration
|
||||
string PostgresMainDbConnectionString { get; }
|
||||
string PostgresLogDbConnectionString { get; }
|
||||
bool TrustCgnatIpAddresses { get; }
|
||||
bool ProfilerEnabled { get; }
|
||||
string ProfilerPosition { get; }
|
||||
}
|
||||
|
||||
public class ConfigFileProvider : IConfigFileProvider
|
||||
@@ -234,6 +236,8 @@ namespace NzbDrone.Core.Configuration
|
||||
? enumValue
|
||||
: GetValueEnum("AuthenticationRequired", AuthenticationRequiredType.Enabled);
|
||||
|
||||
public bool TrustCgnatIpAddresses => _authOptions.TrustCgnatIpAddresses ?? GetValueBoolean("TrustCgnatIpAddresses", false, persist: false);
|
||||
|
||||
public bool AnalyticsEnabled => _logOptions.AnalyticsEnabled ?? GetValueBoolean("AnalyticsEnabled", true, persist: false);
|
||||
|
||||
public string Branch => _updateOptions.Branch ?? GetValue("Branch", "main").ToLowerInvariant();
|
||||
@@ -312,6 +316,9 @@ namespace NzbDrone.Core.Configuration
|
||||
|
||||
public string SyslogLevel => _logOptions.SyslogLevel ?? GetValue("SyslogLevel", LogLevel, persist: false).ToLowerInvariant();
|
||||
|
||||
public bool ProfilerEnabled => _appOptions.ProfilerEnabled ?? GetValueBoolean("ProfilerEnabled", false, persist: false);
|
||||
public string ProfilerPosition => _appOptions.ProfilerPosition ?? GetValue("ProfilerPosition", "bottom-right", persist: false);
|
||||
|
||||
public int GetValueInt(string key, int defaultValue, bool persist = true)
|
||||
{
|
||||
return Convert.ToInt32(GetValue(key, defaultValue, persist));
|
||||
@@ -499,7 +506,5 @@ namespace NzbDrone.Core.Configuration
|
||||
{
|
||||
SetValue("ApiKey", GenerateApiKey());
|
||||
}
|
||||
|
||||
public bool TrustCgnatIpAddresses => _authOptions.TrustCgnatIpAddresses ?? GetValueBoolean("TrustCgnatIpAddresses", false, persist: false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.Data;
|
||||
using System.Data.Common;
|
||||
using System.Data.SQLite;
|
||||
using Dapper;
|
||||
@@ -10,7 +9,7 @@ namespace NzbDrone.Core.Datastore
|
||||
{
|
||||
public interface IDatabase
|
||||
{
|
||||
IDbConnection OpenConnection();
|
||||
DbConnection OpenConnection();
|
||||
Version Version { get; }
|
||||
int Migration { get; }
|
||||
DatabaseType DatabaseType { get; }
|
||||
@@ -20,17 +19,17 @@ namespace NzbDrone.Core.Datastore
|
||||
public class Database : IDatabase
|
||||
{
|
||||
private readonly string _databaseName;
|
||||
private readonly Func<IDbConnection> _datamapperFactory;
|
||||
private readonly Func<DbConnection> _datamapperFactory;
|
||||
|
||||
private readonly Logger _logger = NzbDroneLogger.GetLogger(typeof(Database));
|
||||
|
||||
public Database(string databaseName, Func<IDbConnection> datamapperFactory)
|
||||
public Database(string databaseName, Func<DbConnection> datamapperFactory)
|
||||
{
|
||||
_databaseName = databaseName;
|
||||
_datamapperFactory = datamapperFactory;
|
||||
}
|
||||
|
||||
public IDbConnection OpenConnection()
|
||||
public DbConnection OpenConnection()
|
||||
{
|
||||
return _datamapperFactory();
|
||||
}
|
||||
@@ -50,7 +49,7 @@ namespace NzbDrone.Core.Datastore
|
||||
get
|
||||
{
|
||||
using var db = _datamapperFactory();
|
||||
var dbConnection = db as DbConnection;
|
||||
var dbConnection = db;
|
||||
|
||||
return DatabaseVersionParser.ParseServerVersion(dbConnection.ServerVersion);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
using System;
|
||||
using System.Data;
|
||||
using System.Data.Common;
|
||||
|
||||
namespace NzbDrone.Core.Datastore
|
||||
{
|
||||
@@ -18,7 +18,7 @@ namespace NzbDrone.Core.Datastore
|
||||
_databaseType = _database == null ? DatabaseType.SQLite : _database.DatabaseType;
|
||||
}
|
||||
|
||||
public IDbConnection OpenConnection()
|
||||
public DbConnection OpenConnection()
|
||||
{
|
||||
return _database.OpenConnection();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
using System;
|
||||
using System.Data;
|
||||
using System.Data.Common;
|
||||
using StackExchange.Profiling;
|
||||
using StackExchange.Profiling.Data;
|
||||
|
||||
namespace NzbDrone.Core.Datastore
|
||||
{
|
||||
@@ -18,9 +20,16 @@ namespace NzbDrone.Core.Datastore
|
||||
_databaseType = _database == null ? DatabaseType.SQLite : _database.DatabaseType;
|
||||
}
|
||||
|
||||
public IDbConnection OpenConnection()
|
||||
public DbConnection OpenConnection()
|
||||
{
|
||||
return _database.OpenConnection();
|
||||
var connection = _database.OpenConnection();
|
||||
|
||||
if (_databaseType == DatabaseType.PostgreSQL)
|
||||
{
|
||||
return new ProfiledImplementations.NpgSqlConnection(connection, MiniProfiler.Current);
|
||||
}
|
||||
|
||||
return new ProfiledDbConnection(connection, MiniProfiler.Current);
|
||||
}
|
||||
|
||||
public Version Version => _database.Version;
|
||||
|
||||
15
src/NzbDrone.Core/Datastore/ProfiledImplementations.cs
Normal file
15
src/NzbDrone.Core/Datastore/ProfiledImplementations.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using System.Data.Common;
|
||||
using StackExchange.Profiling.Data;
|
||||
|
||||
namespace NzbDrone.Core.Datastore;
|
||||
|
||||
public static class ProfiledImplementations
|
||||
{
|
||||
public class NpgSqlConnection : ProfiledDbConnection
|
||||
{
|
||||
public NpgSqlConnection(DbConnection connection, IDbProfiler profiler)
|
||||
: base(connection, profiler)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,7 @@
|
||||
<PackageReference Include="MailKit" Version="4.14.1" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Cryptography.KeyDerivation" Version="10.0.1" />
|
||||
<PackageReference Include="Microsoft.Data.SqlClient" Version="6.1.3" />
|
||||
<PackageReference Include="MiniProfiler.AspNetCore" Version="4.5.4" />
|
||||
<PackageReference Include="Openur.FFMpegCore" Version="5.4.0.31" />
|
||||
<PackageReference Include="Openur.FFprobeStatic" Version="8.0.1.289" />
|
||||
<PackageReference Include="Polly" Version="8.6.5" />
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
<OutputType>Library</OutputType>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="MiniProfiler.AspNetCore.Mvc" Version="4.5.4" />
|
||||
<PackageReference Include="NLog.Extensions.Logging" Version="5.5.0" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerGen" Version="10.1.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="10.0.1" />
|
||||
|
||||
@@ -3,6 +3,7 @@ using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Threading.Tasks;
|
||||
using DryIoc;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
@@ -35,6 +36,7 @@ using Sonarr.Http.ClientSchema;
|
||||
using Sonarr.Http.ErrorManagement;
|
||||
using Sonarr.Http.Frontend;
|
||||
using Sonarr.Http.Middleware;
|
||||
using StackExchange.Profiling;
|
||||
using IPNetwork = System.Net.IPNetwork;
|
||||
using LogLevel = Microsoft.Extensions.Logging.LogLevel;
|
||||
|
||||
@@ -236,6 +238,45 @@ namespace NzbDrone.Host
|
||||
});
|
||||
|
||||
services.AddAppAuthentication();
|
||||
|
||||
services.AddOptions<MiniProfilerOptions>()
|
||||
.Configure<IConfigFileProvider>((options, configFileProvider) =>
|
||||
{
|
||||
options.RouteBasePath = "/profiler";
|
||||
|
||||
switch (configFileProvider.Theme)
|
||||
{
|
||||
case "light":
|
||||
options.ColorScheme = ColorScheme.Light;
|
||||
break;
|
||||
case "dark":
|
||||
options.ColorScheme = ColorScheme.Dark;
|
||||
break;
|
||||
default:
|
||||
options.ColorScheme = ColorScheme.Auto;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (configFileProvider.ProfilerPosition)
|
||||
{
|
||||
case "top-left":
|
||||
options.PopupRenderPosition = RenderPosition.Left;
|
||||
break;
|
||||
case "top-right":
|
||||
options.PopupRenderPosition = RenderPosition.Right;
|
||||
break;
|
||||
case "bottom-left":
|
||||
options.PopupRenderPosition = RenderPosition.BottomLeft;
|
||||
break;
|
||||
default:
|
||||
options.PopupRenderPosition = RenderPosition.BottomRight;
|
||||
break;
|
||||
}
|
||||
|
||||
options.IgnoredPaths.Add("/MediaCover");
|
||||
});
|
||||
|
||||
services.AddMiniProfiler();
|
||||
}
|
||||
|
||||
public void Configure(IApplicationBuilder app,
|
||||
@@ -312,6 +353,7 @@ namespace NzbDrone.Host
|
||||
app.UseMiddleware<BufferingMiddleware>(new List<string> { "/api/v3/command", "/api/v5/command" });
|
||||
|
||||
app.UseWebSockets();
|
||||
app.UseMiniProfiler();
|
||||
|
||||
// Enable middleware to serve generated Swagger as a JSON endpoint.
|
||||
if (BuildInfo.IsDebug)
|
||||
@@ -325,6 +367,7 @@ namespace NzbDrone.Host
|
||||
app.UseEndpoints(x =>
|
||||
{
|
||||
x.MapHub<MessageHub>("/signalr/messages").RequireAuthorization("SignalR");
|
||||
x.MapPost("/profiler/results", context => Task.CompletedTask).RequireAuthorization("UI");
|
||||
x.MapControllers();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text.RegularExpressions;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using NLog;
|
||||
using NzbDrone.Common.Disk;
|
||||
using NzbDrone.Common.EnvironmentInfo;
|
||||
@@ -27,9 +28,9 @@ namespace Sonarr.Http.Frontend.Mappers
|
||||
protected string HtmlPath;
|
||||
protected string UrlBase;
|
||||
|
||||
protected override Stream GetContentStream(string filePath)
|
||||
protected override Stream GetContentStream(HttpContext context, string filePath)
|
||||
{
|
||||
var text = GetHtmlText();
|
||||
var text = GetHtmlText(context);
|
||||
|
||||
var stream = new MemoryStream();
|
||||
var writer = new StreamWriter(stream);
|
||||
@@ -39,7 +40,7 @@ namespace Sonarr.Http.Frontend.Mappers
|
||||
return stream;
|
||||
}
|
||||
|
||||
protected virtual string GetHtmlText()
|
||||
protected virtual string GetHtmlText(HttpContext context)
|
||||
{
|
||||
if (RuntimeInfo.IsProduction && _generatedContent != null)
|
||||
{
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace Sonarr.Http.Frontend.Mappers
|
||||
@@ -7,6 +8,6 @@ namespace Sonarr.Http.Frontend.Mappers
|
||||
{
|
||||
string Map(string resourceUrl);
|
||||
bool CanHandle(string resourceUrl);
|
||||
Task<IActionResult> GetResponse(string resourceUrl);
|
||||
Task<IActionResult> GetResponse(HttpContext context, string resourceUrl);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using NLog;
|
||||
using NzbDrone.Common.Disk;
|
||||
using NzbDrone.Common.EnvironmentInfo;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.Configuration;
|
||||
using StackExchange.Profiling;
|
||||
|
||||
namespace Sonarr.Http.Frontend.Mappers
|
||||
{
|
||||
@@ -38,5 +41,30 @@ namespace Sonarr.Http.Frontend.Mappers
|
||||
!resourceUrl.Contains('.') &&
|
||||
!resourceUrl.StartsWith("/login");
|
||||
}
|
||||
|
||||
protected override string GetHtmlText(HttpContext context)
|
||||
{
|
||||
var html = base.GetHtmlText(context);
|
||||
|
||||
if (_configFileProvider.ProfilerEnabled)
|
||||
{
|
||||
var includes = MiniProfiler.Current?.RenderIncludes(context);
|
||||
|
||||
if (includes == null || includes.Value.IsNullOrWhiteSpace())
|
||||
{
|
||||
html = html.Replace("__MINI_PROFILER__", "");
|
||||
}
|
||||
else
|
||||
{
|
||||
html = html.Replace("__MINI_PROFILER__", includes.Value);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
html = html.Replace("__MINI_PROFILER__", "");
|
||||
}
|
||||
|
||||
return html;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using NLog;
|
||||
using NzbDrone.Common.Disk;
|
||||
using NzbDrone.Common.EnvironmentInfo;
|
||||
@@ -33,9 +34,9 @@ namespace Sonarr.Http.Frontend.Mappers
|
||||
return resourceUrl.StartsWith("/login");
|
||||
}
|
||||
|
||||
protected override string GetHtmlText()
|
||||
protected override string GetHtmlText(HttpContext context)
|
||||
{
|
||||
var html = base.GetHtmlText();
|
||||
var html = base.GetHtmlText(context);
|
||||
var theme = _configFileProvider.Theme;
|
||||
|
||||
html = html.Replace("_THEME_", theme);
|
||||
|
||||
@@ -2,6 +2,7 @@ using System;
|
||||
using System.Net;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.StaticFiles;
|
||||
using NzbDrone.Core.MediaCover;
|
||||
@@ -31,7 +32,7 @@ namespace Sonarr.Http.Frontend.Mappers
|
||||
return resourceUrl.StartsWith("/MediaCoverProxy/", StringComparison.InvariantCultureIgnoreCase);
|
||||
}
|
||||
|
||||
public async Task<IActionResult> GetResponse(string resourceUrl)
|
||||
public async Task<IActionResult> GetResponse(HttpContext context, string resourceUrl)
|
||||
{
|
||||
var match = _regex.Match(resourceUrl);
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.StaticFiles;
|
||||
using Microsoft.Net.Http.Headers;
|
||||
@@ -31,7 +32,7 @@ namespace Sonarr.Http.Frontend.Mappers
|
||||
|
||||
public abstract bool CanHandle(string resourceUrl);
|
||||
|
||||
public Task<IActionResult> GetResponse(string resourceUrl)
|
||||
public Task<IActionResult> GetResponse(HttpContext context, string resourceUrl)
|
||||
{
|
||||
var filePath = Map(resourceUrl);
|
||||
|
||||
@@ -42,7 +43,7 @@ namespace Sonarr.Http.Frontend.Mappers
|
||||
contentType = "application/octet-stream";
|
||||
}
|
||||
|
||||
return Task.FromResult<IActionResult>(new FileStreamResult(GetContentStream(filePath), new MediaTypeHeaderValue(contentType)
|
||||
return Task.FromResult<IActionResult>(new FileStreamResult(GetContentStream(context, filePath), new MediaTypeHeaderValue(contentType)
|
||||
{
|
||||
Encoding = contentType == "text/plain" ? Encoding.UTF8 : null
|
||||
}));
|
||||
@@ -53,7 +54,7 @@ namespace Sonarr.Http.Frontend.Mappers
|
||||
return Task.FromResult<IActionResult>(null);
|
||||
}
|
||||
|
||||
protected virtual Stream GetContentStream(string filePath)
|
||||
protected virtual Stream GetContentStream(HttpContext context, string filePath)
|
||||
{
|
||||
return File.OpenRead(filePath);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.IO;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using NLog;
|
||||
using NzbDrone.Common.Disk;
|
||||
using NzbDrone.Common.EnvironmentInfo;
|
||||
@@ -27,7 +28,7 @@ namespace Sonarr.Http.Frontend.Mappers
|
||||
return FilePath;
|
||||
}
|
||||
|
||||
protected override Stream GetContentStream(string filePath)
|
||||
protected override Stream GetContentStream(HttpContext context, string filePath)
|
||||
{
|
||||
var text = GetFileText();
|
||||
|
||||
|
||||
@@ -54,7 +54,7 @@ namespace Sonarr.Http.Frontend
|
||||
|
||||
if (mapper != null)
|
||||
{
|
||||
var result = await mapper.GetResponse(path);
|
||||
var result = await mapper.GetResponse(Request.HttpContext, path);
|
||||
|
||||
if (result != null)
|
||||
{
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
<ItemGroup>
|
||||
<PackageReference Include="FluentValidation" Version="9.5.4" />
|
||||
<PackageReference Include="ImpromptuInterface" Version="8.0.6" />
|
||||
<PackageReference Include="MiniProfiler.AspNetCore" Version="4.5.4" />
|
||||
<PackageReference Include="NLog" Version="5.5.1" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
||||
Reference in New Issue
Block a user