Logging and more Service setup

This commit is contained in:
Cyberboss
2017-10-24 16:07:44 -04:00
parent df663d8eb1
commit 42a98df47b
16 changed files with 235 additions and 134 deletions
@@ -1,4 +1,6 @@
using System.Security.Principal;
using System;
using System.Diagnostics;
using System.Security.Principal;
using System.ServiceModel;
using TGServiceInterface.Components;
@@ -7,7 +9,7 @@ namespace TGServerService
/// <summary>
/// A <see cref="ServiceAuthorizationManager"/> used to determine only if the caller is an admin
/// </summary>
class AdministrativeAuthorizationManager : ServiceAuthorizationManager
sealed class AdministrativeAuthorizationManager : ServiceAuthorizationManager
{
string LastSeenUser;
protected override bool CheckAccessCore(OperationContext operationContext)
@@ -27,7 +29,7 @@ namespace TGServerService
if (LastSeenUser != user)
{
LastSeenUser = user;
Service.WriteAccess(user, authSuccess);
Service.WriteEntry(String.Format("Root access from: {0}", user), EventID.Authentication, authSuccess ? EventLogEntryType.SuccessAudit : EventLogEntryType.FailureAudit, Service.LoggingID);
}
return authSuccess;
}
@@ -217,7 +217,6 @@ namespace TGServerService.ChatProviders
foreach (var J in I.TextChannels)
if (J.Id == channel)
J.SendMessageAsync(message).Wait();
Service.WriteInfo(String.Format("Discord Send ({0}): {1}", channelname, message), EventID.ChatSend);
return null;
}
}
@@ -237,9 +236,7 @@ namespace TGServerService.ChatProviders
client.StopAsync().Wait();
client.LogoutAsync().Wait();
}
catch (Exception e) {
Service.WriteError("Discord failed DnD: " + e.ToString(), EventID.ChatDisconnectFail);
}
catch { }
client.Dispose();
}
@@ -74,7 +74,6 @@ namespace TGServerService.ChatProviders
channel = channel.Replace(PrivateMessageMarker, "");
irc.SendMessage(SendType.Message, channel, message);
}
Service.WriteInfo(String.Format("IRC Send ({0}): {1}", channel, message), EventID.ChatSend);
return null;
}
catch (Exception e)
@@ -275,7 +274,7 @@ namespace TGServerService.ChatProviders
/// <inheritdoc />
public void Disconnect()
{
{
try
{
lock (IRCLock)
@@ -287,10 +286,7 @@ namespace TGServerService.ChatProviders
}
}
}
catch (Exception e)
{
Service.WriteError("IRC failed QnD: " + e.ToString(), EventID.ChatDisconnectFail);
}
catch { }
}
/// <inheritdoc />
public bool Connected()
+4 -4
View File
@@ -8,10 +8,10 @@ namespace TGServerService
class DeprecatedInstanceConfig : InstanceConfig
{
/// <summary>
/// Convert the 3.1 .NET settings file to a config json
/// Convert the settings version 6 .NET settings file to a config json
/// </summary>
/// <returns>A saved <see cref="InstanceConfig"/> based off the old .NET setting file</returns>
public static InstanceConfig CreateFromNETSettings()
/// <returns>An <see cref="InstanceConfig"/> based off the old .NET setting file</returns>
public static InstanceConfig CreateFromNETSettings(out string instanceDirectory)
{
var Config = Properties.Settings.Default;
var result = new DeprecatedInstanceConfig()
@@ -34,7 +34,7 @@ namespace TGServerService
AuthorizedUserGroupSID = (string)Config.GetPreviousVersion("AuthorizedGroupSID")
};
result.MigrateToCurrentVersion();
result.Save();
instanceDirectory = result.InstanceDir;
return result;
}
+8 -1
View File
@@ -3,7 +3,7 @@
namespace TGServerService
{
/// <summary>
/// Various events and their IDs in no particular order. Found in the Windows event log. These incremented by 100 and are guaranteed to never be reused in the future. Each event ID may be information, a warning, or error and will be documented accordingly. Warnings will occur due to user, data, or network errors. Errors will occur due to filesystem errors or hard faults
/// Various events and their IDs in no particular order. Found in the Windows event log. These key incremented by 100 and are guaranteed to never be reused in the future. In the windows event viewer, these IDs will be offset by the <see cref="ServerInstance.LoggingID"/> to distinguish events between instances. Each event ID may be information, a warning, or error and will be documented accordingly. Warnings will occur due to user, data, or network errors. Errors will occur due to filesystem errors or hard faults
/// </summary>
public enum EventID : int
{
@@ -112,10 +112,12 @@ namespace TGServerService
/// <summary>
/// Info: Successful completion of a <see cref="ChatProviders.IChatProvider.SendMessageDirect(string, string)"/> operation
/// </summary>
[Obsolete("Not in use anymore", true)]
ChatSend = 2600,
/// <summary>
/// Info: Successful completion of a <see cref="ChatProviders.IChatProvider.SendMessage(string, MessageType)"/> operation
/// </summary>
[Obsolete("Not in use anymore", true)]
ChatBroadcast = 2700,
/// <summary>
/// Not in use anymore
@@ -125,6 +127,7 @@ namespace TGServerService
/// <summary>
/// Error: When an error occurs during a <see cref="ChatProviders.IChatProvider.Disconnect"/> operation
/// </summary>
[Obsolete("Not in use anymore", true)]
ChatDisconnectFail = 2900,
/// <summary>
/// Not in use anymore
@@ -315,5 +318,9 @@ namespace TGServerService
/// Info: Successfully delete of a static path. Warning: An error occurred during a delete of a static path
/// </summary>
StaticDelete = 7500,
/// <summary>
/// Info: When an instance's logging ID is first assigned
/// </summary>
InstanceIDAssigned = 7600,
}
}
@@ -109,7 +109,7 @@ namespace TGServerService
//only allow the same user the service is running as to use interop, because that's what DD is running as, and don't spam the logs with it unless it fails
var result = windowsIdent.User == ServiceSID;
if(!result)
Service.WriteAccess(windowsIdent.Name, false);
WriteAccess(windowsIdent.Name, false);
return result;
}
@@ -127,7 +127,7 @@ namespace TGServerService
if (LastSeenUser != user)
{
LastSeenUser = user;
Service.WriteAccess(user, authSuccess);
WriteAccess(user, authSuccess);
}
}
return authSuccess;
+5 -5
View File
@@ -225,7 +225,7 @@ namespace TGServerService
{
SendMessage("BYOND: Update download failed. Does the specified version exist?", MessageType.DeveloperInfo);
lastError = String.Format("Download of BYOND version {0}.{1} failed! Does it exist?", major, minor);
Service.WriteWarning(String.Format("Failed to update BYOND to version {0}.{1}!", major, minor), EventID.BYONDUpdateFail);
WriteWarning(String.Format("Failed to update BYOND to version {0}.{1}!", major, minor), EventID.BYONDUpdateFail);
lock (ByondLock)
{
updateStat = ByondStatus.Idle;
@@ -267,7 +267,7 @@ namespace TGServerService
RequestRestart();
lastError = "Update staged. Awaiting server restart...";
SendMessage(String.Format("BYOND: Staging complete. Awaiting server restart...", major, minor), MessageType.DeveloperInfo);
Service.WriteInfo(String.Format("BYOND update {0}.{1} staged", major, minor), EventID.BYONDUpdateStaged);
WriteInfo(String.Format("BYOND update {0}.{1} staged", major, minor), EventID.BYONDUpdateStaged);
break;
}
}
@@ -277,7 +277,7 @@ namespace TGServerService
}
catch (Exception e)
{
Service.WriteError("Revision staging errror: " + e.ToString(), EventID.BYONDUpdateFail);
WriteError("Revision staging errror: " + e.ToString(), EventID.BYONDUpdateFail);
lock (ByondLock)
{
updateStat = ByondStatus.Idle;
@@ -328,14 +328,14 @@ namespace TGServerService
Program.DeleteDirectory(StagingDirectory);
lastError = null;
SendMessage("BYOND: Update completed!", MessageType.DeveloperInfo);
Service.WriteInfo(String.Format("BYOND update {0} completed!", GetVersion(ByondVersion.Installed)), EventID.BYONDUpdateComplete);
WriteInfo(String.Format("BYOND update {0} completed!", GetVersion(ByondVersion.Installed)), EventID.BYONDUpdateComplete);
return true;
}
catch (Exception e)
{
lastError = e.ToString();
SendMessage("BYOND: Update failed!", MessageType.DeveloperInfo);
Service.WriteError("BYOND update failed! Error: " + e.ToString(), EventID.BYONDUpdateFail);
WriteError("BYOND update failed! Error: " + e.ToString(), EventID.BYONDUpdateFail);
return false;
}
finally
+5 -5
View File
@@ -40,19 +40,19 @@ namespace TGServerService
chatProvider = new IRCChatProvider(info);
break;
default:
Service.WriteError(String.Format("Invalid chat provider: {0}", info.Provider), EventID.InvalidChatProvider);
WriteError(String.Format("Invalid chat provider: {0}", info.Provider), EventID.InvalidChatProvider);
continue;
}
}
catch (Exception e)
{
Service.WriteError(String.Format("Failed to start chat provider {0}! Error: {1}", info.Provider, e.ToString()), EventID.ChatProviderStartFail);
WriteError(String.Format("Failed to start chat provider {0}! Error: {1}", info.Provider, e.ToString()), EventID.ChatProviderStartFail);
continue;
}
chatProvider.OnChatMessage += ChatProvider_OnChatMessage;
var res = chatProvider.Connect();
if (res != null)
Service.WriteWarning(String.Format("Unable to connect to chat! Provider {0}, Error: {1}", chatProvider.GetType().ToString(), res), EventID.ChatConnectFail);
WriteWarning(String.Format("Unable to connect to chat! Provider {0}, Error: {1}", chatProvider.GetType().ToString(), res), EventID.ChatConnectFail);
ChatProviders.Add(chatProvider);
}
}
@@ -86,7 +86,7 @@ namespace TGServerService
Speaker = speaker,
Server = this,
};
Service.WriteInfo(String.Format("Chat Command from {0} ({2}): {1}", speaker, String.Join(" ", asList), channel), EventID.ChatCommand);
WriteInfo(String.Format("Chat Command from {0} ({2}): {1}", speaker, String.Join(" ", asList), channel), EventID.ChatCommand);
if (ServerChatCommands == null)
LoadServerChatCommands();
new RootChatCommand(ServerChatCommands).DoRun(asList);
@@ -229,7 +229,7 @@ namespace TGServerService
}
catch (Exception e)
{
Service.WriteWarning(String.Format("Chat broadcast failed (Provider: {3}) (Flags: {0}) (Message: {1}): {2}", mt, msg, e.ToString(), ChatProvider.ProviderInfo().Provider), EventID.ChatBroadcastFail);
WriteWarning(String.Format("Chat broadcast failed (Provider: {3}) (Flags: {0}) (Message: {1}): {2}", mt, msg, e.ToString(), ChatProvider.ProviderInfo().Provider), EventID.ChatBroadcastFail);
}
}
}
+8 -8
View File
@@ -221,7 +221,7 @@ namespace TGServerService
lock (CompilerLock)
{
SendMessage("DM: Setup failed!", MessageType.DeveloperInfo);
Service.WriteError("Compiler Initialization Error: " + e.ToString(), EventID.DMInitializeCrash);
WriteError("Compiler Initialization Error: " + e.ToString(), EventID.DMInitializeCrash);
lastCompilerError = e.ToString();
compilerCurrentStatus = CompilerStatus.Uninitialized;
return;
@@ -414,7 +414,7 @@ namespace TGServerService
{
var errorMsg = String.Format("Could not find {0}!", dmeName);
SendMessage("DM: " + errorMsg, MessageType.DeveloperInfo);
Service.WriteError(errorMsg, EventID.DMCompileCrash);
WriteError(errorMsg, EventID.DMCompileCrash);
lock (CompilerLock)
{
lastCompilerError = errorMsg;
@@ -427,7 +427,7 @@ namespace TGServerService
{
lastCompilerError = "The precompile hook failed";
compilerCurrentStatus = CompilerStatus.Initialized; //still fairly valid
Service.WriteWarning("Precompile hook failed!", EventID.DMCompileError);
WriteWarning("Precompile hook failed!", EventID.DMCompileError);
return;
}
@@ -525,13 +525,13 @@ namespace TGServerService
{
lastCompilerError = "The postcompile hook failed";
compilerCurrentStatus = CompilerStatus.Initialized; //still fairly valid
Service.WriteWarning("Postcompile hook failed!", EventID.DMCompileError);
WriteWarning("Postcompile hook failed!", EventID.DMCompileError);
return;
}
UpdateLiveSha(CurrentSha);
var msg = String.Format("Compile complete!{0}", !staged ? "" : " Server will update next round.");
SendMessage("DM: " + msg, MessageType.DeveloperInfo);
Service.WriteInfo(msg, EventID.DMCompileSuccess);
WriteInfo(msg, EventID.DMCompileSuccess);
lock (CompilerLock)
{
if (staged)
@@ -543,7 +543,7 @@ namespace TGServerService
else
{
SendMessage("DM: Compile failed!", MessageType.DeveloperInfo); //Also happens for warnings
Service.WriteWarning("Compile error: " + OutputList.ToString(), EventID.DMCompileError);
WriteWarning("Compile error: " + OutputList.ToString(), EventID.DMCompileError);
lock (CompilerLock)
{
lastCompilerError = "DM compile failure";
@@ -560,7 +560,7 @@ namespace TGServerService
catch (Exception e)
{
SendMessage("DM: Compiler thread crashed!", MessageType.DeveloperInfo);
Service.WriteError("Compile manager errror: " + e.ToString(), EventID.DMCompileCrash);
WriteError("Compile manager errror: " + e.ToString(), EventID.DMCompileCrash);
lock (CompilerLock)
{
lastCompilerError = e.ToString();
@@ -577,7 +577,7 @@ namespace TGServerService
compilerCurrentStatus = CompilerStatus.Initialized;
compilationCancellationRequestation = false;
SendMessage("DM: Compile cancelled!", MessageType.DeveloperInfo);
Service.WriteInfo("Compilation cancelled", EventID.DMCompileCancel);
WriteInfo("Compilation cancelled", EventID.DMCompileCancel);
}
}
}
+6 -6
View File
@@ -81,7 +81,7 @@ namespace TGServerService
var output = File.ReadAllText(path);
Service.CancelImpersonation();
Service.WriteInfo("Read of " + path, EventID.StaticRead);
WriteInfo("Read of " + path, EventID.StaticRead);
error = null;
unauthorized = false;
return output;
@@ -98,7 +98,7 @@ namespace TGServerService
{
error = e.ToString();
Service.CancelImpersonation();
Service.WriteWarning(String.Format("Read of {0} failed! Error: {1}", path, e.ToString()), EventID.StaticRead);
WriteWarning(String.Format("Read of {0} failed! Error: {1}", path, e.ToString()), EventID.StaticRead);
unauthorized = false;
return null;
}
@@ -137,7 +137,7 @@ namespace TGServerService
Directory.CreateDirectory(destdir);
File.WriteAllText(path, data);
Service.CancelImpersonation();
Service.WriteInfo("Write to " + path, EventID.StaticWrite);
WriteInfo("Write to " + path, EventID.StaticWrite);
unauthorized = false;
return null;
}
@@ -152,7 +152,7 @@ namespace TGServerService
{
unauthorized = false;
Service.CancelImpersonation();
Service.WriteWarning(String.Format("Write of {0} failed! Error: {1}", path, e.ToString()), EventID.StaticRead);
WriteWarning(String.Format("Write of {0} failed! Error: {1}", path, e.ToString()), EventID.StaticRead);
return e.ToString();
}
}
@@ -191,7 +191,7 @@ namespace TGServerService
else if (Directory.Exists(path))
Program.DeleteDirectory(path);
Service.CancelImpersonation();
Service.WriteInfo("Delete of " + path, EventID.StaticDelete);
WriteInfo("Delete of " + path, EventID.StaticDelete);
unauthorized = false;
return null;
}
@@ -206,7 +206,7 @@ namespace TGServerService
{
unauthorized = false;
Service.CancelImpersonation();
Service.WriteWarning(String.Format("Delete of {0} failed! Error: {1}", path, e.ToString()), EventID.StaticRead);
WriteWarning(String.Format("Delete of {0} failed! Error: {1}", path, e.ToString()), EventID.StaticRead);
return e.ToString();
}
}
+10 -10
View File
@@ -105,7 +105,7 @@ namespace TGServerService
Proc = Process.GetProcessById(Config.ReattachProcessID);
if (Proc == null)
throw new Exception("GetProcessById returned null!");
Service.WriteInfo("Reattached to running DD process!", EventID.DDReattachSuccess);
WriteInfo("Reattached to running DD process!", EventID.DDReattachSuccess);
ThreadPool.QueueUserWorkItem(_ =>
{
Thread.Sleep(5000);
@@ -131,7 +131,7 @@ namespace TGServerService
}
catch (Exception e)
{
Service.WriteError(String.Format("Failed to reattach to DreamDaemon! PID: {0}. Exception: {1}", Config.ReattachProcessID, e.ToString()), EventID.DDReattachFail);
WriteError(String.Format("Failed to reattach to DreamDaemon! PID: {0}. Exception: {1}", Config.ReattachProcessID, e.ToString()), EventID.DDReattachFail);
}
finally
{
@@ -309,13 +309,13 @@ namespace TGServerService
if (!RestartInProgress)
{
SendMessage("DD: Server started, watchdog active...", MessageType.WatchdogInfo);
Service.WriteInfo("Watchdog started", EventID.DDWatchdogStarted);
WriteInfo("Watchdog started", EventID.DDWatchdogStarted);
}
else
{
RestartInProgress = false;
if (!ReattachInsteadOfRestart)
Service.WriteInfo("Watchdog restarted", EventID.DDWatchdogRestarted);
WriteInfo("Watchdog restarted", EventID.DDWatchdogRestarted);
else
ReattachInsteadOfRestart = false;
}
@@ -383,7 +383,7 @@ namespace TGServerService
retries = 0;
var msg = "DD: DreamDaemon crashed! Watchdog rebooting DD...";
SendMessage(msg, MessageType.WatchdogInfo);
Service.WriteWarning(msg, EventID.DDWatchdogRebootingServer);
WriteWarning(msg, EventID.DDWatchdogRebootingServer);
}
}
@@ -420,7 +420,7 @@ namespace TGServerService
catch (Exception e)
{
SendMessage("DD: Watchdog thread crashed!", MessageType.WatchdogInfo);
Service.WriteError("Watch dog thread crashed: " + e.ToString(), EventID.DDWatchdogCrash);
WriteError("Watch dog thread crashed: " + e.ToString(), EventID.DDWatchdogCrash);
}
finally
{
@@ -435,10 +435,10 @@ namespace TGServerService
{
if (!Config.ReattachRequired)
SendMessage("DD: Server stopped, watchdog exiting...", MessageType.WatchdogInfo);
Service.WriteInfo("Watch dog exited", EventID.DDWatchdogExit);
WriteInfo("Watch dog exited", EventID.DDWatchdogExit);
}
else
Service.WriteInfo("Watch dog restarting...", EventID.DDWatchdogRestart);
WriteInfo("Watch dog restarting...", EventID.DDWatchdogRestart);
}
}
}
@@ -538,7 +538,7 @@ namespace TGServerService
return; //no need
}
File.Copy(InterfacePath, InterfaceDLLName, overwrite);
Service.WriteInfo("Updated interface DLL", EventID.InterfaceDLLUpdated);
WriteInfo("Updated interface DLL", EventID.InterfaceDLLUpdated);
}
catch
{
@@ -551,7 +551,7 @@ namespace TGServerService
catch (Exception e)
{
//intentionally using the fi
Service.WriteError("Failed to update interface DLL! Error: " + e.ToString(), EventID.InterfaceDLLUpdateFail);
WriteError("Failed to update interface DLL! Error: " + e.ToString(), EventID.InterfaceDLLUpdateFail);
}
}
}
+5 -5
View File
@@ -89,7 +89,7 @@ namespace TGServerService
SendMessage("RELAY: " + String.Join(" ", splits), MessageType.AdminInfo);
break;
case SRWorldReboot:
Service.WriteInfo("World Rebooted", EventID.WorldReboot);
WriteInfo("World Rebooted", EventID.WorldReboot);
WriteCurrentDDLog("World rebooted");
ServerChatCommands = null;
ChatConnectivityCheck();
@@ -102,7 +102,7 @@ namespace TGServerService
{
GameAPIVersion = null; //needs updating
}
Service.WriteInfo("Staged update applied", EventID.ServerUpdateApplied);
WriteInfo("Staged update applied", EventID.ServerUpdateApplied);
}
}
break;
@@ -117,7 +117,7 @@ namespace TGServerService
}
catch
{
Service.WriteWarning(String.Format("API version of the game ({0}) is incompatible with the current supported API versions (3.{2}.x.x). Interop disabled.", splits.Count > 1 ? splits[1] : "NULL", AllowedMajorAPIVersion), EventID.APIVersionMismatch);
WriteWarning(String.Format("API version of the game ({0}) is incompatible with the current supported API versions (3.{2}.x.x). Interop disabled.", splits.Count > 1 ? splits[1] : "NULL", AllowedMajorAPIVersion), EventID.APIVersionMismatch);
GameAPIVersion = null;
break;
}
@@ -230,7 +230,7 @@ namespace TGServerService
serviceCommsKey += tmp;
} while (serviceCommsKey.Length < CommsKeyLen);
serviceCommsKey = serviceCommsKey.Substring(0, CommsKeyLen);
Service.WriteInfo("Service Comms Key set to: " + serviceCommsKey, EventID.CommsKeySet);
WriteInfo("Service Comms Key set to: " + serviceCommsKey, EventID.CommsKeySet);
}
/// <inheritdoc />
@@ -243,7 +243,7 @@ namespace TGServerService
}
catch(Exception e)
{
Service.WriteWarning(String.Format("Handle command for \"{0}\" failed: {1}", command, e.ToString()), EventID.InteropCallException);
WriteWarning(String.Format("Handle command for \"{0}\" failed: {1}", command, e.ToString()), EventID.InteropCallException);
return false;
}
}
@@ -74,9 +74,9 @@ namespace TGServerService
var eventData = String.Format("Preaction Event: {0} @ {1} ran. Stdout:\n{2}\nStderr:\n{3}", eventName, GetEventPath(eventName), stdout, stderr);
if (success)
Service.WriteInfo(eventData, EventID.PreactionEvent);
WriteInfo(eventData, EventID.PreactionEvent);
else
Service.WriteWarning(eventData, EventID.PreactionFail);
WriteWarning(eventData, EventID.PreactionFail);
return success;
}
+25 -25
View File
@@ -255,7 +255,7 @@ namespace TGServerService
InitialConfigureRepository();
SendMessage("REPO: Clone complete!", MessageType.DeveloperInfo);
Service.WriteInfo("Repository {0}:{1} successfully cloned", EventID.RepoClone);
WriteInfo("Repository {0}:{1} successfully cloned", EventID.RepoClone);
}
finally
{
@@ -266,7 +266,7 @@ namespace TGServerService
{
SendMessage("REPO: Setup failed!", MessageType.DeveloperInfo);
Service.WriteWarning(String.Format("Failed to clone {2}:{0}: {1}", BranchName, e.ToString(), RepoURL), EventID.RepoCloneFail);
WriteWarning(String.Format("Failed to clone {2}:{0}: {1}", BranchName, e.ToString(), RepoURL), EventID.RepoCloneFail);
}
finally
{
@@ -352,7 +352,7 @@ namespace TGServerService
}
catch
{
Service.WriteError("Could not setup static directory: " + I, EventID.RepoConfigurationFail);
WriteError("Could not setup static directory: " + I, EventID.RepoConfigurationFail);
}
}
foreach(var I in Config.DLLPaths)
@@ -362,7 +362,7 @@ namespace TGServerService
var source = Path.Combine(RepoPath, I);
if (!File.Exists(source))
{
Service.WriteWarning("Could not find DLL: " + I, EventID.RepoConfigurationFail);
WriteWarning("Could not find DLL: " + I, EventID.RepoConfigurationFail);
continue;
}
var dest = Path.Combine(StaticDirs, I);
@@ -370,7 +370,7 @@ namespace TGServerService
}
catch
{
Service.WriteError("Could not setup static DLL: " + I, EventID.RepoConfigurationFail);
WriteError("Could not setup static DLL: " + I, EventID.RepoConfigurationFail);
}
}
}
@@ -524,13 +524,13 @@ namespace TGServerService
var res = ResetNoLock(null);
UpdateSubmodules();
SendMessage("REPO: Checkout complete!", MessageType.DeveloperInfo);
Service.WriteInfo("Repo checked out " + sha, EventID.RepoCheckout);
WriteInfo("Repo checked out " + sha, EventID.RepoCheckout);
return res;
}
catch (Exception e)
{
SendMessage("REPO: Checkout failed!", MessageType.DeveloperInfo);
Service.WriteWarning(String.Format("Repo checkout of {0} failed: {1}", sha, e.ToString()), EventID.RepoCheckoutFail);
WriteWarning(String.Format("Repo checkout of {0} failed: {1}", sha, e.ToString()), EventID.RepoCheckoutFail);
return e.ToString();
}
}
@@ -602,20 +602,20 @@ namespace TGServerService
if (error != null)
throw new Exception(error);
DeletePRList();
Service.WriteInfo("Repo hard updated to " + originBranch.Tip.Sha, EventID.RepoHardUpdate);
WriteInfo("Repo hard updated to " + originBranch.Tip.Sha, EventID.RepoHardUpdate);
return error;
}
res = MergeBranch(originBranch.FriendlyName);
if (res != null)
throw new Exception(res);
UpdateSubmodules();
Service.WriteInfo("Repo merge updated to " + originBranch.Tip.Sha, EventID.RepoMergeUpdate);
WriteInfo("Repo merge updated to " + originBranch.Tip.Sha, EventID.RepoMergeUpdate);
return null;
}
catch (Exception E)
{
SendMessage("REPO: Update failed!", MessageType.DeveloperInfo);
Service.WriteWarning(String.Format("Repo{0} update failed", reset ? " hard" : ""), reset ? EventID.RepoHardUpdateFail : EventID.RepoMergeUpdateFail);
WriteWarning(String.Format("Repo{0} update failed", reset ? " hard" : ""), reset ? EventID.RepoHardUpdateFail : EventID.RepoMergeUpdateFail);
return E.ToString();
}
}
@@ -650,7 +650,7 @@ namespace TGServerService
Repo.Submodules.Update(I.Name, suo);
var msg = String.Format("I had to reclone submodule {0}. If this is happening a lot find a better hack or fix https://github.com/libgit2/libgit2/issues/3820!", I.Name);
SendMessage(String.Format("REPO: {0}", msg), MessageType.DeveloperInfo);
Service.WriteWarning(msg, EventID.SubmoduleReclone);
WriteWarning(msg, EventID.SubmoduleReclone);
}
}
@@ -679,7 +679,7 @@ namespace TGServerService
if (tag != null)
{
Service.WriteInfo("Repo backup created at tag: " + tagName + " commit: " + HEAD, EventID.RepoBackupTag);
WriteInfo("Repo backup created at tag: " + tagName + " commit: " + HEAD, EventID.RepoBackupTag);
return null;
}
throw new Exception("Tag creation failed!");
@@ -687,7 +687,7 @@ namespace TGServerService
}
catch (Exception e)
{
Service.WriteWarning(String.Format("Failed backup tag creation at commit {0}!", Repo.Head.Tip.Sha), EventID.RepoBackupTagFail);
WriteWarning(String.Format("Failed backup tag creation at commit {0}!", Repo.Head.Tip.Sha), EventID.RepoBackupTagFail);
return e.ToString();
}
}
@@ -732,10 +732,10 @@ namespace TGServerService
SendMessage(String.Format("REPO: Hard reset to {0}branch", trackedBranch ? "tracked " : ""), MessageType.DeveloperInfo);
if (trackedBranch)
DeletePRList();
Service.WriteInfo(String.Format("Repo branch reset{0}", trackedBranch ? " to tracked branch" : ""), trackedBranch ? EventID.RepoResetTracked : EventID.RepoReset);
WriteInfo(String.Format("Repo branch reset{0}", trackedBranch ? " to tracked branch" : ""), trackedBranch ? EventID.RepoResetTracked : EventID.RepoReset);
return null;
}
Service.WriteWarning(String.Format("Failed to reset{0}: {1}", trackedBranch ? " to tracked branch" : "", res), trackedBranch ? EventID.RepoResetTrackedFail : EventID.RepoResetFail);
WriteWarning(String.Format("Failed to reset{0}: {1}", trackedBranch ? " to tracked branch" : "", res), trackedBranch ? EventID.RepoResetTrackedFail : EventID.RepoResetFail);
return res;
}
}
@@ -761,7 +761,7 @@ namespace TGServerService
}
catch (Exception e)
{
Service.WriteError("Failed to delete PR list: " + e.ToString(), EventID.RepoPRListError);
WriteError("Failed to delete PR list: " + e.ToString(), EventID.RepoPRListError);
}
}
@@ -849,7 +849,7 @@ namespace TGServerService
if (Result == null)
{
Service.WriteInfo(String.Format("Merged pull request #{0}", PRNumber), EventID.RepoPRMerge);
WriteInfo(String.Format("Merged pull request #{0}", PRNumber), EventID.RepoPRMerge);
try
{
var CurrentPRs = GetCurrentPRList();
@@ -882,7 +882,7 @@ namespace TGServerService
}
catch (Exception e)
{
Service.WriteError("Failed to update PR list", EventID.RepoPRListError);
WriteError("Failed to update PR list", EventID.RepoPRListError);
return "PR Merged, JSON update failed: " + e.ToString();
}
}
@@ -891,7 +891,7 @@ namespace TGServerService
catch (Exception E)
{
SendMessage("REPO: PR merge failed!", MessageType.DeveloperInfo);
Service.WriteWarning(String.Format("Failed to merge pull request #{0}: {1}", PRNumber, E.ToString()), EventID.RepoPRMergeFail);
WriteWarning(String.Format("Failed to merge pull request #{0}: {1}", PRNumber, E.ToString()), EventID.RepoPRMergeFail);
return E.ToString();
}
}
@@ -1054,13 +1054,13 @@ namespace TGServerService
var authorandcommitter = MakeSig();
// Commit to the repository
Service.WriteInfo(String.Format("Commit {0} created from changelogs", Repo.Commit(CommitMessage, authorandcommitter, authorandcommitter)), EventID.RepoCommit);
WriteInfo(String.Format("Commit {0} created from changelogs", Repo.Commit(CommitMessage, authorandcommitter, authorandcommitter)), EventID.RepoCommit);
DeletePRList();
return null;
}
catch (Exception e)
{
Service.WriteWarning("Repo commit failed: " + e.ToString(), EventID.RepoCommitFail);
WriteWarning("Repo commit failed: " + e.ToString(), EventID.RepoCommitFail);
return e.ToString();
}
}
@@ -1086,12 +1086,12 @@ namespace TGServerService
CredentialsProvider = GenerateGitCredentials,
};
Repo.Network.Push(Repo.Network.Remotes[SSHPushRemote], Repo.Head.CanonicalName, options);
Service.WriteInfo("Repo pushed up to commit: " + Repo.Head.Tip.Sha, EventID.RepoPush);
WriteInfo("Repo pushed up to commit: " + Repo.Head.Tip.Sha, EventID.RepoPush);
return null;
}
catch (Exception e)
{
Service.WriteWarning("Repo push failed: " + e.ToString(), EventID.RepoPushFail);
WriteWarning("Repo push failed: " + e.ToString(), EventID.RepoPushFail);
return e.ToString();
}
}
@@ -1237,13 +1237,13 @@ namespace TGServerService
return GenerateChangelogImpl(out error, true);
}
error = null;
Service.WriteInfo("Changelog generated" + error, EventID.RepoChangelog);
WriteInfo("Changelog generated" + error, EventID.RepoChangelog);
return result;
}
catch (Exception e)
{
error = e.ToString();
Service.WriteWarning("Changelog generation failed: " + error, EventID.RepoChangelogFail);
WriteWarning("Changelog generation failed: " + error, EventID.RepoChangelogFail);
return null;
}
}
@@ -1,4 +1,5 @@
using System;
using System.Diagnostics;
using System.ServiceModel;
using TGServiceInterface.Components;
@@ -15,6 +16,10 @@ namespace TGServerService
[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple, InstanceContextMode = InstanceContextMode.Single)]
sealed partial class ServerInstance : IDisposable, ITGConnectivity
{
/// <summary>
/// Used to assign the instance to event IDs
/// </summary>
public readonly byte LoggingID;
/// <summary>
/// The configuration settings for the instance
/// </summary>
@@ -22,8 +27,9 @@ namespace TGServerService
/// <summary>
/// Constructs and a <see cref="ServerInstance"/>
/// </summary>
public ServerInstance(InstanceConfig config)
public ServerInstance(InstanceConfig config, byte logID)
{
LoggingID = logID;
Config = config;
FindTheDroidsWereLookingFor();
InitEventHandlers();
@@ -46,6 +52,46 @@ namespace TGServerService
DisposeChat();
}
/// <summary>
/// Writes information to the Windows event log
/// </summary>
/// <param name="message">The log message</param>
/// <param name="id">The <see cref="EventID"/> of the message</param>
void WriteInfo(string message, EventID id)
{
Service.WriteEntry(message, id, EventLogEntryType.Information, LoggingID);
}
/// <summary>
/// Writes an error to the Windows event log
/// </summary>
/// <param name="message">The log message</param>
/// <param name="id">The <see cref="EventID"/> of the message</param>
void WriteError(string message, EventID id)
{
Service.WriteEntry(message, id, EventLogEntryType.Error, LoggingID);
}
/// <summary>
/// Writes a warning to the Windows event log
/// </summary>
/// <param name="message">The log message</param>
/// <param name="id">The <see cref="EventID"/> of the message</param>
void WriteWarning(string message, EventID id)
{
Service.WriteEntry(message, id, EventLogEntryType.Warning, LoggingID);
}
/// <summary>
/// Writes an access event to the Windows event log
/// </summary>
/// <param name="username">The (un)authenticated Windows user's name</param>
/// <param name="authSuccess"><see langword="true"/> if <paramref name="username"/> authenticated sucessfully, <see langword="false"/> otherwise</param>
void WriteAccess(string username, bool authSuccess)
{
Service.WriteEntry(String.Format("Access from: {0}", username), EventID.Authentication, authSuccess ? EventLogEntryType.SuccessAudit : EventLogEntryType.FailureAudit, LoggingID);
}
/// <inheritdoc />
public string Version()
{
+100 -47
View File
@@ -15,6 +15,11 @@ namespace TGServerService
/// </summary>
sealed partial class Service : ServiceBase
{
/// <summary>
/// The logging ID used for <see cref="Service"/> events
/// </summary>
public const byte LoggingID = 0;
/// <summary>
/// The service version <see cref="string"/> based on the <see cref="FileVersionInfo"/>
/// </summary>
@@ -34,57 +39,44 @@ namespace TGServerService
}
/// <summary>
/// Writes information to Windows the event log
/// Writes an event to Windows the event log
/// </summary>
/// <param name="message">The log message</param>
/// <param name="id">The <see cref="EventID"/> of the message</param>
public static void WriteInfo(string message, EventID id)
/// <param name="eventType">The <see cref="EventLogEntryType"/> of the event</param>
/// <param name="loggingID">The logging source ID for the event</param>
public static void WriteEntry(string message, EventID id, EventLogEntryType eventType, byte loggingID)
{
ActiveService.EventLog.WriteEntry(message, EventLogEntryType.Information, (int)id);
}
/// <summary>
/// Writes an error to the Windows event log
/// </summary>
/// <param name="message">The log message</param>
/// <param name="id">The <see cref="EventID"/> of the message</param>
public static void WriteError(string message, EventID id)
{
ActiveService.EventLog.WriteEntry(message, EventLogEntryType.Error, (int)id);
}
/// <summary>
/// Writes a warning to the Windows event log
/// </summary>
/// <param name="message">The log message</param>
/// <param name="id">The <see cref="EventID"/> of the message</param>
public static void WriteWarning(string message, EventID id)
{
ActiveService.EventLog.WriteEntry(message, EventLogEntryType.Warning, (int)id);
}
/// <summary>
/// Writes an access event to the Windows event log
/// </summary>
/// <param name="username">The (un)authenticated Windows user's name</param>
/// <param name="authSuccess"><see langword="true"/> if <paramref name="username"/> authenticated sucessfully, <see langword="false"/> otherwise</param>
public static void WriteAccess(string username, bool authSuccess)
{
ActiveService.EventLog.WriteEntry(String.Format("Access from: {0}", username), authSuccess ? EventLogEntryType.SuccessAudit : EventLogEntryType.FailureAudit, (int)EventID.Authentication);
ActiveService.EventLog.WriteEntry(message, eventType, (int)id + loggingID);
}
/// <summary>
/// The WCF host that contains <see cref="ITGSService"/> connects to
/// </summary>
ServiceHost serviceHost;
/// <summary>
/// Map of <see cref="InstanceConfig.Name"/> to the respective <see cref=""/>
/// </summary>
IDictionary<string, ServiceHost> hosts;
/// <summary>
/// List of <see cref="ServerInstance.LoggingID"/>s in use
/// </summary>
IList<int> UsedLoggingIDs = new List<int>();
/// <summary>
/// Migrates the .NET config from <paramref name="oldVersion"/> to <paramref name="newVersion"/>
/// Migrates the .NET config from <paramref name="oldVersion"/> to <paramref name="oldVersion"/> + 1
/// </summary>
/// <param name="oldVersion">The version to migrate from</param>
/// <param name="newVersion">The version to migrate to</param>
void MigrateSettings(int oldVersion, int newVersion)
void MigrateSettings(int oldVersion)
{
//Uneeded... So far...
switch (oldVersion)
{
case 6: //switch to per-instance configs
var IC = DeprecatedInstanceConfig.CreateFromNETSettings(out string instanceDir);
IC.Save();
Properties.Settings.Default.InstancePaths.Add(instanceDir);
break;
}
}
//you should seriously not add anything here
@@ -102,10 +94,11 @@ namespace TGServerService
{
var newVersion = Config.SettingsVersion;
Config.Upgrade();
var oldVersion = Config.SettingsVersion;
Config.SettingsVersion = newVersion;
for(var oldVersion = Config.SettingsVersion; oldVersion < newVersion; ++oldVersion)
MigrateSettings(oldVersion);
MigrateSettings(oldVersion, newVersion);
Config.SettingsVersion = newVersion;
Config.UpgradeRequired = false;
Config.Save();
@@ -120,6 +113,10 @@ namespace TGServerService
}
}
/// <summary>
/// Overrides and saves the configured <see cref="Properties.Settings.RemoteAccessPort"/> if requested by command line parameters
/// </summary>
/// <param name="args">The command line parameters for the <see cref="Service"/></param>
void ChangePortFromCommandLine(string[] args)
{
var Config = Properties.Settings.Default;
@@ -142,7 +139,11 @@ namespace TGServerService
break;
}
}
//when babby is formed
/// <summary>
/// Called by the Windows service manager. Initializes and starts configured <see cref="ServerInstance"/>s
/// </summary>
/// <param name="args">Command line arguments for the <see cref="Service"/></param>
protected override void OnStart(string[] args)
{
ChangePortFromCommandLine(args);
@@ -154,6 +155,9 @@ namespace TGServerService
OnlineAllHosts();
}
/// <summary>
/// Creates the <see cref="ServiceHost"/> for <see cref="ITGSService"/>
/// </summary>
void SetupService()
{
serviceHost = CreateHost(this);
@@ -161,6 +165,9 @@ namespace TGServerService
serviceHost.Authorization.ServiceAuthorizationManager = new AdministrativeAuthorizationManager(); //only admins can diddle us
}
/// <summary>
/// Opens all created <see cref="ServiceHost"/>s
/// </summary>
void OnlineAllHosts()
{
serviceHost.Open();
@@ -168,6 +175,11 @@ namespace TGServerService
I.Value.Open();
}
/// <summary>
/// Creates a <see cref="ServiceHost"/> for <paramref name="singleton"/> using the default pipe, <see cref="ServiceHost.CloseTimeout"/>, and the configured <see cref="Properties.Settings.RemoteAccessPort"/>
/// </summary>
/// <param name="singleton">The <see cref="ServiceHost.SingletonInstance"/></param>
/// <returns>The created <see cref="ServiceHost"/></returns>
static ServiceHost CreateHost(object singleton)
{
return new ServiceHost(singleton, new Uri[] { new Uri("net.pipe://localhost"), new Uri(String.Format("https://localhost:{0}", Properties.Settings.Default.RemoteAccessPort)) })
@@ -176,13 +188,52 @@ namespace TGServerService
};
}
/// <summary>
/// Creates <see cref="ServiceHost"/>s for all <see cref="ServerInstance"/>s as listed in <see cref="Properties.Settings.InstancePaths"/>
/// </summary>
void SetupInstances()
{
hosts = new Dictionary<string, ServiceHost>();
var pathsToRemove = new List<string>();
foreach (var I in Properties.Settings.Default.InstancePaths)
if (SetupInstance(I) != null)
pathsToRemove.Add(I);
}
/// <summary>
/// Unlocks a <see cref="ServerInstance.LoggingID"/> acquired with <see cref="LockLoggingID"/>
/// </summary>
/// <param name="ID">The <see cref="ServerInstance.LoggingID"/> to unlock</param>
void UnlockLoggingID(byte ID)
{
lock (UsedLoggingIDs)
{
UsedLoggingIDs.Remove(ID);
}
}
/// <summary>
/// Gets and locks a <see cref="ServerInstance.LoggingID"/>
/// </summary>
/// <returns>A logging ID for the <see cref="ServerInstance"/> must be released using <see cref="UnlockLoggingID(byte)"/></returns>
byte LockLoggingID()
{
lock (UsedLoggingIDs)
{
for (byte I = 1; I < 100; ++I)
if (!UsedLoggingIDs.Contains(I))
{
return I;
}
}
throw new Exception("All logging IDs in use!");
}
/// <summary>
/// Creates and starts a <see cref="ServiceHost"/> for a <see cref="ServerInstance"/> at <paramref name="path"/>
/// </summary>
/// <param name="path">The path to the <see cref="ServerInstance"/></param>
/// <returns>The inactive <see cref="ServiceHost"/> on success, <see langword="null"/> on failure</returns>
ServiceHost SetupInstance(string path)
{
ServerInstance instance;
@@ -192,16 +243,18 @@ namespace TGServerService
if (hosts.ContainsKey(path))
{
var datInstance = ((ServerInstance)hosts[path].SingletonInstance);
WriteError(String.Format("Unable to start instance at path {0}. Has the same name as instance at path {1} ({2}). Detaching...", path, datInstance.ServerDirectory(), datInstance.Config.Name), EventID.InstanceInitializationFailure);
WriteEntry(String.Format("Unable to start instance at path {0}. Has the same name as instance at path {1} ({2}). Detaching...", path, datInstance.ServerDirectory(), datInstance.Config.Name), EventID.InstanceInitializationFailure, EventLogEntryType.Error, LoggingID);
return null;
}
if (!config.Enabled)
return null;
instance = new ServerInstance(config);
var ID = LockLoggingID();
WriteEntry(String.Format("Instance {0} ({1}) assigned logging ID {2}", config.Name, path, ID), EventID.InstanceIDAssigned, EventLogEntryType.Information, ID);
instance = new ServerInstance(config, ID);
}
catch (Exception e)
{
WriteError(String.Format("Unable to start instance at path {0}. Detaching... Error: {1}", path, e.ToString()), EventID.InstanceInitializationFailure);
WriteEntry(String.Format("Unable to start instance at path {0}. Detaching... Error: {1}", path, e.ToString()), EventID.InstanceInitializationFailure, EventLogEntryType.Error, LoggingID);
return null;
}
@@ -217,11 +270,11 @@ namespace TGServerService
}
/// <summary>
/// Adds a WCF endpoint for a component <paramref name="type"/>
/// Adds a WCF endpoint for a component <paramref name="typetype"/>
/// </summary>
/// <param name="host"></param>
/// <param name="typetype"></param>
/// <param name="PipePrefix"></param>
/// <param name="host">The service host to add the component to</param>
/// <param name="typetype">The type of the component</param>
/// <param name="PipePrefix">The URI prefix for accessing the <paramref name="host"/></param>
void AddEndpoint(ServiceHost host, Type typetype, string PipePrefix)
{
var bindingName = PipePrefix + "/" + typetype.Name;
@@ -255,7 +308,7 @@ namespace TGServerService
}
catch (Exception e)
{
WriteError(e.ToString(), EventID.ServiceShutdownFail);
WriteEntry(e.ToString(), EventID.ServiceShutdownFail, EventLogEntryType.Error, LoggingID);
}
}