Ejemplo n.º 1
0
        /// <summary>
        /// Add a crash passed in the payload as Xml to the database.
        /// </summary>
        /// <param name="id">Unused.</param>
        /// <returns>The row id of the newly added crash.</returns>
        public ActionResult AddCrash(int id)
        {
            using (FAutoScopedLogTimer LogTimer = new FAutoScopedLogTimer(this.GetType().ToString() + "(NewCrashId=" + id + ")"))
            {
                CrashReporterResult NewCrashResult = new CrashReporterResult();
                NewCrashResult.ID = -1;

                try
                {
                    using (StreamReader Reader = new StreamReader(Request.InputStream, Request.ContentEncoding))
                    {
                        string           Result   = Reader.ReadToEnd();
                        CrashDescription NewCrash = XmlHandler.FromXmlString <CrashDescription>(Result);
                        NewCrashResult.ID       = LocalCrashRepository.AddNewCrash(NewCrash);
                        NewCrashResult.bSuccess = true;
                    }
                }
                catch (Exception Ex)
                {
                    NewCrashResult.Message  = Ex.ToString();
                    NewCrashResult.bSuccess = false;
                }

                string ReturnResult = XmlHandler.ToXmlString <CrashReporterResult>(NewCrashResult);
                return(Content(ReturnResult, "text/xml"));
            }
        }
Ejemplo n.º 2
0
 private void UnsafeAddCrash(CrashReporterResult NewCrashResult, CrashRepository Crashes)
 {
     using (StreamReader Reader = new StreamReader(Request.InputStream, Request.ContentEncoding))
     {
         string           Result   = Reader.ReadToEnd();
         CrashDescription NewCrash = XmlHandler.FromXmlString <CrashDescription>(Result);
         NewCrashResult.ID       = Crashes.AddNewCrash(NewCrash);
         NewCrashResult.bSuccess = true;
     }
 }
        /// <summary>
        /// Add a crash passed in the payload as Xml to the database.
        /// </summary>
        /// <param name="id">Unused.</param>
        /// <returns>The row id of the newly added crash.</returns>
        public ActionResult AddCrash(int id)
        {
            using (FAutoScopedLogTimer LogTimer = new FAutoScopedLogTimer(this.GetType().ToString() + "(NewCrashId=" + id + ")"))
            {
                CrashRepository Crashes = new CrashRepository();

                CrashReporterResult NewCrashResult = new CrashReporterResult();
                NewCrashResult.ID = -1;
                string PayloadString = string.Empty;

                for (int Index = 0; Index < 3; Index++)
                {
                    try
                    {
                        using (StreamReader Reader = new StreamReader(Request.InputStream, Request.ContentEncoding))
                        {
                            PayloadString = Reader.ReadToEnd();
                            CrashDescription NewCrash = XmlHandler.FromXmlString <CrashDescription>(PayloadString);
                            NewCrashResult.ID       = Crashes.AddNewCrash(NewCrash);
                            NewCrashResult.bSuccess = true;
                        }
                        break;
                    }
                    catch (SqlException SqlExc)
                    {
                        if (SqlExc.Number == -2)
                        {
                            FLogger.Global.WriteEvent(string.Format("AddCrash:Timeout, retrying {0} of 3", Index + 1));
                        }
                        else
                        {
                            NewCrashResult.Message  = SqlExc.ToString();
                            NewCrashResult.bSuccess = false;
                            break;
                        }
                    }
                    catch (Exception Ex)
                    {
                        StringBuilder MessageBuilder = new StringBuilder();
                        MessageBuilder.AppendLine("Exception was:");
                        MessageBuilder.AppendLine(Ex.ToString());
                        MessageBuilder.AppendLine("Received payload was:");
                        MessageBuilder.AppendLine(PayloadString);

                        NewCrashResult.Message  = MessageBuilder.ToString();
                        NewCrashResult.bSuccess = false;
                        break;
                    }
                    System.Threading.Thread.Sleep(5000 * (Index + 1));
                }

                string ReturnResult = XmlHandler.ToXmlString <CrashReporterResult>(NewCrashResult);
                return(Content(ReturnResult, "text/xml"));
            }
        }
        /// <summary>
        /// Add a new crash to the db based on a CrashDescription sent from the client.
        /// </summary>
        /// <param name="NewCrashInfo">The crash description sent from the client.</param>
        /// <returns>The id of the newly added crash.</returns>
        public int AddNewCrash(CrashDescription NewCrashInfo)
        {
            int NewID = -1;

            Crash NewCrash = new Crash();

            NewCrash.Branch       = NewCrashInfo.BranchName;
            NewCrash.BaseDir      = NewCrashInfo.BaseDir;
            NewCrash.BuildVersion = NewCrashInfo.BuildVersion;
            NewCrash.BuiltFromCL  = NewCrashInfo.BuiltFromCL.ToString();
            NewCrash.CommandLine  = NewCrashInfo.CommandLine;
            NewCrash.EngineMode   = NewCrashInfo.EngineMode;
            NewCrash.MachineId    = NewCrashInfo.MachineGuid;

            //if there's a valid username assign the associated UserNameId else use "anonymous"
            NewCrash.UserNameId = FRepository.Get(this).FindOrAddUser(!string.IsNullOrEmpty(NewCrashInfo.UserName) ? NewCrashInfo.UserName : UserNameAnonymous);

            //If there's a valid EpicAccountId assign that.
            if (!string.IsNullOrEmpty(NewCrashInfo.EpicAccountId))
            {
                NewCrash.EpicAccountId = NewCrashInfo.EpicAccountId;
            }

            NewCrash.Description = "";
            if (NewCrashInfo.UserDescription != null)
            {
                NewCrash.Description = string.Join(Environment.NewLine, NewCrashInfo.UserDescription);
            }

            NewCrash.EngineMode   = NewCrashInfo.EngineMode;
            NewCrash.GameName     = NewCrashInfo.GameName;
            NewCrash.LanguageExt  = NewCrashInfo.Language;            // Converted by the crash process.
            NewCrash.PlatformName = NewCrashInfo.Platform;

            if (NewCrashInfo.ErrorMessage != null)
            {
                NewCrash.Summary = string.Join("\n", NewCrashInfo.ErrorMessage);
            }

            if (NewCrashInfo.CallStack != null)
            {
                NewCrash.RawCallStack = string.Join("\n", NewCrashInfo.CallStack);
            }

            if (NewCrashInfo.SourceContext != null)
            {
                NewCrash.SourceContext = string.Join("\n", NewCrashInfo.SourceContext);
            }

            NewCrash.TimeOfCrash         = NewCrashInfo.TimeofCrash;
            NewCrash.bAllowToBeContacted = NewCrashInfo.bAllowToBeContacted;

            NewCrash.Jira            = "";
            NewCrash.FixedChangeList = "";

            // Set the crash type
            NewCrash.CrashType = 1;
            if (NewCrash.RawCallStack != null)
            {
                if (NewCrash.RawCallStack.Contains("FDebug::AssertFailed"))
                {
                    NewCrash.CrashType = 2;
                }
                else if (NewCrash.RawCallStack.Contains("FDebug::Ensure"))
                {
                    NewCrash.CrashType = 3;
                }
                else if (NewCrash.RawCallStack.Contains("FDebug::OptionallyLogFormattedEnsureMessageReturningFalse"))
                {
                    NewCrash.CrashType = 3;
                }
                else if (NewCrash.RawCallStack.Contains("NewReportEnsure"))
                {
                    NewCrash.CrashType = 3;
                }
            }

            // As we're adding it, the status is always new
            NewCrash.Status = "New";

            /*
             *      Unused Crashes' fields.
             *
             *      Title				nchar(20)
             *      Selected			bit
             *      Version				int
             *      AutoReporterID		int
             *      Processed			bit	-> renamed to AllowToBeContacted
             *      HasDiagnosticsFile	bit	always true
             *      HasNewLogFile		bit
             *      HasMetaData			bit	always true
             */
            // Set the unused fields to the default values.
            //NewCrash.Title = "";			removed from dbml
            //NewCrash.Selected = false;	removed from dbml
            //NewCrash.Version = 4;			removed from dbml
            //NewCrash.AutoReporterID = 0;	removed from dbml
            //NewCrash.HasNewLogFile = false;removed from dbml
            //
            //NewCrash.HasDiagnosticsFile = true;
            //NewCrash.HasMetaData = true;

            NewCrash.UserActivityHint = NewCrashInfo.UserActivityHint;

            // Add the crash to the database
            Context.Crashes.InsertOnSubmit(NewCrash);
            SubmitChanges();

            NewID = NewCrash.Id;

            // Build a callstack pattern for crash bucketing
            NewCrash.BuildPattern(Context);

            return(NewID);
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Create a new crash data model object and insert it into the database
        /// </summary>
        /// <param name="description"></param>
        /// <returns></returns>
        private Crash CreateCrash(CrashDescription description)
        {
            var newCrash = new Crash
            {
                Branch            = description.BranchName,
                BaseDir           = description.BaseDir,
                BuildVersion      = description.EngineVersion,
                EngineVersion     = description.BuildVersion,
                ChangeListVersion = description.BuiltFromCL.ToString(),
                CommandLine       = description.CommandLine,
                EngineMode        = description.EngineMode,
                ComputerName      = description.MachineGuid
            };

            //if there's a valid username assign the associated UserNameId else use "anonymous".
            var userName = (!string.IsNullOrEmpty(description.UserName)) ? description.UserName : UserNameAnonymous;
            var user     = _unitOfWork.UserRepository.GetByUserName(userName);

            if (user != null)
            {
                newCrash.UserNameId = user.Id;
            }
            else
            {
                newCrash.User = new User()
                {
                    UserName = description.UserName, UserGroupId = 5
                };
            }

            //If there's a valid EpicAccountId assign that.
            if (!string.IsNullOrEmpty(description.EpicAccountId))
            {
                newCrash.EpicAccountId = description.EpicAccountId;
            }

            newCrash.Description = "";
            if (description.UserDescription != null)
            {
                newCrash.Description = string.Join(Environment.NewLine, description.UserDescription);
            }

            newCrash.EngineMode   = description.EngineMode;
            newCrash.GameName     = description.GameName;
            newCrash.LanguageExt  = description.Language;    //Converted by the crash process.
            newCrash.PlatformName = description.Platform;

            if (description.ErrorMessage != null)
            {
                newCrash.Summary = string.Join("\n", description.ErrorMessage);
            }

            if (description.CallStack != null)
            {
                newCrash.RawCallStack = string.Join("\n", description.CallStack);
            }

            if (description.SourceContext != null)
            {
                newCrash.SourceContext = string.Join("\n", description.SourceContext);
            }

            newCrash.TimeOfCrash = description.TimeofCrash;
            newCrash.Processed   = description.bAllowToBeContacted;

            newCrash.Jira            = "";
            newCrash.FixedChangeList = "";
            newCrash.ProcessFailed   = description.bProcessorFailed;

            // Set the crash type
            newCrash.CrashType = 1;

            //if we have a crash type set the crash type
            if (!string.IsNullOrEmpty(description.CrashType))
            {
                switch (description.CrashType.ToLower())
                {
                case "crash":
                    newCrash.CrashType = 1;
                    break;

                case "assert":
                    newCrash.CrashType = 2;
                    break;

                case "ensure":
                    newCrash.CrashType = 3;
                    break;

                case "":
                case null:
                default:
                    newCrash.CrashType = 1;
                    break;
                }
            }
            else     //else fall back to the old behavior and try to determine type from RawCallStack
            {
                if (newCrash.RawCallStack != null)
                {
                    if (newCrash.RawCallStack.Contains("FDebug::AssertFailed"))
                    {
                        newCrash.CrashType = 2;
                    }
                    else if (newCrash.RawCallStack.Contains("FDebug::Ensure"))
                    {
                        newCrash.CrashType = 3;
                    }
                    else if (newCrash.RawCallStack.Contains("FDebug::OptionallyLogFormattedEnsureMessageReturningFalse"))
                    {
                        newCrash.CrashType = 3;
                    }
                    else if (newCrash.RawCallStack.Contains("NewReportEnsure"))
                    {
                        newCrash.CrashType = 3;
                    }
                }
            }

            // As we're adding it, the status is always new
            newCrash.Status = "New";

            /*
             * Unused Crashes' fields.
             *
             * Title				nchar(20)
             * Selected			bit
             * Version				int
             * AutoReporterID		int
             * Processed			bit	-> renamed to AllowToBeContacted
             * HasDiagnosticsFile	bit	always true
             * HasNewLogFile		bit
             * HasMetaData			bit	always true
             */

            // Set the unused fields to the default values.
            //NewCrash.Title = "";			removed from dbml
            //NewCrash.Selected = false;	removed from dbml
            //NewCrash.Version = 4;			removed from dbml
            //NewCrash.AutoReporterID = 0;	removed from dbml
            //NewCrash.HasNewLogFile = false;removed from dbml

            //NewCrash.HasDiagnosticsFile = true;
            //NewCrash.HasMetaData = true;
            newCrash.UserActivityHint = description.UserActivityHint;

            BuildPattern(newCrash);

            if (newCrash.CommandLine == null)
            {
                newCrash.CommandLine = "";
            }

            _unitOfWork.Dispose();
            _unitOfWork = new UnitOfWork(new CrashReportEntities());
            var callStackRepository = _unitOfWork.CallstackRepository;

            try
            {
                var crashRepo = _unitOfWork.CrashRepository;
                //if we don't have any callstack data then insert the crash and return
                if (string.IsNullOrEmpty(newCrash.Pattern))
                {
                    crashRepo.Save(newCrash);
                    _unitOfWork.Save();
                    return(newCrash);
                }

                //If this isn't a new pattern then link it to our crash data model
                if (callStackRepository.Any(data => data.Pattern == newCrash.Pattern))
                {
                    var callstackPattern = callStackRepository.First(data => data.Pattern == newCrash.Pattern);
                    newCrash.PatternId = callstackPattern.id;
                }
                else
                {
                    //if this is a new callstack pattern then insert into data model and create a new bugg.
                    var callstackPattern = new CallStackPattern {
                        Pattern = newCrash.Pattern
                    };
                    callStackRepository.Save(callstackPattern);
                    _unitOfWork.Save();
                    newCrash.PatternId = callstackPattern.id;
                }

                //Mask out the line number and File path from our error message.
                var errorMessageString = description.ErrorMessage != null?String.Join("", description.ErrorMessage) : "";

                //Create our masking regular expressions
                var fileRegex = new Regex(@"(\[File:).*?(])"); //Match the filename out the file name
                var lineRegex = new Regex(@"(\[Line:).*?(])"); //Match the line no.

                /**
                 * Regex to match ints of two characters or longer
                 * First term ((?<=\s)|(-)) : Positive look behind, match if preceeded by whitespace or if first character is '-'
                 * Second term (\d{3,}) match three or more decimal chracters in a row.
                 * Third term (?=(\s|$)) positive look ahead match if followed by whitespace or end of line/file.
                 */
                var intRegex = new Regex(@"-?\d{3,}");

                /**
                 * Regular expression for masking out floats
                 */
                var floatRegex = new Regex(@"-?\d+\.\d+");

                /**
                 * Regular expression for masking out hexadecimal numbers
                 */
                var hexRegex = new Regex(@"0x[\da-fA-F]+");

                //mask out terms matches by our regex's
                var trimmedError = fileRegex.Replace(errorMessageString, "");
                trimmedError = lineRegex.Replace(trimmedError, "");
                trimmedError = floatRegex.Replace(trimmedError, "");
                trimmedError = hexRegex.Replace(trimmedError, "");
                trimmedError = intRegex.Replace(trimmedError, "");

                //Check to see if the masked error message is unique
                ErrorMessage errorMessage = null;
                if (_unitOfWork.ErrorMessageRepository.Any(data => data.Message.Contains(trimmedError)))
                {
                    errorMessage =
                        _unitOfWork.ErrorMessageRepository.First(data => data.Message.Contains(trimmedError));
                }
                else
                {
                    //if it's a new message then add it to the database.
                    errorMessage = new ErrorMessage()
                    {
                        Message = trimmedError
                    };
                    _unitOfWork.ErrorMessageRepository.Save(errorMessage);
                    _unitOfWork.Save();
                }

                //Check for an existing bugg with this pattern and error message / no error message
                if (_unitOfWork.BuggRepository.Any(data =>
                                                   (data.PatternId == newCrash.PatternId || data.Pattern == newCrash.Pattern) && (newCrash.CrashType == 3 ||
                                                                                                                                  (data.ErrorMessageId == errorMessage.Id || data.ErrorMessageId == null))))
                {
                    //if a bugg exists for this pattern update the bugg data
                    var bugg = _unitOfWork.BuggRepository.First(data => data.PatternId == newCrash.PatternId) ??
                               _unitOfWork.BuggRepository.First(data => data.Pattern == newCrash.Pattern);
                    bugg.PatternId = newCrash.PatternId;

                    if (newCrash.CrashType != 3)
                    {
                        bugg.CrashType      = newCrash.CrashType;
                        bugg.ErrorMessageId = errorMessage.Id;
                    }

                    //also update the bugg data while we're here
                    bugg.TimeOfLastCrash = newCrash.TimeOfCrash;

                    if (String.Compare(newCrash.BuildVersion, bugg.BuildVersion,
                                       StringComparison.Ordinal) != 1)
                    {
                        bugg.BuildVersion = newCrash.BuildVersion;
                    }

                    _unitOfWork.Save();

                    //if a bugg exists update this crash from the bugg
                    //buggs are authoritative in this case
                    newCrash.Buggs.Add(bugg);
                    newCrash.Jira            = bugg.TTPID;
                    newCrash.FixedChangeList = bugg.FixedChangeList;
                    newCrash.Status          = bugg.Status;
                    _unitOfWork.CrashRepository.Save(newCrash);
                    _unitOfWork.Save();
                }
                else
                {
                    //if there's no bugg for this pattern create a new bugg and insert into the data store.
                    var bugg = new Bugg();
                    bugg.TimeOfFirstCrash       = newCrash.TimeOfCrash;
                    bugg.TimeOfLastCrash        = newCrash.TimeOfCrash;
                    bugg.TTPID                  = newCrash.Jira;
                    bugg.Pattern                = newCrash.Pattern;
                    bugg.PatternId              = newCrash.PatternId;
                    bugg.NumberOfCrashes        = 1;
                    bugg.NumberOfUsers          = 1;
                    bugg.NumberOfUniqueMachines = 1;
                    bugg.BuildVersion           = newCrash.BuildVersion;
                    bugg.CrashType              = newCrash.CrashType;
                    bugg.Status                 = newCrash.Status;
                    bugg.FixedChangeList        = newCrash.FixedChangeList;
                    bugg.ErrorMessageId         = errorMessage.Id;
                    newCrash.Buggs.Add(bugg);
                    _unitOfWork.BuggRepository.Save(bugg);
                    _unitOfWork.CrashRepository.Save(newCrash);
                    _unitOfWork.Save();
                }
            }
            catch (DbEntityValidationException dbentEx)
            {
                var messageBuilder = new StringBuilder();
                messageBuilder.AppendLine("Db Entity Validation Exception Exception was:");
                messageBuilder.AppendLine(dbentEx.ToString());

                var innerEx = dbentEx.InnerException;
                while (innerEx != null)
                {
                    messageBuilder.AppendLine("Inner Exception : " + innerEx.Message);
                    innerEx = innerEx.InnerException;
                }

                if (dbentEx.EntityValidationErrors != null)
                {
                    messageBuilder.AppendLine("Validation Errors : ");
                    foreach (var valErr in dbentEx.EntityValidationErrors)
                    {
                        messageBuilder.AppendLine(valErr.ValidationErrors.Select(data => data.ErrorMessage).Aggregate((current, next) => current + "; /n" + next));
                    }
                }
                FLogger.Global.WriteException(messageBuilder.ToString());
            }
            catch (Exception ex)
            {
                var messageBuilder = new StringBuilder();
                messageBuilder.AppendLine("Create Crash Exception : ");
                messageBuilder.AppendLine(ex.Message.ToString());
                var innerEx = ex.InnerException;
                while (innerEx != null)
                {
                    messageBuilder.AppendLine("Inner Exception : " + innerEx.Message);
                    innerEx = innerEx.InnerException;
                }

                FLogger.Global.WriteException("Create Crash Exception : " +
                                              messageBuilder.ToString());
                _slackWriter.Write("Create Crash Exception : " + messageBuilder.ToString());
                throw;
            }

            return(newCrash);
        }
Ejemplo n.º 6
0
        /// <summary>
        /// Create an Xml payload representing a new crash.
        /// </summary>
        /// <param name="DirInfo">The DirectoryInfo of the report folder.</param>
        /// <param name="NewContext">The generic crash context.</param>
        /// <param name="bHasVideoFile">Whether the report contains a video file.</param>
        /// <param name="bHasLog">Whether the report contains a log file.</param>
        /// <param name="bHasMinidump">Whether the report contains a minidump.</param>
        /// <returns>A string of Xml payload representing the newly found crash report.</returns>
        private string CreateCrash(DirectoryInfo DirInfo, FGenericCrashContext NewContext, bool bHasVideoFile, bool bHasLog, bool bHasMinidump)
        {
            string XmlPayload = "";

            try
            {
                FEngineVersion EngineVersion = new FEngineVersion(NewContext.PrimaryCrashProperties.EngineVersion);

                // Create a new crash description for uploading
                CrashDescription NewCrash = new CrashDescription();

                NewCrash.BranchName   = EngineVersion.GetCleanedBranch();
                NewCrash.GameName     = NewContext.PrimaryCrashProperties.GameName;
                NewCrash.Platform     = NewContext.PrimaryCrashProperties.PlatformFullName;
                NewCrash.EngineMode   = NewContext.PrimaryCrashProperties.EngineMode;
                NewCrash.BuildVersion = EngineVersion.VersionNumber;
                NewCrash.CommandLine  = NewContext.PrimaryCrashProperties.CommandLine;
                NewCrash.BaseDir      = NewContext.PrimaryCrashProperties.BaseDir;

                NewCrash.Language = NewContext.PrimaryCrashProperties.AppDefaultLocale;

//              // Create a locate and get the system language.
//              int SystemLanguageCode = 0;
//              int.TryParse( ReportData.SystemLanguage, out SystemLanguageCode );
//              try
//              {
//                  if( SystemLanguageCode > 0 )
//                  {
//                      CultureInfo SystemLanguageCI = new CultureInfo( SystemLanguageCode );
//                      NewCrash.SystemLanguage = SystemLanguageCI.Name;
//                  }
//              }
//              catch( System.Exception )
//              {
//                  // Default to en-US
//                  NewCrash.SystemLanguage = "en-US";
//              }

                NewCrash.MachineGuid     = NewContext.PrimaryCrashProperties.MachineId;         // Valid for all kind of builds, previously only for UE4 releases.
                NewCrash.UserName        = NewContext.PrimaryCrashProperties.UserName;          // Only valid for non-UE4 releases.
                NewCrash.EpicAccountId   = NewContext.PrimaryCrashProperties.EpicAccountId;     // Only valid for UE4 releases.
                NewCrash.CallStack       = NewContext.PrimaryCrashProperties.GetCallstack();
                NewCrash.SourceContext   = NewContext.PrimaryCrashProperties.GetSourceContext();
                NewCrash.ErrorMessage    = NewContext.PrimaryCrashProperties.GetErrorMessage();
                NewCrash.UserDescription = NewContext.PrimaryCrashProperties.GetUserDescription();

                // Iterate through all files and find a file with the earliest date.
                DateTime TimeOfCrash = DateTime.UtcNow;
                foreach (var File in DirInfo.GetFiles())
                {
                    if (File.CreationTimeUtc < TimeOfCrash)
                    {
                        TimeOfCrash = File.CreationTimeUtc;
                    }
                }

                //NewCrash.TimeofCrash = NewContext.PrimaryCrashProperties.TimeofCrash;
                NewCrash.TimeofCrash = TimeOfCrash;

                NewCrash.bHasMiniDump        = bHasMinidump;
                NewCrash.bHasLog             = bHasLog;
                NewCrash.bHasVideo           = bHasVideoFile;
                NewCrash.BuiltFromCL         = (int)EngineVersion.Changelist;
                NewCrash.bAllowToBeContacted = NewContext.PrimaryCrashProperties.bAllowToBeContacted;

                // Ignore any callstack that is shorter than expected, usually the callstack is invalid.
                if (NewCrash.CallStack.Length <= CrashReporterConstants.MinCallstackDepth)
                {
                    CrashReporterProcessServicer.WriteFailure("! BadStack: BuiltFromCL=" + string.Format("{0,7}", NewContext.PrimaryCrashProperties.EngineVersion) + " Path=" + NewContext.CrashDirectory);
                }
                else
                {
                    XmlPayload = XmlHandler.ToXmlString <CrashDescription>(NewCrash);
                }
            }
            catch (Exception Ex)
            {
                CrashReporterProcessServicer.WriteException("CreateCrash: " + Ex.ToString());
            }

            return(XmlPayload);
        }
Ejemplo n.º 7
0
        /// <summary>
        /// Add a new crash to the db based on a CrashDescription sent from the client.
        /// </summary>
        /// <param name="NewCrashInfo">The crash description sent from the client.</param>
        /// <returns>The id of the newly added crash.</returns>
        public int AddNewCrash(CrashDescription NewCrashInfo)
        {
            int NewID = -1;

            Crash NewCrash = new Crash();

            NewCrash.Branch            = NewCrashInfo.BranchName;
            NewCrash.BaseDir           = NewCrashInfo.BaseDir;
            NewCrash.BuildVersion      = NewCrashInfo.BuildVersion;
            NewCrash.ChangeListVersion = NewCrashInfo.BuiltFromCL.ToString();
            NewCrash.CommandLine       = NewCrashInfo.CommandLine;
            NewCrash.EngineMode        = NewCrashInfo.EngineMode;

            // Valid MachineID and UserName, updated crash from non-UE4 release
            if (!string.IsNullOrEmpty(NewCrashInfo.MachineGuid) && !string.IsNullOrEmpty(NewCrashInfo.UserName))
            {
                NewCrash.ComputerName = NewCrashInfo.MachineGuid;
                NewCrash.UserNameId   = CrashRepositoryDataContext.FindOrAddUser(NewCrashInfo.UserName);
            }
            // Valid MachineID and EpicAccountId, updated crash from UE4 release
            else if (!string.IsNullOrEmpty(NewCrashInfo.MachineGuid) && !string.IsNullOrEmpty(NewCrashInfo.EpicAccountId))
            {
                NewCrash.EpicAccountId = NewCrashInfo.EpicAccountId;
                NewCrash.UserNameId    = CrashRepositoryDataContext.FindOrAddUser(UserNameAnonymous);
            }
            // Crash from an older version.
            else
            {
                // MachineGuid for older crashes is obsolete, so ignore it.
                //NewCrash.ComputerName = NewCrashInfo.MachineGuid;
                NewCrash.UserNameId = CrashRepositoryDataContext.FindOrAddUser
                                      (
                    !string.IsNullOrEmpty(NewCrashInfo.UserName) ? NewCrashInfo.UserName : UserNameAnonymous
                                      );
            }

            NewCrash.Description = "";
            if (NewCrashInfo.UserDescription != null)
            {
                NewCrash.Description = string.Join(Environment.NewLine, NewCrashInfo.UserDescription);
            }

            NewCrash.EngineMode   = NewCrashInfo.EngineMode;
            NewCrash.GameName     = NewCrashInfo.GameName;
            NewCrash.LanguageExt  = NewCrashInfo.Language;            // Converted by the crash process.
            NewCrash.PlatformName = NewCrashInfo.Platform;

            if (NewCrashInfo.ErrorMessage != null)
            {
                NewCrash.Summary = string.Join("\n", NewCrashInfo.ErrorMessage);
            }

            if (NewCrashInfo.CallStack != null)
            {
                NewCrash.RawCallStack = string.Join("\n", NewCrashInfo.CallStack);
            }

            if (NewCrashInfo.SourceContext != null)
            {
                NewCrash.SourceContext = string.Join("\n", NewCrashInfo.SourceContext);
            }

            NewCrash.TimeOfCrash = NewCrashInfo.TimeofCrash;

            NewCrash.HasLogFile         = NewCrashInfo.bHasLog;
            NewCrash.HasMiniDumpFile    = NewCrashInfo.bHasMiniDump;
            NewCrash.HasDiagnosticsFile = NewCrashInfo.bHasDiags;
            NewCrash.HasVideoFile       = NewCrashInfo.bHasVideo;
            NewCrash.HasMetaData        = NewCrashInfo.bHasWERData;

            NewCrash.TTPID           = "";
            NewCrash.FixedChangeList = "";

            // Set the crash type
            NewCrash.CrashType = 1;
            if (NewCrash.RawCallStack != null)
            {
                if (NewCrash.RawCallStack.Contains("FDebug::AssertFailed()"))
                {
                    NewCrash.CrashType = 2;
                }
                else if (NewCrash.RawCallStack.Contains("FDebug::EnsureFailed()"))
                {
                    NewCrash.CrashType = 3;
                }
            }

            // As we're adding it, the status is always new
            NewCrash.Status = "New";

            /*
             *      Unused Crashes' fields.
             *
             *      Title				nchar(20)
             *      Selected			bit
             *      Version				int
             *      AutoReporterID		int
             *      Processed			bit
             *      HasDiagnosticsFile	bit
             *      HasNewLogFile		bit
             *      HasMetaData			bit
             */
            // Set the unused fields to the default values.
            NewCrash.Title          = "";
            NewCrash.Selected       = false;
            NewCrash.Version        = 4;
            NewCrash.AutoReporterID = 0;
            NewCrash.Processed      = true;
            //NewCrash.HasDiagnosticsFile = true;
            NewCrash.HasNewLogFile = false;
            //NewCrash.HasMetaData = true;

            // Add the crash to the database
            CrashRepositoryDataContext.Crashes.InsertOnSubmit(NewCrash);
            CrashRepositoryDataContext.SubmitChanges();

            NewID = NewCrash.Id;

            // Build a callstack pattern for crash bucketing
            CrashRepositoryDataContext.BuildPattern(NewCrash);

            return(NewID);
        }