/// <summary> /// Create a new Jira for this bug /// </summary> public void CopyToJira() { var jc = JiraConnection.Get(); Dictionary <string, object> issueFields; switch (this.JiraProject) { case "UE": issueFields = CreateGeneralIssue(jc); break; case "FORT": issueFields = CreateFortniteIssue(jc); break; case "ORION": issueFields = CreateOrionIssue(jc); break; default: issueFields = CreateProjectIssue(jc, this.JiraProject); break; } if (jc.CanBeUsed() && string.IsNullOrEmpty(this.TTPID)) { // Additional Info URL / Link to Crash/Bugg var key = jc.AddJiraTicket(issueFields); if (!string.IsNullOrEmpty(key)) { TTPID = key; } } }
/// <summary> /// Adds the bugg as a new JIRA ticket /// </summary> public void CopyToJira() { var jc = JiraConnection.Get(); Dictionary <string, object> issueFields; if (BranchesFoundIn.Any(data => data.ToLower().Contains("//fort"))) { issueFields = CreateFortniteIssue(jc); } //else if (BranchesFoundIn.Any(data => data.ToLower().Contains("//orion"))) //{ // issueFields = CreateOrionIssue(); //} else { issueFields = CreateGeneralIssue(jc); } if (jc.CanBeUsed() && string.IsNullOrEmpty(this.Jira)) { // Additional Info URL / Link to Crash/Bugg string Key = jc.AddJiraTicket(issueFields); if (!string.IsNullOrEmpty(Key)) { Jira = Key; var buggs = new BuggRepository(); buggs.SetJIRAForBuggAndCrashes(Key, Id); } } }
/// <summary> /// Adds the bugg as a new JIRA ticket /// </summary> public void CopyToJira() { var JC = JiraConnection.Get(); if (JC.CanBeUsed() && string.IsNullOrEmpty(this.TTPID)) { Dictionary <string, object> Fields = new Dictionary <string, object>(); Fields.Add("project", new Dictionary <string, object> { { "id", 11205 } }); // UE Fields.Add("summary", "[CrashReport] " + ToJiraSummary); // Call Stack, Line 1 Fields.Add("description", "____________"); // Description Fields.Add("issuetype", new Dictionary <string, object> { { "id", "1" } }); // Bug Fields.Add("labels", new string[] { "crash" }); // <label>crash</label> Fields.Add("customfield_11500", ToJiraFirstCLAffected); // Changelist # / Found Changelist Fields.Add("environment", LatestOSAffected); // Platform // Components var SupportComponent = JC.GetNameToComponents()["Support"]; Fields.Add("components", new object[] { SupportComponent }); // ToJiraVersions Fields.Add("versions", ToJiraVersions); // ToJiraBranches Fields.Add("customfield_11201", ToJiraBranches); // ToJiraPlatforms Fields.Add("customfield_11203", ToJiraPlatforms); // Callstack customfield_11807 var Callstack = GetFunctionCalls(); string JiraCallstack = string.Join("\r\n", Callstack); Fields.Add("customfield_11807", JiraCallstack); // Callstack string Key = JC.AddJiraTicket(Fields); if (!string.IsNullOrEmpty(Key)) { TTPID = Key; BuggRepository.SetJIRAForBuggAndCrashes(Key, Id); // Update the JIRA in the bugg. Dictionary <string, object> FieldsToUpdate = new Dictionary <string, object>(); string BuggLink = "http://crashreporter/Buggs/Show/" + Id; FieldsToUpdate.Add("customfield_11205", BuggLink); // Additional Info URL / Link to Crash/Bugg JC.UpdateJiraTicket(Key, FieldsToUpdate); } } }
/// <summary> /// Adds the bugg as a new JIRA ticket /// </summary> public void CopyToJira() { var JC = JiraConnection.Get(); if (JC.CanBeUsed() && string.IsNullOrEmpty(this.Jira)) { Dictionary <string, object> Fields = new Dictionary <string, object>(); Fields.Add("project", new Dictionary <string, object> { { "id", 11205 } }); // UE Fields.Add("summary", "[CrashReport] " + ToJiraSummary); // Call Stack, Line 1 Fields.Add("description", string.Join("\r\n", ToJiraDescriptions)); // Description Fields.Add("issuetype", new Dictionary <string, object> { { "id", "1" } }); // Bug Fields.Add("labels", new string[] { "crash", "liveissue" }); // <label>crash, live issue</label> Fields.Add("customfield_11500", ToJiraFirstCLAffected); // Changelist # / Found Changelist Fields.Add("environment", LatestOSAffected); // Platform // Components var SupportComponent = JC.GetNameToComponents()["Support"]; Fields.Add("components", new object[] { SupportComponent }); // ToJiraVersions Fields.Add("versions", ToJiraVersions); // ToJiraBranches Fields.Add("customfield_12402", ToJiraBranches.ToList()); // NewBranchFoundIn // ToJiraPlatforms Fields.Add("customfield_11203", ToJiraPlatforms); // Callstack customfield_11807 string JiraCallstack = "{noformat}" + string.Join("\r\n", ToJiraFunctionCalls) + "{noformat}"; Fields.Add("customfield_11807", JiraCallstack); // Callstack string BuggLink = "http://crashreporter/Buggs/Show/" + Id; Fields.Add("customfield_11205", BuggLink); // Additional Info URL / Link to Crash/Bugg string Key = JC.AddJiraTicket(Fields); if (!string.IsNullOrEmpty(Key)) { Jira = Key; BuggRepository Buggs = new BuggRepository(); Buggs.SetJIRAForBuggAndCrashes(Key, Id); } } }
/// <summary> /// Test method - DELETE ME! /// </summary> public void GetJiraIssueSpec() { var jiraConnection = JiraConnection.Get(); if (!jiraConnection.CanBeUsed()) { return; } var jiraResponse = jiraConnection.JiraRequest( "/issue/createmeta?projectKeys=UE&issuetypeName=Bug&expand=projects.issuetypes.fields", JiraConnection.JiraMethod.GET, null, HttpStatusCode.OK); var projectSpec = JiraConnection.ParseJiraResponse(jiraResponse); var projects = ((ArrayList)projectSpec["projects"]); ArrayList issueTypes = null; foreach (var project in projects) { var kvp = (KeyValuePair <string, object>)project; if (project == "issuetypes") { issueTypes = kvp.Value as ArrayList; } } if (issueTypes != null) { var bug = issueTypes[0]; } //var issuetypes = projdic["issuetypes"]; //var issues = (Dictionary<string, object>) issuetypes; //var bug = (Dictionary<string, object>)issues.First().Value; //var fields = (Dictionary<string, object>)bug["fields"]; }
/// <summary> /// /// </summary> public void TestJiraMethod() { var jiraConnection = JiraConnection.Get(); if (!jiraConnection.CanBeUsed()) { return; } var response = jiraConnection.JiraRequest( "/issue/createmeta?projectKeys=OR&issuetypeNames=Bug&expand=projects.issuetypes.fields", JiraConnection.JiraMethod.GET, null, HttpStatusCode.OK); using (var responseReader = new StreamReader(response.GetResponseStream())) { var responseText = responseReader.ReadToEnd(); JObject jsonObject = JObject.Parse(responseText); var fields = jsonObject["projects"][0]["issuetypes"][0]["fields"]; var requiredFields = fields.Where(c => c["required"].Value <bool>() == true); } }
/// <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> /// Retrieve all Buggs matching the search criteria. /// </summary> /// <param name="FormData">The incoming form of search criteria from the client.</param> /// <param name="BuggIDToBeAddedToJira">ID of the bugg that will be added to JIRA</param> /// <returns>A view to display the filtered Buggs.</returns> public ReportsViewModel GetResults(FormHelper FormData, int BuggIDToBeAddedToJira) { BuggRepository BuggsRepo = new BuggRepository(); CrashRepository CrashRepo = new CrashRepository(); // @TODO yrx 2015-02-17 BuggIDToBeAddedToJira replace with List<int> based on check box and Submit? // Enumerate JIRA projects if needed. // https://jira.ol.epicgames.net//rest/api/2/project var JC = JiraConnection.Get(); var JiraComponents = JC.GetNameToComponents(); var JiraVersions = JC.GetNameToVersions(); using (FAutoScopedLogTimer LogTimer = new FAutoScopedLogTimer(this.GetType().ToString())) { string AnonumousGroup = "Anonymous"; //List<String> Users = FRepository.Get().GetUserNamesFromGroupName( AnonumousGroup ); int AnonymousGroupID = FRepository.Get(BuggsRepo).FindOrAddGroup(AnonumousGroup); HashSet <int> AnonumousIDs = FRepository.Get(BuggsRepo).GetUserIdsFromUserGroup(AnonumousGroup); int AnonymousID = AnonumousIDs.First(); HashSet <string> UserNamesForUserGroup = FRepository.Get(BuggsRepo).GetUserNamesFromGroupName(AnonumousGroup); //FormData.DateFrom = DateTime.Now.AddDays( -1 ); var Crashes = CrashRepo .FilterByDate(CrashRepo.ListAll(), FormData.DateFrom, FormData.DateTo.AddDays(1)) // Only crashes and asserts .Where(Crash => Crash.CrashType == 1 || Crash.CrashType == 2) // Only anonymous user .Where(Crash => Crash.UserNameId.Value == AnonymousID) .Select(Crash => new { ID = Crash.Id, TimeOfCrash = Crash.TimeOfCrash.Value, //UserID = Crash.UserNameId.Value, BuildVersion = Crash.BuildVersion, JIRA = Crash.TTPID, Platform = Crash.PlatformName, FixCL = Crash.FixedChangeList, BuiltFromCL = Crash.ChangeListVersion, Pattern = Crash.Pattern, MachineID = Crash.ComputerName, Branch = Crash.Branch, Description = Crash.Description, RawCallStack = Crash.RawCallStack, }) .ToList(); int NumCrashes = Crashes.Count; /* * // Build patterns for crashes where patters is null. * var CrashesWithoutPattern = FRepository.Get().Crashes * .FilterByDate( FRepository.Get().Crashes.ListAll(), FormData.DateFrom, FormData.DateTo.AddDays( 1 ) ) * // Only crashes and asserts * .Where( Crash => Crash.Pattern == null || Crash.Pattern == "" ) * .Select( Crash => Crash ) * .ToList(); * * foreach( var Crash in CrashesWithoutPattern ) * { * Crash.BuildPattern(); * } */ // Total # of ALL (Anonymous) crashes in timeframe int TotalAnonymousCrashes = NumCrashes; // Total # of UNIQUE (Anonymous) crashes in timeframe HashSet <string> UniquePatterns = new HashSet <string>(); HashSet <string> UniqueMachines = new HashSet <string>(); Dictionary <string, int> PatternToCount = new Dictionary <string, int>(); //List<int> CrashesWithoutPattern = new List<int>(); //List<DateTime> CrashesWithoutPatternDT = new List<DateTime>(); foreach (var Crash in Crashes) { if (string.IsNullOrEmpty(Crash.Pattern)) { //CrashesWithoutPattern.Add( Crash.ID ); //CrashesWithoutPatternDT.Add( Crash.TimeOfCrash ); continue; } UniquePatterns.Add(Crash.Pattern); UniqueMachines.Add(Crash.MachineID); bool bAdd = !PatternToCount.ContainsKey(Crash.Pattern); if (bAdd) { PatternToCount.Add(Crash.Pattern, 1); } else { PatternToCount[Crash.Pattern]++; } } var PatternToCountOrdered = PatternToCount.OrderByDescending(X => X.Value).ToList(); // The 100 top. var PatternAndCount = PatternToCountOrdered.Take(100).ToDictionary(X => X.Key, Y => Y.Value); int TotalUniqueAnonymousCrashes = UniquePatterns.Count; // Total # of AFFECTED USERS (Anonymous) in timeframe int TotalAffectedUsers = UniqueMachines.Count; var RealBuggs = BuggsRepo.Context.Buggs.Where(Bugg => PatternAndCount.Keys.Contains(Bugg.Pattern)).ToList(); // Build search string. HashSet <string> FoundJiras = new HashSet <string>(); Dictionary <string, List <Bugg> > JiraIDtoBugg = new Dictionary <string, List <Bugg> >(); List <Bugg> Buggs = new List <Bugg>(100); foreach (var Top in PatternAndCount) { Bugg NewBugg = RealBuggs.Where(X => X.Pattern == Top.Key).FirstOrDefault(); if (NewBugg != null) { using (FAutoScopedLogTimer TopTimer = new FAutoScopedLogTimer(string.Format("{0}:{1}", Buggs.Count + 1, NewBugg.Id))) { var CrashesForBugg = Crashes.Where(Crash => Crash.Pattern == Top.Key).ToList(); // Convert anonymous to full type; var FullCrashesForBugg = new List <Crash>(CrashesForBugg.Count); foreach (var Anon in CrashesForBugg) { FullCrashesForBugg.Add(new Crash() { ID = Anon.ID, TimeOfCrash = Anon.TimeOfCrash, BuildVersion = Anon.BuildVersion, JIRA = Anon.JIRA, Platform = Anon.Platform, FixCL = Anon.FixCL, BuiltFromCL = Anon.BuiltFromCL, Pattern = Anon.Pattern, MachineID = Anon.MachineID, Branch = Anon.Branch, Description = Anon.Description, RawCallStack = Anon.RawCallStack, }); } NewBugg.PrepareBuggForJira(FullCrashesForBugg); // Verify valid JiraID, this may be still a TTP if (!string.IsNullOrEmpty(NewBugg.TTPID)) { int TTPID = 0; int.TryParse(NewBugg.TTPID, out TTPID); if (TTPID == 0) { AddBuggJiraMapping(NewBugg, ref FoundJiras, ref JiraIDtoBugg); } } Buggs.Add(NewBugg); } } else { FLogger.Global.WriteEvent("Bugg for pattern " + Top.Key + " not found"); } } if (BuggIDToBeAddedToJira > 0) { var Bugg = Buggs.Where(X => X.Id == BuggIDToBeAddedToJira).FirstOrDefault(); if (Bugg != null) { Bugg.CopyToJira(); AddBuggJiraMapping(Bugg, ref FoundJiras, ref JiraIDtoBugg); } } if (JC.CanBeUsed()) { var BuggsCopy = new List <Bugg>(Buggs); // Grab the data form JIRA. string JiraSearchQuery = string.Join(" OR ", FoundJiras); using (FAutoScopedLogTimer JiraResultsTimer = new FAutoScopedLogTimer("JiraResults")) { 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; List <Bugg> BuggsForJira; JiraIDtoBugg.TryGetValue(JiraID, out BuggsForJira); //var BuggsForJira = JiraIDtoBugg[JiraID]; if (BuggsForJira != null) { foreach (Bugg Bugg in BuggsForJira) { Bugg.JiraSummary = Summary; Bugg.JiraComponentsText = ComponentsText; Bugg.JiraResolution = Resolution; Bugg.JiraFixVersionsText = FixVersionsText; if (FixCL != 0) { Bugg.JiraFixCL = FixCL.ToString(); } BuggsCopy.Remove(Bugg); } } } } // If there are buggs, we need to update the summary to indicate an error. // Usually caused when bugg's project has changed. foreach (var Bugg in BuggsCopy.Where(b => !string.IsNullOrEmpty(b.TTPID))) { Bugg.JiraSummary = "JIRA MISMATCH"; Bugg.JiraComponentsText = "JIRA MISMATCH"; Bugg.JiraResolution = "JIRA MISMATCH"; Bugg.JiraFixVersionsText = "JIRA MISMATCH"; Bugg.JiraFixCL = "JIRA MISMATCH"; } } Buggs = Buggs.OrderByDescending(b => b.NumberOfCrashes).ToList(); return(new ReportsViewModel { Buggs = Buggs, /*Crashes = Crashes,*/ DateFrom = (long)(FormData.DateFrom - CrashesViewModel.Epoch).TotalMilliseconds, DateTo = (long)(FormData.DateTo - CrashesViewModel.Epoch).TotalMilliseconds, TotalAffectedUsers = TotalAffectedUsers, TotalAnonymousCrashes = TotalAnonymousCrashes, TotalUniqueAnonymousCrashes = TotalUniqueAnonymousCrashes }); } }
/// <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 HashSetDecsriptions = 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.MachineID != null && Crash.MachineID.Length == 32) { MachineIds.Add(Crash.MachineID); // Sent in the unattended mode 29 char if (Crash.Description.Length > 32) { HashSetDecsriptions.Add(Crash.Description); } } // Ignore bad build versions. // @TODO yrx 2015-02-17 What about launcher? if (Crash.BuildVersion.StartsWith("4.")) { if (!string.IsNullOrEmpty(Crash.BuildVersion)) { this.AffectedVersions.Add(Crash.BuildVersion); } if (!string.IsNullOrEmpty(Crash.Branch) && Crash.Branch.StartsWith("UE4")) { this.BranchesFoundIn.Add(Crash.Branch); } int CrashBuiltFromCL = 0; int.TryParse(Crash.BuiltFromCL, out CrashBuiltFromCL); if (CrashBuiltFromCL > 0) { FirstCLAffected = Math.Min(FirstCLAffected, CrashBuiltFromCL); } if (!string.IsNullOrEmpty(Crash.Platform)) { // Platform = "Platform [Desc]"; var PlatSubs = Crash.Platform.Split(" ".ToCharArray(), StringSplitOptions.RemoveEmptyEntries); if (PlatSubs.Length >= 1) { this.AffectedPlatforms.Add(PlatSubs[0]); } } } } // CopyToJira foreach (var Line in HashSetDecsriptions) { 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.BuiltFromCL); int ILatestCLAffected = -1; int.TryParse(LatestCLAffected, out ILatestCLAffected); this.LatestCLAffected = ILatestCLAffected; // Latest CL Affected string LatestOSAffected = CrashesForBugg.OrderByDescending(Crash => Crash.TimeOfCrash).First().Platform; this.LatestOSAffected = LatestOSAffected; // Latest Environment Affected // ToJiraSummary var FunctionCalls = CrashesForBugg.First().GetCallStack().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 List <object>(); foreach (var Platform in this.BranchesFoundIn) { string CleanedBranch = Platform.Contains("UE4-Releases") ? "UE4-Releases" : Platform; Dictionary <string, object> JiraBranch = null; JC.GetNameToBranchFoundIn().TryGetValue(CleanedBranch, out JiraBranch); if (JiraBranch != null && !this.ToJiraBranches.Contains(JiraBranch)) { this.ToJiraBranches.Add(JiraBranch); } } // 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]); } } }
/// <summary> /// Retrieve all Buggs matching the search criteria. /// </summary> /// <param name="FormData">The incoming form of search criteria from the client.</param> /// <param name="BuggIDToBeAddedToJira">ID of the bugg that will be added to JIRA</param> /// <returns>A view to display the filtered Buggs.</returns> public ReportsViewModel GetResults(FormHelper FormData, int BuggIDToBeAddedToJira) { // @TODO yrx 2015-02-17 BuggIDToBeAddedToJira replace with List<int> based on check box and Submit? // Enumerate JIRA projects if needed. // https://jira.ol.epicgames.net//rest/api/2/project var JC = JiraConnection.Get(); var JiraComponents = JC.GetNameToComponents(); var JiraVersions = JC.GetNameToVersions(); using (FAutoScopedLogTimer LogTimer = new FAutoScopedLogTimer(this.GetType().ToString())) { string AnonumousGroup = "Anonymous"; List <String> Users = CrashRepository.GetUsersForGroup(AnonumousGroup); int AnonymousGroupID = BuggRepository.GetIdFromUserGroup(AnonumousGroup); HashSet <int> AnonumousIDs = BuggRepository.GetUserIdsFromUserGroup(AnonumousGroup); int AnonymousID = AnonumousIDs.First(); HashSet <string> UserNamesForUserGroup = BuggRepository.GetUserNamesFromUserGroups(AnonumousGroup); //FormData.DateFrom = DateTime.Now.AddDays( -1 ); var Crashes = CrashRepository .FilterByDate(CrashRepository.ListAll(), FormData.DateFrom, FormData.DateTo.AddDays(1)) // Only crashes and asserts .Where(Crash => Crash.CrashType == 1 || Crash.CrashType == 2) // Only anonymous user .Where(Crash => Crash.UserNameId.Value == AnonymousID) .Select(Crash => new { ID = Crash.Id, TimeOfCrash = Crash.TimeOfCrash.Value, //UserID = Crash.UserNameId.Value, BuildVersion = Crash.BuildVersion, JIRA = Crash.TTPID, Platform = Crash.PlatformName, FixCL = Crash.FixedChangeList, BuiltFromCL = Crash.ChangeListVersion, Pattern = Crash.Pattern, MachineID = Crash.ComputerName, Branch = Crash.Branch, }) .ToList(); int NumCrashes = Crashes.Count; /* * // Build patterns for crashes where patters is null. * var CrashesWithoutPattern = CrashRepository * .FilterByDate( CrashRepository.ListAll(), FormData.DateFrom, FormData.DateTo.AddDays( 1 ) ) * // Only crashes and asserts * .Where( Crash => Crash.Pattern == null || Crash.Pattern == "" ) * .Select( Crash => Crash ) * .ToList(); * * foreach( var Crash in CrashesWithoutPattern ) * { * ////BuildPattern( Crash ); * } */ // Total # of ALL (Anonymous) crashes in timeframe int TotalAnonymousCrashes = NumCrashes; // Total # of UNIQUE (Anonymous) crashes in timeframe HashSet <string> UniquePatterns = new HashSet <string>(); HashSet <string> UniqueMachines = new HashSet <string>(); Dictionary <string, int> PatternToCount = new Dictionary <string, int>(); //List<int> CrashesWithoutPattern = new List<int>(); //List<DateTime> CrashesWithoutPatternDT = new List<DateTime>(); foreach (var Crash in Crashes) { if (string.IsNullOrEmpty(Crash.Pattern)) { //CrashesWithoutPattern.Add( Crash.ID ); //CrashesWithoutPatternDT.Add( Crash.TimeOfCrash ); continue; } UniquePatterns.Add(Crash.Pattern); UniqueMachines.Add(Crash.MachineID); bool bAdd = !PatternToCount.ContainsKey(Crash.Pattern); if (bAdd) { PatternToCount.Add(Crash.Pattern, 1); } else { PatternToCount[Crash.Pattern]++; } } var PatternToCountOrdered = PatternToCount.OrderByDescending(X => X.Value).ToList(); // The 100 top. var PatternAndCount = PatternToCountOrdered.Take(100).ToDictionary(X => X.Key, Y => Y.Value); int TotalUniqueAnonymousCrashes = UniquePatterns.Count; // Total # of AFFECTED USERS (Anonymous) in timeframe int TotalAffectedUsers = UniqueMachines.Count; var RealBuggs = BuggRepository.GetDataContext().Buggs.Where(Bugg => PatternAndCount.Keys.Contains(Bugg.Pattern)).ToList(); // Build search string. List <string> FoundJiras = new List <string>(); Dictionary <string, List <Bugg> > JiraIDtoBugg = new Dictionary <string, List <Bugg> >(); List <Bugg> Buggs = new List <Bugg>(100); foreach (var Top in PatternAndCount) { Bugg NewBugg = new Bugg(); Bugg RealBugg = RealBuggs.Where(X => X.Pattern == Top.Key).FirstOrDefault(); if (RealBugg != null) { using (FAutoScopedLogTimer TopTimer = new FAutoScopedLogTimer(string.Format("{0}:{1}", Buggs.Count + 1, RealBugg.Id))) { // Index // number NewBugg.Id = RealBugg.Id; // CrashGroup URL (a link to the Bugg) NewBugg.TTPID = RealBugg.TTPID; // JIRA NewBugg.FixedChangeList = RealBugg.FixedChangeList; // FixCL NewBugg.NumberOfCrashes = Top.Value; // # Occurrences NewBugg.Pattern = RealBugg.Pattern; // # Occurrences //NewBugg.BuildVersion = var CrashesForBugg = Crashes.Where(Crash => Crash.Pattern == Top.Key).ToList(); NewBugg.AffectedVersions = new SortedSet <string>(); NewBugg.AffectedMajorVersions = new SortedSet <string>(); // 4.4, 4.5 and so NewBugg.BranchesFoundIn = new SortedSet <string>(); NewBugg.AffectedPlatforms = new SortedSet <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.MachineID != null && Crash.MachineID.Length == 32) { MachineIds.Add(Crash.MachineID); } // Ignore bad build versions. // @TODO yrx 2015-02-17 What about launcher? if (Crash.BuildVersion.StartsWith("4.")) { if (!string.IsNullOrEmpty(Crash.BuildVersion)) { NewBugg.AffectedVersions.Add(Crash.BuildVersion); } if (!string.IsNullOrEmpty(Crash.Branch) && Crash.Branch.StartsWith("UE4")) { NewBugg.BranchesFoundIn.Add(Crash.Branch); } int CrashBuiltFromCL = 0; int.TryParse(Crash.BuiltFromCL, out CrashBuiltFromCL); if (CrashBuiltFromCL > 0) { FirstCLAffected = Math.Min(FirstCLAffected, CrashBuiltFromCL); } if (!string.IsNullOrEmpty(Crash.Platform)) { // Platform = "Platform [Desc]"; var PlatSubs = Crash.Platform.Split(" ".ToCharArray(), StringSplitOptions.RemoveEmptyEntries); if (PlatSubs.Length >= 1) { NewBugg.AffectedPlatforms.Add(PlatSubs[0]); } } } } // CopyToJira NewBugg.ToJiraFirstCLAffected = FirstCLAffected; if (NewBugg.AffectedVersions.Count > 0) { NewBugg.BuildVersion = NewBugg.AffectedVersions.Last(); // Latest Version Affected } foreach (var AffectedBuild in NewBugg.AffectedVersions) { var Subs = AffectedBuild.Split(".".ToCharArray(), StringSplitOptions.RemoveEmptyEntries); if (Subs.Length >= 2) { string MajorVersion = Subs[0] + "." + Subs[1]; NewBugg.AffectedMajorVersions.Add(MajorVersion); } } NewBugg.NumberOfUniqueMachines = MachineIds.Count; // # Affected Users string LatestCLAffected = CrashesForBugg. // CL of the latest build Where(Crash => Crash.BuildVersion == NewBugg.BuildVersion). Max(Crash => Crash.BuiltFromCL); int ILatestCLAffected = -1; int.TryParse(LatestCLAffected, out ILatestCLAffected); NewBugg.LatestCLAffected = ILatestCLAffected; // Latest CL Affected string LatestOSAffected = CrashesForBugg.OrderByDescending(Crash => Crash.TimeOfCrash).First().Platform; NewBugg.LatestOSAffected = LatestOSAffected; // Latest Environment Affected NewBugg.TimeOfFirstCrash = RealBugg.TimeOfFirstCrash; // First Crash Timestamp // ToJiraSummary var Callstack = RealBugg.GetFunctionCalls(); NewBugg.ToJiraSummary = Callstack.Count > 1 ? Callstack[0] : "No valid callstack found"; // ToJiraVersions NewBugg.ToJiraVersions = new List <object>(); foreach (var Version in NewBugg.AffectedMajorVersions) { bool bValid = JC.GetNameToVersions().ContainsKey(Version); if (bValid) { NewBugg.ToJiraVersions.Add(JC.GetNameToVersions()[Version]); } } // ToJiraBranches NewBugg.ToJiraBranches = new List <object>(); foreach (var Platform in NewBugg.BranchesFoundIn) { string CleanedBranch = Platform.Contains("UE4-Releases") ? "UE4-Releases" : Platform; Dictionary <string, object> JiraBranch = null; JC.GetNameToBranchFoundIn().TryGetValue(CleanedBranch, out JiraBranch); if (JiraBranch != null && !NewBugg.ToJiraBranches.Contains(JiraBranch)) { NewBugg.ToJiraBranches.Add(JiraBranch); } } // ToJiraPlatforms NewBugg.ToJiraPlatforms = new List <object>(); foreach (var Platform in NewBugg.AffectedPlatforms) { bool bValid = JC.GetNameToPlatform().ContainsKey(Platform); if (bValid) { NewBugg.ToJiraPlatforms.Add(JC.GetNameToPlatform()[Platform]); } } // Verify valid JiraID, this may be still a TTP if (!string.IsNullOrEmpty(NewBugg.TTPID)) { int TTPID = 0; int.TryParse(NewBugg.TTPID, out TTPID); if (TTPID == 0) { AddBuggJiraMapping(NewBugg, ref FoundJiras, ref JiraIDtoBugg); } } Buggs.Add(NewBugg); } } else { FLogger.WriteEvent("Bugg for pattern " + Top.Key + " not found"); } } if (BuggIDToBeAddedToJira > 0) { var Bugg = Buggs.Where(X => X.Id == BuggIDToBeAddedToJira).FirstOrDefault(); if (Bugg != null) { Bugg.CopyToJira(); AddBuggJiraMapping(Bugg, ref FoundJiras, ref JiraIDtoBugg); } } if (JC.CanBeUsed()) { // Grab the data form JIRA. string JiraSearchQuery = string.Join(" OR ", FoundJiras); using (FAutoScopedLogTimer JiraResultsTimer = new FAutoScopedLogTimer("JiraResults")) { 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; var BuggsForJira = JiraIDtoBugg[JiraID]; foreach (Bugg Bugg in BuggsForJira) { Bugg.JiraSummary = Summary; Bugg.JiraComponentsText = ComponentsText; Bugg.JiraResolution = Resolution; Bugg.JiraFixVersionsText = FixVersionsText; if (FixCL != 0) { Bugg.JiraFixCL = FixCL.ToString(); } } } } } return(new ReportsViewModel { Buggs = Buggs, /*Crashes = Crashes,*/ DateFrom = (long)(FormData.DateFrom - CrashesViewModel.Epoch).TotalMilliseconds, DateTo = (long)(FormData.DateTo - CrashesViewModel.Epoch).TotalMilliseconds, TotalAffectedUsers = TotalAffectedUsers, TotalAnonymousCrashes = TotalAnonymousCrashes, TotalUniqueAnonymousCrashes = TotalUniqueAnonymousCrashes }); } }
/// <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.MachineId != null && Crash.MachineId.Length == 32) { MachineIds.Add(Crash.MachineId); 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.BuiltFromCL, out CrashBuiltFromCL); if (CrashBuiltFromCL > 0) { FirstCLAffected = Math.Min(FirstCLAffected, CrashBuiltFromCL); } if (!string.IsNullOrEmpty(Crash.Platform)) { // Platform = "Platform [Desc]"; var PlatSubs = Crash.Platform.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.BuiltFromCL); int ILatestCLAffected = -1; int.TryParse(LatestCLAffected, out ILatestCLAffected); this.LatestCLAffected = ILatestCLAffected; // Latest CL Affected string LatestOSAffected = CrashesForBugg.OrderByDescending(Crash => Crash.TimeOfCrash).First().Platform; 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> /// 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> /// /// </summary> /// <param name="branchName"></param> /// <param name="startDate"></param> /// <param name="endDate"></param> /// <returns></returns> private ReportsViewModel GetResults(string branchName, DateTime startDate, DateTime endDate, int BuggIDToBeAddedToJira) { const string anonymousGroup = "Anonymous"; var anonymousGroupId = _unitOfWork.UserGroupRepository.First(data => data.Name == anonymousGroup).Id; var anonymousIDs = _unitOfWork.UserGroupRepository.First(data => data.Id == anonymousGroupId).Users.Select(data => data.Id).ToList(); var anonymousId = anonymousIDs.First(); var crashesQuery = _unitOfWork.CrashRepository.ListAll() .Where(data => data.TimeOfCrash > startDate && data.TimeOfCrash <= endDate) // Only crashes and asserts .Where(crash => crash.CrashType == 1 || crash.CrashType == 2); // Only anonymous user //.Where(crash => crash.UserNameId.Value == anonymousId); // Filter by BranchName if (!string.IsNullOrEmpty(branchName)) { crashesQuery = crashesQuery.Where(data => data.Branch == branchName); } var crashesList = crashesQuery.ToList(); var buggsList = crashesQuery.Where(data => data.Bugg != null).GroupBy(data => data.Bugg).Select(data => data.Key).ToList(); foreach (var bugg in buggsList) { if (bugg == null) { continue; } var crashes = crashesList.Where(data => data.BuggId == bugg.Id).ToList(); bugg.PrepareBuggForJira(crashes); bugg.CrashesInTimeFrameGroup = crashesList.Count(data => data.BuggId == bugg.Id); bugg.AffectedVersions = new SortedSet <string>(crashes.Select(data => data.BuildVersion)); bugg.NumberOfUniqueMachines = crashes.GroupBy(data => data.ComputerName).Count(); //get latest changelist int latestClAffected; int.TryParse(crashes.Max(data => data.ChangeListVersion), out latestClAffected); bugg.LatestCLAffected = latestClAffected; if (string.IsNullOrWhiteSpace(bugg.TTPID)) { bugg.JiraSummary = "JIRA MISMATCH"; bugg.JiraComponentsText = "JIRA MISMATCH"; bugg.JiraResolution = "JIRA MISMATCH"; bugg.JiraFixVersionsText = "JIRA MISMATCH"; bugg.JiraFixCL = "JIRA MISMATCH"; } } //Get jira connection var jiraConnection = JiraConnection.Get(); if (BuggIDToBeAddedToJira > 0) { var bugg = buggsList.FirstOrDefault(x => x.Id == BuggIDToBeAddedToJira); if (bugg != null) { bugg.CopyToJira(); } } var jiraResults = new Dictionary <string, Dictionary <string, object> >(); foreach (var Query in buggsList.Where(data => !string.IsNullOrWhiteSpace(data.TTPID)).Select(data => data.TTPID)) { try { var TempResult = jiraConnection.SearchJiraTickets( "key = " + Query, 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 }); foreach (var Temp in TempResult) { jiraResults.Add(Temp.Key, Temp.Value); } } catch (System.Exception) { } } // Jira Key, Summary, Components, Resolution, Fix version, Fix changelist foreach (var Jira in jiraResults) { var jiraId = Jira.Key; var summary = (string)Jira.Value["summary"]; var 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; if (buggsList.Any(data => data.TTPID == jiraId)) { var bugg = buggsList.First(data => data.TTPID == jiraId); bugg.JiraSummary = summary; bugg.JiraComponentsText = ComponentsText; bugg.JiraResolution = Resolution; bugg.JiraFixVersionsText = FixVersionsText; if (FixCL != 0) { bugg.JiraFixCL = FixCL.ToString(); } } } return(new ReportsViewModel { Buggs = buggsList.OrderByDescending(data => data.CrashesInTimeFrameGroup).ToList(), BranchName = branchName, BranchNames = _unitOfWork.CrashRepository.GetBranchesAsListItems(), DateFrom = (long)(startDate - CrashesViewModel.Epoch).TotalMilliseconds, DateTo = (long)(endDate - CrashesViewModel.Epoch).TotalMilliseconds, TotalAffectedUsers = crashesQuery.GroupBy(data => data.ComputerName).Count(), TotalAnonymousCrashes = crashesQuery.Count(), TotalUniqueAnonymousCrashes = crashesQuery.GroupBy(data => data.BuggId).Count() }); }
/// <summary> /// Retrieve all Buggs matching the search criteria. /// </summary> /// <returns></returns> private ReportsViewModel GetResults(string branchName, DateTime startDate, DateTime endDate, int BuggIDToBeAddedToJira, bool sigbool) { // It would be great to have a CSV export of this as well with buggs ID being the key I can then use to join them :) // // Enumerate JIRA projects if needed. // https://jira.it.epicgames.net//rest/api/2/project var JC = JiraConnection.Get(); var JiraComponents = JC.GetNameToComponents(); var JiraVersions = JC.GetNameToVersions(); using (var logTimer = new FAutoScopedLogTimer(this.GetType().ToString())) { const string anonymousGroup = "Anonymous"; var anonymousGroupId = _unitOfWork.UserGroupRepository.First(data => data.Name == anonymousGroup).Id; var anonymousIDs = _unitOfWork.UserGroupRepository.First(data => data.Id == anonymousGroupId).Users.Select(data => data.Id).ToList(); var anonymousId = anonymousIDs.First(); var crashesQuery = _unitOfWork.CrashRepository.ListAll().Where(data => data.TimeOfCrash > startDate && data.TimeOfCrash <= endDate) // Only crashes and asserts .Where(crash => crash.CrashType == 1 || crash.CrashType == 2) // Only anonymous user .Where(crash => crash.UserNameId.Value == anonymousId); // Filter by BranchName if (!string.IsNullOrEmpty(branchName)) { crashesQuery = crashesQuery.Where(data => data.Branch == branchName); } var crashes = crashesQuery.Select(data => new { ID = data.Id, TimeOfCrash = data.TimeOfCrash.Value, UserID = data.UserNameId, BuildVersion = data.BuildVersion, JIRA = data.Jira, Platform = data.PlatformName, FixCL = data.FixedChangeList, BuiltFromCL = data.ChangeListVersion, Pattern = data.Pattern, MachineID = data.ComputerName, Branch = data.Branch, Description = data.Description, RawCallStack = data.RawCallStack, }).ToList(); var numCrashes = crashesQuery.Count(); // Total # of ALL (Anonymous) crashes in timeframe var totalAnonymousCrashes = numCrashes; // Total # of UNIQUE (Anonymous) crashes in timeframe var uniquePatterns = new HashSet <string>(); var uniqueMachines = new HashSet <string>(); var patternToCount = new Dictionary <string, int>(); foreach (var crash in crashes) { uniquePatterns.Add(crash.Pattern); uniqueMachines.Add(crash.MachineID); var bAdd = !patternToCount.ContainsKey(crash.Pattern); if (bAdd) { patternToCount.Add(crash.Pattern, 1); } else { patternToCount[crash.Pattern]++; } } var PatternToCountOrdered = patternToCount.OrderByDescending(X => X.Value).ToList(); const int NumTopRecords = 200; var PatternAndCount = PatternToCountOrdered.Take(NumTopRecords).ToDictionary(x => x.Key, y => y.Value); int TotalUniqueAnonymousCrashes = uniquePatterns.Count; // Total # of AFFECTED USERS (Anonymous) in timeframe int TotalAffectedUsers = uniqueMachines.Count; var RealBuggs = _unitOfWork.BuggRepository.ListAll().Where(Bugg => PatternAndCount.Keys.Contains(Bugg.Pattern)); // Build search string. var foundJiras = new HashSet <string>(); var jiraIDtoBugg = new Dictionary <string, List <Bugg> >(); var buggs = new List <Bugg>(NumTopRecords); foreach (var Top in PatternAndCount) { var newBugg = RealBuggs.FirstOrDefault(X => X.Pattern == Top.Key); if (newBugg != null) { var crashesForBugg = crashes.Where(Crash => Crash.Pattern == Top.Key).ToList(); // Convert anonymous to full type; var fullCrashesForBugg = new List <Crash>(crashesForBugg.Count); foreach (var anon in crashesForBugg) { fullCrashesForBugg.Add(new Crash() { Id = anon.ID, TimeOfCrash = anon.TimeOfCrash, BuildVersion = anon.BuildVersion, Jira = anon.JIRA, PlatformName = anon.Platform, FixedChangeList = anon.FixCL, ChangeListVersion = anon.BuiltFromCL, Pattern = anon.Pattern, ComputerName = anon.MachineID, Branch = anon.Branch, Description = anon.Description, RawCallStack = anon.RawCallStack, }); } newBugg.PrepareBuggForJira(fullCrashesForBugg); // Verify valid JiraID, this may be still a TTP if (!string.IsNullOrEmpty(newBugg.TTPID)) { int ttpid = 0; int.TryParse(newBugg.TTPID, out ttpid); if (ttpid == 0) { AddBuggJiraMapping(newBugg, ref foundJiras, ref jiraIDtoBugg); } } buggs.Add(newBugg); } else { FLogger.Global.WriteEvent("Bugg for pattern " + Top.Key + " not found"); } } if (BuggIDToBeAddedToJira > 0) { var bugg = buggs.FirstOrDefault(x => x.Id == BuggIDToBeAddedToJira); if (bugg != null) { bugg.CopyToJira(); AddBuggJiraMapping(bugg, ref foundJiras, ref jiraIDtoBugg); } } if (JC.CanBeUsed()) { var buggsCopy = new List <Bugg>(buggs); var invalidJiras = new HashSet <string>(); // Simple verification of JIRA foreach (var Value in foundJiras) { if (Value.Length < 3 || !Value.Contains('-')) { invalidJiras.Add(Value); } } foreach (var invalidJira in invalidJiras) { foundJiras.Remove(invalidJira); } // Grab the data form JIRA. string JiraSearchQuery = string.Join(" OR ", foundJiras); bool bInvalid = false; var jiraResults = new Dictionary <string, Dictionary <string, object> >(); try { if (!string.IsNullOrWhiteSpace(JiraSearchQuery)) { 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) { bInvalid = true; } // Invalid records have been found, find the broken using the slow path. if (bInvalid) { foreach (var Query in foundJiras) { try { var TempResult = JC.SearchJiraTickets( Query, 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 }); foreach (var Temp in TempResult) { jiraResults.Add(Temp.Key, Temp.Value); } } catch (System.Exception) { } } } // 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; List <Bugg> BuggsForJira; jiraIDtoBugg.TryGetValue(JiraID, out BuggsForJira); //var BuggsForJira = JiraIDtoBugg[JiraID]; if (BuggsForJira != null) { foreach (Bugg Bugg in BuggsForJira) { Bugg.JiraSummary = Summary; Bugg.JiraComponentsText = ComponentsText; Bugg.JiraResolution = Resolution; Bugg.JiraFixVersionsText = FixVersionsText; if (FixCL != 0) { Bugg.JiraFixCL = FixCL.ToString(); } buggsCopy.Remove(Bugg); } } } // If there are buggs, we need to update the summary to indicate an error. // Usually caused when bugg's project has changed. foreach (var Bugg in buggsCopy.Where(b => !string.IsNullOrEmpty(b.TTPID))) { Bugg.JiraSummary = "JIRA MISMATCH"; Bugg.JiraComponentsText = "JIRA MISMATCH"; Bugg.JiraResolution = "JIRA MISMATCH"; Bugg.JiraFixVersionsText = "JIRA MISMATCH"; Bugg.JiraFixCL = "JIRA MISMATCH"; } } buggs = buggs.OrderByDescending(b => b.CrashesInTimeFrameGroup).ToList(); return(new ReportsViewModel { Buggs = buggs, BranchName = branchName, BranchNames = _unitOfWork.CrashRepository.GetBranchesAsListItems(), DateFrom = (long)(startDate - CrashesViewModel.Epoch).TotalMilliseconds, DateTo = (long)(endDate - CrashesViewModel.Epoch).TotalMilliseconds, TotalAffectedUsers = TotalAffectedUsers, TotalAnonymousCrashes = totalAnonymousCrashes, TotalUniqueAnonymousCrashes = TotalUniqueAnonymousCrashes }); } }