public void ThreadSafeLogger_SaveMultiThreadLog() { var messages = new List <string>(); var logger = new LambdaLogger(m => { messages.Add(m.Message); }); var saveLogger = new ThreadSafeLogger(logger); var task1 = Task.Run(() => { Enumerable.Range(1, 1500).Each(x => { saveLogger.Log(new LogRecord { Message = "1" }); }); }); var task2 = Task.Run(() => { Enumerable.Range(1, 1500).Each(x => { saveLogger.Log(new LogRecord { Message = "2" }); }); }); Task.WaitAll(task1, task2); Assert.AreEqual(3000, messages.Count); Assert.AreEqual(messages.Count(x => x == "1"), messages.Count(x => x == "2")); }
public override void OnGameLoaded(Game g, Harmony h) { var factionManger = g.World.factionManager; foreach (var fac in factionManger.allFactions.Where(f => f.def == null)) { fac.def = FactionDef.Named("OutlanderCivil"); } foreach (var wo in g.World.worldObjects.worldObjects.Where(w => w.factionInt.def == null)) { var faction = factionManger.allFactions.Where(f => !f.IsPlayer && (!f.hidden ?? true)).RandomElement(); ThreadSafeLogger.Warning($"[Analyzer] Changed the world object {wo.Label}'s faction from {wo.factionInt.name}(Removed) to {faction.name}"); wo.factionInt = faction; } foreach (var wp in g.World.worldPawns.AllPawnsAliveOrDead.Where(p => p.factionInt.def == null)) { var faction = factionManger.allFactions.Where(f => !f.IsPlayer && (!f.hidden ?? true)).RandomElement(); ThreadSafeLogger.Warning($"[Analyzer] Changed the pawn {wp.Label}'s faction from {wp.factionInt.name}(Removed) to {faction.name}"); wp.factionInt = faction; } Active = false; }
public Modbase(ModContentPack content) : base(content) { Settings = GetSettings <Settings>(); ThreadSafeLogger.Message($"[Analyzer] Loaded version {analyzerVersion.Major}.{analyzerVersion.Minor}.{analyzerVersion.Build} rev {analyzerVersion.Revision}"); { // Profiling ModInfoCache.PopulateCache(Content.Name); GUIController.InitialiseTabs(); // GUI needs to be initialised before xml (the tabs need to exist for entries to be inserted into them) XmlParser.CollectXmlData(); } { // Always Running StaticHarmony.Patch(AccessTools.Method(typeof(GlobalControlsUtility), nameof(GlobalControlsUtility.DoTimespeedControls)), prefix: new HarmonyMethod(typeof(GUIElement_TPS), nameof(GUIElement_TPS.Prefix))); } { // Performance Patches PerformancePatches.InitialisePatches(); } #if DEBUG ThreadSafeLogger.Warning("=========================================================================="); ThreadSafeLogger.Warning(" Analyzer Running In Debug Mode "); ThreadSafeLogger.Warning("=========================================================================="); #endif }
public static void OnGUI() { if (restartkey.KeyDownEvent) { GenCommandLine.Restart(); } try { if (key != null && key.KeyDownEvent) { if (Find.WindowStack.WindowOfType <Window_Analyzer>() != null) { Find.WindowStack.RemoveWindowsOfType(typeof(Window_Analyzer)); } else { Find.WindowStack.Add(new Window_Analyzer()); } } } catch (Exception e) { ThreadSafeLogger.Error(e.ToString()); } if (alertKey.KeyDownEvent) { H_AlertsReadoutUpdate.DisableAlerts = !H_AlertsReadoutUpdate.DisableAlerts; } }
public static bool CheckAddOrRemoveAlert(AlertsReadout __instance, Alert alert, bool forceRemove) { if (DisableAlerts) { return(false); } if (!OverrideAlerts) { return(true); } try { var alertActive = false; var alertType = alert.GetType(); if (AlertFilter.TryGetValue(alertType, out var active)) { if (!active) { alert.Recalculate(); alertActive = alert.Active; } else // We ensure alerts show up so you can re-enable disabled alerts. { if (AlertRecalculate.Active) { var prof = ProfileController.Start(alertType.Name, () => alertType.FullName, alertType, AlertRecalculate.recalculate); prof?.Stop(); } } } else { alert.Recalculate(); alertActive = alert.Active; } if (!forceRemove && alertActive) { if (!__instance.activeAlerts.Contains(alert)) { __instance.activeAlerts.Add(alert); alert.Notify_Started(); } } else { __instance.activeAlerts.Remove(alert); } } catch (Exception e) { ThreadSafeLogger.ReportExceptionOnce(e, $"Exception processing alert {alert}", alert.GetHashCode()); __instance.activeAlerts.Remove(alert); } return(false); }
public void Initialise(Type subType) { EnabledRefAccess = AccessTools.StaticFieldRefAccess <bool>(subType.GetField("Active", BindingFlags.Public | BindingFlags.Static)); if (EnabledRefAccess == null) { ThreadSafeLogger.Error("Add an 'Active' field you bloody muppet"); } }
//Thread safe public static ThreadSafeLogger GetInstance() { lock (obj) { if (logger == null) { logger = new ThreadSafeLogger(); } } return(logger); }
public static bool Load(UnityModManager.ModEntry modEntry) { var harmony = HarmonyInstance.Create(modEntry.Info.Id); harmony.PatchAll(Assembly.GetExecutingAssembly()); Logger = new ThreadSafeLogger(modEntry.Logger); settings = UnityModManager.ModSettings.Load <Settings>(modEntry); modEntry.OnToggle = OnToggle; modEntry.OnGUI = OnGUI; modEntry.OnSaveGUI = OnSaveGUI; return(true); }
public override void PreOpen() { if (Analyzer.CurrentlyCleaningUp) { Find.WindowStack.TryRemove(this); ThreadSafeLogger.Error("[Analyzer] Analyzer is currently in the process of cleaning up - This is unlikely to happen, and shouldn't take long. please attempt to re-open the window in a couple seconds"); return; } base.PreOpen(); if (firstOpen) // If we have not been opened yet, load all our entries { LoadEntries(); firstOpen = false; } Analyzer.BeginProfiling(); if (Modbase.isPatched) { return; } Modbase.Harmony.Patch(AccessTools.Method(typeof(Root_Play), nameof(Root_Play.Update)), prefix: new HarmonyMethod(typeof(H_RootUpdate), nameof(H_RootUpdate.Prefix)), postfix: new HarmonyMethod(typeof(H_RootUpdate), nameof(H_RootUpdate.Postfix))); Modbase.Harmony.Patch(AccessTools.Method(typeof(TickManager), nameof(TickManager.DoSingleTick)), #if DEBUG prefix: new HarmonyMethod(typeof(H_DoSingleTickUpdate), nameof(H_DoSingleTickUpdate.Prefix)), #endif postfix: new HarmonyMethod(typeof(H_DoSingleTickUpdate), nameof(H_DoSingleTickUpdate.Postfix))); Modbase.isPatched = true; if (Settings.SavedPatches_Tick == null) { Settings.SavedPatches_Tick = new HashSet <string>(); Settings.SavedPatches_Update = new HashSet <string>(); } foreach (var patch in Settings.SavedPatches_Tick) { Panel_DevOptions.ExecutePatch(CurrentInput.Method, patch, Category.Tick); } foreach (var patch in Settings.SavedPatches_Update) { Panel_DevOptions.ExecutePatch(CurrentInput.Method, patch, Category.Update); } }
public static void LoadEntries() { List <Type> allEntries = GenTypes.AllTypes.Where(m => m.TryGetAttribute <Entry>(out _)).OrderBy(m => m.TryGetAttribute <Entry>().name).ToList(); foreach (Type entryType in allEntries) { try { Entry entry = entryType.TryGetAttribute <Entry>(); entry.Settings = new Dictionary <FieldInfo, Setting>(); foreach (FieldInfo fieldInfo in entryType.GetFields().Where(m => m.TryGetAttribute <Setting>(out _))) { Setting sett = fieldInfo.TryGetAttribute <Setting>(); entry.Settings.SetOrAdd(fieldInfo, sett); } entry.onMouseOver = AccessTools.Method(entryType, "MouseOver"); entry.onClick = AccessTools.Method(entryType, "Clicked"); entry.onSelect = AccessTools.Method(entryType, "Selected"); entry.checkBox = AccessTools.Method(entryType, "Checkbox"); entry.type = entryType; // Find and append Entry to the correct Tab if (!GUIController.Tab(entry.category).entries.ContainsKey(entry)) { GUIController.Tab(entry.category).entries.Add(entry, entryType); } } catch (Exception e) { ThreadSafeLogger.ReportException(e, "Failed to initialise entries"); } } // Loop through our static instances and add them to the Correct Tab foreach (Entry entry in Entry.entries) { if (!GUIController.Tab(entry.category).entries.ContainsKey(entry)) { GUIController.Tab(entry.category).entries.Add(entry, entry.type); } } Panel_Logs.Initialise(); }
public void ThreadSafeLogger_OptionsPropagation() { var verifier = new MinimumLogLevelVerifier(LogLevel.Debug); var oldSaveVerifier = default(ILogLevelVerifier); var loggerMock = new Mock <ILogger>() .SetupProperty(x => x.IsEnabled, true) .SetupProperty(x => x.LevelVerifier, verifier); var saveLogger = new ThreadSafeLogger(loggerMock.Object); oldSaveVerifier = saveLogger.LevelVerifier; saveLogger.LevelVerifier = new MinimumLogLevelVerifier(LogLevel.Error); saveLogger.IsEnabled = false; Assert.AreEqual(verifier, oldSaveVerifier); Assert.AreNotEqual(oldSaveVerifier, saveLogger.LevelVerifier); Assert.IsInstanceOf <MinimumLogLevelVerifier>(saveLogger.LevelVerifier); Assert.AreEqual(LogLevel.Error, saveLogger.LevelVerifier.CastTo <MinimumLogLevelVerifier>().MinimumLevel); Assert.AreEqual(false, loggerMock.Object.IsEnabled); }
public static void OnGUI() { try { if (restartkey.KeyDownEvent) { GenCommandLine.Restart(); } if (key != null && key.KeyDownEvent) { if (Find.WindowStack.WindowOfType <Window_Analyzer>() != null) { Find.WindowStack.RemoveWindowsOfType(typeof(Window_Analyzer)); } else { Find.WindowStack.Add(new Window_Analyzer()); } } if (alertKey.KeyDownEvent) { H_AlertsReadoutUpdate.DisableAlerts = !H_AlertsReadoutUpdate.DisableAlerts; } } catch (Exception e) { if ((attemptedInitialise is false) && AttemptToInitialiseKeys()) { return; } if (Settings.verboseLogging) { ThreadSafeLogger.ReportException(e, "Error while handling analyzer keybindings"); } } }
public override void GameComponentUpdate() { // Display our logged messages that we may have recieved from other threads. ThreadSafeLogger.DisplayLogs(); if (TimeTillCleanup == -1) { return; } if (Profiling.Analyzer.CurrentlyProfiling) { TimeTillCleanup = -1; return; } TimeTillCleanup -= Time.deltaTime; if (TimeTillCleanup <= 0) { Profiling.Analyzer.Cleanup(); TimeTillCleanup = -1; } }
public static bool AttemptToInitialiseKeys() { attemptedInitialise = true; try { key = KeyBindingDef.Named("DubsOptimizerKey"); restartkey = KeyBindingDef.Named("DubsOptimizerRestartKey"); alertKey = KeyBindingDef.Named("dpa_ToggleAlertBlock"); var biff = new HarmonyMethod(typeof(H_KeyPresses).GetMethod(nameof(OnGUI))); var skiff = typeof(UIRoot_Entry).GetMethod(nameof(UIRoot_Entry.UIRootOnGUI)); Modbase.StaticHarmony.Patch(skiff, biff); skiff = typeof(UIRoot_Play).GetMethod(nameof(UIRoot_Play.UIRootOnGUI)); Modbase.StaticHarmony.Patch(skiff, biff); } catch (Exception e) { ThreadSafeLogger.ReportException(e, "Failed to load keybindings"); return(false); } return(true); }
public Modbase(ModContentPack content) : base(content) { try { Settings = GetSettings <Settings>(); ThreadSafeLogger.Message($"[Analyzer] Loaded version {analyzerVersion.Major}.{analyzerVersion.Minor}.{analyzerVersion.Build} rev {analyzerVersion.Revision}"); staticHarmony = new Harmony("Dubwise.PerformanceAnalyzer"); harmony = new Harmony("Dubwise.DubsProfiler");; if (ModLister.HasActiveModWithName("Visual Exceptions")) { var type = AccessTools.TypeByName("VisualExceptions.ExceptionState"); var field = AccessTools.Field(type, "configuration"); type = AccessTools.TypeByName("VisualExceptions.Configuration"); var property = AccessTools.PropertyGetter(type, "Debugging"); visualExceptionIntegration = (bool)property.Invoke(field.GetValue(null), null); var str = "Detected Visual Exceptions - " + (visualExceptionIntegration ? "Integrating" : "Is disabled, relying on inbuilt functionality"); ThreadSafeLogger.Message(str); } if (visualExceptionIntegration is false) { // For registering harmony patches StaticHarmony.Patch(AccessTools.Constructor(typeof(Harmony), new[] { typeof(string) }), new HarmonyMethod(typeof(RememberHarmonyIDs), nameof(RememberHarmonyIDs.Prefix))); if (ModLister.HasActiveModWithName("HugsLib")) { StaticHarmony.Patch(AccessTools.Method("HugsLib.ModBase:ApplyHarmonyPatches"), transpiler: new HarmonyMethod(typeof(RememberHarmonyIDs), nameof(RememberHarmonyIDs.Transpiler))); } } { // Profiling ModInfoCache.PopulateCache(Content.Name); GUIController.InitialiseTabs(); // GUI needs to be initialised before xml (the tabs need to exist for entries to be inserted into them) XmlParser.CollectXmlData(); StackTraceUtility.Initialise(); } { // Always Running StaticHarmony.Patch( AccessTools.Method(typeof(GlobalControlsUtility), nameof(GlobalControlsUtility.DoTimespeedControls)), prefix: new HarmonyMethod(typeof(GUIElement_TPS), nameof(GUIElement_TPS.Prefix))); var logError = AccessTools.Method(typeof(Log), nameof(Log.Error), new Type[] { typeof(string) }); StaticHarmony.Patch(logError, prefix: new HarmonyMethod(typeof(DebugLogenabler), nameof(DebugLogenabler.ErrorPrefix)), new HarmonyMethod(typeof(DebugLogenabler), nameof(DebugLogenabler.ErrorPostfix))); StaticHarmony.Patch(AccessTools.Method(typeof(Prefs), "get_DevMode"), prefix: new HarmonyMethod(typeof(DebugLogenabler), nameof(DebugLogenabler.DevModePrefix))); StaticHarmony.Patch(AccessTools.Method(typeof(DebugWindowsOpener), "DevToolStarterOnGUI"), prefix: new HarmonyMethod(typeof(DebugLogenabler), nameof(DebugLogenabler.DebugKeysPatch))); } { // Performance Patches PerformancePatches.InitialisePatches(); } #if DEBUG ThreadSafeLogger.Warning("=========================================================================="); ThreadSafeLogger.Warning(" Analyzer Running In Debug Mode "); ThreadSafeLogger.Warning("=========================================================================="); #endif } catch (Exception e) { ThreadSafeLogger.ReportException(e, "Failed to initialise analyzer, dumping messages to debug log"); } finally { ThreadSafeLogger.DisplayLogs(); } }