/// <summary> /// Return a dictionary of crashes per group grouped by week. /// </summary> /// <param name="Crashes">A set of crashes to interrogate.</param> /// <param name="UserGroupId">The id of the user group to interrogate.</param> /// <returns>A dictionary of week vs. crash count.</returns> public Dictionary <DateTime, int> GetWeeklyCountsByGroup(List <FCrashMinimal> Crashes, int UserGroupId) { using (FAutoScopedLogTimer LogTimer = new FAutoScopedLogTimer(this.GetType().ToString() + "(UserGroupId=" + UserGroupId + ")")) { Dictionary <DateTime, int> Results = new Dictionary <DateTime, int>(); var UsersIds = FRepository.Get(_Crashes).GetUserIdsFromUserGroupId(UserGroupId); // Trim crashes to user group. if (UserGroupId != DashboardController.AllUserGroupId) { Crashes = Crashes.Where(Crash => UsersIds.Contains(Crash.UserId)).ToList(); } try { Results = ( from CrashDetail in Crashes group CrashDetail by CrashDetail.TimeOfCrash.AddDays(-(int)CrashDetail.TimeOfCrash.DayOfWeek).Date into GroupCount orderby GroupCount.Key select new { Count = GroupCount.Count(), Date = GroupCount.Key } ).ToDictionary(x => x.Date, y => y.Count); } catch (Exception Ex) { Debug.WriteLine("Exception in GetWeeklyCountsByGroup: " + Ex.ToString()); } return(Results); } }
/// <summary> /// Display the main user groups. /// </summary> /// <param name="UserForms">A form of user data passed up from the client.</param> /// <param name="UserGroup">The name of the current user group to display users for.</param> /// <returns>A view to show a list of users in the current user group.</returns> public ActionResult Index(FormCollection UserForms, string UserGroup) { CrashRepository Crashes = new CrashRepository(); // Examine an incoming form for a new user group foreach (var FormInstance in UserForms) { string UserName = FormInstance.ToString(); string NewUserGroup = UserForms[UserName]; FRepository.Get(Crashes).SetUserGroup(UserName, NewUserGroup); } UsersViewModel Model = new UsersViewModel(); Model.UserGroup = UserGroup; Model.Users = FRepository.Get(Crashes).GetUserNamesFromGroupName(UserGroup); Model.GroupCounts = FRepository.Get(Crashes).GetCountsByGroup(); return(View("Index", Model)); }
//static readonly int MinNumberOfCrashes = 2; /// <summary> /// Retrieve all Buggs matching the search criteria. /// </summary> /// <param name="FormData">The incoming form of search criteria from the client.</param> /// <returns>A view to display the filtered Buggs.</returns> public CSV_ViewModel GetResults(FormHelper FormData) { BuggRepository BuggsRepo = new BuggRepository(); CrashRepository CrashRepo = new CrashRepository(); using (FAutoScopedLogTimer LogTimer = new FAutoScopedLogTimer(this.GetType().ToString())) { string AnonymousGroup = "Anonymous"; //List<String> Users = FRepository.Get().GetUserNamesFromGroupName( AnonumousGroup ); int AnonymousGroupID = FRepository.Get(BuggsRepo).FindOrAddGroup(AnonymousGroup); HashSet <int> AnonumousIDs = FRepository.Get(BuggsRepo).GetUserIdsFromUserGroup(AnonymousGroup); int AnonymousID = AnonumousIDs.First(); HashSet <string> UserNamesForUserGroup = FRepository.Get(BuggsRepo).GetUserNamesFromGroupName(AnonymousGroup); // Enable to narrow results and improve debugging performance. //FormData.DateFrom = FormData.DateTo.AddDays( -1 ); FormData.DateTo = FormData.DateTo.AddDays(1); var FilteringQueryJoin = CrashRepo .ListAll() .Where(c => c.EpicAccountId != "") // Only crashes and asserts .Where(c => c.CrashType == 1 || c.CrashType == 2) // Only anonymous user .Where(c => c.UserNameId == AnonymousID) // Filter be date .Where(c => c.TimeOfCrash > FormData.DateFrom && c.TimeOfCrash < FormData.DateTo) .Join ( CrashRepo.Context.Buggs_Crashes, c => c, bc => bc.Crash, (c, bc) => new { GameName = c.GameName, TimeOfCrash = c.TimeOfCrash.Value, BuiltFromCL = c.BuiltFromCL, PlatformName = c.PlatformName, EngineMode = c.EngineMode, MachineId = c.MachineId, Module = c.Module, BuildVersion = c.BuildVersion, Jira = c.Jira, Branch = c.Branch, CrashType = c.CrashType.Value, EpicId = c.EpicAccountId, BuggId = bc.BuggId, } ); var FilteringQueryCrashes = CrashRepo .ListAll() .Where(c => c.EpicAccountId != "") // Only crashes and asserts .Where(c => c.CrashType == 1 || c.CrashType == 2) // Only anonymous user .Where(c => c.UserNameId == AnonymousID); int TotalCrashes = CrashRepo .ListAll() .Count(); int TotalCrashesYearToDate = CrashRepo .ListAll() // Year to date .Where(c => c.TimeOfCrash > new DateTime(DateTime.UtcNow.Year, 1, 1)) .Count(); var CrashesFilteredWithDateQuery = FilteringQueryCrashes // Filter be date .Where(c => c.TimeOfCrash > FormData.DateFrom && c.TimeOfCrash < FormData.DateTo); int CrashesFilteredWithDate = CrashesFilteredWithDateQuery .Count(); int CrashesYearToDateFiltered = FilteringQueryCrashes // Year to date .Where(c => c.TimeOfCrash > new DateTime(DateTime.UtcNow.Year, 1, 1)) .Count(); int AffectedUsersFiltered = FilteringQueryCrashes .Select(c => c.EpicAccountId) .Distinct() .Count(); int UniqueCrashesFiltered = FilteringQueryCrashes .Select(c => c.Pattern) .Distinct() .Count(); int NumCrashes = FilteringQueryJoin.Count(); // Get all users // SLOW //var Users = FRepository.Get( BuggsRepo ).GetAnalyticsUsers().ToDictionary( X => X.EpicAccountId, Y => Y ); // Export data to the file. string CSVPathname = Path.Combine(Settings.Default.CrashReporterCSV, DateTime.UtcNow.ToString("yyyy-MM-dd.HH-mm-ss")); CSVPathname += string .Format("__[{0}---{1}]__{2}", FormData.DateFrom.ToString("yyyy-MM-dd"), FormData.DateTo.ToString("yyyy-MM-dd"), NumCrashes) + ".csv"; string ServerPath = Server.MapPath(CSVPathname); var CSVFile = new StreamWriter(ServerPath, true, Encoding.UTF8); using (FAutoScopedLogTimer ExportToCSVTimer = new FAutoScopedLogTimer("ExportToCSV")) { var RowType = FilteringQueryJoin.FirstOrDefault().GetType(); string AllProperties = ""; foreach (var Property in RowType.GetProperties()) { AllProperties += Property.Name; AllProperties += "; "; } // Write header CSVFile.WriteLine(AllProperties); foreach (var Row in FilteringQueryJoin) { var BVParts = Row.BuildVersion.Split(new char[] { '.' }, StringSplitOptions.RemoveEmptyEntries); if (BVParts.Length > 2 && BVParts[0] != "0") { string CleanEngineVersion = string.Format("{0}.{1}.{2}", BVParts[0], BVParts[1], BVParts[2]); string[] RowProperties = new string[] { Row.GameName, Row.TimeOfCrash.ToString(), Row.BuiltFromCL, Row.PlatformName, Row.EngineMode, Row.MachineId, Row.Module, CleanEngineVersion, Row.Jira, Row.Branch, Row.CrashType == 1 ? "Crash" : "Assert", Row.EpicId, Row.BuggId.ToString() }; string JoinedLine = string.Join("; ", RowProperties); JoinedLine += "; "; CSVFile.WriteLine(JoinedLine); } } CSVFile.Flush(); CSVFile.Close(); CSVFile = null; } List <FCSVRow> CSVRows = FilteringQueryJoin .OrderByDescending(X => X.TimeOfCrash) .Take(32) .Select(c => new FCSVRow { GameName = c.GameName, TimeOfCrash = c.TimeOfCrash, BuiltFromCL = c.BuiltFromCL, PlatformName = c.PlatformName, EngineMode = c.EngineMode, MachineId = c.MachineId, Module = c.Module, BuildVersion = c.BuildVersion, Jira = c.Jira, Branch = c.Branch, CrashType = c.CrashType, EpicId = c.EpicId, BuggId = c.BuggId, }) .ToList(); return(new CSV_ViewModel { CSVRows = CSVRows, CSVPathname = CSVPathname, DateFrom = (long)(FormData.DateFrom - CrashesViewModel.Epoch).TotalMilliseconds, DateTo = (long)(FormData.DateTo - CrashesViewModel.Epoch).TotalMilliseconds, DateTimeFrom = FormData.DateFrom, DateTimeTo = FormData.DateTo, AffectedUsersFiltered = AffectedUsersFiltered, UniqueCrashesFiltered = UniqueCrashesFiltered, CrashesFilteredWithDate = CrashesFilteredWithDate, TotalCrashes = TotalCrashes, TotalCrashesYearToDate = TotalCrashesYearToDate, }); } }
/// <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> /// The main view of the dash board. /// </summary> /// <returns>A view showing two charts of crashes over time.</returns> public ActionResult Index() { using (FAutoScopedLogTimer LogTimer = new FAutoScopedLogTimer(this.GetType().ToString(), bCreateNewLog: true)) { DateTime Today = DateTime.UtcNow; DateTime AfewMonthsAgo = Today.AddMonths(-6); FAutoScopedLogTimer LogTimerSQL = new FAutoScopedLogTimer("CrashesFilterByDate", "", ""); IQueryable <Crash> CrashesInTimeFrame = _Crashes.ListAll() .Where(MyCrash => MyCrash.TimeOfCrash >= AfewMonthsAgo && MyCrash.TimeOfCrash <= Today.AddDays(1)); //IEnumerable<Crash> Crashes = FRepository.Get().Crashes.FilterByDate( FRepository.Get().Crashes.ListAll(), AfewMonthsAgo, Today ); var VMinimalCrashes = CrashesInTimeFrame.Select(Crash => new { TimeOfCrash = Crash.TimeOfCrash.Value, UserID = Crash.UserNameId.Value }).ToList(); List <FCrashMinimal> MinimalCrashes = new List <FCrashMinimal>(VMinimalCrashes.Count); foreach (var Anotype in VMinimalCrashes) { MinimalCrashes.Add(new FCrashMinimal(Anotype.TimeOfCrash, Anotype.UserID)); } LogTimerSQL.Dispose(); int GeneralUserGroupId = FRepository.Get(_Crashes).FindOrAddGroup("General"); int CoderUserGroupId = FRepository.Get(_Crashes).FindOrAddGroup("Coder"); int EngineQAUserGroupId = FRepository.Get(_Crashes).FindOrAddGroup("EngineQA"); int GameQAUserGroupId = FRepository.Get(_Crashes).FindOrAddGroup("GameQA"); int AnonymousUserGroupId = FRepository.Get(_Crashes).FindOrAddGroup("Anonymous"); Dictionary <DateTime, int> GeneralResults = GetWeeklyCountsByGroup(MinimalCrashes, GeneralUserGroupId); Dictionary <DateTime, int> CoderResults = GetWeeklyCountsByGroup(MinimalCrashes, CoderUserGroupId); Dictionary <DateTime, int> EngineQAResults = GetWeeklyCountsByGroup(MinimalCrashes, EngineQAUserGroupId); Dictionary <DateTime, int> GameQAResults = GetWeeklyCountsByGroup(MinimalCrashes, GameQAUserGroupId); Dictionary <DateTime, int> AnonymousResults = GetWeeklyCountsByGroup(MinimalCrashes, AnonymousUserGroupId); Dictionary <DateTime, int> AllResults = GetWeeklyCountsByGroup(MinimalCrashes, AllUserGroupId); Dictionary <DateTime, int> DailyGeneralResults = GetDailyCountsByGroup(MinimalCrashes, GeneralUserGroupId); Dictionary <DateTime, int> DailyCoderResults = GetDailyCountsByGroup(MinimalCrashes, CoderUserGroupId); Dictionary <DateTime, int> DailyEngineQAResults = GetDailyCountsByGroup(MinimalCrashes, EngineQAUserGroupId); Dictionary <DateTime, int> DailyGameQAResults = GetDailyCountsByGroup(MinimalCrashes, GameQAUserGroupId); Dictionary <DateTime, int> DailyAnonymousResults = GetDailyCountsByGroup(MinimalCrashes, AnonymousUserGroupId); Dictionary <DateTime, int> DailyAllResults = GetDailyCountsByGroup(MinimalCrashes, AllUserGroupId); // Get daily buggs stats. List <Bugg> Buggs = _Buggs.ListAll().Where(Bugg => Bugg.TimeOfFirstCrash >= AfewMonthsAgo).ToList(); Dictionary <DateTime, int> BuggDailyAllResults = ( from Bugg in Buggs group Bugg by Bugg.TimeOfFirstCrash.Value.Date into GroupCount orderby GroupCount.Key select new { Count = GroupCount.Count(), Date = GroupCount.Key } ).ToDictionary(x => x.Date, y => y.Count); string CrashesByWeek = ""; foreach (KeyValuePair <DateTime, int> Result in AllResults) { int GeneralCrashes = 0; GeneralResults.TryGetValue(Result.Key, out GeneralCrashes); int CoderCrashes = 0; CoderResults.TryGetValue(Result.Key, out CoderCrashes); int EngineQACrashes = 0; EngineQAResults.TryGetValue(Result.Key, out EngineQACrashes); int GameQACrashes = 0; GameQAResults.TryGetValue(Result.Key, out GameQACrashes); int AnonymousCrashes = 0; AnonymousResults.TryGetValue(Result.Key, out AnonymousCrashes); int Year = Result.Key.Year; int Month = Result.Key.AddMonths(-1).Month; if (Result.Key.Month == 13 || Result.Key.Month == 1) { Month = 0; } int Day = Result.Key.Day + 6; string Line = "[new Date(" + Year + ", " + Month + ", " + Day + "), " + GeneralCrashes + ", " + CoderCrashes + ", " + EngineQACrashes + ", " + GameQACrashes + ", " + AnonymousCrashes + ", " + Result.Value + "], "; CrashesByWeek += Line; } CrashesByWeek = CrashesByWeek.TrimEnd(", ".ToCharArray()); string CrashesByDay = ""; foreach (KeyValuePair <DateTime, int> DailyResult in DailyAllResults) { int GeneralCrashes = 0; DailyGeneralResults.TryGetValue(DailyResult.Key, out GeneralCrashes); int CoderCrashes = 0; DailyCoderResults.TryGetValue(DailyResult.Key, out CoderCrashes); int EngineQACrashes = 0; DailyEngineQAResults.TryGetValue(DailyResult.Key, out EngineQACrashes); int GameQACrashes = 0; DailyGameQAResults.TryGetValue(DailyResult.Key, out GameQACrashes); int AnonymousCrashes = 0; DailyAnonymousResults.TryGetValue(DailyResult.Key, out AnonymousCrashes); int Year = DailyResult.Key.Year; int Month = DailyResult.Key.AddMonths(-1).Month; if (DailyResult.Key.Month == 13 || DailyResult.Key.Month == 1) { Month = 0; } int Day = DailyResult.Key.Day; string Line = "[new Date(" + Year + ", " + Month + ", " + Day + "), " + GeneralCrashes + ", " + CoderCrashes + ", " + EngineQACrashes + ", " + GameQACrashes + ", " + AnonymousCrashes + ", " + DailyResult.Value + "], "; CrashesByDay += Line; } CrashesByDay = CrashesByDay.TrimEnd(", ".ToCharArray()); string BuggsByDay = ""; foreach (KeyValuePair <DateTime, int> DailyResult in BuggDailyAllResults) { int Year = DailyResult.Key.Year; int Month = DailyResult.Key.AddMonths(-1).Month; if (DailyResult.Key.Month == 13 || DailyResult.Key.Month == 1) { Month = 0; } int Day = DailyResult.Key.Day; string Line = "[new Date(" + Year + ", " + Month + ", " + Day + "), " + DailyResult.Value + "], "; BuggsByDay += Line; } BuggsByDay = BuggsByDay.TrimEnd(", ".ToCharArray()); var ResultDashboard = new DashboardViewModel { CrashesByWeek = CrashesByWeek, CrashesByDay = CrashesByDay, BuggsByDay = BuggsByDay }; ResultDashboard.GenerationTime = LogTimer.GetElapsedSeconds().ToString("F2"); return(View("Index", ResultDashboard)); } }
/// <summary> /// The main view of the dash board. /// </summary> /// <returns>A view showing two charts of crashes over time.</returns> public ActionResult Index() { using (FAutoScopedLogTimer LogTimer = new FAutoScopedLogTimer(this.GetType().ToString(), bCreateNewLog: true)) { DateTime Today = DateTime.UtcNow; DateTime AfewMonthsAgo = Today.AddMonths(-6); FAutoScopedLogTimer LogTimerSQL = new FAutoScopedLogTimer("CrashesFilterByDate", "", ""); // Get engine versions from the last 6 months. var TempVersions = CrashRepository.GetVersions(); List <string> EngineUE4Versions = new List <string>(); foreach (var Version in TempVersions) { if (Version.StartsWith("4.")) { EngineUE4Versions.Add(Version); } } // Only 4 latest version. EngineUE4Versions = EngineUE4Versions.OrderByDescending(item => item).Take(5).ToList(); IQueryable <Crash> CrashesInTimeFrame = _Crashes.ListAll() .Where(MyCrash => MyCrash.TimeOfCrash >= AfewMonthsAgo && MyCrash.TimeOfCrash <= Today.AddDays(1)); //IEnumerable<Crash> Crashes = FRepository.Get().Crashes.FilterByDate( FRepository.Get().Crashes.ListAll(), AfewMonthsAgo, Today ); var VMinimalCrashes = CrashesInTimeFrame.Select(Crash => new { TimeOfCrash = Crash.TimeOfCrash.Value, UserID = Crash.UserNameId.Value, EngineVersion = Crash.BuildVersion, }) .ToList(); List <FCrashMinimal> MinimalCrashes = new List <FCrashMinimal>(VMinimalCrashes.Count); foreach (var Anotype in VMinimalCrashes) { MinimalCrashes.Add(new FCrashMinimal(Anotype.TimeOfCrash, Anotype.UserID, Anotype.EngineVersion)); } LogTimerSQL.Dispose(); HashSet <int> AnonumousIDs = FRepository.Get(_Crashes).GetUserIdsFromUserGroup("Anonymous"); int AnonymousID = AnonumousIDs.First(); int GeneralUserGroupId = FRepository.Get(_Crashes).FindOrAddGroup("General"); int CoderUserGroupId = FRepository.Get(_Crashes).FindOrAddGroup("Coder"); int EngineQAUserGroupId = FRepository.Get(_Crashes).FindOrAddGroup("EngineQA"); int GameQAUserGroupId = FRepository.Get(_Crashes).FindOrAddGroup("GameQA"); // Weekly Dictionary <DateTime, int> WeeklyGeneralResults = GetWeeklyCountsByGroup(MinimalCrashes, GeneralUserGroupId); Dictionary <DateTime, int> WeeklyCoderResults = GetWeeklyCountsByGroup(MinimalCrashes, CoderUserGroupId); Dictionary <DateTime, int> WeeklyEngineQAResults = GetWeeklyCountsByGroup(MinimalCrashes, EngineQAUserGroupId); Dictionary <DateTime, int> WeeklyGameQAResults = GetWeeklyCountsByGroup(MinimalCrashes, GameQAUserGroupId); Dictionary <string, Dictionary <DateTime, int> > WeeklyEngineVersionResults = new Dictionary <string, Dictionary <DateTime, int> >(); foreach (string UE4Version in EngineUE4Versions) { Dictionary <DateTime, int> Results = GetWeeklyCountsByVersion(MinimalCrashes, UE4Version, AnonymousID); WeeklyEngineVersionResults.Add(UE4Version, Results); } Dictionary <DateTime, int> WeeklyAllResults = GetWeeklyCountsByGroup(MinimalCrashes, AllUserGroupId); // Daily Dictionary <DateTime, int> DailyGeneralResults = GetDailyCountsByGroup(MinimalCrashes, GeneralUserGroupId); Dictionary <DateTime, int> DailyCoderResults = GetDailyCountsByGroup(MinimalCrashes, CoderUserGroupId); Dictionary <DateTime, int> DailyEngineQAResults = GetDailyCountsByGroup(MinimalCrashes, EngineQAUserGroupId); Dictionary <DateTime, int> DailyGameQAResults = GetDailyCountsByGroup(MinimalCrashes, GameQAUserGroupId); Dictionary <string, Dictionary <DateTime, int> > DailyEngineVersionResults = new Dictionary <string, Dictionary <DateTime, int> >(); foreach (string UE4Version in EngineUE4Versions) { Dictionary <DateTime, int> Results = GetDailyCountsByVersion(MinimalCrashes, UE4Version, AnonymousID); DailyEngineVersionResults.Add(UE4Version, Results); } Dictionary <DateTime, int> DailyAllResults = GetDailyCountsByGroup(MinimalCrashes, AllUserGroupId); // Get daily buggs stats. List <Bugg> Buggs = _Buggs.ListAll().Where(Bugg => Bugg.TimeOfFirstCrash >= AfewMonthsAgo).ToList(); Dictionary <DateTime, int> BuggDailyAllResults = ( from Bugg in Buggs group Bugg by Bugg.TimeOfFirstCrash.Value.Date into GroupCount orderby GroupCount.Key select new { Count = GroupCount.Count(), Date = GroupCount.Key } ).ToDictionary(x => x.Date, y => y.Count); string CrashesByWeek = ""; foreach (KeyValuePair <DateTime, int> WeeklyResult in WeeklyAllResults) { int GeneralCrashes = 0; WeeklyGeneralResults.TryGetValue(WeeklyResult.Key, out GeneralCrashes); int CoderCrashes = 0; WeeklyCoderResults.TryGetValue(WeeklyResult.Key, out CoderCrashes); int EngineQACrashes = 0; WeeklyEngineQAResults.TryGetValue(WeeklyResult.Key, out EngineQACrashes); int GameQACrashes = 0; WeeklyGameQAResults.TryGetValue(WeeklyResult.Key, out GameQACrashes); string AnonymousLine = ""; foreach (var VersionCrashes in WeeklyEngineVersionResults) { int EngineVersionCrashes = 0; VersionCrashes.Value.TryGetValue(WeeklyResult.Key, out EngineVersionCrashes); AnonymousLine += EngineVersionCrashes; AnonymousLine += ", "; } int Year = WeeklyResult.Key.Year; int Month = WeeklyResult.Key.AddMonths(-1).Month; if (WeeklyResult.Key.Month == 13 || WeeklyResult.Key.Month == 1) { Month = 0; } int Day = WeeklyResult.Key.Day + 6; string Line = "[new Date(" + Year + ", " + Month + ", " + Day + "), " + GeneralCrashes + ", " + CoderCrashes + ", " + EngineQACrashes + ", " + GameQACrashes + ", " + AnonymousLine + WeeklyResult.Value + "], "; CrashesByWeek += Line; } CrashesByWeek = CrashesByWeek.TrimEnd(", ".ToCharArray()); string CrashesByDay = ""; foreach (KeyValuePair <DateTime, int> DailyResult in DailyAllResults) { int GeneralCrashes = 0; DailyGeneralResults.TryGetValue(DailyResult.Key, out GeneralCrashes); int CoderCrashes = 0; DailyCoderResults.TryGetValue(DailyResult.Key, out CoderCrashes); int EngineQACrashes = 0; DailyEngineQAResults.TryGetValue(DailyResult.Key, out EngineQACrashes); int GameQACrashes = 0; DailyGameQAResults.TryGetValue(DailyResult.Key, out GameQACrashes); string AnonymousLine = ""; foreach (var VersionCrashes in DailyEngineVersionResults) { int EngineVersionCrashes = 0; VersionCrashes.Value.TryGetValue(DailyResult.Key, out EngineVersionCrashes); AnonymousLine += EngineVersionCrashes; AnonymousLine += ", "; } int Year = DailyResult.Key.Year; int Month = DailyResult.Key.AddMonths(-1).Month; if (DailyResult.Key.Month == 13 || DailyResult.Key.Month == 1) { Month = 0; } int Day = DailyResult.Key.Day; string Line = "[new Date(" + Year + ", " + Month + ", " + Day + "), " + GeneralCrashes + ", " + CoderCrashes + ", " + EngineQACrashes + ", " + GameQACrashes + ", " + AnonymousLine + DailyResult.Value + "], "; CrashesByDay += Line; } CrashesByDay = CrashesByDay.TrimEnd(", ".ToCharArray()); string BuggsByDay = ""; foreach (KeyValuePair <DateTime, int> DailyResult in BuggDailyAllResults) { int Year = DailyResult.Key.Year; int Month = DailyResult.Key.AddMonths(-1).Month; if (DailyResult.Key.Month == 13 || DailyResult.Key.Month == 1) { Month = 0; } int Day = DailyResult.Key.Day; string Line = "[new Date(" + Year + ", " + Month + ", " + Day + "), " + DailyResult.Value + "], "; BuggsByDay += Line; } BuggsByDay = BuggsByDay.TrimEnd(", ".ToCharArray()); var ResultDashboard = new DashboardViewModel { CrashesByWeek = CrashesByWeek, CrashesByDay = CrashesByDay, BuggsByDay = BuggsByDay, EngineVersions = EngineUE4Versions, }; ResultDashboard.GenerationTime = LogTimer.GetElapsedSeconds().ToString("F2"); return(View("Index", ResultDashboard)); } }