/// <summary> /// Create call stack pattern and either insert into database or match to existing. /// Update Associate Buggs. /// </summary> /// <param name="newCrash"></param> private void BuildPattern(Crash newCrash) { var callstack = new CallStackContainer(newCrash); newCrash.Module = callstack.GetModuleName(); if (newCrash.PatternId == null) { var patternList = new List <string>(); try { foreach (var entry in callstack.CallStackEntries.Take(CallStackContainer.MaxLinesToParse)) { FunctionCall currentFunctionCall; var csEntry = entry; if (_unitOfWork.FunctionRepository.Any(f => f.Call == csEntry.FunctionName)) { currentFunctionCall = _unitOfWork.FunctionRepository.First(f => f.Call == csEntry.FunctionName); } else { currentFunctionCall = new FunctionCall { Call = csEntry.FunctionName }; _unitOfWork.FunctionRepository.Save(currentFunctionCall); _unitOfWork.Save(); } patternList.Add(currentFunctionCall.Id.ToString()); } newCrash.Pattern = string.Join("+", patternList); } catch (Exception ex) { var messageBuilder = new StringBuilder(); FLogger.Global.WriteException("Build Pattern exception: " + ex.Message.ToString(CultureInfo.InvariantCulture)); messageBuilder.AppendLine("Exception was:"); messageBuilder.AppendLine(ex.ToString()); while (ex.InnerException != null) { ex = ex.InnerException; messageBuilder.AppendLine(ex.ToString()); } _slackWriter.Write("Build Pattern Exception : " + ex.Message.ToString(CultureInfo.InvariantCulture)); throw; } } }
/// <summary> /// Show detailed information about a crash. /// </summary> /// <param name="CrashesForm">A form of user data passed up from the client.</param> /// <param name="id">The unique id of the crash we wish to show the details of.</param> /// <returns>A view to show crash details.</returns> public ActionResult Show(FormCollection CrashesForm, int id) { using (var logTimer = new FAutoScopedLogTimer(this.GetType().ToString() + "(CrashId=" + id + ")", bCreateNewLog: true)) { CallStackContainer currentCallStack = null; // Update the selected crash based on the form contents var currentCrash = _unitOfWork.CrashRepository.GetById(id); if (currentCrash == null) { return(RedirectToAction("Index")); } string FormValue; FormValue = CrashesForm["SetStatus"]; if (!string.IsNullOrEmpty(FormValue)) { currentCrash.Status = FormValue; } FormValue = CrashesForm["SetFixedIn"]; if (!string.IsNullOrEmpty(FormValue)) { currentCrash.FixedChangeList = FormValue; } FormValue = CrashesForm["SetTTP"]; if (!string.IsNullOrEmpty(FormValue)) { currentCrash.Jira = FormValue; } // Valid to set description to an empty string FormValue = CrashesForm["Description"]; if (FormValue != null) { currentCrash.Description = FormValue; } currentCallStack = new CallStackContainer(currentCrash); currentCrash.Module = currentCallStack.GetModuleName(); //Set call stack properties currentCallStack.bDisplayModuleNames = true; currentCallStack.bDisplayFunctionNames = true; currentCallStack.bDisplayFileNames = true; currentCallStack.bDisplayFilePathNames = true; currentCallStack.bDisplayUnformattedCallStack = false; currentCrash.CallStackContainer = new CallStackContainer(currentCrash); // Populate the crash with the correct user data //_crashRepo.PopulateUserInfo( CurrentCrash ); //_crashRepo.SubmitChanges(); var Model = new CrashViewModel { Crash = currentCrash, CallStack = currentCallStack }; Model.GenerationTime = logTimer.GetElapsedSeconds().ToString("F2"); return(View("Show", Model)); } }
/// <summary> /// Prepares Bugg for JIRA /// </summary> /// <param name="CrashesForBugg"></param> public void PrepareBuggForJira(List <CrashDataModel> CrashesForBugg) { var jiraConnection = JiraConnection.Get(); this.AffectedVersions = new SortedSet <string>(); this.AffectedMajorVersions = new SortedSet <string>(); // 4.4, 4.5 and so on this.BranchesFoundIn = new SortedSet <string>(); this.AffectedPlatforms = new SortedSet <string>(); var hashSetDescriptions = new HashSet <string>(); var machineIds = new HashSet <string>(); var firstClAffected = int.MaxValue; foreach (var crashDataModel in CrashesForBugg) { // Only add machine if the number has 32 characters if (crashDataModel.ComputerName != null && crashDataModel.ComputerName.Length == 32) { machineIds.Add(crashDataModel.ComputerName); if (crashDataModel.Description.Length > 4) { hashSetDescriptions.Add(crashDataModel.Description); } } if (!string.IsNullOrEmpty(crashDataModel.BuildVersion)) { this.AffectedVersions.Add(crashDataModel.BuildVersion); } // Depot || Stream if (!string.IsNullOrEmpty(crashDataModel.Branch)) { this.BranchesFoundIn.Add(crashDataModel.Branch); } var CrashBuiltFromCl = 0; int.TryParse(crashDataModel.ChangelistVersion, out CrashBuiltFromCl); if (CrashBuiltFromCl > 0) { firstClAffected = Math.Min(firstClAffected, CrashBuiltFromCl); } if (!string.IsNullOrEmpty(crashDataModel.PlatformName)) { // Platform = "Platform [Desc]"; var platSubs = crashDataModel.PlatformName.Split(" ".ToCharArray(), StringSplitOptions.RemoveEmptyEntries); if (platSubs.Length >= 1) { this.AffectedPlatforms.Add(platSubs[0]); } } } //ToJiraDescriptons foreach (var line in hashSetDescriptions) { var listItem = "- " + HttpUtility.HtmlEncode(line); ToJiraDescriptions.Add(listItem); } this.ToJiraFirstCLAffected = firstClAffected; if (this.AffectedVersions.Count > 0) { this.BuildVersion = this.AffectedVersions.Last(); // Latest Version Affected } foreach (var affectedBuild in this.AffectedVersions) { var subs = affectedBuild.Split(".".ToCharArray(), StringSplitOptions.RemoveEmptyEntries); if (subs.Length >= 2) { var majorVersion = subs[0] + "." + subs[1]; this.AffectedMajorVersions.Add(majorVersion); } } var bv = this.BuildVersion; var latestClAffected = CrashesForBugg. // CL of the latest build Where(Crash => Crash.BuildVersion == bv). Max(Crash => Crash.ChangelistVersion); var ILatestCLAffected = -1; int.TryParse(latestClAffected, out ILatestCLAffected); this.LatestCLAffected = ILatestCLAffected; // Latest CL Affected var latestOsAffected = CrashesForBugg.OrderByDescending(Crash => Crash.TimeOfCrash).First().PlatformName; this.LatestOSAffected = latestOsAffected; // Latest Environment Affected // ToJiraSummary var functionCalls = new CallStackContainer(CrashesForBugg.First().CrashType, CrashesForBugg.First().RawCallStack, CrashesForBugg.First().PlatformName).GetFunctionCallsForJira(); if (functionCalls.Count > 0) { this.ToJiraSummary = functionCalls[0]; this.ToJiraFunctionCalls = functionCalls; } else { this.ToJiraSummary = "No valid callstack found"; this.ToJiraFunctionCalls = new List <string>(); } // ToJiraVersions this.ToJiraVersions = new List <object>(); foreach (var version in this.AffectedMajorVersions) { var bValid = jiraConnection.GetNameToVersions().ContainsKey(version); if (bValid) { this.ToJiraVersions.Add(jiraConnection.GetNameToVersions()[version]); } } // ToJiraBranches this.ToJiraBranches = new HashSet <string>(); foreach (var branchName in this.BranchesFoundIn) { if (!string.IsNullOrEmpty(branchName)) { // Stream if (branchName.StartsWith("//")) { this.ToJiraBranches.Add(branchName); } // Depot else { this.ToJiraBranches.Add(CrashReporterConstants.P4_DEPOT_PREFIX + branchName); } } } // ToJiraPlatforms this.ToJiraPlatforms = new List <object>(); foreach (var platform in this.AffectedPlatforms) { bool bValid = jiraConnection.GetNameToPlatform().ContainsKey(platform); if (bValid) { this.ToJiraPlatforms.Add(jiraConnection.GetNameToPlatform()[platform]); } } // ToJiraPlatforms this.ToBranchName = new List <object>(); foreach (var BranchName in this.BranchesFoundIn) { bool bValid = jiraConnection.GetNameToBranch().ContainsKey(BranchName); if (bValid) { this.ToBranchName.Add(jiraConnection.GetNameToBranch()[BranchName]); } } }
/// <summary> /// Prepares Bugg for JIRA /// </summary> /// <param name="CrashesForBugg"></param> public void PrepareBuggForJira(List <Crash> CrashesForBugg) { var JC = JiraConnection.Get(); this.AffectedVersions = new SortedSet <string>(); this.AffectedMajorVersions = new SortedSet <string>(); // 4.4, 4.5 and so this.BranchesFoundIn = new SortedSet <string>(); this.AffectedPlatforms = new SortedSet <string>(); this.CrashesInTimeFrameAll = CrashesForBugg.Count; this.CrashesInTimeFrameGroup = CrashesForBugg.Count; var HashSetDescriptions = new HashSet <string>(); HashSet <string> MachineIds = new HashSet <string>(); int FirstCLAffected = int.MaxValue; foreach (var Crash in CrashesForBugg) { // Only add machine if the number has 32 characters if (Crash.ComputerName != null && Crash.ComputerName.Length == 32) { MachineIds.Add(Crash.ComputerName); if (Crash.Description.Length > 4) { HashSetDescriptions.Add(Crash.Description); } } // @TODO Ignore bad build versions. { if (!string.IsNullOrEmpty(Crash.BuildVersion)) { this.AffectedVersions.Add(Crash.BuildVersion); } // Depot || Stream if (!string.IsNullOrEmpty(Crash.Branch)) { this.BranchesFoundIn.Add(Crash.Branch); } int CrashBuiltFromCL = 0; int.TryParse(Crash.ChangeListVersion, out CrashBuiltFromCL); if (CrashBuiltFromCL > 0) { FirstCLAffected = Math.Min(FirstCLAffected, CrashBuiltFromCL); } if (!string.IsNullOrEmpty(Crash.PlatformName)) { // Platform = "Platform [Desc]"; var PlatSubs = Crash.PlatformName.Split(" ".ToCharArray(), StringSplitOptions.RemoveEmptyEntries); if (PlatSubs.Length >= 1) { this.AffectedPlatforms.Add(PlatSubs[0]); } } } } // CopyToJira foreach (var Line in HashSetDescriptions) { string ListItem = "- " + HttpUtility.HtmlEncode(Line); ToJiraDescriptions.Add(ListItem); } this.ToJiraFirstCLAffected = FirstCLAffected; if (this.AffectedVersions.Count > 0) { this.BuildVersion = this.AffectedVersions.Last(); // Latest Version Affected } foreach (var AffectedBuild in this.AffectedVersions) { var Subs = AffectedBuild.Split(".".ToCharArray(), StringSplitOptions.RemoveEmptyEntries); if (Subs.Length >= 2) { string MajorVersion = Subs[0] + "." + Subs[1]; this.AffectedMajorVersions.Add(MajorVersion); } } string BV = this.BuildVersion; this.NumberOfUniqueMachines = MachineIds.Count; // # Affected Users string LatestCLAffected = CrashesForBugg. // CL of the latest build Where(Crash => Crash.BuildVersion == BV). Max(Crash => Crash.ChangeListVersion); int ILatestCLAffected = -1; int.TryParse(LatestCLAffected, out ILatestCLAffected); this.LatestCLAffected = ILatestCLAffected; // Latest CL Affected string LatestOSAffected = CrashesForBugg.OrderByDescending(Crash => Crash.TimeOfCrash).First().PlatformName; this.LatestOSAffected = LatestOSAffected; // Latest Environment Affected // ToJiraSummary var FunctionCalls = new CallStackContainer(CrashesForBugg.First()).GetFunctionCallsForJira(); if (FunctionCalls.Count > 0) { this.ToJiraSummary = FunctionCalls[0]; this.ToJiraFunctionCalls = FunctionCalls; } else { this.ToJiraSummary = "No valid callstack found"; this.ToJiraFunctionCalls = new List <string>(); } // ToJiraVersions this.ToJiraVersions = new List <object>(); foreach (var Version in this.AffectedMajorVersions) { bool bValid = JC.GetNameToVersions().ContainsKey(Version); if (bValid) { this.ToJiraVersions.Add(JC.GetNameToVersions()[Version]); } } // ToJiraBranches this.ToJiraBranches = new HashSet <string>(); foreach (var BranchName in this.BranchesFoundIn) { if (!string.IsNullOrEmpty(BranchName)) { // Stream if (BranchName.StartsWith("//")) { this.ToJiraBranches.Add(BranchName); } // Depot else { this.ToJiraBranches.Add(CrashReporterConstants.P4_DEPOT_PREFIX + BranchName); } } } // ToJiraPlatforms this.ToJiraPlatforms = new List <object>(); foreach (var platform in this.AffectedPlatforms) { bool bValid = JC.GetNameToPlatform().ContainsKey(platform); if (bValid) { this.ToJiraPlatforms.Add(JC.GetNameToPlatform()[platform]); } } // ToJiraPlatforms this.ToBranchName = new List <object>(); foreach (var BranchName in this.BranchesFoundIn) { bool bValid = JC.GetNameToBranch().ContainsKey(BranchName); if (bValid) { this.ToBranchName.Add(JC.GetNameToBranch()[BranchName]); } } }
/// <summary> /// Create call stack pattern and either insert into database or match to existing. /// Update Associate Buggs. /// </summary> /// <param name="newCrash"></param> private void BuildPattern(Crash newCrash) { var callstack = new CallStackContainer(newCrash); newCrash.Module = callstack.GetModuleName(); if (newCrash.PatternId == null) { var patternList = new List<string>(); try { foreach (var entry in callstack.CallStackEntries.Take(CallStackContainer.MaxLinesToParse)) { FunctionCall currentFunctionCall; var csEntry = entry; if (_unitOfWork.FunctionRepository.Any(f => f.Call == csEntry.FunctionName)) { currentFunctionCall = _unitOfWork.FunctionRepository.First(f => f.Call == csEntry.FunctionName); } else { currentFunctionCall = new FunctionCall { Call = csEntry.FunctionName }; _unitOfWork.FunctionRepository.Save(currentFunctionCall); _unitOfWork.Save(); } patternList.Add(currentFunctionCall.Id.ToString()); } newCrash.Pattern = string.Join("+", patternList); } catch (Exception ex) { var messageBuilder = new StringBuilder(); FLogger.Global.WriteException("Build Pattern exception: " + ex.Message.ToString(CultureInfo.InvariantCulture)); messageBuilder.AppendLine("Exception was:"); messageBuilder.AppendLine(ex.ToString()); while (ex.InnerException != null) { ex = ex.InnerException; messageBuilder.AppendLine(ex.ToString()); } _slackWriter.Write("Build Pattern Exception : " + ex.Message.ToString(CultureInfo.InvariantCulture)); throw; } } }
/// <summary> /// Show detailed information about a crash. /// </summary> /// <param name="CrashesForm">A form of user data passed up from the client.</param> /// <param name="id">The unique id of the crash we wish to show the details of.</param> /// <returns>A view to show crash details.</returns> public ActionResult Show( FormCollection CrashesForm, int id ) { using( var logTimer = new FAutoScopedLogTimer( this.GetType().ToString() + "(CrashId=" + id + ")", bCreateNewLog: true ) ) { CallStackContainer currentCallStack = null; // Update the selected crash based on the form contents var currentCrash = _unitOfWork.CrashRepository.GetById(id); if( currentCrash == null ) { return RedirectToAction( "Index" ); } string FormValue; FormValue = CrashesForm["SetStatus"]; if( !string.IsNullOrEmpty( FormValue ) ) { currentCrash.Status = FormValue; } FormValue = CrashesForm["SetFixedIn"]; if( !string.IsNullOrEmpty( FormValue ) ) { currentCrash.FixedChangeList = FormValue; } FormValue = CrashesForm["SetTTP"]; if( !string.IsNullOrEmpty( FormValue ) ) { currentCrash.Jira = FormValue; } // Valid to set description to an empty string FormValue = CrashesForm["Description"]; if( FormValue != null ) { currentCrash.Description = FormValue; } currentCallStack = new CallStackContainer( currentCrash ); currentCrash.Module = currentCallStack.GetModuleName(); //Set call stack properties currentCallStack.bDisplayModuleNames = true; currentCallStack.bDisplayFunctionNames = true; currentCallStack.bDisplayFileNames = true; currentCallStack.bDisplayFilePathNames = true; currentCallStack.bDisplayUnformattedCallStack = false; currentCrash.CallStackContainer = new CallStackContainer(currentCrash); // Populate the crash with the correct user data //_crashRepo.PopulateUserInfo( CurrentCrash ); //_crashRepo.SubmitChanges(); var Model = new CrashViewModel { Crash = currentCrash, CallStack = currentCallStack }; Model.GenerationTime = logTimer.GetElapsedSeconds().ToString( "F2" ); return View( "Show", Model ); } }