Functional server start/stop with log output
This commit is contained in:
parent
c618e05cf0
commit
8f1b013c0a
10 changed files with 231 additions and 9 deletions
|
@ -2,13 +2,13 @@
|
|||
{
|
||||
public class Server : BaseModel
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public string Path { get; set; }
|
||||
public string Arguments { get; set; }
|
||||
public string WorkingDirectory { get; set; }
|
||||
|
||||
public string OnStartScriptPath { get; set; }
|
||||
public string OnStopScriptPath { get; set; }
|
||||
public string Name { get; set; } = "";
|
||||
public string Path { get; set; } = "";
|
||||
public string Arguments { get; set; } = "";
|
||||
public string WorkingDirectory { get; set; } = "";
|
||||
|
||||
public string OnStartScriptPath { get; set; } = "";
|
||||
public string OnStopScriptPath { get; set; } = "";
|
||||
|
||||
public bool Autostart { get; set; }
|
||||
}
|
||||
|
|
12
LANCommander/Hubs/LoggingHub.cs
Normal file
12
LANCommander/Hubs/LoggingHub.cs
Normal file
|
@ -0,0 +1,12 @@
|
|||
using Microsoft.AspNetCore.SignalR;
|
||||
|
||||
namespace LANCommander.Hubs
|
||||
{
|
||||
public class LoggingHub : Hub
|
||||
{
|
||||
public void Log(string logMessage)
|
||||
{
|
||||
Clients.All.SendAsync("Log", logMessage);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -21,6 +21,7 @@
|
|||
<PackageReference Include="Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore" Version="7.0.4" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="7.0.4" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Identity.UI" Version="7.0.4" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="7.0.5" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Proxies" Version="7.0.4" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="7.0.4" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="7.0.4" />
|
||||
|
@ -34,6 +35,8 @@
|
|||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.17.0" />
|
||||
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="7.0.5" />
|
||||
<PackageReference Include="NLog" Version="5.1.3" />
|
||||
<PackageReference Include="NLog.Web.AspNetCore" Version="5.2.3" />
|
||||
<PackageReference Include="rix0rrr.BeaconLib" Version="1.0.2" />
|
||||
<PackageReference Include="swashbuckle" Version="5.6.0" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
|
||||
|
|
59
LANCommander/Logging/LoggingHubConnection.cs
Normal file
59
LANCommander/Logging/LoggingHubConnection.cs
Normal file
|
@ -0,0 +1,59 @@
|
|||
using Microsoft.AspNetCore.SignalR.Client;
|
||||
|
||||
namespace LANCommander.Logging
|
||||
{
|
||||
public class LoggingHubConnection : IAsyncDisposable
|
||||
{
|
||||
private HubConnection? HubConnection;
|
||||
private string HubUrl;
|
||||
|
||||
public LoggingHubConnection(string hubUrl)
|
||||
{
|
||||
HubUrl = hubUrl;
|
||||
}
|
||||
|
||||
public async Task Log(string logMessage)
|
||||
{
|
||||
await EnsureConnection();
|
||||
|
||||
if (HubConnection != null)
|
||||
await HubConnection.SendAsync("Log", logMessage);
|
||||
}
|
||||
|
||||
public async Task EnsureConnection()
|
||||
{
|
||||
if (HubConnection == null)
|
||||
{
|
||||
HubConnection = new HubConnectionBuilder()
|
||||
.WithUrl(HubUrl)
|
||||
.Build();
|
||||
|
||||
await HubConnection.StartAsync();
|
||||
}
|
||||
else if (HubConnection.State == HubConnectionState.Disconnected)
|
||||
{
|
||||
await HubConnection.StartAsync();
|
||||
}
|
||||
}
|
||||
|
||||
public async ValueTask DisposeAsync()
|
||||
{
|
||||
if (HubConnection != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
await HubConnection.StopAsync();
|
||||
await HubConnection.DisposeAsync();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
NLog.Common.InternalLogger.Error(ex, "Exception in LoggingHubConnection.DisposeAsync");
|
||||
}
|
||||
finally
|
||||
{
|
||||
HubConnection = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
37
LANCommander/Logging/LoggingHubTarget.cs
Normal file
37
LANCommander/Logging/LoggingHubTarget.cs
Normal file
|
@ -0,0 +1,37 @@
|
|||
using NLog;
|
||||
using NLog.Config;
|
||||
using NLog.Targets;
|
||||
|
||||
namespace LANCommander.Logging
|
||||
{
|
||||
[Target("LoggingHub")]
|
||||
public class LoggingHubTarget : AsyncTaskTarget
|
||||
{
|
||||
private LoggingHubConnection? Connection;
|
||||
|
||||
[RequiredParameter]
|
||||
public string HubUrl { get; set; }
|
||||
|
||||
protected override void InitializeTarget()
|
||||
{
|
||||
Connection = new LoggingHubConnection(HubUrl);
|
||||
}
|
||||
|
||||
protected override async Task WriteAsyncTask(LogEventInfo logEvent, CancellationToken token)
|
||||
{
|
||||
string message = Layout.Render(logEvent);
|
||||
|
||||
if (Connection != null)
|
||||
await Connection.Log(message);
|
||||
}
|
||||
|
||||
protected override async void CloseTarget()
|
||||
{
|
||||
if (Connection != null)
|
||||
{
|
||||
await Connection.DisposeAsync();
|
||||
Connection = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -24,6 +24,7 @@
|
|||
<Space Direction="DirectionVHType.Horizontal">
|
||||
<SpaceItem>
|
||||
<Button OnClick="() => Edit(context)">Edit</Button>
|
||||
<Button OnClick="() => Logs(context)">Logs</Button>
|
||||
<Button OnClick="() => Start(context)">Start</Button>
|
||||
<Button OnClick="() => Stop(context)">Stop</Button>
|
||||
</SpaceItem>
|
||||
|
@ -63,6 +64,11 @@
|
|||
NavigationManager.NavigateTo($"/Servers/{server.Id}/Edit");
|
||||
}
|
||||
|
||||
private void Logs(Server server)
|
||||
{
|
||||
NavigationManager.NavigateTo($"/Servers/{server.Id}/Logs");
|
||||
}
|
||||
|
||||
private void Start(Server server)
|
||||
{
|
||||
ServerProcessService.StartServer(server);
|
||||
|
|
42
LANCommander/Pages/Servers/Logs.razor
Normal file
42
LANCommander/Pages/Servers/Logs.razor
Normal file
|
@ -0,0 +1,42 @@
|
|||
@page "/Servers/{id:guid}/Logs"
|
||||
@using Microsoft.AspNetCore.SignalR.Client
|
||||
@attribute [Authorize]
|
||||
@inject ServerService ServerService
|
||||
@inject ServerProcessService ServerProcessService
|
||||
@inject NavigationManager NavigationManager
|
||||
@implements IAsyncDisposable
|
||||
|
||||
<pre>
|
||||
@foreach (var message in Messages)
|
||||
{
|
||||
@message <br />
|
||||
}
|
||||
</pre>
|
||||
|
||||
@code {
|
||||
[Parameter] public Guid Id { get; set; }
|
||||
|
||||
HubConnection? HubConnection;
|
||||
List<string> Messages = new List<string>();
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
HubConnection = new HubConnectionBuilder()
|
||||
.WithUrl(NavigationManager.ToAbsoluteUri("/hubs/logging"))
|
||||
.Build();
|
||||
|
||||
HubConnection.On<string>("Log", (message) =>
|
||||
{
|
||||
Messages.Add(message);
|
||||
InvokeAsync(StateHasChanged);
|
||||
});
|
||||
|
||||
await HubConnection.StartAsync();
|
||||
}
|
||||
|
||||
public async ValueTask DisposeAsync()
|
||||
{
|
||||
if (HubConnection is not null)
|
||||
await HubConnection.DisposeAsync();
|
||||
}
|
||||
}
|
|
@ -1,12 +1,14 @@
|
|||
using BeaconLib;
|
||||
using LANCommander.Data;
|
||||
using LANCommander.Data.Models;
|
||||
using LANCommander.Hubs;
|
||||
using LANCommander.Services;
|
||||
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.IdentityModel.Tokens;
|
||||
using NLog.Web;
|
||||
using System.Text;
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
|
@ -114,6 +116,8 @@ builder.WebHost.UseKestrel(options =>
|
|||
options.Limits.MaxRequestBodySize = 1024 * 1024 * 150;
|
||||
});
|
||||
|
||||
builder.Host.UseNLog();
|
||||
|
||||
var app = builder.Build();
|
||||
|
||||
// Configure the HTTP request pipeline.
|
||||
|
@ -140,6 +144,8 @@ app.UseAuthorization();
|
|||
|
||||
app.UseMvcWithDefaultRoute();
|
||||
|
||||
app.MapHub<LoggingHub>("/hubs/logging");
|
||||
|
||||
app.UseEndpoints(endpoints =>
|
||||
{
|
||||
endpoints.MapBlazorHub();
|
||||
|
|
|
@ -1,10 +1,13 @@
|
|||
using LANCommander.Data.Models;
|
||||
using NLog;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace LANCommander.Services
|
||||
{
|
||||
public class ServerProcessService
|
||||
{
|
||||
private readonly Logger Logger = LogManager.GetCurrentClassLogger();
|
||||
|
||||
public Dictionary<Guid, Process> Processes = new Dictionary<Guid, Process>();
|
||||
public Dictionary<Guid, int> Threads { get; set; } = new Dictionary<Guid, int>();
|
||||
|
||||
|
@ -15,19 +18,40 @@ namespace LANCommander.Services
|
|||
process.StartInfo.FileName = server.Path;
|
||||
process.StartInfo.WorkingDirectory = server.WorkingDirectory;
|
||||
process.StartInfo.Arguments = server.Arguments;
|
||||
process.StartInfo.UseShellExecute = true;
|
||||
process.StartInfo.UseShellExecute = false;
|
||||
process.StartInfo.RedirectStandardOutput = true;
|
||||
process.StartInfo.RedirectStandardError = true;
|
||||
process.EnableRaisingEvents = true;
|
||||
|
||||
process.OutputDataReceived += new DataReceivedEventHandler((sender, e) =>
|
||||
{
|
||||
Logger.Info("Game Server {ServerName} ({ServerId}) Info: {Message}", server.Name, server.Id, e.Data);
|
||||
});
|
||||
|
||||
process.ErrorDataReceived += new DataReceivedEventHandler((sender, e) =>
|
||||
{
|
||||
Logger.Error("Game Server {ServerName} ({ServerId}) Error: {Message}", server.Name, server.Id, e.Data);
|
||||
});
|
||||
|
||||
process.Start();
|
||||
|
||||
process.BeginErrorReadLine();
|
||||
process.BeginOutputReadLine();
|
||||
|
||||
Processes[server.Id] = process;
|
||||
|
||||
await process.WaitForExitAsync();
|
||||
}
|
||||
|
||||
|
||||
public void StopServer(Server server)
|
||||
{
|
||||
if (Processes.ContainsKey(server.Id))
|
||||
Processes[server.Id].Kill();
|
||||
{
|
||||
var process = Processes[server.Id];
|
||||
|
||||
process.Kill();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
33
LANCommander/nlog.config
Normal file
33
LANCommander/nlog.config
Normal file
|
@ -0,0 +1,33 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
autoReload="true"
|
||||
internalLogFile="internal.log"
|
||||
internalLogLevel="Info">
|
||||
|
||||
<!-- enable asp.net core layout renderers -->
|
||||
<extensions>
|
||||
<add assembly="NLog.Web.AspNetCore"/>
|
||||
<add assembly="LANCommander"/>
|
||||
</extensions>
|
||||
|
||||
<!-- the targets to write to -->
|
||||
<targets>
|
||||
<!-- File Target for all log messages with basic details -->
|
||||
<target xsi:type="File" name="MainLogFile" fileName="${basedir}/Logs/log.txt" archiveEvery="Day" />
|
||||
<target xsi:type="File" name="GameServerLogFile" fileName="${basedir}/Logs/GameServers/${event-properties:ServerName}.log" archiveEvery="Day" />
|
||||
<target xsi:type="LoggingHub" name="GameServerHub" hubUrl="http://localhost:1337/hubs/logging" />
|
||||
</targets>
|
||||
|
||||
<!-- rules to map from logger name to target -->
|
||||
<rules>
|
||||
<!--All logs, including from Microsoft-->
|
||||
<logger name="*" minlevel="Trace" writeTo="MainLogFile,LoggingHub" />
|
||||
<logger name="LANCommander.Services.ServerProcessService" minlevel="Info" writeTo="GameServerLogFile,GameServerHub" />
|
||||
<!--Skip non-critical Microsoft logs and so log only own logs (BlackHole) -->
|
||||
<!--<logger name="Microsoft.*" maxlevel="Info" final="true" />
|
||||
<logger name="System.Net.Http.*" maxlevel="Info" final="true" />
|
||||
|
||||
<logger name="*" minlevel="Trace" writeTo="ownFile-web" />-->
|
||||
</rules>
|
||||
</nlog>
|
Loading…
Add table
Reference in a new issue