diff --git a/src/Tgstation.Server.Host.Console/Program.cs b/src/Tgstation.Server.Host.Console/Program.cs
index f7ab19864e..b407ddbcb1 100644
--- a/src/Tgstation.Server.Host.Console/Program.cs
+++ b/src/Tgstation.Server.Host.Console/Program.cs
@@ -1,4 +1,7 @@
-using System.Threading.Tasks;
+using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Logging.Console;
+using System.Collections.Generic;
+using System.Threading.Tasks;
using Tgstation.Server.Host.Watchdog;
namespace Tgstation.Server.Host.Console
@@ -13,11 +16,29 @@ namespace Tgstation.Server.Host.Console
///
internal static IWatchdogFactory WatchdogFactory { get; set; } = new WatchdogFactory();
- ///
- /// Entrypoint for the application
- ///
- /// The arguments for the
- /// A representing the running operation
- internal static Task Main(string[] args) => WatchdogFactory.CreateWatchdog().RunAsync(args, default);
+ ///
+ /// Entrypoint for the application
+ ///
+ /// The arguments for the
+ /// A representing the running operation
+ internal static async Task Main(string[] args)
+ {
+ using (var loggerFactory = new LoggerFactory())
+ {
+ var arguments = new List(args);
+ var trace = arguments.Remove("--trace-host-watchdog");
+ var debug = arguments.Remove("--debug-host-watchdog");
+
+ loggerFactory.AddConsole(trace ? LogLevel.Trace : debug ? LogLevel.Debug : LogLevel.Information, true);
+
+ if (trace && debug)
+ {
+ loggerFactory.CreateLogger(nameof(Program)).LogCritical("Please specify only 1 of --trace-host-watchdog or --debug-host-watchdog!");
+ return;
+ }
+ //default CancellationToken because the Host handles that internally
+ await WatchdogFactory.CreateWatchdog(loggerFactory).RunAsync(arguments.ToArray(), default).ConfigureAwait(false);
+ }
+ }
}
}
diff --git a/src/Tgstation.Server.Host.Service/Program.cs b/src/Tgstation.Server.Host.Service/Program.cs
index 1a5a1a9dcf..742b7e7ac6 100644
--- a/src/Tgstation.Server.Host.Service/Program.cs
+++ b/src/Tgstation.Server.Host.Service/Program.cs
@@ -1,4 +1,5 @@
using McMaster.Extensions.CommandLineUtils;
+using Microsoft.Extensions.Logging;
using System;
using System.Collections.Specialized;
using System.Configuration.Install;
@@ -97,7 +98,8 @@ namespace Tgstation.Server.Host.Service
installer.Uninstall(null);
}
else
- ServiceBase.Run(new ServerService(new WatchdogFactory()));
+ using (var loggerFactory = new LoggerFactory())
+ ServiceBase.Run(new ServerService(new WatchdogFactory(), loggerFactory));
}
///
diff --git a/src/Tgstation.Server.Host.Service/ServerService.cs b/src/Tgstation.Server.Host.Service/ServerService.cs
index 1242ea88fc..97ff6944ea 100644
--- a/src/Tgstation.Server.Host.Service/ServerService.cs
+++ b/src/Tgstation.Server.Host.Service/ServerService.cs
@@ -1,4 +1,8 @@
-using System;
+using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Logging.EventLog;
+using Microsoft.Extensions.Logging.EventLog.Internal;
+using System;
+using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.ServiceProcess;
using System.Threading;
@@ -10,7 +14,7 @@ namespace Tgstation.Server.Host.Service
///
/// Represents a as a
///
- sealed class ServerService : ServiceBase
+ sealed class ServerService : ServiceBase, IEventLog
{
///
/// The canonical windows service name
@@ -20,7 +24,7 @@ namespace Tgstation.Server.Host.Service
///
/// The for the
///
- IWatchdog watchdog;
+ readonly IWatchdog watchdog;
///
/// The recieved from of
@@ -32,18 +36,33 @@ namespace Tgstation.Server.Host.Service
///
CancellationTokenSource cancellationTokenSource;
- ///
- /// Construct a
- ///
- /// The to create with
- public ServerService(IWatchdogFactory watchdogFactory)
+ ///
+ /// Construct a
+ ///
+ /// The to create with
+ /// The for
+ public ServerService(IWatchdogFactory watchdogFactory, ILoggerFactory loggerFactory)
{
if (watchdogFactory == null)
throw new ArgumentNullException(nameof(watchdogFactory));
+ if(loggerFactory == null)
+ throw new ArgumentNullException(nameof(loggerFactory));
+
+ loggerFactory.AddEventLog(new EventLogSettings
+ {
+ EventLog = this
+ });
+
ServiceName = Name;
- watchdog = watchdogFactory.CreateWatchdog();
+ watchdog = watchdogFactory.CreateWatchdog(loggerFactory);
}
+ ///
+ public int MaxMessageSize => (int)EventLog.MaximumKilobytes * 1024;
+
+ ///
+ public void WriteEntry(string message, EventLogEntryType type, int eventID, short category) => EventLog.WriteEntry(message, type, eventID, category);
+
///
[SuppressMessage("Microsoft.Usage", "CA2213:DisposableFieldsShouldBeDisposed", MessageId = "cancellationTokenSource")]
protected override void Dispose(bool disposing)
diff --git a/src/Tgstation.Server.Host.Service/Tgstation.Server.Host.Service.csproj b/src/Tgstation.Server.Host.Service/Tgstation.Server.Host.Service.csproj
index 2ea140835e..ed7a2783e3 100644
--- a/src/Tgstation.Server.Host.Service/Tgstation.Server.Host.Service.csproj
+++ b/src/Tgstation.Server.Host.Service/Tgstation.Server.Host.Service.csproj
@@ -90,7 +90,10 @@
- 2.2.4
+ 2.2.5
+
+
+ 2.1.1
diff --git a/src/Tgstation.Server.Host.Watchdog/IWatchdogFactory.cs b/src/Tgstation.Server.Host.Watchdog/IWatchdogFactory.cs
index a1b203761a..9534709a2f 100644
--- a/src/Tgstation.Server.Host.Watchdog/IWatchdogFactory.cs
+++ b/src/Tgstation.Server.Host.Watchdog/IWatchdogFactory.cs
@@ -1,4 +1,6 @@
-namespace Tgstation.Server.Host.Watchdog
+using Microsoft.Extensions.Logging;
+
+namespace Tgstation.Server.Host.Watchdog
{
///
/// Factory for creating s
@@ -8,7 +10,8 @@
///
/// Create a
///
+ /// The to use for error reporting
/// A new
- IWatchdog CreateWatchdog();
+ IWatchdog CreateWatchdog(ILoggerFactory loggerFactory);
}
}
diff --git a/src/Tgstation.Server.Host.Watchdog/Watchdog.cs b/src/Tgstation.Server.Host.Watchdog/Watchdog.cs
index ef74711534..e4c3fc6a74 100644
--- a/src/Tgstation.Server.Host.Watchdog/Watchdog.cs
+++ b/src/Tgstation.Server.Host.Watchdog/Watchdog.cs
@@ -1,4 +1,5 @@
-using System;
+using Microsoft.Extensions.Logging;
+using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
@@ -24,38 +25,67 @@ namespace Tgstation.Server.Host.Watchdog
///
readonly IIsolatedAssemblyContextFactory isolatedAssemblyLoader;
+ ///
+ /// The for the
+ ///
+ readonly ILogger logger;
+
///
/// Construct a
///
/// The value of
/// The value of
/// The value of
- public Watchdog(IServerFactory initialServerFactory, IActiveAssemblyDeleter activeAssemblyDeleter, IIsolatedAssemblyContextFactory isolatedAssemblyLoader)
+ /// The value of
+ public Watchdog(IServerFactory initialServerFactory, IActiveAssemblyDeleter activeAssemblyDeleter, IIsolatedAssemblyContextFactory isolatedAssemblyLoader, ILogger logger)
{
this.initialServerFactory = initialServerFactory ?? throw new ArgumentNullException(nameof(initialServerFactory));
this.activeAssemblyDeleter = activeAssemblyDeleter ?? throw new ArgumentNullException(nameof(activeAssemblyDeleter));
this.isolatedAssemblyLoader = isolatedAssemblyLoader ?? throw new ArgumentNullException(nameof(isolatedAssemblyLoader));
+ this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
}
///
public async Task RunAsync(string[] args, CancellationToken cancellationToken)
{
- //first run the host we started with
- var serverFactory = initialServerFactory;
- var assemblyPath = serverFactory.GetType().Assembly.Location;
- do
- {
- var server = serverFactory.CreateServer(args);
- await server.RunAsync(cancellationToken).ConfigureAwait(false);
+ logger.LogInformation("Host watchdog starting...");
+ try
+ {
+ //first run the host we started with
+ logger.LogTrace("Running with initial server factory...");
+ var serverFactory = initialServerFactory;
+ logger.LogTrace("Determining location of host assembly...");
+ var assemblyPath = serverFactory.GetType().Assembly.Location;
+ logger.LogDebug("Path to initial host assembly: {0}", assemblyPath);
+ do
+ using (logger.BeginScope("Host invocation"))
+ {
+ var server = serverFactory.CreateServer(args);
+ logger.LogTrace("Running server...");
+ await server.RunAsync(cancellationToken).ConfigureAwait(false);
+ logger.LogInformation("Active host exited.");
- if (server.UpdatePath == null)
- break;
+ if (server.UpdatePath == null)
+ break;
- activeAssemblyDeleter.DeleteActiveAssembly(assemblyPath);
- File.Move(server.UpdatePath, assemblyPath);
- serverFactory = isolatedAssemblyLoader.CreateIsolatedServerFactory(assemblyPath);
- }
- while (!cancellationToken.IsCancellationRequested);
+ logger.LogInformation("Update path is set to \"{0}\", attempting host assembly hotswap...", server.UpdatePath);
+ activeAssemblyDeleter.DeleteActiveAssembly(assemblyPath);
+ logger.LogTrace("Moving new host assembly in place...");
+ File.Move(server.UpdatePath, assemblyPath);
+ logger.LogTrace("Atttempting to create new server factory...");
+ serverFactory = isolatedAssemblyLoader.CreateIsolatedServerFactory(assemblyPath);
+ }
+ while (!cancellationToken.IsCancellationRequested);
+ }
+ catch (OperationCanceledException)
+ {
+ logger.LogDebug("Exiting due to cancellation...");
+ }
+ catch (Exception e)
+ {
+ logger.LogCritical("Error running host assembly! Exception: {0}", e);
+ }
+ logger.LogInformation("Host watchdog exiting...");
}
}
}
diff --git a/src/Tgstation.Server.Host.Watchdog/WatchdogFactory.cs b/src/Tgstation.Server.Host.Watchdog/WatchdogFactory.cs
index ddb00dafe0..436e051429 100644
--- a/src/Tgstation.Server.Host.Watchdog/WatchdogFactory.cs
+++ b/src/Tgstation.Server.Host.Watchdog/WatchdogFactory.cs
@@ -1,4 +1,5 @@
-using System.Diagnostics.CodeAnalysis;
+using Microsoft.Extensions.Logging;
+using System.Diagnostics.CodeAnalysis;
using System.Runtime.InteropServices;
namespace Tgstation.Server.Host.Watchdog
@@ -8,6 +9,6 @@ namespace Tgstation.Server.Host.Watchdog
{
///
[ExcludeFromCodeCoverage]
- public IWatchdog CreateWatchdog() => new Watchdog(new ServerFactory(), RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? (IActiveAssemblyDeleter)new WindowsActiveAssemblyDeleter() : new PosixActiveAssemblyDeleter(), new IsolatedAssemblyContextFactory());
+ public IWatchdog CreateWatchdog(ILoggerFactory loggerFactory) => new Watchdog(new ServerFactory(), RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? (IActiveAssemblyDeleter)new WindowsActiveAssemblyDeleter() : new PosixActiveAssemblyDeleter(), new IsolatedAssemblyContextFactory(), loggerFactory.CreateLogger());
}
}