/// <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); var Model = new CrashViewModel { Crash = currentCrash, CallStack = currentCallStack }; Model.GenerationTime = logTimer.GetElapsedSeconds().ToString("F2"); return(View("Show", Model)); } }
/// <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; var functionCall = _unitOfWork.FunctionRepository.First(f => f.Call == csEntry.FunctionName); if (functionCall != null) { currentFunctionCall = functionCall; } 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; } } }
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()); } } }
/// <summary> /// The Show action. /// </summary> /// <param name="BuggsForm">The form of user data passed up from the client.</param> /// <param name="id">The unique id of the Bugg.</param> /// <returns>The view to display a Bugg on the client.</returns> public ActionResult Show(FormCollection BuggsForm, int id) { using (FAutoScopedLogTimer LogTimer = new FAutoScopedLogTimer(this.GetType().ToString() + "(BuggId=" + id + ")", bCreateNewLog: true)) { // Handle 'CopyToJira' button int BuggIDToBeAddedToJira = 0; foreach (var Entry in BuggsForm) { if (Entry.ToString().Contains(Bugg.JiraSubmitName)) { int.TryParse(Entry.ToString().Substring(Bugg.JiraSubmitName.Length), out BuggIDToBeAddedToJira); break; } } BuggRepository Buggs = new BuggRepository(); // Set the display properties based on the radio buttons bool DisplayModuleNames = false; if (BuggsForm["DisplayModuleNames"] == "true") { DisplayModuleNames = true; } bool DisplayFunctionNames = false; if (BuggsForm["DisplayFunctionNames"] == "true") { DisplayFunctionNames = true; } bool DisplayFileNames = false; if (BuggsForm["DisplayFileNames"] == "true") { DisplayFileNames = true; } bool DisplayFilePathNames = false; if (BuggsForm["DisplayFilePathNames"] == "true") { DisplayFilePathNames = true; DisplayFileNames = false; } bool DisplayUnformattedCallStack = false; if (BuggsForm["DisplayUnformattedCallStack"] == "true") { DisplayUnformattedCallStack = true; } // Create a new view and populate with crashes List <Crash> Crashes = null; BuggViewModel Model = new BuggViewModel(); Bugg NewBugg = Buggs.GetBugg(id); if (NewBugg == null) { return(RedirectToAction("")); } Crashes = NewBugg.GetCrashes(); using (FAutoScopedLogTimer GetCrashesTimer = new FAutoScopedLogTimer("Bugg.PrepareBuggForJira")) { if (Crashes.Count > 0) { NewBugg.PrepareBuggForJira(Crashes); if (BuggIDToBeAddedToJira != 0) { NewBugg.CopyToJira(); } } } using (FAutoScopedLogTimer JiraResultsTimer = new FAutoScopedLogTimer("Bugg.GrabJira")) { var JC = JiraConnection.Get(); bool bValidJira = false; // Verify valid JiraID, this may be still a TTP if (!string.IsNullOrEmpty(NewBugg.Jira)) { int TTPID = 0; int.TryParse(NewBugg.Jira, out TTPID); if (TTPID == 0) { //AddBuggJiraMapping( NewBugg, ref FoundJiras, ref JiraIDtoBugg ); bValidJira = true; } } if (JC.CanBeUsed() && bValidJira) { // Grab the data form JIRA. string JiraSearchQuery = "key = " + NewBugg.Jira; var JiraResults = JC.SearchJiraTickets( JiraSearchQuery, new string[] { "key", // string "summary", // string "components", // System.Collections.ArrayList, Dictionary<string,object>, name "resolution", // System.Collections.Generic.Dictionary`2[System.String,System.Object], name "fixVersions", // System.Collections.ArrayList, Dictionary<string,object>, name "customfield_11200" // string }); // Jira Key, Summary, Components, Resolution, Fix version, Fix changelist foreach (var Jira in JiraResults) { string JiraID = Jira.Key; string Summary = (string)Jira.Value["summary"]; string ComponentsText = ""; System.Collections.ArrayList Components = (System.Collections.ArrayList)Jira.Value["components"]; foreach (Dictionary <string, object> Component in Components) { ComponentsText += (string)Component["name"]; ComponentsText += " "; } Dictionary <string, object> ResolutionFields = (Dictionary <string, object>)Jira.Value["resolution"]; string Resolution = ResolutionFields != null ? (string)ResolutionFields["name"] : ""; string FixVersionsText = ""; System.Collections.ArrayList FixVersions = (System.Collections.ArrayList)Jira.Value["fixVersions"]; foreach (Dictionary <string, object> FixVersion in FixVersions) { FixVersionsText += (string)FixVersion["name"]; FixVersionsText += " "; } int FixCL = Jira.Value["customfield_11200"] != null ? (int)(decimal)Jira.Value["customfield_11200"] : 0; NewBugg.JiraSummary = Summary; NewBugg.JiraComponentsText = ComponentsText; NewBugg.JiraResolution = Resolution; NewBugg.JiraFixVersionsText = FixVersionsText; if (FixCL != 0) { NewBugg.JiraFixCL = FixCL.ToString(); } break; } } } // Apply any user settings if (BuggsForm.Count > 0) { if (!string.IsNullOrEmpty(BuggsForm["SetStatus"])) { NewBugg.Status = BuggsForm["SetStatus"]; Buggs.SetBuggStatus(NewBugg.Status, id); } if (!string.IsNullOrEmpty(BuggsForm["SetFixedIn"])) { NewBugg.FixedChangeList = BuggsForm["SetFixedIn"]; Buggs.SetBuggFixedChangeList(NewBugg.FixedChangeList, id); } if (!string.IsNullOrEmpty(BuggsForm["SetTTP"])) { NewBugg.Jira = BuggsForm["SetTTP"]; Buggs.SetJIRAForBuggAndCrashes(NewBugg.Jira, id); } // <STATUS> } // Set up the view model with the crash data Model.Bugg = NewBugg; Model.Crashes = Crashes; Crash NewCrash = Model.Crashes.FirstOrDefault(); if (NewCrash != null) { using (FScopedLogTimer LogTimer2 = new FScopedLogTimer("CallstackTrimming")) { CallStackContainer CallStack = new CallStackContainer(NewCrash); // Set callstack properties CallStack.bDisplayModuleNames = DisplayModuleNames; CallStack.bDisplayFunctionNames = DisplayFunctionNames; CallStack.bDisplayFileNames = DisplayFileNames; CallStack.bDisplayFilePathNames = DisplayFilePathNames; CallStack.bDisplayUnformattedCallStack = DisplayUnformattedCallStack; Model.CallStack = CallStack; // Shorten very long function names. foreach (CallStackEntry Entry in Model.CallStack.CallStackEntries) { Entry.FunctionName = Entry.GetTrimmedFunctionName(128); } Model.SourceContext = NewCrash.SourceContext; } Model.Bugg.LatestCrashSummary = NewCrash.Summary; } Model.GenerationTime = LogTimer.GetElapsedSeconds().ToString("F2"); return(View("Show", Model)); } }
/// <summary> /// The Show action. /// </summary> /// <param name="buggsForm">The form of user data passed up from the client.</param> /// <param name="id">The unique id of the Bugg.</param> /// <returns>The view to display a Bugg on the client.</returns> public ActionResult Show(FormCollection buggsForm, int id, int page = 0) { using (var logTimer = new FAutoScopedLogTimer(this.GetType().ToString() + "(BuggId=" + id + ")")) { using (var unitOfWork = new UnitOfWork(new CrashReportEntities())) { // Set the display properties based on the radio buttons var displayModuleNames = buggsForm["DisplayModuleNames"] == "true"; var displayFunctionNames = buggsForm["DisplayFunctionNames"] == "true"; var displayFileNames = buggsForm["DisplayFileNames"] == "true"; var displayFilePathNames = false; // Set up the view model with the Crash data if (buggsForm["Page"] != null) { int.TryParse(buggsForm["Page"], out page); } if (buggsForm["DisplayFilePathNames"] == "true") { displayFilePathNames = true; displayFileNames = false; } var displayUnformattedCallStack = buggsForm["DisplayUnformattedCallStack"] == "true"; var model = GetResult(id, page, pageSize, unitOfWork); model.SourceContext = model.CrashData.First().SourceContext; model.Bugg.PrepareBuggForJira(model.CrashData); // Handle 'CopyToJira' button var buggIdToBeAddedToJira = 0; foreach (var entry in buggsForm.Cast <object>().Where(entry => entry.ToString().Contains("CopyToJira-"))) { int.TryParse(entry.ToString().Substring("CopyToJira-".Length), out buggIdToBeAddedToJira); break; } if (buggIdToBeAddedToJira != 0) { model.Bugg.JiraProject = buggsForm["JiraProject"]; model.Bugg.CopyToJira(); } var jc = JiraConnection.Get(); var bValidJira = false; // Verify valid JiraID, this may be still a TTP if (!string.IsNullOrEmpty(model.Bugg.TTPID)) { var jira = 0; int.TryParse(model.Bugg.TTPID, out jira); if (jira == 0) { bValidJira = true; } } if (jc.CanBeUsed() && bValidJira) { // Grab the data form JIRA. var jiraSearchQuery = "key = " + model.Bugg.TTPID; var jiraResults = new Dictionary <string, Dictionary <string, object> >(); try { jiraResults = jc.SearchJiraTickets( jiraSearchQuery, new string[] { "key", // string "summary", // string "components", // System.Collections.ArrayList, Dictionary<string,object>, name "resolution", // System.Collections.Generic.Dictionary`2[System.String,System.Object], name "fixVersions", // System.Collections.ArrayList, Dictionary<string,object>, name "customfield_11200" // string }); } catch (System.Exception) { model.Bugg.JiraSummary = "JIRA MISMATCH"; model.Bugg.JiraComponentsText = "JIRA MISMATCH"; model.Bugg.JiraResolution = "JIRA MISMATCH"; model.Bugg.JiraFixVersionsText = "JIRA MISMATCH"; model.Bugg.JiraFixCL = "JIRA MISMATCH"; } // Jira Key, Summary, Components, Resolution, Fix version, Fix changelist if (jiraResults.Any()) { var jira = jiraResults.First(); var summary = (string)jira.Value["summary"]; var componentsText = ""; var components = (System.Collections.ArrayList)jira.Value["components"]; foreach (Dictionary <string, object> component in components) { componentsText += (string)component["name"]; componentsText += " "; } var resolutionFields = (Dictionary <string, object>)jira.Value["resolution"]; var resolution = resolutionFields != null ? (string)resolutionFields["name"] : ""; var fixVersionsText = ""; var fixVersions = (System.Collections.ArrayList)jira.Value["fixVersions"]; foreach (Dictionary <string, object> fixVersion in fixVersions) { fixVersionsText += (string)fixVersion["name"]; fixVersionsText += " "; } var fixCl = jira.Value["customfield_11200"] != null ? (int)(decimal)jira.Value["customfield_11200"] : 0; //Conversion to ado.net entity framework model.Bugg.JiraSummary = summary; model.Bugg.JiraComponentsText = componentsText; model.Bugg.JiraResolution = resolution; model.Bugg.JiraFixVersionsText = fixVersionsText; if (fixCl != 0) { model.Bugg.FixedChangeList = fixCl.ToString(); } } } // Apply any user settings if (buggsForm.Count > 0) { if (!string.IsNullOrEmpty(buggsForm["SetStatus"])) { model.Bugg.Status = buggsForm["SetStatus"]; unitOfWork.CrashRepository.SetStatusByBuggId(model.Bugg.Id, buggsForm["SetFixedIn"]); } if (!string.IsNullOrEmpty(buggsForm["SetFixedIn"])) { model.Bugg.FixedChangeList = buggsForm["SetFixedIn"]; unitOfWork.CrashRepository.SetFixedCLByBuggId(model.Bugg.Id, buggsForm["SetFixedIn"]); } if (!string.IsNullOrEmpty(buggsForm["SetTTP"])) { model.Bugg.TTPID = buggsForm["SetTTP"]; unitOfWork.CrashRepository.SetJiraByBuggId(model.Bugg.Id, buggsForm["SetTTP"]); } unitOfWork.BuggRepository.Update(model.Bugg); unitOfWork.Save(); } var newCrash = model.CrashData.FirstOrDefault(); if (newCrash != null) { var callStack = new CallStackContainer(newCrash.CrashType, newCrash.RawCallStack, newCrash.PlatformName); // Set callstack properties callStack.bDisplayModuleNames = displayModuleNames; callStack.bDisplayFunctionNames = displayFunctionNames; callStack.bDisplayFileNames = displayFileNames; callStack.bDisplayFilePathNames = displayFilePathNames; callStack.bDisplayUnformattedCallStack = displayUnformattedCallStack; model.CallStack = callStack; // Shorten very long function names. foreach (var entry in model.CallStack.CallStackEntries) { entry.FunctionName = entry.GetTrimmedFunctionName(128); } model.SourceContext = newCrash.SourceContext; model.LatestCrashSummary = newCrash.Summary; } model.LatestCrashSummary = newCrash.Summary; model.Bugg.LatestCrashSummary = newCrash.Summary; model.GenerationTime = logTimer.GetElapsedSeconds().ToString("F2"); //Populate Jira Projects var jiraConnection = JiraConnection.Get(); var response = jiraConnection.JiraRequest("/issue/createmeta", JiraConnection.JiraMethod.GET, null, HttpStatusCode.OK); using (var responseReader = new StreamReader(response.GetResponseStream())) { var responseText = responseReader.ReadToEnd(); JObject jsonObject = JObject.Parse(responseText); JToken fields = jsonObject["projects"]; foreach (var project in fields) { model.JiraProjects.Add(new SelectListItem() { Text = project["name"].ToObject <string>(), Value = project["key"].ToObject <string>() }); } } model.PagingInfo = new PagingInfo { CurrentPage = page, PageSize = pageSize, TotalResults = model.Bugg.NumberOfCrashes.Value }; return(View("Show", model)); } } }
/// <summary> /// The Show action. /// </summary> /// <param name="BuggsForm">The form of user data passed up from the client.</param> /// <param name="id">The unique id of the Bugg.</param> /// <returns>The view to display a Bugg on the client.</returns> public ActionResult Show(FormCollection BuggsForm, int id) { // Set the display properties based on the radio buttons bool DisplayModuleNames = false; if (BuggsForm["DisplayModuleNames"] == "true") { DisplayModuleNames = true; } bool DisplayFunctionNames = false; if (BuggsForm["DisplayFunctionNames"] == "true") { DisplayFunctionNames = true; } bool DisplayFileNames = false; if (BuggsForm["DisplayFileNames"] == "true") { DisplayFileNames = true; } bool DisplayFilePathNames = false; if (BuggsForm["DisplayFilePathNames"] == "true") { DisplayFilePathNames = true; DisplayFileNames = false; } bool DisplayUnformattedCallStack = false; if (BuggsForm["DisplayUnformattedCallStack"] == "true") { DisplayUnformattedCallStack = true; } // Create a new view and populate with crashes List <Crash> Crashes = null; Bugg Bugg = new Bugg(); BuggViewModel Model = new BuggViewModel(); Bugg = LocalBuggRepository.GetBugg(id); if (Bugg == null) { return(RedirectToAction("")); } Crashes = Bugg.GetCrashes().ToList(); // Apply any user settings if (BuggsForm.Count > 0) { if (!string.IsNullOrEmpty(BuggsForm["SetStatus"])) { Bugg.Status = BuggsForm["SetStatus"]; LocalCrashRepository.SetBuggStatus(Bugg.Status, id); } if (!string.IsNullOrEmpty(BuggsForm["SetFixedIn"])) { Bugg.FixedChangeList = BuggsForm["SetFixedIn"]; LocalCrashRepository.SetBuggFixedChangeList(Bugg.FixedChangeList, id); } if (!string.IsNullOrEmpty(BuggsForm["SetTTP"])) { Bugg.TTPID = BuggsForm["SetTTP"]; LocalCrashRepository.SetBuggTTPID(Bugg.TTPID, id); } if (!string.IsNullOrEmpty(BuggsForm["Description"])) { Bugg.Description = BuggsForm["Description"]; } // <STATUS> } // Set up the view model with the crash data Model.Bugg = Bugg; Model.Crashes = Crashes; Crash NewCrash = Model.Crashes.FirstOrDefault(); if (NewCrash != null) { CallStackContainer CallStack = new CallStackContainer(NewCrash); // Set callstack properties CallStack.bDisplayModuleNames = DisplayModuleNames; CallStack.bDisplayFunctionNames = DisplayFunctionNames; CallStack.bDisplayFileNames = DisplayFileNames; CallStack.bDisplayFilePathNames = DisplayFilePathNames; CallStack.bDisplayUnformattedCallStack = DisplayUnformattedCallStack; Model.CallStack = CallStack; NewCrash.CallStackContainer = NewCrash.GetCallStack(); } // Add in the users for each crash in the Bugg foreach (Crash CrashInstance in Model.Crashes) { LocalCrashRepository.PopulateUserInfo(CrashInstance); } return(View("Show", Model)); }
/// <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 (FAutoScopedLogTimer LogTimer = new FAutoScopedLogTimer(this.GetType().ToString() + "(CrashId=" + id + ")")) { CallStackContainer CurrentCallStack = null; // Update the selected crash based on the form contents Crash CurrentCrash = LocalCrashRepository.GetCrash(id); if (CurrentCrash == null) { return(RedirectToAction("")); } 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.TTPID = FormValue; } // Valid to set description to an empty string FormValue = CrashesForm["Description"]; if (FormValue != null) { CurrentCrash.Description = FormValue; } CurrentCallStack = new CallStackContainer(CurrentCrash); // Set callstack properties CurrentCallStack.bDisplayModuleNames = true; CurrentCallStack.bDisplayFunctionNames = true; CurrentCallStack.bDisplayFileNames = true; CurrentCallStack.bDisplayFilePathNames = true; CurrentCallStack.bDisplayUnformattedCallStack = false; CurrentCrash.CallStackContainer = LocalCrashRepository.GetCallStack(CurrentCrash); // Populate the crash with the correct user data LocalCrashRepository.PopulateUserInfo(CurrentCrash); LocalCrashRepository.SubmitChanges(); return(View("Show", new CrashViewModel { Crash = CurrentCrash, CallStack = CurrentCallStack })); } }
/// <summary> /// The Show action. /// </summary> /// <param name="buggsForm">The form of user data passed up from the client.</param> /// <param name="id">The unique id of the Bugg.</param> /// <returns>The view to display a Bugg on the client.</returns> public ActionResult Show(FormCollection buggsForm, int id) { using (var logTimer = new FAutoScopedLogTimer(this.GetType().ToString() + "(BuggId=" + id + ")", bCreateNewLog: true)) { // Set the display properties based on the radio buttons var displayModuleNames = buggsForm["DisplayModuleNames"] == "true"; var displayFunctionNames = buggsForm["DisplayFunctionNames"] == "true"; var displayFileNames = buggsForm["DisplayFileNames"] == "true"; var displayFilePathNames = false; if (buggsForm["DisplayFilePathNames"] == "true") { displayFilePathNames = true; displayFileNames = false; } var displayUnformattedCallStack = buggsForm["DisplayUnformattedCallStack"] == "true"; // Create a new view and populate with crashes List <Crash> crashes = null; var model = new BuggViewModel(); var newBugg = _unitOfWork.BuggRepository.GetById(id); if (newBugg == null) { return(RedirectToAction("Index")); } crashes = newBugg.Crashes.OrderByDescending(data => data.TimeOfCrash).ToList(); newBugg.CrashesInTimeFrameAll = crashes.Count; newBugg.CrashesInTimeFrameGroup = crashes.Count; newBugg.NumberOfCrashes = crashes.Count; // Handle 'CopyToJira' button var buggIdToBeAddedToJira = 0; foreach (var entry in buggsForm.Cast <object>().Where(entry => entry.ToString().Contains("CopyToJira-"))) { int.TryParse(entry.ToString().Substring("CopyToJira-".Length), out buggIdToBeAddedToJira); break; } newBugg.PrepareBuggForJira(crashes); if (buggIdToBeAddedToJira != 0) { newBugg.JiraProject = buggsForm["JiraProject"]; newBugg.CopyToJira(); } var jc = JiraConnection.Get(); var bValidJira = false; // Verify valid JiraID, this may be still a TTP if (!string.IsNullOrEmpty(newBugg.TTPID)) { var jira = 0; int.TryParse(newBugg.TTPID, out jira); if (jira == 0) { bValidJira = true; } } if (jc.CanBeUsed() && bValidJira) { // Grab the data form JIRA. var jiraSearchQuery = "key = " + newBugg.TTPID; var jiraResults = new Dictionary <string, Dictionary <string, object> >(); try { jiraResults = jc.SearchJiraTickets( jiraSearchQuery, new string[] { "key", // string "summary", // string "components", // System.Collections.ArrayList, Dictionary<string,object>, name "resolution", // System.Collections.Generic.Dictionary`2[System.String,System.Object], name "fixVersions", // System.Collections.ArrayList, Dictionary<string,object>, name "customfield_11200" // string }); } catch (System.Exception) { newBugg.JiraSummary = "JIRA MISMATCH"; newBugg.JiraComponentsText = "JIRA MISMATCH"; newBugg.JiraResolution = "JIRA MISMATCH"; newBugg.JiraFixVersionsText = "JIRA MISMATCH"; newBugg.JiraFixCL = "JIRA MISMATCH"; } // Jira Key, Summary, Components, Resolution, Fix version, Fix changelist if (jiraResults.Any()) { var jira = jiraResults.First(); var summary = (string)jira.Value["summary"]; var componentsText = ""; var components = (System.Collections.ArrayList)jira.Value["components"]; foreach (Dictionary <string, object> component in components) { componentsText += (string)component["name"]; componentsText += " "; } var resolutionFields = (Dictionary <string, object>)jira.Value["resolution"]; var resolution = resolutionFields != null ? (string)resolutionFields["name"] : ""; var fixVersionsText = ""; var fixVersions = (System.Collections.ArrayList)jira.Value["fixVersions"]; foreach (Dictionary <string, object> fixVersion in fixVersions) { fixVersionsText += (string)fixVersion["name"]; fixVersionsText += " "; } var fixCl = jira.Value["customfield_11200"] != null ? (int)(decimal)jira.Value["customfield_11200"] : 0; //Conversion to ado.net entity framework newBugg.JiraSummary = summary; newBugg.JiraComponentsText = componentsText; newBugg.JiraResolution = resolution; newBugg.JiraFixVersionsText = fixVersionsText; if (fixCl != 0) { newBugg.FixedChangeList = fixCl.ToString(); } } } // Apply any user settings if (buggsForm.Count > 0) { if (!string.IsNullOrEmpty(buggsForm["SetStatus"])) { newBugg.Status = buggsForm["SetStatus"]; newBugg.Crashes.ForEach(data => data.Status = buggsForm["SetStatus"]); } if (!string.IsNullOrEmpty(buggsForm["SetFixedIn"])) { newBugg.FixedChangeList = buggsForm["SetFixedIn"]; newBugg.Crashes.ForEach(data => data.FixedChangeList = buggsForm["SetFixedIn"]); } if (!string.IsNullOrEmpty(buggsForm["SetTTP"])) { newBugg.TTPID = buggsForm["SetTTP"]; newBugg.Crashes.ForEach(data => data.Jira = buggsForm["SetTTP"]); } _unitOfWork.BuggRepository.Update(newBugg); _unitOfWork.Save(); } // Set up the view model with the crash data model.Crashes = crashes; model.Bugg = newBugg; var newCrash = model.Crashes.FirstOrDefault(); if (newCrash != null) { var callStack = new CallStackContainer(newCrash); // Set callstack properties callStack.bDisplayModuleNames = displayModuleNames; callStack.bDisplayFunctionNames = displayFunctionNames; callStack.bDisplayFileNames = displayFileNames; callStack.bDisplayFilePathNames = displayFilePathNames; callStack.bDisplayUnformattedCallStack = displayUnformattedCallStack; model.CallStack = callStack; // Shorten very long function names. foreach (var entry in model.CallStack.CallStackEntries) { entry.FunctionName = entry.GetTrimmedFunctionName(128); } model.SourceContext = newCrash.SourceContext; model.LatestCrashSummary = newCrash.Summary; } model.LatestCrashSummary = newCrash.Summary; model.Bugg.LatestCrashSummary = newCrash.Summary; model.GenerationTime = logTimer.GetElapsedSeconds().ToString("F2"); return(View("Show", model)); } }
/// <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> /// 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) { if (!Id.HasValue) { return(RedirectToAction("")); } CallStackContainer CurrentCallStack = null; // Update the selected crash based on the form contents Crash CurrentCrash = LocalCrashRepository.GetCrash(Id.Value); if (CurrentCrash == null) { return(RedirectToAction("")); } string FormValue; FormValue = CrashesForm["SetStatus"]; if (!string.IsNullOrEmpty(FormValue)) { CurrentCrash.Status = FormValue; LocalCrashRepository.SetCrashStatus(FormValue, Id.Value); } FormValue = CrashesForm["SetFixedIn"]; if (!string.IsNullOrEmpty(FormValue)) { CurrentCrash.FixedChangeList = FormValue; LocalCrashRepository.SetCrashFixedChangeList(FormValue, Id.Value); } FormValue = CrashesForm["SetTTP"]; if (!string.IsNullOrEmpty(FormValue)) { CurrentCrash.TTPID = FormValue; LocalCrashRepository.SetCrashTTPID(FormValue, Id.Value); } // Valid to set description to an empty string FormValue = CrashesForm["Description"]; if (FormValue != null) { CurrentCrash.Description = FormValue; LocalCrashRepository.SetCrashDescription(FormValue, Id.Value); } CurrentCallStack = new CallStackContainer(CurrentCrash); // Set callstack properties CurrentCallStack.bDisplayModuleNames = true; CurrentCallStack.bDisplayFunctionNames = true; CurrentCallStack.bDisplayFileNames = true; CurrentCallStack.bDisplayFilePathNames = true; CurrentCallStack.bDisplayUnformattedCallStack = false; CurrentCrash.CallStackContainer = CurrentCrash.GetCallStack(); // Populate the crash with the correct user data LocalCrashRepository.PopulateUserInfo(CurrentCrash); return(View("Show", new CrashViewModel { Crash = CurrentCrash, CallStack = CurrentCallStack })); }
/// <summary> /// The Show action. /// </summary> /// <param name="BuggsForm">The form of user data passed up from the client.</param> /// <param name="id">The unique id of the Bugg.</param> /// <returns>The view to display a Bugg on the client.</returns> public ActionResult Show(FormCollection BuggsForm, int id) { using (FAutoScopedLogTimer LogTimer = new FAutoScopedLogTimer(this.GetType().ToString() + "(BuggId=" + id + ")")) { // Set the display properties based on the radio buttons bool DisplayModuleNames = false; if (BuggsForm["DisplayModuleNames"] == "true") { DisplayModuleNames = true; } bool DisplayFunctionNames = false; if (BuggsForm["DisplayFunctionNames"] == "true") { DisplayFunctionNames = true; } bool DisplayFileNames = false; if (BuggsForm["DisplayFileNames"] == "true") { DisplayFileNames = true; } bool DisplayFilePathNames = false; if (BuggsForm["DisplayFilePathNames"] == "true") { DisplayFilePathNames = true; DisplayFileNames = false; } bool DisplayUnformattedCallStack = false; if (BuggsForm["DisplayUnformattedCallStack"] == "true") { DisplayUnformattedCallStack = true; } // Create a new view and populate with crashes List <Crash> Crashes = null; Bugg Bugg = new Bugg(); BuggViewModel Model = new BuggViewModel(); Bugg = LocalBuggRepository.GetBugg(id); if (Bugg == null) { return(RedirectToAction("")); } // @TODO yrx 2015-02-17 JIRA using (FAutoScopedLogTimer GetCrashesTimer = new FAutoScopedLogTimer("Bugg.GetCrashes().ToList")) { Crashes = Bugg.GetCrashes(); Bugg.AffectedVersions = new SortedSet <string>(); HashSet <string> MachineIds = new HashSet <string>(); foreach (Crash Crash in Crashes) { MachineIds.Add(Crash.ComputerName); // Ignore bad build versions. if (Crash.BuildVersion.StartsWith("4.")) { Bugg.AffectedVersions.Add(Crash.BuildVersion); } if (Crash.User == null) { //?? } } Bugg.NumberOfUniqueMachines = MachineIds.Count; } // Apply any user settings if (BuggsForm.Count > 0) { if (!string.IsNullOrEmpty(BuggsForm["SetStatus"])) { Bugg.Status = BuggsForm["SetStatus"]; LocalCrashRepository.SetBuggStatus(Bugg.Status, id); } if (!string.IsNullOrEmpty(BuggsForm["SetFixedIn"])) { Bugg.FixedChangeList = BuggsForm["SetFixedIn"]; LocalCrashRepository.SetBuggFixedChangeList(Bugg.FixedChangeList, id); } if (!string.IsNullOrEmpty(BuggsForm["SetTTP"])) { Bugg.TTPID = BuggsForm["SetTTP"]; BuggRepository.SetJIRAForBuggAndCrashes(Bugg.TTPID, id); } if (!string.IsNullOrEmpty(BuggsForm["Description"])) { Bugg.Description = BuggsForm["Description"]; } // <STATUS> } // Set up the view model with the crash data Model.Bugg = Bugg; Model.Crashes = Crashes; Crash NewCrash = Model.Crashes.FirstOrDefault(); if (NewCrash != null) { using (FScopedLogTimer LogTimer2 = new FScopedLogTimer("CallstackTrimming")) { CallStackContainer CallStack = new CallStackContainer(NewCrash); // Set callstack properties CallStack.bDisplayModuleNames = DisplayModuleNames; CallStack.bDisplayFunctionNames = DisplayFunctionNames; CallStack.bDisplayFileNames = DisplayFileNames; CallStack.bDisplayFilePathNames = DisplayFilePathNames; CallStack.bDisplayUnformattedCallStack = DisplayUnformattedCallStack; Model.CallStack = CallStack; // Shorten very long function names. foreach (CallStackEntry Entry in Model.CallStack.CallStackEntries) { Entry.FunctionName = Entry.GetTrimmedFunctionName(128); } Model.SourceContext = NewCrash.SourceContext; } } /*using( FScopedLogTimer LogTimer2 = new FScopedLogTimer( "BuggsController.Show.PopulateUserInfo" + "(id=" + id + ")" ) ) * { * // Add in the users for each crash in the Bugg * foreach( Crash CrashInstance in Model.Crashes ) * { * LocalCrashRepository.PopulateUserInfo( CrashInstance ); * } * }*/ return(View("Show", Model)); } }