/// <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> /// 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> /// 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]); } } }