Merge pull request #685 from Cyberboss/FixWatchdogMessage

Some watchdog fixups
This commit is contained in:
Jordan Brown
2018-09-20 13:34:41 -04:00
committed by GitHub
10 changed files with 100 additions and 48 deletions
+48 -2
View File
@@ -65,9 +65,9 @@ Create an `appsettings.Production.json` file next to `appsettings.json`. This wi
- `General:GitHubAccessToken`: Specify a GitHub personal access token with no scopes here to highly mitigate the possiblity of 429 response codes from GitHub requests
- `Logging:LogLevel:Default`: Can be one of `Trace`, `Debug`, `Information`, `Warning`, `Error`, or `Critical`. Restricts what is put into the log files. Currently `Debug` is reccommended for help with error reporting.
- `General:LogFileLevel`: Can be one of `Trace`, `Debug`, `Information`, `Warning`, `Error`, or `Critical`. Restricts what is put into the log files. Currently `Debug` is reccommended for help with error reporting.
- `Kestrel:Endpoints:Http:Url`: The URL (i.e. interface and ports) your application should listen on. General use case should be `http://localhost:<port>` for restricted local connections. See the Remote Access section for configuring public access to the World Wide Web.
- `Kestrel:Endpoints:Http:Url`: The URL (i.e. interface and ports) your application should listen on. General use case should be `http://localhost:<port>` for restricted local connections. See the Remote Access section for configuring public access to the World Wide Web. This doesn't need to be changed using the docker setup and should be mapped with the `-p` option instead
- `Database:DatabaseType`: Can be one of `SqlServer`, `MariaDB`, or `MySql`
@@ -107,6 +107,52 @@ A breaking change from V3: tgstation-server 4 now REQUIRES the DMAPI to be integ
The DMAPI is fully backwards compatible and should function with any tgstation-server version to date. Updates can be performed in the same manner. Using the `TGS_EXTERNAL_CONFIGURATION` is recommended in order to make the process as easy as replacing `tgs.dm` and the `tgs` folder with a new version
### Example
Here is a bare minimum example project that implements the essential code changes for integrating the DMAPI
Before `tgs.dm`:
```
//Remember, every codebase is different, you probably have better methods for these defines than the ones given here
#define TGS_EXTERNAL_CONFIGURATION
#define TGS_DEFINE_AND_SET_GLOBAL(Name, Value) var/global/##Name = ##Value
#define TGS_READ_GLOBAL(Name) global.##Name
#define TGS_WRITE_GLOBAL(Name, Value) global.##Name = ##Value
#define TGS_WORLD_ANNOUNCE(message) world << ##message
#define TGS_INFO_LOG(message) world.log << "TGS Info: [##message]"
#define TGS_ERROR_LOG(message) world.log << "TGS Error: [##message]"
#define TGS_NOTIFY_ADMINS(event) world.log << "TGS Admin Message: [##event]"
#define TGS_CLIENT_COUNT global.client_cout
#define TGS_PROTECT_DATUM(Path) // Leave blank if your codebase doesn't give administrators code reflection capabilities
```
Anywhere else:
```dm
var/global/client_count = 0
/world/New()
..()
TgsNew()
TgsInitializationsComplete()
/world/Reboot()
TgsReboot()
..()
/world/Topic()
TGS_TOPIC
..()
/client/New()
..()
++global.client_count
/client/Del()
..()
--global.client_count
```
## Remote Access
tgstation-server is an [ASP.Net Core](https://docs.microsoft.com/en-us/aspnet/core/) based on the Kestrel web server. This section is meant to serve as a general use case overview, but the entire Kestrel configuration can be modified to your liking with the configuration JSON. See [the official documentation](https://docs.microsoft.com/en-us/aspnet/core/fundamentals/servers/kestrel) for details.
+2 -3
View File
@@ -20,7 +20,7 @@ WORKDIR /src/src/Tgstation.Server.Host
RUN dotnet publish -c Release -o /app/lib/Default && mv /app/lib/Default/appsettings* /app
FROM microsoft/dotnet:2.1-aspnetcore-runtime
EXPOSE 5000
EXPOSE 80
#needed for byond
RUN apt-get update \
@@ -32,9 +32,8 @@ WORKDIR /app
COPY --from=build /app .
COPY --from=build /src/build/tgs.docker.sh tgs.sh
COPY --from=build /src/src/Tgstation.Server.Host/appsettings.Docker.json .
RUN mkdir /config_data && mv appsettings.Docker.json /config_data/appsettings.Production.json
RUN mkdir /config_data
VOLUME ["/config_data", "/tgs_logs", "/app/lib"]
ENTRYPOINT ["./tgs.sh"]
+1 -2
View File
@@ -1,6 +1,5 @@
#!/bin/sh
mkdir /config_data
cp -r /config_data/* ./
ln -s /config_data/appsettings.Production.json /app/appsettings.Production.json
exec dotnet Tgstation.Server.Host.Console.dll "$@"
@@ -1,4 +1,5 @@
using System.ComponentModel.DataAnnotations;
using System;
using System.ComponentModel.DataAnnotations;
namespace Tgstation.Server.Api.Models.Internal
{
@@ -36,5 +37,17 @@ namespace Tgstation.Server.Api.Models.Internal
/// </summary>
[Required]
public uint? StartupTimeout { get; set; }
/// <summary>
/// Check if we match a given set of <paramref name="otherParameters"/>
/// </summary>
/// <param name="otherParameters">The <see cref="DreamDaemonLaunchParameters"/> to compare against</param>
/// <returns><see langword="true"/> if they match, <see langword="false"/> otherwise</returns>
public bool Match(DreamDaemonLaunchParameters otherParameters) =>
AllowWebClient == otherParameters.AllowWebClient
&& SecurityLevel == otherParameters.SecurityLevel
&& PrimaryPort == otherParameters.PrimaryPort
&& SecondaryPort == otherParameters.SecondaryPort
&& StartupTimeout == otherParameters.StartupTimeout;
}
}
@@ -369,7 +369,10 @@ namespace Tgstation.Server.Host.Components.Repository
var remote = repository.Network.Remotes.First();
try
{
repository.Network.Push(remote, String.Format(CultureInfo.InvariantCulture, "+{0}:{0}", branch.CanonicalName), GeneratePushOptions(progressReporter, username, password, cancellationToken));
var forcePushString = String.Format(CultureInfo.InvariantCulture, "+{0}:{0}", branch.CanonicalName);
repository.Network.Push(remote,forcePushString, GeneratePushOptions(progress => progressReporter((int)(0.9f * progress)), username, password, cancellationToken));
var removalString = String.Format(CultureInfo.InvariantCulture, ":{0}", branch.CanonicalName);
repository.Network.Push(remote, removalString, GeneratePushOptions(progress => progressReporter(90 + (int)(0.1f * progress)), username, password, cancellationToken));
}
catch (UserCancelledException)
{
@@ -441,11 +441,10 @@ namespace Tgstation.Server.Host.Components.Watchdog
monitorState.NextAction = MonitorAction.Continue;
break;
case MonitorActivationReason.NewDmbAvailable:
monitorState.InactiveServerHasStagedDmb = true;
await UpdateAndRestartInactiveServer(true).ConfigureAwait(false); //next case does same thing
break;
monitorState.InactiveServerHasStagedDmb = true;
goto case MonitorActivationReason.ActiveLaunchParametersUpdated;
case MonitorActivationReason.ActiveLaunchParametersUpdated:
await UpdateAndRestartInactiveServer(false).ConfigureAwait(false);
await UpdateAndRestartInactiveServer(true).ConfigureAwait(false);
break;
}
}
@@ -617,6 +616,8 @@ namespace Tgstation.Server.Host.Components.Watchdog
{
using (await SemaphoreSlimContext.Lock(semaphore, cancellationToken).ConfigureAwait(false))
{
if (launchParameters.Match(ActiveLaunchParameters))
return;
ActiveLaunchParameters = launchParameters;
if (Running)
//queue an update
@@ -780,6 +781,7 @@ namespace Tgstation.Server.Host.Components.Watchdog
/// <inheritdoc />
public async Task<WatchdogLaunchResult> Restart(bool graceful, CancellationToken cancellationToken)
{
logger.LogTrace("Begin Restart. Graceful: {0}", graceful);
using (await SemaphoreSlimContext.Lock(semaphore, cancellationToken).ConfigureAwait(false))
{
if (!graceful || !Running)
@@ -15,6 +15,11 @@
/// </summary>
public string LogFileDirectory { get; set; }
/// <summary>
/// The stringified <see cref="Microsoft.Extensions.Logging.LogLevel"/> for file logging
/// </summary>
public string LogFileLevel { get; set; }
/// <summary>
/// If file logging is disabled
/// </summary>
+19 -12
View File
@@ -25,7 +25,6 @@ using Tgstation.Server.Host.Components.Chat;
using Tgstation.Server.Host.Components.Repository;
using Tgstation.Server.Host.Components.Watchdog;
using Tgstation.Server.Host.Configuration;
using Tgstation.Server.Host.Controllers;
using Tgstation.Server.Host.IO;
using Tgstation.Server.Host.Models;
using Tgstation.Server.Host.Security;
@@ -47,7 +46,7 @@ namespace Tgstation.Server.Host.Core
/// <summary>
/// The <see cref="IConfiguration"/> for the <see cref="Application"/>
/// </summary>
readonly Microsoft.Extensions.Configuration.IConfiguration configuration;
readonly IConfiguration configuration;
/// <summary>
/// The <see cref="Microsoft.AspNetCore.Hosting.IHostingEnvironment"/> for the <see cref="Application"/>
@@ -55,13 +54,19 @@ namespace Tgstation.Server.Host.Core
readonly Microsoft.AspNetCore.Hosting.IHostingEnvironment hostingEnvironment;
readonly TaskCompletionSource<object> startupTcs;
static LogLevel GetMinimumLogLevel(string stringLevel)
{
if (String.IsNullOrWhiteSpace(stringLevel) || !Enum.TryParse<LogLevel>(stringLevel, out var minimumLevel))
minimumLevel = LogLevel.Information;
return minimumLevel;
}
/// <summary>
/// Construct an <see cref="Application"/>
/// </summary>
/// <param name="configuration">The value of <see cref="configuration"/></param>
/// <param name="hostingEnvironment">The value of <see cref="hostingEnvironment"/></param>
public Application(Microsoft.Extensions.Configuration.IConfiguration configuration, Microsoft.AspNetCore.Hosting.IHostingEnvironment hostingEnvironment)
public Application(IConfiguration configuration, Microsoft.AspNetCore.Hosting.IHostingEnvironment hostingEnvironment)
{
this.configuration = configuration ?? throw new ArgumentNullException(nameof(configuration));
this.hostingEnvironment = hostingEnvironment ?? throw new ArgumentNullException(nameof(hostingEnvironment));
@@ -76,9 +81,7 @@ namespace Tgstation.Server.Host.Core
/// Configure dependency injected services
/// </summary>
/// <param name="services">The <see cref="IServiceCollection"/> to configure</param>
#pragma warning disable CA1822 // Mark members as static
public void ConfigureServices(IServiceCollection services)
#pragma warning restore CA1822 // Mark members as static
{
if (services == null)
throw new ArgumentNullException(nameof(services));
@@ -97,7 +100,8 @@ namespace Tgstation.Server.Host.Core
if (generalConfiguration?.DisableFileLogging != true)
{
var logPath = !String.IsNullOrEmpty(generalConfiguration?.LogFileDirectory) ? generalConfiguration.LogFileDirectory : ioManager.ConcatPath(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), VersionPrefix, "Logs");
services.AddLogging(builder => builder.AddFile(ioManager.ConcatPath(logPath, "tgs-{Date}.log")));
services.AddLogging(builder => builder.AddFile(ioManager.ConcatPath(logPath, "tgs-{Date}.log"), GetMinimumLogLevel(generalConfiguration?.LogFileLevel)));
}
services.AddOptions();
@@ -266,12 +270,15 @@ namespace Tgstation.Server.Host.Core
///<inheritdoc />
public void Ready(Exception initializationError)
{
if (startupTcs.Task.IsCompleted)
throw new InvalidOperationException("Ready has already been called!");
if (initializationError == null)
startupTcs.SetResult(null);
else
startupTcs.SetException(initializationError);
lock (startupTcs)
{
if (startupTcs.Task.IsCompleted)
throw new InvalidOperationException("Ready has already been called!");
if (initializationError == null)
startupTcs.SetResult(null);
else
startupTcs.SetException(initializationError);
}
}
}
}
@@ -1,19 +0,0 @@
{
"General": {
"LogFileDirectory": "/tgs_logs",
"MinimumPasswordLength": 15,
"GitHubAccessToken": null
},
"Kestrel": {
"Endpoints": {
"Http": {
"Url": "http://localhost:5000"
}
}
},
"Database": {
"DatabaseType": "SqlServer or MySQL or MariaDB",
"ConnectionString": "<Your connection string>",
"MySqlServerVersion": "<Set if using MySQL/MariaDB i.e. 10.2.7>"
}
}
+1 -4
View File
@@ -2,6 +2,7 @@
"General": {
"LogFileDirectory": null, //use the default path
"DisableFileLogging": false,
"LogFileLevel": "Debug",
"MinimumPasswordLength": 15,
"GitHubAccessToken": null
},
@@ -25,10 +26,6 @@
"Default": "Trace",
"Microsoft": "Warning"
}
},
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning"
}
},
"Updates": {