Example #1
0
 private void OnCrashesAdd(Crash CrashInstance)
 {
     Buggs_Crashes.Add(new Buggs_Crash {
         Bugg = this, Crash = CrashInstance
     });
     SendPropertyChanged(null);
 }
Example #2
0
 /// <summary>
 /// Construct a processed callstack.
 /// </summary>
 /// <param name="CurrentCrash"></param>
 public CallStackContainer(Crash CurrentCrash)
 {
     using (FAutoScopedLogTimer LogTimer = new FAutoScopedLogTimer(this.GetType().ToString() + "(CrashId=" + CurrentCrash.Id + ")"))
     {
         ParseCallStack(CurrentCrash);
     }
 }
        /// <summary>
        /// Gets the crash from an id.
        /// </summary>
        /// <param name="Id">The id of the crash we wish to examine.</param>
        /// <returns>The crash with the requested id.</returns>
        public Crash GetCrash(int Id)
        {
            using (FAutoScopedLogTimer LogTimer = new FAutoScopedLogTimer(this.GetType().ToString() + "(CrashId=" + Id + ")"))
            {
                try
                {
                    IQueryable <Crash> Crashes =
                        (
                            from CrashDetail in Context.Crashes
                            where CrashDetail.Id == Id
                            select CrashDetail
                        );

                    Crash Result = Crashes.FirstOrDefault();
                    Result.ReadCrashContextIfAvailable();
                    return(Result);
                }
                catch (Exception Ex)
                {
                    Debug.WriteLine("Exception in GetCrash: " + Ex.ToString());
                }

                return(null);
            }
        }
Example #4
0
        private void OnCrashesRemove(Crash CrashInstance)
        {
            Buggs_Crash BuggCrash = Buggs_Crashes.FirstOrDefault(BuggCrashInstance => BuggCrashInstance.BuggId == Id && BuggCrashInstance.CrashId == CrashInstance.Id);

            Buggs_Crashes.Remove(BuggCrash);
            SendPropertyChanged(null);
        }
 /// <summary>
 /// Construct a processed callstack.
 /// </summary>
 /// <param name="CurrentCrash"></param>
 public CallStackContainer( Crash CurrentCrash )
 {
     using( FAutoScopedLogTimer LogTimer = new FAutoScopedLogTimer( this.GetType().ToString() + "(CrashId=" + CurrentCrash.Id + ")" ) )
     {
         ParseCallStack( CurrentCrash );
     }
 }
        /// <summary>
        /// Build a callstack pattern for a crash to ease bucketing of crashes into Buggs.
        /// </summary>
        /// <param name="CrashInstance">A crash that was recently added to the database.</param>
        public void BuildPattern(Crash CrashInstance)
        {
            List <string> Pattern = new List <string>();

            // Get an array of callstack items
            CallStackContainer CallStack = new CallStackContainer(CrashInstance);

            CallStack.bDisplayFunctionNames = true;

            if (CrashInstance.Pattern == null)
            {
                // Set the module based on the modules in the callstack
                CrashInstance.Module = CallStack.GetModuleName();
                try
                {
                    foreach (CallStackEntry Entry in CallStack.CallStackEntries)
                    {
                        FunctionCall CurrentFunctionCall = new FunctionCall();

                        if (FunctionCalls.Where(f => f.Call == Entry.FunctionName).Count() > 0)
                        {
                            CurrentFunctionCall = FunctionCalls.Where(f => f.Call == Entry.FunctionName).First();
                        }
                        else
                        {
                            CurrentFunctionCall      = new FunctionCall();
                            CurrentFunctionCall.Call = Entry.FunctionName;
                            FunctionCalls.InsertOnSubmit(CurrentFunctionCall);
                        }

                        int Count = Crash_FunctionCalls.Where(c => c.CrashId == CrashInstance.Id && c.FunctionCallId == CurrentFunctionCall.Id).Count();
                        if (Count < 1)
                        {
                            Crash_FunctionCall JoinTable = new Crash_FunctionCall();
                            JoinTable.Crash        = CrashInstance;
                            JoinTable.FunctionCall = CurrentFunctionCall;
                            Crash_FunctionCalls.InsertOnSubmit(JoinTable);
                        }

                        SubmitChanges();

                        Pattern.Add(CurrentFunctionCall.Id.ToString());
                    }

                    CrashInstance.Pattern = string.Join("+", Pattern);
                    SubmitChanges();
                }
                catch (Exception Ex)
                {
                    Debug.WriteLine("Exception in BuildPattern: " + Ex.ToString());
                }
            }
        }
        /// <summary>
        /// Retrieve a cached (and pre-parsed) callstack container from the cache, or parse the raw callstack, and add to the cache.
        /// </summary>
        /// <param name="CurrentCrash">The crash to retrieve the parsed callstack for.</param>
        /// <returns>A parsed callstack.</returns>
        public CallStackContainer GetCallStack(Crash CurrentCrash)
        {
            string             Key       = CacheKeyPrefix + CallstackKeyPrefix + CurrentCrash.Id;
            CallStackContainer CallStack = ( CallStackContainer )CacheInstance[Key];

            if (CallStack == null)
            {
                CallStack = new CallStackContainer(CurrentCrash);
                CallStack.bDisplayFunctionNames = true;
                CacheInstance.Insert(Key, CallStack);
            }

            return(CallStack);
        }
Example #8
0
        /// <summary>
        /// Build a callstack pattern for a crash to ease bucketing of crashes into Buggs.
        /// </summary>
        /// <param name="CrashInstance">A crash that was recently added to the database.</param>
        public void BuildPattern(Crash CrashInstance)
        {
            using (FAutoScopedLogTimer LogTimer = new FAutoScopedLogTimer(this.GetType().ToString() + "(Crash=" + CrashInstance.Id + ")"))
            {
                List <string> Pattern = new List <string>();

                // Get an array of callstack items
                CallStackContainer CallStack = new CallStackContainer(CrashInstance);
                CallStack.bDisplayFunctionNames = true;

                if (CrashInstance.Pattern == null)
                {
                    // Set the module based on the modules in the callstack
                    CrashInstance.Module = CallStack.GetModuleName();
                    try
                    {
                        foreach (CallStackEntry Entry in CallStack.CallStackEntries)
                        {
                            FunctionCall CurrentFunctionCall = new FunctionCall();

                            if (FunctionCalls.Where(f => f.Call == Entry.FunctionName).Count() > 0)
                            {
                                CurrentFunctionCall = FunctionCalls.Where(f => f.Call == Entry.FunctionName).First();
                            }
                            else
                            {
                                CurrentFunctionCall      = new FunctionCall();
                                CurrentFunctionCall.Call = Entry.FunctionName;
                                FunctionCalls.InsertOnSubmit(CurrentFunctionCall);
                            }

                            SubmitChanges();

                            Pattern.Add(CurrentFunctionCall.Id.ToString());
                        }

                        //CrashInstance.Pattern = "+";
                        CrashInstance.Pattern = string.Join("+", Pattern);
                        // We need something like this +1+2+3+5+ for searching for exact pattern like +5+
                        //CrashInstance.Pattern += "+";

                        SubmitChanges();
                    }
                    catch (Exception Ex)
                    {
                        FLogger.WriteException("BuildPattern: " + Ex.ToString());
                    }
                }
            }
        }
        /// <summary>
        /// Retrieve a cached (and pre-parsed) callstack container from the cache, or parse the raw callstack, and add to the cache.
        /// </summary>
        /// <param name="CurrentCrash">The crash to retrieve the parsed callstack for.</param>
        /// <returns>A parsed callstack.</returns>
        public CallStackContainer GetCallStackFast( Crash CurrentCrash )
        {
            using( FAutoScopedLogTimer LogTimer = new FAutoScopedLogTimer( this.GetType().ToString() + "(CrashId=" + CurrentCrash.Id + ")" ) )
            {
                string Key = CacheKeyPrefix + CallstackKeyPrefix + CurrentCrash.Id;
                CallStackContainer CallStack = (CallStackContainer)CacheInstance[Key];
                if( CallStack == null )
                {
                    CallStack = new CallStackContainer( CurrentCrash );
                    CallStack.bDisplayFunctionNames = true;
                    CacheInstance.Insert( Key, CallStack );
                }

                return CallStack;
            }
        }
Example #10
0
        /// <summary>
        /// Retrieve a cached (and pre-parsed) callstack container from the cache, or parse the raw callstack, and add to the cache.
        /// </summary>
        /// <param name="CurrentCrash">The crash to retrieve the parsed callstack for.</param>
        /// <returns>A parsed callstack.</returns>
        public CallStackContainer GetCallStack(Crash CurrentCrash)
        {
            using (FAutoScopedLogTimer LogTimer = new FAutoScopedLogTimer(this.GetType().ToString() + "(CrashId=" + CurrentCrash.Id + ")"))
            {
                string             Key       = CacheKeyPrefix + CallstackKeyPrefix + CurrentCrash.Id;
                CallStackContainer CallStack = (CallStackContainer)CacheInstance[Key];
                if (CallStack == null)
                {
                    CallStack = new CallStackContainer(CurrentCrash);
                    CallStack.bDisplayFunctionNames = true;
                    CacheInstance.Insert(Key, CallStack);
                }

                return(CallStack);
            }
        }
 /// <summary>
 /// Sets the UserName and UserGroupName as derived data for a crash.
 /// </summary>
 /// <param name="CrashInstance">An instance of a crash we wish to augment with additional data.</param>
 public void PopulateUserInfo(Crash CrashInstance)
 {
     using (FAutoScopedLogTimer LogTimer = new FAutoScopedLogTimer(this.GetType().ToString() + "(CrashId=" + CrashInstance.Id + ")"))
     {
         try
         {
             int UserGroupId = CrashInstance.User.UserGroupId;
             var Result      = Context.UserGroups.Where(i => i.Id == UserGroupId).First();
             CrashInstance.UserGroupName = Result.Name;
         }
         catch (Exception Ex)
         {
             FLogger.Global.WriteException("PopulateUserInfo: " + Ex.ToString());
         }
     }
 }
Example #12
0
        /// <summary>
        /// Retrieve a cached (and pre-parsed) callstack container from the cache, or parse the raw callstack, and add to the cache.
        /// </summary>
        /// <param name="currentCrash">The Crash to retrieve the parsed callstack for.</param>
        /// <returns>A parsed callstack.</returns>
        public DataModels.CallStackContainer GetCallStackFast(Crash currentCrash)
        {
            using (var logTimer = new FAutoScopedLogTimer(this.GetType().ToString() + "(CrashId=" + currentCrash.Id + ")"))
            {
                var key       = CacheKeyPrefix + CallstackKeyPrefix + currentCrash.Id;
                var callStack = (CallStackContainer)CacheInstance[key];
                if (callStack != null)
                {
                    return(callStack);
                }
                callStack = new CallStackContainer(currentCrash);
                callStack.bDisplayFunctionNames = true;
                CacheInstance.Insert(key, callStack);

                return(callStack);
            }
        }
        /// <summary>
        /// Sets the UserName and UserGroupName as derived data for a crash.
        /// </summary>
        /// <param name="CrashInstance">An instance of a crash we wish to augment with additional data.</param>
        public void PopulateUserInfo(Crash CrashInstance)
        {
            try
            {
                var query = (
                    from UserDetail in CrashRepositoryDataContext.Users
                    where UserDetail.Id == CrashInstance.User.Id
                    join UserGroupDetail in CrashRepositoryDataContext.UserGroups on UserDetail.UserGroupId equals UserGroupDetail.Id
                    select UserGroupDetail.Name
                    );

                CrashInstance.UserGroupName = query.First();
            }
            catch (Exception Ex)
            {
                Debug.WriteLine("Exception in PopulateUserInfo: " + Ex.ToString());
            }
        }
Example #14
0
        /// <summary>
        /// Associate a crash with a Bugg.
        /// </summary>
        /// <param name="Bugg">The Bugg to add the crash reference to.</param>
        /// <param name="CurrentCrash">The crash to add to the Bugg.</param>
        /// <returns>true if a new relationship was added, false otherwise.</returns>
        public bool LinkCrashToBugg(Bugg Bugg, Crash CurrentCrash)
        {
            try
            {
                // Make sure we don't already have this relationship
                if (Context.Buggs_Crashes.Where(BuggInstance => BuggInstance.CrashId == CurrentCrash.Id && BuggInstance.BuggId == Bugg.Id).Count() < 1)
                {
                    // We don't so create the relationship
                    Buggs_Crash NewBugg = new Buggs_Crash();
                    NewBugg.CrashId = CurrentCrash.Id;
                    NewBugg.BuggId  = Bugg.Id;
                    Context.Buggs_Crashes.InsertOnSubmit(NewBugg);
                    return(true);
                }
            }
            catch (Exception Ex)
            {
                Debug.WriteLine("Exception in LinkCrashToBugg: " + Ex.ToString());
            }

            return(false);
        }
Example #15
0
		void BuildPattern( Crash CrashInstance )
		{

			List<string> Pattern = new List<string>();

			// Get an array of callstack items
			CallStackContainer CallStack = new CallStackContainer( CrashInstance );
			CallStack.bDisplayFunctionNames = true;

			if( CrashInstance.Pattern == null )
			{
				// Set the module based on the modules in the callstack
				CrashInstance.Module = CallStack.GetModuleName();
				try
				{
					using( FAutoScopedLogTimer LogTimer = new FAutoScopedLogTimer( this.GetType().ToString() + "(Id=" + CrashInstance.Id + ")" ) )
					{
						foreach( CallStackEntry Entry in CallStack.CallStackEntries.Take( 64 ) )
						{
							FunctionCall CurrentFunctionCall = new FunctionCall();

							if( FunctionCalls.Where( f => f.Call == Entry.FunctionName ).Count() > 0 )
							{
								CurrentFunctionCall = FunctionCalls.Where( f => f.Call == Entry.FunctionName ).First();
							}
							else
							{
								CurrentFunctionCall = new FunctionCall();
								CurrentFunctionCall.Call = Entry.FunctionName;
								FunctionCalls.InsertOnSubmit( CurrentFunctionCall );
							}

							//CrashRepository.Context.SubmitChanges();

							Pattern.Add( CurrentFunctionCall.Id.ToString() );
						}

						//CrashInstance.Pattern = "+";
						CrashInstance.Pattern = string.Join( "+", Pattern );
						// We need something like this +1+2+3+5+ for searching for exact pattern like +5+
						//CrashInstance.Pattern += "+";

						CrashRepository.Context.SubmitChanges();
					}

				}
				catch( Exception Ex )
				{
					FLogger.WriteEvent( "Exception in BuildPattern: " + Ex.ToString() );
				}
			}
		}
Example #16
0
        /// <summary>
        /// Associate a crash with a Bugg.
        /// </summary>
        /// <param name="Bugg">The Bugg to add the crash reference to.</param>
        /// <param name="CurrentCrash">The crash to add to the Bugg.</param>
        /// <returns>true if a new relationship was added, false otherwise.</returns>
        public bool LinkCrashToBugg( Bugg Bugg, Crash CurrentCrash )
        {
            try
            {
                // Make sure we don't already have this relationship
                if( BuggsDataContext.Buggs_Crashes.Where( BuggInstance => BuggInstance.CrashId == CurrentCrash.Id && BuggInstance.BuggId == Bugg.Id ).Count() < 1 )
                {
                    // We don't so create the relationship
                    Buggs_Crash NewBugg = new Buggs_Crash();
                    NewBugg.CrashId = CurrentCrash.Id;
                    NewBugg.BuggId = Bugg.Id;
                    BuggsDataContext.Buggs_Crashes.InsertOnSubmit( NewBugg );
                    return true;
                }
            }
            catch( Exception Ex )
            {
                Debug.WriteLine( "Exception in LinkCrashToBugg: " + Ex.ToString() );
            }

            return false;
        }
Example #17
0
		/// <summary>
		/// Parse a raw callstack into a pattern
		/// </summary>
		/// <param name="CurrentCrash">The crash with a raw callstack to parse.</param>
		private void ParseCallStack( Crash CurrentCrash )
		{
			// Everything is disabled by default
			bDisplayUnformattedCallStack = false;
			bDisplayModuleNames = false;
			bDisplayFunctionNames = false;
			bDisplayFileNames = false;
			bDisplayFilePathNames = false;

			bool bSkipping = false;
			string LineToSkipUpto = "";
			switch( CurrentCrash.CrashType )
			{
			case 2:
				bSkipping = true;
				LineToSkipUpto = "FDebug::AssertFailed()";
				break;
			case 3:
				bSkipping = true;
				LineToSkipUpto = "FDebug::EnsureFailed()";
				break;
			}

			if (string.IsNullOrEmpty(CurrentCrash.RawCallStack))
			{
				return;
			}

			CallStackEntries.Clear();

			// Store off a pre split array of call stack lines
			string[] RawCallStackLines = CurrentCrash.RawCallStack.Split(new[] { '\n' }, StringSplitOptions.RemoveEmptyEntries);

			// Support older callstacks uploaded before UE4 upgrade
			if (!NewCallstackFormat.Match(RawCallStackLines[0]).Success)
			{
				foreach (string CurrentLine in RawCallStackLines)
				{
					// Exit if we've hit the max number of lines we want
					if (CallStackEntries.Count >= MaxLinesToParse)
					{
						break;
					}

					ParseUE3FormatCallstackLine(CurrentLine);
				}
				return;
			}

			foreach (string CurrentLine in RawCallStackLines)
			{
				// Exit if we've hit the max number of lines we want
				if( CallStackEntries.Count >= MaxLinesToParse )
				{
					break;
				}

				if( bSkipping )
				{
					if( CurrentLine.Contains( LineToSkipUpto ) )
					{
						bSkipping = false;
					}
				}

				if( bSkipping )
				{
					continue;
				}

				string ModuleName = "<Unknown>";
				string FuncName = "<Unknown>";
				string FilePath = "";
				int LineNumber = 0;

				// Sample line "UE4_Engine!UEngine::Exec() + 21105 bytes [d:\depot\ue4\engine\source\runtime\engine\private\unrealengine.cpp:2777]"

				int PlingOffset = CurrentLine.IndexOf( '!' );
				int PlusOffset = CurrentLine.IndexOf( " + " );
				int BytesOffset = CurrentLine.IndexOf( " bytes" );
				int OpenBracketOffset = CurrentLine.IndexOf( '[' );
				int CloseBracketOffset = CurrentLine.LastIndexOf( ']' );

				// Parse out the juicy info from the line of the callstack
				if( PlingOffset > 0 )
				{
					ModuleName = CurrentLine.Substring( 0, PlingOffset ).Trim();
					if( BytesOffset > PlingOffset )
					{
						// Grab the function name if it exists
						FuncName = CurrentLine.Substring( PlingOffset + 1, BytesOffset - PlingOffset + " bytes".Length - 1 ).Trim();

						// Grab the source file
						if( OpenBracketOffset > BytesOffset && CloseBracketOffset > BytesOffset && CloseBracketOffset > OpenBracketOffset )
						{
							string FileLinePath = CurrentLine.Substring( OpenBracketOffset + 1, CloseBracketOffset - OpenBracketOffset - 1 ).Trim();

							FilePath = FileLinePath.TrimEnd( "0123456789:".ToCharArray() );
							int SourceLine = 0;
						    Debug.Assert(FilePath.Length < FileLinePath.Length,"WRONG SIZE");
							if( int.TryParse( FileLinePath.Substring(FilePath.Length + 1 ), out SourceLine ) )
							{
								LineNumber = SourceLine;
							}
						}
					}
				}
				else if( BytesOffset > 0 )
				{
					// Grab the module name if there is no function name
					ModuleName = CurrentLine.Substring( 0, PlusOffset ).Trim();
				}

				CallStackEntries.Add( new CallStackEntry( CurrentLine, ModuleName, FilePath, FuncName, LineNumber ) );
			}
		}
Example #18
0
 private void OnCrashesAdd( Crash CrashInstance )
 {
     Buggs_Crashes.Add( new Buggs_Crash { Bugg = this, Crash = CrashInstance } );
     SendPropertyChanged( null );
 }
        /// <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);
        }
 partial void DeleteCrash(Crash instance);
		private void detach_Crashes(Crash entity)
		{
			this.SendPropertyChanging();
			entity.UserById = null;
		}
 partial void InsertCrash(Crash instance);
        /// <summary>
        /// Retrieve the parsed callstack for the crash.
        /// </summary>
        /// <param name="CrashInstance">The crash we require the callstack for.</param>
        /// <returns>A class containing the parsed callstack.</returns>
        public CallStackContainer GetCallStack(Crash CrashInstance)
        {
            CachedDataService CachedResults = new CachedDataService(HttpContext.Current.Cache, this);

            return(CachedResults.GetCallStackFast(CrashInstance));
        }
        public int CreateNewCrash(int AutoReporterId, string ComputerName, string UserName, string GameName, string PlatformName, string LanguageExt,
			string TimeOfCrash, string BuildVer, string ChangelistVer, string CommandLine, string BaseDir,
			string CallStack, string EngineMode)
        {
            string LogFileName = ConfigurationManager.AppSettings["LogFileName"];
            int newID = -1;

            StreamWriter LogFile = null;
            try
            {
                LogFile = new StreamWriter(LogFileName, true);
            }
            catch (Exception)
            {
                // Ignore cases where the log file can't be opened (another instance may be writing to it already)
            }

            DateTime currentDate = DateTime.Now;
            if (LogFile != null)
            {
                LogFile.WriteLine("");
                LogFile.WriteLine("Creating new report..." + currentDate.ToString("G"));
            }

            try
            {
                //TODO Catch exception if we fail to connect to the database

                var NewCrash = new Crash();

                if (CallStack.Contains("Assertion failed:"))
                {
                    NewCrash.CrashType = 2;
                }
                else if (CallStack.Contains("Ensure condition failed:"))
                {
                    NewCrash.CrashType = 3;
                }
                else
                {
                    NewCrash.CrashType = 1;
                }

                NewCrash.BaseDir = BaseDir;
                NewCrash.BuildVersion = BuildVer;
                NewCrash.ChangeListVersion = ChangelistVer;
                NewCrash.CommandLine = CommandLine;
                NewCrash.ComputerName = ComputerName;
                NewCrash.EngineMode = EngineMode;
                NewCrash.GameName = GameName;
                NewCrash.LanguageExt = LanguageExt;
                NewCrash.PlatformName = PlatformName;
                NewCrash.RawCallStack = CallStack;
                NewCrash.TimeOfCrash = ConvertDumpTimeToDateTime(TimeOfCrash);
                NewCrash.Status = "New";

                using (var DataContext = new CrashReportDataContext())
                {
                    // Crashes after this upgrade refer to users by ID
                    NewCrash.UserNameId = DataContext.FindOrAddUser(UserName);

                    DataContext.Crashes.InsertOnSubmit(NewCrash);
                    DataContext.SubmitChanges();
                }

                newID = NewCrash.Id;
            }
            catch (Exception e)
            {
                if (LogFile != null)
                {
                    LogFile.WriteLine("Exception caught!");
                    LogFile.WriteLine(e.Message);
                    LogFile.Close();
                }
                return newID;
            }
            //TODO Catch any execptions from failing to open the connection to the db.
            /*     catch (conn e)
                 {
                     if (LogFile != null)
                     {
                         LogFile.WriteLine("Failed to open connection to database!");
                         LogFile.WriteLine("ConnectionString");
                         LogFile.WriteLine(e.Message);
                         LogFile.Close();
                     }
                     return -1;
                 }*/

            if (LogFile != null)
            {
                LogFile.WriteLine("Successfully created new record with id " + newID.ToString());
                LogFile.Close();
            }
            return newID;
        }
 /// <summary>
 /// Construct a processed callstack.
 /// </summary>
 /// <param name="CurrentCrash"></param>
 public CallStackContainer(Crash CurrentCrash)
 {
     ParseCallStack(CurrentCrash);
 }
Example #26
0
		/// <summary>
		/// Constructor
		/// </summary>
		/// <param name="Crash">Crash</param>
		public FCrashMinimal( Crash Crash )
		{
			TimeOfCrash = Crash.TimeOfCrash.Value;
			UserId = Crash.UserNameId.Value;
		}
        /// <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);
        }
Example #28
0
        //.*?\(.*?\).*?\[.*?\]

        /// <summary>
        /// Parse a raw callstack into a pattern
        /// </summary>
        /// <param name="CurrentCrash">The crash with a raw callstack to parse.</param>
        private void ParseCallStack(Crash CurrentCrash)
        {
            // Everything is disabled by default
            bDisplayUnformattedCallStack = false;
            bDisplayModuleNames          = false;
            bDisplayFunctionNames        = false;
            bDisplayFileNames            = false;
            bDisplayFilePathNames        = false;

            bool   bSkipping      = false;
            string LineToSkipUpto = "";

            switch (CurrentCrash.CrashType)
            {
            case 2:
                bSkipping      = true;
                LineToSkipUpto = "FDebug::AssertFailed()";
                break;

            case 3:
                bSkipping      = true;
                LineToSkipUpto = "FDebug::EnsureFailed()";
                break;
            }

            if (string.IsNullOrEmpty(CurrentCrash.RawCallStack))
            {
                return;
            }

            CallStackEntries.Clear();

            // Store off a pre split array of call stack lines
            string[] RawCallStackLines = CurrentCrash.RawCallStack.Split(new[] { '\n' }, StringSplitOptions.RemoveEmptyEntries);

            int Middle = RawCallStackLines.Length / 2;

            // Support older callstacks uploaded before UE4 upgrade
            if (!NewCallstackFormat.Match(RawCallStackLines[Middle]).Success)
            {
                foreach (string CurrentLine in RawCallStackLines)
                {
                    // Exit if we've hit the max number of lines we want
                    if (CallStackEntries.Count >= MaxLinesToParse)
                    {
                        break;
                    }

                    ParseUE3FormatCallstackLine(CurrentLine);
                }
                return;
            }

            foreach (string CurrentLine in RawCallStackLines)
            {
                // Exit if we've hit the max number of lines we want
                if (CallStackEntries.Count >= MaxLinesToParse)
                {
                    break;
                }

                if (bSkipping)
                {
                    if (CurrentLine.Contains(LineToSkipUpto))
                    {
                        bSkipping = false;
                    }
                }

                if (bSkipping)
                {
                    continue;
                }

                string ModuleName = "<Unknown>";
                string FuncName   = "<Unknown>";
                string FilePath   = "";
                int    LineNumber = 0;

                //
                // Generic sample line "UE4_Engine!UEngine::Exec() {+ 21105 bytes} [d:\depot\ue4\engine\source\runtime\engine\private\unrealengine.cpp:2777]"
                //
                // Mac
                // thread_start()  Address = 0x7fff87ae141d (filename not found) [in libsystem_pthread.dylib]
                //
                // Linux
                // Unknown!AFortPlayerController::execServerSaveLoadoutData(FFrame&, void*) + some bytes

                int ModuleSeparator    = CurrentLine.IndexOf('!');
                int PlusOffset         = CurrentLine.IndexOf(" + ");
                int OpenFuncSymbol     = CurrentLine.IndexOf('(');
                int CloseFuncSymbol    = CurrentLine.IndexOf(')');
                int OpenBracketOffset  = CurrentLine.IndexOf('[');
                int CloseBracketOffset = CurrentLine.LastIndexOf(']');

                int MacModuleStart = CurrentLine.IndexOf("[in ");
                int MacModuleEnd   = MacModuleStart > 0 ? CurrentLine.IndexOf("]", MacModuleStart) : 0;

                bool bLinux   = CurrentCrash.PlatformName.Contains("Linux");
                bool bMac     = CurrentCrash.PlatformName.Contains("Mac");
                bool bWindows = CurrentCrash.PlatformName.Contains("Windows");


                // Parse out the juicy info from the line of the callstack
                if (ModuleSeparator > 0)
                {
                    ModuleName = CurrentLine.Substring(0, ModuleSeparator).Trim();
                    if (OpenFuncSymbol > ModuleSeparator && CloseFuncSymbol > OpenFuncSymbol)
                    {
                        // Grab the function name if it exists
                        FuncName  = CurrentLine.Substring(ModuleSeparator + 1, OpenFuncSymbol - ModuleSeparator - 1).Trim();
                        FuncName += "()";

                        // Grab the source file
                        if (OpenBracketOffset > CloseFuncSymbol && CloseBracketOffset > OpenBracketOffset && bWindows)
                        {
                            string FileLinePath = CurrentLine.Substring(OpenBracketOffset + 1, CloseBracketOffset - OpenBracketOffset - 1).Trim();

                            FilePath = FileLinePath.TrimEnd("0123456789:".ToCharArray());
                            int SourceLine = 0;
                            Debug.Assert(FilePath.Length < FileLinePath.Length, "WRONG SIZE");
                            if (int.TryParse(FileLinePath.Substring(FilePath.Length + 1), out SourceLine))
                            {
                                LineNumber = SourceLine;
                            }
                        }
                    }
                }
                else if (bWindows)
                {
                    // Grab the module name if there is no function name
                    int WhiteSpacePos = CurrentLine.IndexOf(' ');
                    ModuleName = WhiteSpacePos > 0 ? CurrentLine.Substring(0, WhiteSpacePos) : CurrentLine;
                }

                if (bMac && MacModuleStart > 0 && MacModuleEnd > 0)
                {
                    int AddressOffset     = CurrentLine.IndexOf("Address =");
                    int OpenFuncSymbolMac = AddressOffset > 0 ? CurrentLine.Substring(0, AddressOffset).LastIndexOf('(') : 0;
                    if (OpenFuncSymbolMac > 0)
                    {
                        FuncName  = CurrentLine.Substring(0, OpenFuncSymbolMac).Trim();
                        FuncName += "()";
                    }

                    ModuleName = CurrentLine.Substring(MacModuleStart + 3, MacModuleEnd - MacModuleStart - 3).Trim();
                }

                // Remove callstack entries that match any of these functions.
                var FuncsToRemove = new HashSet <string>(new string[]
                {
                    "RaiseException",
                    "FDebug::",
                    "Error::Serialize",
                    "FOutputDevice::Logf",
                    "FMsg::Logf",
                    "ReportCrash",
                    "NewReportEnsure",
                });

                bool Contains = FuncsToRemove.Contains(FuncName, new CustomFuncComparer());
                if (!Contains)
                {
                    CallStackEntries.Add(new CallStackEntry(CurrentLine, ModuleName, FilePath, FuncName, LineNumber));
                }
            }
        }
 partial void UpdateCrash(Crash instance);
		private void detach_Crashes(Crash entity)
		{
			this.SendPropertyChanging();
			entity.CallStackPattern = null;
		}
		private void attach_Crashes(Crash entity)
		{
			this.SendPropertyChanging();
			entity.UserById = this;
		}
Example #32
0
        /// <summary>
        /// Parse a raw callstack into a pattern
        /// </summary>
        /// <param name="CurrentCrash">The crash with a raw callstack to parse.</param>
        private void ParseCallStack(Crash CurrentCrash)
        {
            // Everything is disabled by default
            bDisplayUnformattedCallStack = false;
            bDisplayModuleNames          = false;
            bDisplayFunctionNames        = false;
            bDisplayFileNames            = false;
            bDisplayFilePathNames        = false;

            bool   bSkipping      = false;
            string LineToSkipUpto = "";

            switch (CurrentCrash.CrashType)
            {
            case 2:
                bSkipping      = true;
                LineToSkipUpto = "FDebug::AssertFailed()";
                break;

            case 3:
                bSkipping      = true;
                LineToSkipUpto = "FDebug::EnsureFailed()";
                break;
            }

            if (string.IsNullOrEmpty(CurrentCrash.RawCallStack))
            {
                return;
            }

            CallStackEntries.Clear();

            // Store off a pre split array of call stack lines
            string[] RawCallStackLines = CurrentCrash.RawCallStack.Split(new[] { '\n' }, StringSplitOptions.RemoveEmptyEntries);

            // Support older callstacks uploaded before UE4 upgrade
            if (!NewCallstackFormat.Match(RawCallStackLines[0]).Success)
            {
                foreach (string CurrentLine in RawCallStackLines)
                {
                    // Exit if we've hit the max number of lines we want
                    if (CallStackEntries.Count >= MaxLinesToParse)
                    {
                        break;
                    }

                    ParseUE3FormatCallstackLine(CurrentLine);
                }
                return;
            }

            foreach (string CurrentLine in RawCallStackLines)
            {
                // Exit if we've hit the max number of lines we want
                if (CallStackEntries.Count >= MaxLinesToParse)
                {
                    break;
                }

                if (bSkipping)
                {
                    if (CurrentLine.Contains(LineToSkipUpto))
                    {
                        bSkipping = false;
                    }
                }

                if (bSkipping)
                {
                    continue;
                }

                string ModuleName = "<Unknown>";
                string FuncName   = "<Unknown>";
                string FilePath   = "";
                int    LineNumber = 0;

                // Sample line "UE4_Engine!UEngine::Exec() + 21105 bytes [d:\depot\ue4\engine\source\runtime\engine\private\unrealengine.cpp:2777]"

                int PlingOffset        = CurrentLine.IndexOf('!');
                int PlusOffset         = CurrentLine.IndexOf(" + ");
                int BytesOffset        = CurrentLine.IndexOf(" bytes");
                int OpenBracketOffset  = CurrentLine.IndexOf('[');
                int CloseBracketOffset = CurrentLine.LastIndexOf(']');

                // Parse out the juicy info from the line of the callstack
                if (PlingOffset > 0)
                {
                    ModuleName = CurrentLine.Substring(0, PlingOffset).Trim();
                    if (BytesOffset > PlingOffset)
                    {
                        // Grab the function name if it exists
                        FuncName = CurrentLine.Substring(PlingOffset + 1, BytesOffset - PlingOffset + " bytes".Length - 1).Trim();

                        // Grab the source file
                        if (OpenBracketOffset > BytesOffset && CloseBracketOffset > BytesOffset && CloseBracketOffset > OpenBracketOffset)
                        {
                            string FileLinePath = CurrentLine.Substring(OpenBracketOffset + 1, CloseBracketOffset - OpenBracketOffset - 1).Trim();

                            FilePath = FileLinePath.TrimEnd("0123456789:".ToCharArray());
                            int SourceLine = 0;
                            Debug.Assert(FilePath.Length < FileLinePath.Length, "WRONG SIZE");
                            if (int.TryParse(FileLinePath.Substring(FilePath.Length + 1), out SourceLine))
                            {
                                LineNumber = SourceLine;
                            }
                        }
                    }
                }
                else if (BytesOffset > 0)
                {
                    // Grab the module name if there is no function name
                    ModuleName = CurrentLine.Substring(0, PlusOffset).Trim();
                }

                CallStackEntries.Add(new CallStackEntry(CurrentLine, ModuleName, FilePath, FuncName, LineNumber));
            }
        }
		private void detach_CrashesFromName(Crash entity)
		{
			this.SendPropertyChanging();
			entity.UserByName = null;
		}
Example #34
0
 private void OnCrashesRemove( Crash CrashInstance )
 {
     Buggs_Crash BuggCrash = Buggs_Crashes.FirstOrDefault( BuggCrashInstance => BuggCrashInstance.BuggId == Id && BuggCrashInstance.CrashId == CrashInstance.Id );
     Buggs_Crashes.Remove( BuggCrash );
     SendPropertyChanged( null );
 }