Fix Sevice logging

This commit is contained in:
Dominion
2023-03-25 15:48:44 -04:00
parent fc71f8a5e1
commit f04d1973e7
3 changed files with 58 additions and 93 deletions
+24 -48
View File
@@ -160,61 +160,37 @@ namespace Tgstation.Server.Host.Service
}
}
ServerService service = null;
ILoggerFactory loggerFactory;
try
if (Install)
{
loggerFactory = LoggerFactory.Create(builder =>
{
if (Configure)
{
builder.AddConsole();
}
if (Uninstall)
return; // oh no, it's retarded...
service = new ServerService(builder, Trace ? LogLevel.Trace : Debug ? LogLevel.Debug : LogLevel.Information);
});
}
catch
{
service?.Dispose();
throw;
}
using (loggerFactory)
using (service)
{
if (Install)
{
if (Uninstall)
return; // oh no, it's retarded...
RunServiceInstall();
if (Configure)
{
Console.WriteLine("For this first run we'll launch the console runner so you may use the setup wizard.");
Console.WriteLine("If it starts successfully, feel free to close it and then start the service from the Windows control panel.");
}
}
else if (Uninstall)
using (var installer = new ServiceInstaller())
{
installer.Context = new InstallContext("tgs-uninstall.log", null);
installer.ServiceName = ServerService.Name;
installer.Uninstall(null);
}
else if (!Configure)
{
service.SetupWatchdog(WatchdogFactory.CreateWatchdog(loggerFactory));
ServiceBase.Run(service);
}
RunServiceInstall();
if (Configure)
{
// DCT: None available
await WatchdogFactory.CreateWatchdog(loggerFactory).RunAsync(true, Array.Empty<string>(), default);
Console.WriteLine("For this first run we'll launch the console runner so you may use the setup wizard.");
Console.WriteLine("If it starts successfully, feel free to close it and then start the service from the Windows control panel.");
}
}
else if (Uninstall)
using (var installer = new ServiceInstaller())
{
installer.Context = new InstallContext("tgs-uninstall.log", null);
installer.ServiceName = ServerService.Name;
installer.Uninstall(null);
}
else if (!Configure)
{
using (var service = new ServerService(WatchdogFactory, Trace ? LogLevel.Trace : Debug ? LogLevel.Debug : LogLevel.Information))
ServiceBase.Run(service);
}
if (Configure)
{
using (var loggerFactory = LoggerFactory.Create(builder => builder.AddConsole()))
await WatchdogFactory.CreateWatchdog(loggerFactory).RunAsync(true, Array.Empty<string>(), default); // DCT: None available
}
}
}
}
@@ -25,10 +25,15 @@ namespace Tgstation.Server.Host.Service
/// <summary>
/// The <see cref="IWatchdog"/> for the <see cref="ServerService"/>.
/// </summary>
IWatchdog watchdog;
readonly IWatchdogFactory watchdogFactory;
/// <summary>
/// The <see cref="Task"/> recieved from <see cref="IWatchdog.RunAsync(bool, string[], CancellationToken)"/> of <see cref="watchdog"/>.
/// The minimum <see cref="Microsoft.Extensions.Logging.LogLevel"/> for the <see cref="EventLog"/>.
/// </summary>
readonly LogLevel minimumLogLevel;
/// <summary>
/// The <see cref="Task"/> that represents the running service.
/// </summary>
Task watchdogTask;
@@ -40,41 +45,15 @@ namespace Tgstation.Server.Host.Service
/// <summary>
/// Initializes a new instance of the <see cref="ServerService"/> class.
/// </summary>
/// <param name="loggingBuilder">The <see cref="ILoggingBuilder"/> to configure.</param>
/// <param name="minumumLogLevel">The minimum <see cref="Microsoft.Extensions.Logging.LogLevel"/> to record in the event log.</param>
public ServerService(ILoggingBuilder loggingBuilder, LogLevel minumumLogLevel)
/// <param name="watchdogFactory">The value of <see cref="watchdogFactory"/>.</param>
/// <param name="minimumLogLevel">The minimum <see cref="Microsoft.Extensions.Logging.LogLevel"/> to record in the event log.</param>
public ServerService(IWatchdogFactory watchdogFactory, LogLevel minimumLogLevel)
{
if (loggingBuilder == null)
throw new ArgumentNullException(nameof(loggingBuilder));
loggingBuilder.AddEventLog(new EventLogSettings
{
LogName = EventLog.Log,
MachineName = EventLog.MachineName,
SourceName = EventLog.Source,
Filter = (message, logLevel) => logLevel >= minumumLogLevel,
});
this.watchdogFactory = watchdogFactory ?? throw new ArgumentNullException(nameof(watchdogFactory));
this.minimumLogLevel = minimumLogLevel;
ServiceName = Name;
}
/// <summary>
/// Setup the <see cref="IWatchdog"/> for the service.
/// </summary>
/// <param name="watchdog">The value of <see cref="watchdog"/>.</param>
public void SetupWatchdog(IWatchdog watchdog)
{
if (watchdog == null)
#pragma warning disable IDE0016 // Use 'throw' expression
throw new ArgumentNullException(nameof(watchdog));
#pragma warning restore IDE0016 // Use 'throw' expression
if (this.watchdog != null)
throw new InvalidOperationException("SetupWatchdog called twice!");
this.watchdog = watchdog;
}
/// <inheritdoc />
protected override void Dispose(bool disposing)
{
@@ -85,12 +64,20 @@ namespace Tgstation.Server.Host.Service
/// <inheritdoc />
protected override void OnStart(string[] args)
{
if (watchdog == null)
throw new InvalidOperationException("Cannot start without watchdog!");
var loggerFactory = LoggerFactory.Create(builder => builder.AddEventLog(new EventLogSettings
{
LogName = EventLog.Log,
MachineName = EventLog.MachineName,
SourceName = EventLog.Source,
Filter = (message, logLevel) => logLevel >= minimumLogLevel,
}));
var watchdog = watchdogFactory.CreateWatchdog(loggerFactory);
cancellationTokenSource?.Dispose();
cancellationTokenSource = new CancellationTokenSource();
watchdogTask = RunWatchdog(args, cancellationTokenSource.Token);
watchdogTask = RunWatchdog(watchdog, args, cancellationTokenSource.Token);
}
/// <inheritdoc />
@@ -101,12 +88,13 @@ namespace Tgstation.Server.Host.Service
}
/// <summary>
/// Executes the <see cref="watchdog"/>, stopping the service if it exits.
/// Executes the <paramref name="watchdog"/>, stopping the service if it exits.
/// </summary>
/// <param name="args">The arguments for the <see cref="watchdog"/>.</param>
/// <param name="watchdog">The <see cref="IWatchdog"/> to run.</param>
/// <param name="args">The arguments for the <paramref name="watchdog"/>.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task"/> representing the running operation.</returns>
async Task RunWatchdog(string[] args, CancellationToken cancellationToken)
async Task RunWatchdog(IWatchdog watchdog, string[] args, CancellationToken cancellationToken)
{
await watchdog.RunAsync(false, args, cancellationTokenSource.Token);
@@ -20,8 +20,8 @@ namespace Tgstation.Server.Host.Service.Tests
public void TestConstructionAndDisposal()
{
Assert.ThrowsException<ArgumentNullException>(() => new ServerService(null, default));
var mockLoggingBuilder = Mock.Of<ILoggingBuilder>();
new ServerService(mockLoggingBuilder, default).Dispose();
var mockWatchdogFactory = new Mock<IWatchdogFactory>();
new ServerService(mockWatchdogFactory.Object, default).Dispose();
}
[TestMethod]
@@ -35,16 +35,17 @@ namespace Tgstation.Server.Host.Service.Tests
var args = Array.Empty<string>();
CancellationToken cancellationToken;
mockWatchdog.Setup(x => x.RunAsync(false, args, It.IsAny<CancellationToken>())).Callback((bool x, string[] _, CancellationToken token) => cancellationToken = token).Returns(Task.CompletedTask).Verifiable();
var mockLoggerFactory = Mock.Of<ILoggingBuilder>();
var mockWatchdogFactory = new Mock<IWatchdogFactory>();
mockWatchdogFactory.Setup(x => x.CreateWatchdog(It.IsNotNull<ILoggerFactory>())).Returns(mockWatchdog.Object).Verifiable();
using (var service = new ServerService(mockLoggerFactory, default))
using (var service = new ServerService(mockWatchdogFactory.Object, default))
{
Assert.ThrowsException<InvalidOperationException>(() => onStart.Invoke(service, new object[] { args }));
service.SetupWatchdog(mockWatchdog.Object);
onStart.Invoke(service, new object[] { args });
onStop.Invoke(service, Array.Empty<object>());
mockWatchdog.VerifyAll();
}
mockWatchdogFactory.VerifyAll();
}
}
}