示例#1
0
        private void AddBuggJiraMapping(Bugg NewBugg, ref HashSet <string> FoundJiras, ref Dictionary <string, List <Bugg> > JiraIDtoBugg)
        {
            string JiraID = NewBugg.TTPID;

            FoundJiras.Add("key = " + JiraID);

            bool bAdd = !JiraIDtoBugg.ContainsKey(JiraID);

            if (bAdd)
            {
                JiraIDtoBugg.Add(JiraID, new List <Bugg>());
            }

            JiraIDtoBugg[JiraID].Add(NewBugg);
        }
示例#2
0
        /// <summary>
        /// Update an existing Bugg
        /// </summary>
        /// <param name="entity"></param>
        public void Update(Bugg entity)
        {
            var set   = _entityContext.Set <Bugg>();
            var entry = set.Local.SingleOrDefault(f => f.Id == entity.Id);

            if (entry != null)
            {
                var attachedFeature = _entityContext.Entry(entry);
                attachedFeature.CurrentValues.SetValues(entity);
                attachedFeature.State = EntityState.Modified;
            }
            else
            {
                _entityContext.Buggs.Attach(entity);
                _entityContext.Entry(entity).State = EntityState.Modified;
            }
        }
示例#3
0
        /*
         * /// <summary>
         * /// The empty view of the buggs page.
         * /// </summary>
         * ///
         * public ActionResult Index()
         * {
         *      using (FAutoScopedLogTimer LogTimer = new FAutoScopedLogTimer( this.GetType().ToString(), bCreateNewLog: true ))
         *      {
         *              BuggsViewModel Results = new BuggsViewModel();
         *              Results.GenerationTime = LogTimer.GetElapsedSeconds().ToString( "F2" );
         *              return View( "Index", Results );
         *      }
         * }*/

        /// <summary>
        /// The Index action.
        /// </summary>
        /// <param name="BuggsForm">The form of user data passed up from the client.</param>
        /// <returns>The view to display a list of Buggs on the client.</returns>
        public ActionResult Index(FormCollection BuggsForm)
        {
            using (FAutoScopedLogTimer LogTimer = new FAutoScopedLogTimer(this.GetType().ToString(), bCreateNewLog: true))
            {
                BuggRepository Buggs = new BuggRepository();

                FormHelper     FormData = new FormHelper(Request, BuggsForm, "CrashesInTimeFrameGroup");
                BuggsViewModel Results  = Buggs.GetResults(FormData);
                foreach (var Bugg in Results.Results)
                {
                    // Populate function calls.
                    Bugg.GetFunctionCalls();
                }
                Results.GenerationTime = LogTimer.GetElapsedSeconds().ToString("F2");
                return(View("Index", Results));
            }
        }
        /// <summary>
        /// Create a new crash data model object and insert it into the database
        /// </summary>
        /// <param name="description"></param>
        /// <returns></returns>
        private Crash CreateCrash(CrashDescription description)
        {
            var newCrash = new Crash
            {
                Branch            = description.BranchName,
                BaseDir           = description.BaseDir,
                BuildVersion      = description.EngineVersion,
                EngineVersion     = description.BuildVersion,
                ChangeListVersion = description.BuiltFromCL.ToString(),
                CommandLine       = description.CommandLine,
                EngineMode        = description.EngineMode,
                ComputerName      = description.MachineGuid
            };

            //if there's a valid username assign the associated UserNameId else use "anonymous".
            var userName = (!string.IsNullOrEmpty(description.UserName)) ? description.UserName : UserNameAnonymous;
            var user     = _unitOfWork.UserRepository.GetByUserName(userName);

            if (user != null)
            {
                newCrash.UserNameId = user.Id;
            }
            else
            {
                newCrash.User = new User()
                {
                    UserName = description.UserName, UserGroupId = 5
                };
            }

            //If there's a valid EpicAccountId assign that.
            if (!string.IsNullOrEmpty(description.EpicAccountId))
            {
                newCrash.EpicAccountId = description.EpicAccountId;
            }

            newCrash.Description = "";
            if (description.UserDescription != null)
            {
                newCrash.Description = string.Join(Environment.NewLine, description.UserDescription);
            }

            newCrash.EngineMode   = description.EngineMode;
            newCrash.GameName     = description.GameName;
            newCrash.LanguageExt  = description.Language;    //Converted by the crash process.
            newCrash.PlatformName = description.Platform;

            if (description.ErrorMessage != null)
            {
                newCrash.Summary = string.Join("\n", description.ErrorMessage);
            }

            if (description.CallStack != null)
            {
                newCrash.RawCallStack = string.Join("\n", description.CallStack);
            }

            if (description.SourceContext != null)
            {
                newCrash.SourceContext = string.Join("\n", description.SourceContext);
            }

            newCrash.TimeOfCrash = description.TimeofCrash;
            newCrash.Processed   = description.bAllowToBeContacted;

            newCrash.Jira            = "";
            newCrash.FixedChangeList = "";
            newCrash.ProcessFailed   = description.bProcessorFailed;

            // Set the crash type
            newCrash.CrashType = 1;

            //if we have a crash type set the crash type
            if (!string.IsNullOrEmpty(description.CrashType))
            {
                switch (description.CrashType.ToLower())
                {
                case "crash":
                    newCrash.CrashType = 1;
                    break;

                case "assert":
                    newCrash.CrashType = 2;
                    break;

                case "ensure":
                    newCrash.CrashType = 3;
                    break;

                case "":
                case null:
                default:
                    newCrash.CrashType = 1;
                    break;
                }
            }
            else     //else fall back to the old behavior and try to determine type from RawCallStack
            {
                if (newCrash.RawCallStack != null)
                {
                    if (newCrash.RawCallStack.Contains("FDebug::AssertFailed"))
                    {
                        newCrash.CrashType = 2;
                    }
                    else if (newCrash.RawCallStack.Contains("FDebug::Ensure"))
                    {
                        newCrash.CrashType = 3;
                    }
                    else if (newCrash.RawCallStack.Contains("FDebug::OptionallyLogFormattedEnsureMessageReturningFalse"))
                    {
                        newCrash.CrashType = 3;
                    }
                    else if (newCrash.RawCallStack.Contains("NewReportEnsure"))
                    {
                        newCrash.CrashType = 3;
                    }
                }
            }

            // As we're adding it, the status is always new
            newCrash.Status = "New";

            /*
             * Unused Crashes' fields.
             *
             * Title				nchar(20)
             * Selected			bit
             * Version				int
             * AutoReporterID		int
             * Processed			bit	-> renamed to AllowToBeContacted
             * HasDiagnosticsFile	bit	always true
             * HasNewLogFile		bit
             * HasMetaData			bit	always true
             */

            // Set the unused fields to the default values.
            //NewCrash.Title = "";			removed from dbml
            //NewCrash.Selected = false;	removed from dbml
            //NewCrash.Version = 4;			removed from dbml
            //NewCrash.AutoReporterID = 0;	removed from dbml
            //NewCrash.HasNewLogFile = false;removed from dbml

            //NewCrash.HasDiagnosticsFile = true;
            //NewCrash.HasMetaData = true;
            newCrash.UserActivityHint = description.UserActivityHint;

            BuildPattern(newCrash);

            if (newCrash.CommandLine == null)
            {
                newCrash.CommandLine = "";
            }

            _unitOfWork.Dispose();
            _unitOfWork = new UnitOfWork(new CrashReportEntities());
            var callStackRepository = _unitOfWork.CallstackRepository;

            try
            {
                var crashRepo = _unitOfWork.CrashRepository;
                //if we don't have any callstack data then insert the crash and return
                if (string.IsNullOrEmpty(newCrash.Pattern))
                {
                    crashRepo.Save(newCrash);
                    _unitOfWork.Save();
                    return(newCrash);
                }

                //If this isn't a new pattern then link it to our crash data model
                if (callStackRepository.Any(data => data.Pattern == newCrash.Pattern))
                {
                    var callstackPattern = callStackRepository.First(data => data.Pattern == newCrash.Pattern);
                    newCrash.PatternId = callstackPattern.id;
                }
                else
                {
                    //if this is a new callstack pattern then insert into data model and create a new bugg.
                    var callstackPattern = new CallStackPattern {
                        Pattern = newCrash.Pattern
                    };
                    callStackRepository.Save(callstackPattern);
                    _unitOfWork.Save();
                    newCrash.PatternId = callstackPattern.id;
                }

                //Mask out the line number and File path from our error message.
                var errorMessageString = description.ErrorMessage != null?String.Join("", description.ErrorMessage) : "";

                //Create our masking regular expressions
                var fileRegex = new Regex(@"(\[File:).*?(])"); //Match the filename out the file name
                var lineRegex = new Regex(@"(\[Line:).*?(])"); //Match the line no.

                /**
                 * Regex to match ints of two characters or longer
                 * First term ((?<=\s)|(-)) : Positive look behind, match if preceeded by whitespace or if first character is '-'
                 * Second term (\d{3,}) match three or more decimal chracters in a row.
                 * Third term (?=(\s|$)) positive look ahead match if followed by whitespace or end of line/file.
                 */
                var intRegex = new Regex(@"-?\d{3,}");

                /**
                 * Regular expression for masking out floats
                 */
                var floatRegex = new Regex(@"-?\d+\.\d+");

                /**
                 * Regular expression for masking out hexadecimal numbers
                 */
                var hexRegex = new Regex(@"0x[\da-fA-F]+");

                //mask out terms matches by our regex's
                var trimmedError = fileRegex.Replace(errorMessageString, "");
                trimmedError = lineRegex.Replace(trimmedError, "");
                trimmedError = floatRegex.Replace(trimmedError, "");
                trimmedError = hexRegex.Replace(trimmedError, "");
                trimmedError = intRegex.Replace(trimmedError, "");

                //Check to see if the masked error message is unique
                ErrorMessage errorMessage = null;
                if (_unitOfWork.ErrorMessageRepository.Any(data => data.Message.Contains(trimmedError)))
                {
                    errorMessage =
                        _unitOfWork.ErrorMessageRepository.First(data => data.Message.Contains(trimmedError));
                }
                else
                {
                    //if it's a new message then add it to the database.
                    errorMessage = new ErrorMessage()
                    {
                        Message = trimmedError
                    };
                    _unitOfWork.ErrorMessageRepository.Save(errorMessage);
                    _unitOfWork.Save();
                }

                //Check for an existing bugg with this pattern and error message / no error message
                if (_unitOfWork.BuggRepository.Any(data =>
                                                   (data.PatternId == newCrash.PatternId || data.Pattern == newCrash.Pattern) && (newCrash.CrashType == 3 ||
                                                                                                                                  (data.ErrorMessageId == errorMessage.Id || data.ErrorMessageId == null))))
                {
                    //if a bugg exists for this pattern update the bugg data
                    var bugg = _unitOfWork.BuggRepository.First(data => data.PatternId == newCrash.PatternId) ??
                               _unitOfWork.BuggRepository.First(data => data.Pattern == newCrash.Pattern);
                    bugg.PatternId = newCrash.PatternId;

                    if (newCrash.CrashType != 3)
                    {
                        bugg.CrashType      = newCrash.CrashType;
                        bugg.ErrorMessageId = errorMessage.Id;
                    }

                    //also update the bugg data while we're here
                    bugg.TimeOfLastCrash = newCrash.TimeOfCrash;

                    if (String.Compare(newCrash.BuildVersion, bugg.BuildVersion,
                                       StringComparison.Ordinal) != 1)
                    {
                        bugg.BuildVersion = newCrash.BuildVersion;
                    }

                    _unitOfWork.Save();

                    //if a bugg exists update this crash from the bugg
                    //buggs are authoritative in this case
                    newCrash.Buggs.Add(bugg);
                    newCrash.Jira            = bugg.TTPID;
                    newCrash.FixedChangeList = bugg.FixedChangeList;
                    newCrash.Status          = bugg.Status;
                    _unitOfWork.CrashRepository.Save(newCrash);
                    _unitOfWork.Save();
                }
                else
                {
                    //if there's no bugg for this pattern create a new bugg and insert into the data store.
                    var bugg = new Bugg();
                    bugg.TimeOfFirstCrash       = newCrash.TimeOfCrash;
                    bugg.TimeOfLastCrash        = newCrash.TimeOfCrash;
                    bugg.TTPID                  = newCrash.Jira;
                    bugg.Pattern                = newCrash.Pattern;
                    bugg.PatternId              = newCrash.PatternId;
                    bugg.NumberOfCrashes        = 1;
                    bugg.NumberOfUsers          = 1;
                    bugg.NumberOfUniqueMachines = 1;
                    bugg.BuildVersion           = newCrash.BuildVersion;
                    bugg.CrashType              = newCrash.CrashType;
                    bugg.Status                 = newCrash.Status;
                    bugg.FixedChangeList        = newCrash.FixedChangeList;
                    bugg.ErrorMessageId         = errorMessage.Id;
                    newCrash.Buggs.Add(bugg);
                    _unitOfWork.BuggRepository.Save(bugg);
                    _unitOfWork.CrashRepository.Save(newCrash);
                    _unitOfWork.Save();
                }
            }
            catch (DbEntityValidationException dbentEx)
            {
                var messageBuilder = new StringBuilder();
                messageBuilder.AppendLine("Db Entity Validation Exception Exception was:");
                messageBuilder.AppendLine(dbentEx.ToString());

                var innerEx = dbentEx.InnerException;
                while (innerEx != null)
                {
                    messageBuilder.AppendLine("Inner Exception : " + innerEx.Message);
                    innerEx = innerEx.InnerException;
                }

                if (dbentEx.EntityValidationErrors != null)
                {
                    messageBuilder.AppendLine("Validation Errors : ");
                    foreach (var valErr in dbentEx.EntityValidationErrors)
                    {
                        messageBuilder.AppendLine(valErr.ValidationErrors.Select(data => data.ErrorMessage).Aggregate((current, next) => current + "; /n" + next));
                    }
                }
                FLogger.Global.WriteException(messageBuilder.ToString());
            }
            catch (Exception ex)
            {
                var messageBuilder = new StringBuilder();
                messageBuilder.AppendLine("Create Crash Exception : ");
                messageBuilder.AppendLine(ex.Message.ToString());
                var innerEx = ex.InnerException;
                while (innerEx != null)
                {
                    messageBuilder.AppendLine("Inner Exception : " + innerEx.Message);
                    innerEx = innerEx.InnerException;
                }

                FLogger.Global.WriteException("Create Crash Exception : " +
                                              messageBuilder.ToString());
                _slackWriter.Write("Create Crash Exception : " + messageBuilder.ToString());
                throw;
            }

            return(newCrash);
        }
示例#5
0
 /// <summary>
 /// Remove a Bugg from the data store
 /// </summary>
 /// <param name="entity"></param>
 public void Delete(Bugg entity)
 {
     _entityContext.Buggs.Remove(entity);
 }
示例#6
0
 /// <summary>
 /// Add a new Bugg to the data store
 /// </summary>
 /// <param name="entity"></param>
 public void Save(Bugg entity)
 {
     _entityContext.Buggs.Add(entity);
 }
示例#7
0
        /// <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
                });
            }
        }
示例#8
0
        /// <summary>
        /// Retrieve all Buggs matching the search criteria.
        /// </summary>
        /// <returns></returns>
        private ReportsViewModel GetResults(string branchName, DateTime startDate, DateTime endDate, int BuggIDToBeAddedToJira)
        {
            // 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.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 = _unitOfWork.UserGroupRepository.First(data => data.Name == "Anonymous").Id;
                List <int> AnonumousIDs     =
                    _unitOfWork.UserGroupRepository.First(data => data.Name == "Anonymous").Users.Select(data => data.Id).ToList();
                int AnonymousID = AnonumousIDs.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 =
                        (
                            from CrashDetail in CrashesQuery
                            where CrashDetail.Branch.Equals(branchName)
                            select CrashDetail
                        );
                }

                var crashes = CrashesQuery.Select(data => new
                {
                    ID          = data.Id,
                    TimeOfCrash = data.TimeOfCrash.Value,
                    //UserID = Crash.UserNameId.Value,
                    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();

                /*
                 * // Build patterns for crashes where patters is null.
                 * var CrashesWithoutPattern = FRepository.Get().Crashes
                 * .FilterByDate( FRepository.Get().Crashes.ListAll(), startDate, endDate.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();
                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.
                HashSet <string> FoundJiras = new HashSet <string>();
                Dictionary <string, List <Bugg> > JiraIDtoBugg = new Dictionary <string, List <Bugg> >();

                List <Bugg> Buggs = new List <Bugg>(NumTopRecords);
                foreach (var Top in PatternAndCount)
                {
                    Bugg NewBugg = RealBuggs.FirstOrDefault(X => X.Pattern == Top.Key);
                    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,
                                    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.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);

                    HashSet <string> 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);

                    using (FAutoScopedLogTimer JiraResultsTimer = new FAutoScopedLogTimer("JiraResults"))
                    {
                        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
                });
            }
        }
示例#9
0
        /// <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>
        /// Update an existing Bugg
        /// </summary>
        /// <param name="entity"></param>
        public void Update(Bugg entity)
        {
            var set = _entityContext.Set<Bugg>();
            var entry = set.Local.SingleOrDefault(f => f.Id == entity.Id);

            if (entry != null)
            {
                var attachedFeature = _entityContext.Entry(entry);
                attachedFeature.CurrentValues.SetValues(entity);
                attachedFeature.State = EntityState.Modified;
            }
            else
            {
                _entityContext.Buggs.Attach(entity);
                _entityContext.Entry(entity).State = EntityState.Modified;
            }
        }
 /// <summary>
 /// Remove a Bugg from the data store
 /// </summary>
 /// <param name="entity"></param>
 public void Delete(Bugg entity)
 {
     _entityContext.Buggs.Remove(entity);
 }
 /// <summary>
 /// Add a new Bugg to the data store
 /// </summary>
 /// <param name="entity"></param>
 public void Save(Bugg entity)
 {
     _entityContext.Buggs.Add(entity);
 }
示例#13
0
		private void OnBuggsRemove( Bugg BuggInstance )
		{
			var BuggCrash = Buggs_Crashes.FirstOrDefault(
				c => c.CrashId == Id
				&& c.BuggId == BuggInstance.Id );
			Buggs_Crashes.Remove( BuggCrash );

			SendPropertyChanged( null );
		}
示例#14
0
		private void OnBuggsAdd( Bugg BuggInstance )
		{
			Buggs_Crashes.Add( new Buggs_Crash { Crash = this, Bugg = BuggInstance } );
			SendPropertyChanged( null );
		}
        private void AddBuggJiraMapping(Bugg NewBugg, ref HashSet<string> FoundJiras, ref Dictionary<string, List<Bugg>> JiraIDtoBugg)
        {
            string JiraID = NewBugg.TTPID;
            FoundJiras.Add("key = " + JiraID);

            bool bAdd = !JiraIDtoBugg.ContainsKey(JiraID);
            if (bAdd)
            {
                JiraIDtoBugg.Add(JiraID, new List<Bugg>());
            }

            JiraIDtoBugg[JiraID].Add(NewBugg);
        }
        /// <summary>
        /// The Show action.
        /// </summary>
        /// <param name="BuggsForm">The form of user data passed up from the client.</param>
        /// <param name="id">The unique id of the Bugg.</param>
        /// <returns>The view to display a Bugg on the client.</returns>
        public ActionResult Show(FormCollection BuggsForm, int id)
        {
            // Set the display properties based on the radio buttons
            bool DisplayModuleNames = false;

            if (BuggsForm["DisplayModuleNames"] == "true")
            {
                DisplayModuleNames = true;
            }

            bool DisplayFunctionNames = false;

            if (BuggsForm["DisplayFunctionNames"] == "true")
            {
                DisplayFunctionNames = true;
            }

            bool DisplayFileNames = false;

            if (BuggsForm["DisplayFileNames"] == "true")
            {
                DisplayFileNames = true;
            }

            bool DisplayFilePathNames = false;

            if (BuggsForm["DisplayFilePathNames"] == "true")
            {
                DisplayFilePathNames = true;
                DisplayFileNames     = false;
            }

            bool DisplayUnformattedCallStack = false;

            if (BuggsForm["DisplayUnformattedCallStack"] == "true")
            {
                DisplayUnformattedCallStack = true;
            }

            // Create a new view and populate with crashes
            List <Crash> Crashes = null;
            Bugg         Bugg    = new Bugg();

            BuggViewModel Model = new BuggViewModel();

            Bugg = LocalBuggRepository.GetBugg(id);
            if (Bugg == null)
            {
                return(RedirectToAction(""));
            }

            Crashes = Bugg.GetCrashes().ToList();

            // Apply any user settings
            if (BuggsForm.Count > 0)
            {
                if (!string.IsNullOrEmpty(BuggsForm["SetStatus"]))
                {
                    Bugg.Status = BuggsForm["SetStatus"];
                    LocalCrashRepository.SetBuggStatus(Bugg.Status, id);
                }

                if (!string.IsNullOrEmpty(BuggsForm["SetFixedIn"]))
                {
                    Bugg.FixedChangeList = BuggsForm["SetFixedIn"];
                    LocalCrashRepository.SetBuggFixedChangeList(Bugg.FixedChangeList, id);
                }

                if (!string.IsNullOrEmpty(BuggsForm["SetTTP"]))
                {
                    Bugg.TTPID = BuggsForm["SetTTP"];
                    LocalCrashRepository.SetBuggTTPID(Bugg.TTPID, id);
                }

                if (!string.IsNullOrEmpty(BuggsForm["Description"]))
                {
                    Bugg.Description = BuggsForm["Description"];
                }

                // <STATUS>
            }

            // Set up the view model with the crash data
            Model.Bugg    = Bugg;
            Model.Crashes = Crashes;

            Crash NewCrash = Model.Crashes.FirstOrDefault();

            if (NewCrash != null)
            {
                CallStackContainer CallStack = new CallStackContainer(NewCrash);

                // Set callstack properties
                CallStack.bDisplayModuleNames          = DisplayModuleNames;
                CallStack.bDisplayFunctionNames        = DisplayFunctionNames;
                CallStack.bDisplayFileNames            = DisplayFileNames;
                CallStack.bDisplayFilePathNames        = DisplayFilePathNames;
                CallStack.bDisplayUnformattedCallStack = DisplayUnformattedCallStack;

                Model.CallStack = CallStack;

                NewCrash.CallStackContainer = NewCrash.GetCallStack();
            }

            // Add in the users for each crash in the Bugg
            foreach (Crash CrashInstance in Model.Crashes)
            {
                LocalCrashRepository.PopulateUserInfo(CrashInstance);
            }

            return(View("Show", Model));
        }
示例#17
0
        /// <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));
            }
        }
示例#18
0
        /// <summary>
        /// The Show action.
        /// </summary>
        /// <param name="BuggsForm">The form of user data passed up from the client.</param>
        /// <param name="id">The unique id of the Bugg.</param>
        /// <returns>The view to display a Bugg on the client.</returns>
        public ActionResult Show(FormCollection BuggsForm, int id)
        {
            using (FAutoScopedLogTimer LogTimer = new FAutoScopedLogTimer(this.GetType().ToString() + "(BuggId=" + id + ")"))
            {
                // Set the display properties based on the radio buttons
                bool DisplayModuleNames = false;
                if (BuggsForm["DisplayModuleNames"] == "true")
                {
                    DisplayModuleNames = true;
                }

                bool DisplayFunctionNames = false;
                if (BuggsForm["DisplayFunctionNames"] == "true")
                {
                    DisplayFunctionNames = true;
                }

                bool DisplayFileNames = false;
                if (BuggsForm["DisplayFileNames"] == "true")
                {
                    DisplayFileNames = true;
                }

                bool DisplayFilePathNames = false;
                if (BuggsForm["DisplayFilePathNames"] == "true")
                {
                    DisplayFilePathNames = true;
                    DisplayFileNames     = false;
                }

                bool DisplayUnformattedCallStack = false;
                if (BuggsForm["DisplayUnformattedCallStack"] == "true")
                {
                    DisplayUnformattedCallStack = true;
                }

                // Create a new view and populate with crashes
                List <Crash> Crashes = null;
                Bugg         Bugg    = new Bugg();

                BuggViewModel Model = new BuggViewModel();
                Bugg = LocalBuggRepository.GetBugg(id);
                if (Bugg == null)
                {
                    return(RedirectToAction(""));
                }

                // @TODO yrx 2015-02-17 JIRA
                using (FAutoScopedLogTimer GetCrashesTimer = new FAutoScopedLogTimer("Bugg.GetCrashes().ToList"))
                {
                    Crashes = Bugg.GetCrashes();
                    Bugg.AffectedVersions = new SortedSet <string>();

                    HashSet <string> MachineIds = new HashSet <string>();
                    foreach (Crash Crash in Crashes)
                    {
                        MachineIds.Add(Crash.ComputerName);
                        // Ignore bad build versions.
                        if (Crash.BuildVersion.StartsWith("4."))
                        {
                            Bugg.AffectedVersions.Add(Crash.BuildVersion);
                        }

                        if (Crash.User == null)
                        {
                            //??
                        }
                    }
                    Bugg.NumberOfUniqueMachines = MachineIds.Count;
                }

                // Apply any user settings
                if (BuggsForm.Count > 0)
                {
                    if (!string.IsNullOrEmpty(BuggsForm["SetStatus"]))
                    {
                        Bugg.Status = BuggsForm["SetStatus"];
                        LocalCrashRepository.SetBuggStatus(Bugg.Status, id);
                    }

                    if (!string.IsNullOrEmpty(BuggsForm["SetFixedIn"]))
                    {
                        Bugg.FixedChangeList = BuggsForm["SetFixedIn"];
                        LocalCrashRepository.SetBuggFixedChangeList(Bugg.FixedChangeList, id);
                    }

                    if (!string.IsNullOrEmpty(BuggsForm["SetTTP"]))
                    {
                        Bugg.TTPID = BuggsForm["SetTTP"];
                        BuggRepository.SetJIRAForBuggAndCrashes(Bugg.TTPID, id);
                    }

                    if (!string.IsNullOrEmpty(BuggsForm["Description"]))
                    {
                        Bugg.Description = BuggsForm["Description"];
                    }

                    // <STATUS>
                }

                // Set up the view model with the crash data
                Model.Bugg    = Bugg;
                Model.Crashes = Crashes;

                Crash NewCrash = Model.Crashes.FirstOrDefault();
                if (NewCrash != null)
                {
                    using (FScopedLogTimer LogTimer2 = new FScopedLogTimer("CallstackTrimming"))
                    {
                        CallStackContainer CallStack = new CallStackContainer(NewCrash);

                        // Set callstack properties
                        CallStack.bDisplayModuleNames          = DisplayModuleNames;
                        CallStack.bDisplayFunctionNames        = DisplayFunctionNames;
                        CallStack.bDisplayFileNames            = DisplayFileNames;
                        CallStack.bDisplayFilePathNames        = DisplayFilePathNames;
                        CallStack.bDisplayUnformattedCallStack = DisplayUnformattedCallStack;

                        Model.CallStack = CallStack;

                        // Shorten very long function names.
                        foreach (CallStackEntry Entry in Model.CallStack.CallStackEntries)
                        {
                            Entry.FunctionName = Entry.GetTrimmedFunctionName(128);
                        }

                        Model.SourceContext = NewCrash.SourceContext;
                    }
                }

                /*using( FScopedLogTimer LogTimer2 = new FScopedLogTimer( "BuggsController.Show.PopulateUserInfo" + "(id=" + id + ")" ) )
                 * {
                 *      // Add in the users for each crash in the Bugg
                 *      foreach( Crash CrashInstance in Model.Crashes )
                 *      {
                 *              LocalCrashRepository.PopulateUserInfo( CrashInstance );
                 *      }
                 * }*/
                return(View("Show", Model));
            }
        }