/// <summary> /// A function to add a report to the database, and rename the relevant files. /// Thread-safe. /// </summary> /// <param name="DirInfo">The DirectoryInfo of the report folder.</param> /// <param name="NewContext">The generic crash context.</param> /// <param name="LogFileName">The file name of the log file in the report.</param> /// <param name="DumpFileName">The file name of the minidump in the report.</param> /// <param name="VideoFileName">The file name of the video file in the report, or null if there isn't one.</param> private AddReportResult AddReport(DirectoryInfo DirInfo, FGenericCrashContext NewContext, string LogFileName, string DumpFileName, string VideoFileName) { try { Stopwatch AddReportTime = Stopwatch.StartNew(); // Create an XML representation of a crash string CrashDetails = CreateCrash(DirInfo, NewContext, VideoFileName != null, LogFileName != null, DumpFileName != null); if (CrashDetails == "") { CrashReporterProcessServicer.WriteFailure(string.Format("PROC-{0} ", ProcessorIndex) + "! CreateCrash no payload: Path=" + NewContext.CrashDirectory); return(AddReportResult.Failed); } // Upload the crash to the database, and retrieve the new row id int ReportID = UploadCrash(CrashDetails); if (ReportID <= 0) { if (CancelSource.IsCancellationRequested) { // Cancelled upload CrashReporterProcessServicer.WriteEvent(string.Format("PROC-{0} ", ProcessorIndex) + "CancelUpload: Path=" + NewContext.CrashDirectory); return(AddReportResult.Cancelled); } else { // Upload failed CrashReporterProcessServicer.WriteFailure(string.Format("PROC-{0} ", ProcessorIndex) + "! NoUpload: Path=" + NewContext.CrashDirectory); return(AddReportResult.Failed); } } bool bToS3 = Config.Default.CrashFilesToAWS && CrashReporterProcessServicer.OutputAWS.IsS3Valid; bool bToDisk = Config.Default.CrashFilesToDisk; // Use the row id to name and move the files the way the web site requires string IDThenUnderscore = string.Format("{0}_", ReportID); int ReportIDSegment = (ReportID / 10000) * 10000; string S3IDPrefix = string.Format("/{0}/{1}/{1}_", ReportIDSegment, ReportID); string DestinationFolder = Path.Combine(Config.Default.ProcessedReports, IDThenUnderscore); Stopwatch WriteToS3Timer = new Stopwatch(); Stopwatch WriteToDiskTimer = new Stopwatch(); if (bToDisk) { CrashReporterProcessServicer.StatusReporter.AlertOnLowDisk(DestinationFolder, Config.Default.DiskSpaceAlertPercent); } // Save log file if (LogFileName != null) { LogFileName = Path.Combine(DirInfo.FullName, LogFileName); FileInfo LogInfo = new FileInfo(LogFileName); if (LogInfo.Exists) { if (bToS3) { WriteToS3Timer.Start(); UploadFileToS3(LogInfo, Config.Default.AWSS3OutputKeyPrefix + S3IDPrefix + "Launch.log", Config.Default.CompressCrashFilesOnAWS, Config.Default.AWSS3CompressedSuffix); WriteToS3Timer.Stop(); } if (bToDisk) { WriteToDiskTimer.Start(); LogInfo.MoveTo(DestinationFolder + "Launch.log"); WriteToDiskTimer.Stop(); } } } // Save crash context file string CrashContextRuntimeName = Path.Combine(DirInfo.FullName, FGenericCrashContext.CrashContextRuntimeXMLName); FileInfo CrashContextInfo = new FileInfo(CrashContextRuntimeName); if (CrashContextInfo.Exists) { if (bToS3) { WriteToS3Timer.Start(); UploadFileToS3(CrashContextInfo, Config.Default.AWSS3OutputKeyPrefix + S3IDPrefix + FGenericCrashContext.CrashContextRuntimeXMLName, false); WriteToS3Timer.Stop(); } if (bToDisk) { WriteToDiskTimer.Start(); CrashContextInfo.MoveTo(DestinationFolder + FGenericCrashContext.CrashContextRuntimeXMLName); WriteToDiskTimer.Stop(); } } if (DumpFileName != null) { DumpFileName = Path.Combine(DirInfo.FullName, DumpFileName); FileInfo DumpInfo = new FileInfo(DumpFileName); if (DumpInfo.Exists && NewContext.PrimaryCrashProperties.CrashDumpMode != 1 /* ECrashDumpMode.FullDump = 1*/) { if (bToS3) { WriteToS3Timer.Start(); UploadFileToS3(DumpInfo, Config.Default.AWSS3OutputKeyPrefix + S3IDPrefix + "MiniDump.dmp", Config.Default.CompressCrashFilesOnAWS, Config.Default.AWSS3CompressedSuffix); WriteToS3Timer.Stop(); } if (bToDisk) { WriteToDiskTimer.Start(); DumpInfo.MoveTo(DestinationFolder + "MiniDump.dmp"); WriteToDiskTimer.Stop(); } } } // Move the video (if it exists) to an alternate store if (VideoFileName != null) { DestinationFolder = Path.Combine(Config.Default.ProcessedVideos, IDThenUnderscore); VideoFileName = Path.Combine(DirInfo.FullName, VideoFileName); FileInfo VideoInfo = new FileInfo(VideoFileName); if (VideoInfo.Exists) { if (bToS3) { WriteToS3Timer.Start(); UploadFileToS3(VideoInfo, Config.Default.AWSS3OutputKeyPrefix + S3IDPrefix + CrashReporterConstants.VideoFileName, Config.Default.CompressCrashFilesOnAWS, Config.Default.AWSS3CompressedSuffix); WriteToS3Timer.Stop(); } if (bToDisk) { CrashReporterProcessServicer.StatusReporter.AlertOnLowDisk(DestinationFolder, Config.Default.DiskSpaceAlertPercent); WriteToDiskTimer.Start(); VideoInfo.MoveTo(DestinationFolder + CrashReporterConstants.VideoFileName); WriteToDiskTimer.Stop(); } } } string TimeTakenString = string.Empty; if (bToS3) { TimeTakenString = string.Format("S3UploadTime={0:F1} ", WriteToS3Timer.Elapsed.TotalSeconds); } if (bToDisk) { TimeTakenString += string.Format("DiskMoveTime={0:F1} ", WriteToDiskTimer.Elapsed.TotalSeconds); } CrashReporterProcessServicer.WriteEvent(string.Format("PROC-{0} AddReport: ReportID={1,8} {2}Path={3}", ProcessorIndex, ReportID, TimeTakenString, NewContext.CrashDirectory)); UpdateProcessedReports(); WebAddCounter.AddEvent(); CrashReporterProcessServicer.StatusReporter.IncrementCount(StatusReportingEventNames.ProcessingSucceededEvent); double Ratio = (double)WebAddCounter.TotalEvents / (double)ProcessedReportCount * 100; double AddedPerDay = (double)WebAddCounter.TotalEvents / Timer.Elapsed.TotalDays; CrashReporterProcessServicer.WriteEvent(string.Format("PROC-{0} ", ProcessorIndex) + string.Format( "AddReport: Ratio={0,2} Processed={1,7} WebAdded={2,7} AddReportTime={3} AddedPerDay={4} AddedPerMinute={5:N1}", (int)Ratio, ProcessedReportCount, WebAddCounter.TotalEvents, AddReportTime.Elapsed.TotalSeconds.ToString("0.00"), (int)AddedPerDay, WebAddCounter.EventsPerSecond * 60)); return(AddReportResult.Added); } catch (Exception Ex) { CrashReporterProcessServicer.WriteException(string.Format("PROC-{0} ", ProcessorIndex) + "AddReport: " + DirInfo.Name + "\n\n" + Ex, Ex); } return(AddReportResult.Failed); }
/// <summary> /// A function to add a report to the database, and rename the relevant files. /// Thread-safe. /// </summary> /// <param name="DirInfo">The DirectoryInfo of the report folder.</param> /// <param name="NewContext">The generic crash context.</param> /// <param name="LogFileName">The file name of the log file in the report.</param> /// <param name="DumpFileName">The file name of the minidump in the report.</param> /// <param name="VideoFileName">The file name of the video file in the report, or null if there isn't one.</param> private bool AddReport(DirectoryInfo DirInfo, FGenericCrashContext NewContext, string LogFileName, string DumpFileName, string VideoFileName) { try { Stopwatch AddReportTime = Stopwatch.StartNew(); // Create an XML representation of a crash string CrashDetails = CreateCrash(DirInfo, NewContext, VideoFileName != null, LogFileName != null, DumpFileName != null); if (CrashDetails == "") { CrashReporterProcessServicer.WriteFailure(string.Format("PROC-{0} ", ProcessorIndex) + "! CreateCrash no payload: Path=" + NewContext.CrashDirectory); return(false); } // Upload the crash to the database, and retrieve the new row id int ReportID = UploadCrash(CrashDetails); lock (FailedUploadLock) { if (ReportID <= 0) { // Upload failed ConsecutiveFailedUploads++; if (ConsecutiveFailedUploads == Config.Default.ConsecutiveFailedWebAddLimit) { CrashReporterProcessServicer.StatusReporter.Alert("Cannot contact Crash Report website."); CrashReporterProcessServicer.WriteFailure("Cannot contact Crash Report website."); } CrashReporterProcessServicer.WriteFailure(string.Format("PROC-{0} ", ProcessorIndex) + "! NoUpload: Path=" + NewContext.CrashDirectory); string PayloadFailedFileName = Path.Combine(DirInfo.FullName, "PayloadFailed.xml"); File.WriteAllText(PayloadFailedFileName, CrashDetails); return(false); } // Upload succeeded ConsecutiveFailedUploads = 0; } string IDThenUnderscore = string.Format("{0}_", ReportID); // Use the row id to name and move the files the way the web site requires string DestinationFolder = Path.Combine(Config.Default.ProcessedReports, IDThenUnderscore); // Move report files to crash reporter file store if (LogFileName != null) { LogFileName = Path.Combine(DirInfo.FullName, LogFileName); FileInfo LogInfo = new FileInfo(LogFileName); if (LogInfo.Exists) { LogInfo.MoveTo(DestinationFolder + "Launch.log"); } } string CrashContextRuntimeName = Path.Combine(DirInfo.FullName, FGenericCrashContext.CrashContextRuntimeXMLName); FileInfo CrashContextInfo = new FileInfo(CrashContextRuntimeName); if (CrashContextInfo.Exists) { CrashContextInfo.MoveTo(DestinationFolder + FGenericCrashContext.CrashContextRuntimeXMLName); } // WERMetaDataName = Path.Combine(DirInfo.FullName, WERMetaDataName); // FileInfo MetaInfo = new FileInfo(WERMetaDataName); // if (MetaInfo.Exists) // { // MetaInfo.MoveTo(DestinationFolder + "WERMeta.xml"); // } if (DumpFileName != null) { DumpFileName = Path.Combine(DirInfo.FullName, DumpFileName); FileInfo DumpInfo = new FileInfo(DumpFileName); if (DumpInfo.Exists && NewContext.PrimaryCrashProperties.CrashDumpMode != 1 /* ECrashDumpMode.FullDump = 1*/) { DumpInfo.MoveTo(DestinationFolder + "MiniDump.dmp"); } } // DiagnosticsFileName = Path.Combine(DirInfo.FullName, DiagnosticsFileName); // FileInfo DiagnosticsInfo = new FileInfo(DiagnosticsFileName); // if (DiagnosticsInfo.Exists) // { // DiagnosticsInfo.MoveTo(DestinationFolder + CrashReporterConstants.DiagnosticsFileName); // } // Move the video (if it exists) to an alternate store if (VideoFileName != null) { DestinationFolder = Path.Combine(Config.Default.ProcessedVideos, IDThenUnderscore); VideoFileName = Path.Combine(DirInfo.FullName, VideoFileName); FileInfo VideoInfo = new FileInfo(VideoFileName); if (VideoInfo.Exists) { VideoInfo.MoveTo(DestinationFolder + CrashReporterConstants.VideoFileName); } } CrashReporterProcessServicer.WriteEvent(string.Format("PROC-{0} ", ProcessorIndex) + "# WebAdded: ReportID =" + string.Format("{0,7}", ReportID) + " Path=" + NewContext.CrashDirectory); UpdateProcessedReports(); WebAddCounter.AddEvent(); CrashReporterProcessServicer.StatusReporter.IncrementCount(StatusReportingConstants.ProcessingSucceededEvent); double Ratio = (double)WebAddCounter.TotalEvents / (double)ProcessedReports * 100; double AddedPerDay = (double)WebAddCounter.TotalEvents / Timer.Elapsed.TotalDays; CrashReporterProcessServicer.WriteEvent(string.Format("PROC-{0} ", ProcessorIndex) + string.Format( "Ratio={0,2} Processed={1,7} WebAdded={2,7} AddReportTime={3} AddedPerDay={4} AddedPerMinute={5:N1}", (int)Ratio, ProcessedReports, WebAddCounter.TotalEvents, AddReportTime.Elapsed.TotalSeconds.ToString("0.00"), (int)AddedPerDay, WebAddCounter.EventsPerSecond * 60)); return(true); } catch (Exception Ex) { CrashReporterProcessServicer.WriteException(string.Format("PROC-{0} ", ProcessorIndex) + "AddReport: " + DirInfo.Name + "\n\n" + Ex.ToString()); } return(false); }