/// <summary> /// Clones this ExceptionLog object to a new ExceptionLog object /// </summary> /// <param name="source">The source.</param> /// <param name="deepCopy">if set to <c>true</c> a deep copy is made. If false, only the basic entity properties are copied.</param> /// <returns></returns> public static ExceptionLog Clone(this ExceptionLog source, bool deepCopy) { if (deepCopy) { return(source.Clone() as ExceptionLog); } else { var target = new ExceptionLog(); target.CopyPropertiesFrom(source); return(target); } }
/// <summary> /// Recursively logs exception and any children. /// </summary> /// <param name="ex">The <see cref="System.Exception"/> to log.</param> /// <param name="log">The parent <see cref="Rock.Model.ExceptionLog"/> of the exception being logged. This value is nullable.</param> /// <param name="isParent">A <see cref="System.Boolean"/> flag indicating if this Exception is a parent exception. This value is /// <c>true</c> if the exception that is being logged is a parent exception, otherwise <c>false</c>. /// </param> private static void LogExceptions(Exception ex, ExceptionLog log, bool isParent) { // First, attempt to log exception to the database. try { ExceptionLog exceptionLog; // If this is a recursive call and not the originating exception being logged, // attempt to clone the initial one, and populate it with Exception Type and Message // from the inner exception, while retaining the contextual information from where // the exception originated. if (!isParent) { exceptionLog = log.Clone(false); if (exceptionLog != null) { // Populate with inner exception type, message and update whether or not there is another inner exception. exceptionLog.ExceptionType = ex.GetType().ToString(); exceptionLog.Description = ex.Message; exceptionLog.Source = ex.Source; exceptionLog.StackTrace = ex.StackTrace; exceptionLog.HasInnerException = ex.InnerException != null; // Ensure EF properly recognizes this as a new record. exceptionLog.Id = 0; exceptionLog.Guid = Guid.NewGuid(); exceptionLog.ParentId = log.Id; } } else { exceptionLog = log; } // The only reason this should happen is if the `log.Clone()` operation failed. Compiler sugar. if (exceptionLog == null) { return; } // Write ExceptionLog record to database. var rockContext = new Rock.Data.RockContext(); var exceptionLogService = new ExceptionLogService(rockContext); exceptionLogService.Add(exceptionLog); rockContext.SaveChanges(); // Recurse if inner exception is found if (exceptionLog.HasInnerException.GetValueOrDefault(false)) { LogExceptions(ex.InnerException, exceptionLog, false); } } catch (Exception) { // If logging the exception fails, write the exceptions to a file try { string directory = AppDomain.CurrentDomain.BaseDirectory; directory = Path.Combine(directory, "App_Data", "Logs"); if (!Directory.Exists(directory)) { Directory.CreateDirectory(directory); } string filePath = Path.Combine(directory, "RockExceptions.csv"); string when = RockDateTime.Now.ToString(); while (ex != null) { File.AppendAllText(filePath, string.Format("{0},{1},\"{2}\"\r\n", when, ex.GetType(), ex.Message)); ex = ex.InnerException; } } catch { // failed to write to database and also failed to write to log file, so there is nowhere to log this error } } }