Merge pull request #76 from Moonlight-Panel/SqlLoggingAndOptimisations
Optimized allocation search. Added sql command log interception
This commit is contained in:
commit
7921e9a525
|
@ -2,6 +2,7 @@
|
||||||
using Moonlight.App.Database.Entities;
|
using Moonlight.App.Database.Entities;
|
||||||
using Moonlight.App.Database.Entities.LogsEntries;
|
using Moonlight.App.Database.Entities.LogsEntries;
|
||||||
using Moonlight.App.Database.Entities.Notification;
|
using Moonlight.App.Database.Entities.Notification;
|
||||||
|
using Moonlight.App.Database.Interceptors;
|
||||||
using Moonlight.App.Models.Misc;
|
using Moonlight.App.Models.Misc;
|
||||||
using Moonlight.App.Services;
|
using Moonlight.App.Services;
|
||||||
|
|
||||||
|
@ -65,6 +66,9 @@ public class DataContext : DbContext
|
||||||
builder.EnableRetryOnFailure(5);
|
builder.EnableRetryOnFailure(5);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if(ConfigService.SqlDebugMode)
|
||||||
|
optionsBuilder.AddInterceptors(new SqlLoggingInterceptor());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
40
Moonlight/App/Database/Interceptors/SqlLoggingInterceptor.cs
Normal file
40
Moonlight/App/Database/Interceptors/SqlLoggingInterceptor.cs
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
using System.Data.Common;
|
||||||
|
using Logging.Net;
|
||||||
|
using Microsoft.EntityFrameworkCore.Diagnostics;
|
||||||
|
|
||||||
|
namespace Moonlight.App.Database.Interceptors;
|
||||||
|
|
||||||
|
public class SqlLoggingInterceptor : DbCommandInterceptor
|
||||||
|
{
|
||||||
|
public override InterceptionResult<DbDataReader> ReaderExecuting(
|
||||||
|
DbCommand command,
|
||||||
|
CommandEventData eventData,
|
||||||
|
InterceptionResult<DbDataReader> result)
|
||||||
|
{
|
||||||
|
LogSql(command.CommandText);
|
||||||
|
return base.ReaderExecuting(command, eventData, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override InterceptionResult<object> ScalarExecuting(
|
||||||
|
DbCommand command,
|
||||||
|
CommandEventData eventData,
|
||||||
|
InterceptionResult<object> result)
|
||||||
|
{
|
||||||
|
LogSql(command.CommandText);
|
||||||
|
return base.ScalarExecuting(command, eventData, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override InterceptionResult<int> NonQueryExecuting(
|
||||||
|
DbCommand command,
|
||||||
|
CommandEventData eventData,
|
||||||
|
InterceptionResult<int> result)
|
||||||
|
{
|
||||||
|
LogSql(command.CommandText);
|
||||||
|
return base.NonQueryExecuting(command, eventData, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void LogSql(string sql)
|
||||||
|
{
|
||||||
|
Logger.Info($"[SQL DEBUG] {sql.Replace("\n", "")}");
|
||||||
|
}
|
||||||
|
}
|
28
Moonlight/App/Repositories/NodeAllocationRepository.cs
Normal file
28
Moonlight/App/Repositories/NodeAllocationRepository.cs
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Moonlight.App.Database;
|
||||||
|
using Moonlight.App.Database.Entities;
|
||||||
|
|
||||||
|
namespace Moonlight.App.Repositories;
|
||||||
|
|
||||||
|
public class NodeAllocationRepository : IDisposable
|
||||||
|
{
|
||||||
|
// This repository is ONLY for the server creation service, so allocations can be found
|
||||||
|
// using raw sql. DO NOT use this in any other component
|
||||||
|
|
||||||
|
private readonly DataContext DataContext;
|
||||||
|
|
||||||
|
public NodeAllocationRepository(DataContext dataContext)
|
||||||
|
{
|
||||||
|
DataContext = dataContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DbSet<NodeAllocation> Get()
|
||||||
|
{
|
||||||
|
return DataContext.NodeAllocations;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
DataContext.Dispose();
|
||||||
|
}
|
||||||
|
}
|
|
@ -12,6 +12,7 @@ public class ConfigService : IConfiguration
|
||||||
private IConfiguration Configuration;
|
private IConfiguration Configuration;
|
||||||
|
|
||||||
public bool DebugMode { get; private set; } = false;
|
public bool DebugMode { get; private set; } = false;
|
||||||
|
public bool SqlDebugMode { get; private set; } = false;
|
||||||
|
|
||||||
public ConfigService(StorageService storageService)
|
public ConfigService(StorageService storageService)
|
||||||
{
|
{
|
||||||
|
@ -28,6 +29,14 @@ public class ConfigService : IConfiguration
|
||||||
|
|
||||||
if (DebugMode)
|
if (DebugMode)
|
||||||
Logger.Debug("Debug mode enabled");
|
Logger.Debug("Debug mode enabled");
|
||||||
|
|
||||||
|
var sqlDebugVar = Environment.GetEnvironmentVariable("ML_SQL_DEBUG");
|
||||||
|
|
||||||
|
if (sqlDebugVar != null)
|
||||||
|
SqlDebugMode = bool.Parse(sqlDebugVar);
|
||||||
|
|
||||||
|
if (SqlDebugMode)
|
||||||
|
Logger.Debug("Sql debug mode enabled");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Reload()
|
public void Reload()
|
||||||
|
|
|
@ -21,6 +21,7 @@ public class ServerService
|
||||||
private readonly UserRepository UserRepository;
|
private readonly UserRepository UserRepository;
|
||||||
private readonly ImageRepository ImageRepository;
|
private readonly ImageRepository ImageRepository;
|
||||||
private readonly NodeRepository NodeRepository;
|
private readonly NodeRepository NodeRepository;
|
||||||
|
private readonly NodeAllocationRepository NodeAllocationRepository;
|
||||||
private readonly WingsApiHelper WingsApiHelper;
|
private readonly WingsApiHelper WingsApiHelper;
|
||||||
private readonly MessageService MessageService;
|
private readonly MessageService MessageService;
|
||||||
private readonly UserService UserService;
|
private readonly UserService UserService;
|
||||||
|
@ -44,7 +45,8 @@ public class ServerService
|
||||||
SecurityLogService securityLogService,
|
SecurityLogService securityLogService,
|
||||||
AuditLogService auditLogService,
|
AuditLogService auditLogService,
|
||||||
ErrorLogService errorLogService,
|
ErrorLogService errorLogService,
|
||||||
NodeService nodeService)
|
NodeService nodeService,
|
||||||
|
NodeAllocationRepository nodeAllocationRepository)
|
||||||
{
|
{
|
||||||
ServerRepository = serverRepository;
|
ServerRepository = serverRepository;
|
||||||
WingsApiHelper = wingsApiHelper;
|
WingsApiHelper = wingsApiHelper;
|
||||||
|
@ -59,6 +61,7 @@ public class ServerService
|
||||||
AuditLogService = auditLogService;
|
AuditLogService = auditLogService;
|
||||||
ErrorLogService = errorLogService;
|
ErrorLogService = errorLogService;
|
||||||
NodeService = nodeService;
|
NodeService = nodeService;
|
||||||
|
NodeAllocationRepository = nodeAllocationRepository;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Server EnsureNodeData(Server s)
|
private Server EnsureNodeData(Server s)
|
||||||
|
@ -268,32 +271,19 @@ public class ServerService
|
||||||
.Include(x => x.DockerImages)
|
.Include(x => x.DockerImages)
|
||||||
.First(x => x.Id == i.Id);
|
.First(x => x.Id == i.Id);
|
||||||
|
|
||||||
Node node;
|
Node node = n ?? NodeRepository.Get().First();
|
||||||
|
|
||||||
if (n == null)
|
|
||||||
{
|
|
||||||
node = NodeRepository
|
|
||||||
.Get()
|
|
||||||
.Include(x => x.Allocations)
|
|
||||||
.First(); //TODO: Add smart deploy maybe
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
node = NodeRepository
|
|
||||||
.Get()
|
|
||||||
.Include(x => x.Allocations)
|
|
||||||
.First(x => x.Id == n.Id);
|
|
||||||
}
|
|
||||||
|
|
||||||
NodeAllocation[] freeAllocations;
|
NodeAllocation[] freeAllocations;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
freeAllocations = node.Allocations
|
// We have sadly no choice to use entity framework to do what the sql call does, there
|
||||||
.Where(a => !ServerRepository.Get()
|
// are only slower ways, so we will use a raw sql call as a exception
|
||||||
.SelectMany(s => s.Allocations)
|
|
||||||
.Any(b => b.Id == a.Id))
|
freeAllocations = NodeAllocationRepository
|
||||||
.Take(allocations).ToArray();
|
.Get()
|
||||||
|
.FromSqlRaw($"SELECT * FROM `NodeAllocations` WHERE ServerId IS NULL AND NodeId={node.Id} LIMIT {allocations}")
|
||||||
|
.ToArray();
|
||||||
}
|
}
|
||||||
catch (Exception)
|
catch (Exception)
|
||||||
{
|
{
|
||||||
|
|
|
@ -89,7 +89,7 @@ public class SubscriptionService
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<SubscriptionLimit> GetLimit(string identifier)
|
public async Task<SubscriptionLimit> GetLimit(string identifier) // Cache, optimize sql code
|
||||||
{
|
{
|
||||||
var subscription = await GetCurrent();
|
var subscription = await GetCurrent();
|
||||||
var defaultLimits = await GetDefaultLimits();
|
var defaultLimits = await GetDefaultLimits();
|
||||||
|
|
|
@ -71,9 +71,8 @@ namespace Moonlight
|
||||||
builder.Services.AddScoped<WebsiteRepository>();
|
builder.Services.AddScoped<WebsiteRepository>();
|
||||||
builder.Services.AddScoped<LoadingMessageRepository>();
|
builder.Services.AddScoped<LoadingMessageRepository>();
|
||||||
builder.Services.AddScoped<NewsEntryRepository>();
|
builder.Services.AddScoped<NewsEntryRepository>();
|
||||||
|
builder.Services.AddScoped<NodeAllocationRepository>();
|
||||||
builder.Services.AddScoped<StatisticsRepository>();
|
builder.Services.AddScoped<StatisticsRepository>();
|
||||||
|
|
||||||
builder.Services.AddScoped<AuditLogEntryRepository>();
|
builder.Services.AddScoped<AuditLogEntryRepository>();
|
||||||
builder.Services.AddScoped<ErrorLogEntryRepository>();
|
builder.Services.AddScoped<ErrorLogEntryRepository>();
|
||||||
builder.Services.AddScoped<SecurityLogEntryRepository>();
|
builder.Services.AddScoped<SecurityLogEntryRepository>();
|
||||||
|
|
|
@ -17,12 +17,15 @@
|
||||||
"applicationUrl": "http://moonlight.testy:5118;https://localhost:7118;http://localhost:5118",
|
"applicationUrl": "http://moonlight.testy:5118;https://localhost:7118;http://localhost:5118",
|
||||||
"dotnetRunMessages": true
|
"dotnetRunMessages": true
|
||||||
},
|
},
|
||||||
"IIS Express": {
|
"Sql Debug": {
|
||||||
"commandName": "IISExpress",
|
"commandName": "Project",
|
||||||
"launchBrowser": true,
|
"launchBrowser": true,
|
||||||
"environmentVariables": {
|
"environmentVariables": {
|
||||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
"ASPNETCORE_ENVIRONMENT": "Development",
|
||||||
}
|
"ML_SQL_DEBUG": "true"
|
||||||
|
},
|
||||||
|
"applicationUrl": "http://moonlight.testy:5118;https://localhost:7118;http://localhost:5118",
|
||||||
|
"dotnetRunMessages": true
|
||||||
},
|
},
|
||||||
"Docker": {
|
"Docker": {
|
||||||
"commandName": "Docker",
|
"commandName": "Docker",
|
||||||
|
|
|
@ -103,6 +103,7 @@
|
||||||
.Include(x => x.Node)
|
.Include(x => x.Node)
|
||||||
.Include(x => x.Image)
|
.Include(x => x.Image)
|
||||||
.Where(x => x.Owner.Id == User.Id)
|
.Where(x => x.Owner.Id == User.Id)
|
||||||
|
.OrderBy(x => x.Name)
|
||||||
.ToArray();
|
.ToArray();
|
||||||
|
|
||||||
foreach (var server in AllServers)
|
foreach (var server in AllServers)
|
||||||
|
|
Loading…
Reference in a new issue