bin/projects/dbatools/dbatools/dbaSystem/DebugHost.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 |
using System;
using System.Collections.Concurrent; using System.Collections.Generic; using System.Management.Automation; namespace Sqlcollaborative.Dbatools.dbaSystem { /// <summary> /// Hosts static debugging values and methods /// </summary> public static class DebugHost { #region Defines /// <summary> /// The maximum numbers of error records maintained in-memory. /// </summary> public static int MaxErrorCount = 128; /// <summary> /// The maximum number of messages that can be maintained in the in-memory message queue /// </summary> public static int MaxMessageCount = 1024; /// <summary> /// The maximum size of a given logfile. When reaching this limit, the file will be abandoned and a new log created. Set to 0 to not limit the size. /// </summary> public static int MaxMessagefileBytes = 5242880; // 5MB /// <summary> /// The maximum number of logfiles maintained at a time. Exceeding this number will cause the oldest to be culled. Set to 0 to disable the limit. /// </summary> public static int MaxMessagefileCount = 5; /// <summary> /// The maximum size all error files combined may have. When this number is exceeded, the oldest entry is culled. /// </summary> public static int MaxErrorFileBytes = 20971520; // 20MB /// <summary> /// This is the upper limit of length all items in the log folder may have combined across all processes. /// </summary> public static int MaxTotalFolderSize = 104857600; // 100MB /// <summary> /// Path to where the logfiles live. /// </summary> public static string LoggingPath; /// <summary> /// Any logfile older than this will automatically be cleansed /// </summary> public static TimeSpan MaxLogFileAge = new TimeSpan(7, 0, 0, 0); /// <summary> /// Governs, whether a log file for the system messages is written /// </summary> public static bool MessageLogFileEnabled = true; /// <summary> /// Governs, whether a log of recent messages is kept in memory /// </summary> public static bool MessageLogEnabled = true; /// <summary> /// Governs, whether log files for errors are written /// </summary> public static bool ErrorLogFileEnabled = true; /// <summary> /// Governs, whether a log of recent errors is kept in memory /// </summary> public static bool ErrorLogEnabled = true; /// <summary> /// Enables the developer mode. In this additional information and logs are written, in order to make it easier to troubleshoot issues. /// </summary> public static bool DeveloperMode = false; /// <summary> /// Returns whether the module is currently in a development branch. Some warnings will only be shown in development branch, but hidden in master / public releases /// </summary> public static bool DevelopmentBranch = true; #endregion Defines #region Queues private static ConcurrentQueue<DbatoolsExceptionRecord> ErrorRecords = new ConcurrentQueue<DbatoolsExceptionRecord>(); private static ConcurrentQueue<LogEntry> LogEntries = new ConcurrentQueue<LogEntry>(); /// <summary> /// The outbound queue for errors. These will be processed and written to xml /// </summary> public static ConcurrentQueue<DbatoolsExceptionRecord> OutQueueError = new ConcurrentQueue<DbatoolsExceptionRecord>(); /// <summary> /// The outbound queue for logs. These will be processed and written to logfile /// </summary> public static ConcurrentQueue<LogEntry> OutQueueLog = new ConcurrentQueue<LogEntry>(); #endregion Queues #region Access Queues /// <summary> /// Retrieves a copy of the Error stack /// </summary> /// <returns>All errors thrown by dbatools functions</returns> public static DbatoolsExceptionRecord[] GetErrors() { DbatoolsExceptionRecord[] temp = new DbatoolsExceptionRecord[ErrorRecords.Count]; ErrorRecords.CopyTo(temp, 0); return temp; } /// <summary> /// Retrieves a copy of the message log /// </summary> /// <returns>All messages logged this session.</returns> public static LogEntry[] GetLog() { LogEntry[] temp = new LogEntry[LogEntries.Count]; LogEntries.CopyTo(temp, 0); return temp; } /// <summary> /// Write an error record to the log /// </summary> /// <param name="Record">The actual error record as powershell wrote it</param> /// <param name="FunctionName">The name of the function writing the error</param> /// <param name="Timestamp">When was the error written</param> /// <param name="Message">What message was passed to the user</param> /// <param name="Runspace">The runspace the message was written from</param> public static void WriteErrorEntry(ErrorRecord[] Record, string FunctionName, DateTime Timestamp, string Message, Guid Runspace) { DbatoolsExceptionRecord tempRecord = new DbatoolsExceptionRecord(Runspace, Timestamp, FunctionName, Message); foreach (ErrorRecord rec in Record) { tempRecord.Exceptions.Add(new DbatoolsException(rec, FunctionName, Timestamp, Message, Runspace)); } if (ErrorLogFileEnabled) { OutQueueError.Enqueue(tempRecord); } if (ErrorLogEnabled) { ErrorRecords.Enqueue(tempRecord); } DbatoolsExceptionRecord tmp; while ((MaxErrorCount > 0) && (ErrorRecords.Count > MaxErrorCount)) { ErrorRecords.TryDequeue(out tmp); } } /// <summary> /// Write a new entry to the log /// </summary> /// <param name="Message">The message to log</param> /// <param name="Type">The type of the message logged</param> /// <param name="Timestamp">When was the message generated</param> /// <param name="FunctionName">What function wrote the message</param> /// <param name="Level">At what level was the function written</param> /// <param name="Runspace">The runspace the message is coming from</param> /// <param name="TargetObject">The object associated with a given message.</param> public static void WriteLogEntry(string Message, LogEntryType Type, DateTime Timestamp, string FunctionName, MessageLevel Level, Guid Runspace, object TargetObject = null) { LogEntry temp = new LogEntry(Message, Type, Timestamp, FunctionName, Level, Runspace, TargetObject); if (MessageLogFileEnabled) { OutQueueLog.Enqueue(temp); } if (MessageLogEnabled) { LogEntries.Enqueue(temp); } LogEntry tmp; while ((MaxMessageCount > 0) && (LogEntries.Count > MaxMessageCount)) { LogEntries.TryDequeue(out tmp); } } #endregion Access Queues #region Start Times /// <summary> /// Lists the duration for the last import of dbatools. /// </summary> public static List<StartTimeEntry> ImportTimeEntries = new List<StartTimeEntry>(); /// <summary> /// Returns the calculated time each phase took during the last import of dbatool. /// </summary> public static List<StartTimeResult> ImportTime { get { List<StartTimeResult> result = new List<StartTimeResult>(); int n = 0; foreach (StartTimeEntry entry in ImportTimeEntries) if (n++ > 0) result.Add(new StartTimeResult(entry.Action, ImportTimeEntries[n - 2].Timestamp, entry.Timestamp)); return result; } } #endregion Start Times } } |