Beispiel #1
0
        /// <summary>
        ///     Creates an incident and a report.
        /// </summary>
        public void CreateReportAndIncident(out int reportId, out int incidentId)
        {
            ErrorReportEntity report;

            using (var uow = CreateUnitOfWork())
            {
                report = new ErrorReportEntity(ApplicationId, Guid.NewGuid().ToString("N"), DateTime.UtcNow,
                                               new ErrorReportException(new Exception("mofo")),
                                               new List <ErrorReportContextCollection>
                {
                    new ErrorReportContextCollection("Maps", new Dictionary <string, string>())
                })
                {
                    Title = "Missing here"
                };
                report.Init(report.GenerateHashCodeIdentifier());

                uow.SaveChanges();
            }

            using (var dbContext = CreateUnitOfWork())
            {
                var incident = new IncidentBeingAnalyzed(report);
                var incRepos = new AnalyticsRepository(dbContext);
                incRepos.CreateIncident(incident);
                incidentId = incident.Id;

                report.IncidentId = incident.Id;
                incRepos.CreateReport(report);
                reportId = report.Id;

                dbContext.SaveChanges();
            }
        }
        public void CreateIncident(IncidentBeingAnalyzed incident)
        {
            if (incident == null)
            {
                throw new ArgumentNullException("incident");
            }
            if (string.IsNullOrEmpty(incident.ReportHashCode))
            {
                throw new InvalidOperationException("ReportHashCode is required to be able to detect duplicates");
            }

            using (var cmd = _unitOfWork.CreateCommand())
            {
                cmd.CommandText =
                    "INSERT INTO Incidents (ReportHashCode, ApplicationId, CreatedAtUtc, HashCodeIdentifier, StackTrace, ReportCount, UpdatedAtUtc, Description, FullName, IsReOpened, LastReportAtUtc)" +
                    " VALUES (@ReportHashCode, @ApplicationId, @CreatedAtUtc, @HashCodeIdentifier, @StackTrace, @ReportCount, @UpdatedAtUtc, @Description, @FullName, 0, @LastReportAtUtc);select SCOPE_IDENTITY();";
                cmd.AddParameter("Id", incident.Id);
                cmd.AddParameter("ReportHashCode", incident.ReportHashCode);
                cmd.AddParameter("ApplicationId", incident.ApplicationId);
                cmd.AddParameter("CreatedAtUtc", incident.CreatedAtUtc);
                cmd.AddParameter("HashCodeIdentifier", incident.HashCodeIdentifier);
                cmd.AddParameter("ReportCount", incident.ReportCount);
                cmd.AddParameter("UpdatedAtUtc", incident.UpdatedAtUtc);
                cmd.AddParameter("Description", incident.Description);
                cmd.AddParameter("StackTrace", incident.StackTrace);
                cmd.AddParameter("FullName", incident.FullName);
                cmd.AddParameter("LastReportAtUtc", incident.LastReportAtUtc);
                var id = (int)(decimal)cmd.ExecuteScalar();
                incident.GetType()
                .GetProperty("Id", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance)
                .SetValue(incident, id);
            }
            //_unitOfWork.Insert(incident);
        }
Beispiel #3
0
        /// <summary>
        ///     Creates an incident and a report.
        /// </summary>
        public void CreateReportAndIncident(out int reportId, out int incidentId)
        {
            using (var uow = CreateUnitOfWork())
            {
                CreateUserAndApplication(uow, out var accountId, out var applicationId);

                var report = new ErrorReportEntity(applicationId, Guid.NewGuid().ToString("N"), DateTime.UtcNow,
                                                   new ErrorReportException(new Exception("mofo")),
                                                   new List <ErrorReportContext>
                {
                    new ErrorReportContext("Maps", new Dictionary <string, string>())
                })
                {
                    Title = "Missing here"
                };
                report.Init(report.GenerateHashCodeIdentifier());

                var incident = new IncidentBeingAnalyzed(report);
                var incRepos = new AnalyticsRepository(new AnalysisDbContext(uow), ConfigStore);
                incRepos.CreateIncident(incident);
                incidentId = incident.Id;

                report.IncidentId = incident.Id;
                incRepos.CreateReport(report);
                reportId = report.Id;

                uow.SaveChanges();
            }
        }
 public void UpdateIncident(IncidentBeingAnalyzed incident)
 {
     if (incident == null)
     {
         throw new ArgumentNullException("incident");
     }
     _unitOfWork.Update(incident);
 }
        private IncidentBeingAnalyzed BuildIncident(ErrorReportEntity entity)
        {
            if (entity.Exception == null)
            {
                return(new IncidentBeingAnalyzed(entity));
            }

            if (entity.Exception.Name == "AggregateException")
            {
                try
                {
                    var exception = entity.Exception;

                    //TODO: Check if there are more than one InnerExceptions and then abort this specialization.
                    while (exception != null && exception.Name == "AggregateException")
                    {
                        exception = exception.InnerException;
                    }

                    var incident = new IncidentBeingAnalyzed(entity, exception);
                    return(incident);
                }
                catch (Exception)
                {
                }
            }

            if (entity.Exception.Name == "ReflectionTypeLoadException")
            {
                try
                {
                    var item      = JObject.Parse(entity.Exception.Everything);
                    var i         = new IncidentBeingAnalyzed(entity);
                    var items     = (JObject)item["LoaderExceptions"];
                    var exception = items.First;


                    //var incident = new Incident(entity, exception);
                    //incident.AddIncidentTags(new[] { "ReflectionTypeLoadException" });
                    //return incident;

                    //TODO: load LoaderExceptions which is an Exception[] array
                }
                catch (Exception)
                {
                }
            }

            return(new IncidentBeingAnalyzed(entity));
        }
        public void Should_load_ignored_state_into_class_correctly()
        {
            var report = new ErrorReportEntity(FirstApplicationId, Guid.NewGuid().ToString("N"), DateTime.UtcNow,
                                               new ErrorReportException(new Exception("mofo")),
                                               new List <ErrorReportContext> {
                new ErrorReportContext("Maps", new Dictionary <string, string>())
            })
            {
                Title = "Missing here"
            };

            report.Init(report.GenerateHashCodeIdentifier());

            using (var uow = new AnalysisDbContext(CreateUnitOfWork()))
            {
                var incident = new IncidentBeingAnalyzed(report);
                var incRepos = new AnalyticsRepository(uow, new TestConfigStore());
                incRepos.CreateIncident(incident);
                report.IncidentId = incident.Id;
                incRepos.CreateReport(report);
            }
        }
Beispiel #7
0
        /// <summary>
        ///     Analyze report
        /// </summary>
        /// <param name="report">report</param>
        /// <exception cref="ArgumentNullException">report</exception>
        public async Task Analyze(IMessageContext context, ErrorReportEntity report)
        {
            if (report == null)
            {
                throw new ArgumentNullException(nameof(report));
            }

            var countThisMonth = _repository.GetMonthReportCount();

            if (countThisMonth >= 500)
            {
                _repository.AddMissedReport(DateTime.Today);
                return;
            }

            _logger.Debug("Running as " + context.Principal.ToFriendlyString());
            var exists = _repository.ExistsByClientId(report.ClientReportId);

            if (exists)
            {
                _logger.Warn($"Report have already been uploaded: {report.ClientReportId} for {report.RemoteAddress}.");
                return;
            }

            ErrorHashCode hashcodeResult;

            try
            {
                hashcodeResult = _hashCodeGenerator.GenerateHashCode(report);
                report.Init(hashcodeResult.HashCode);
            }
            catch (Exception ex)
            {
                var reportJson = JsonConvert.SerializeObject(report);
                if (reportJson.Length > 1000000)
                {
                    reportJson = reportJson.Substring(0, 100000) + "[....]";
                }
                _logger.Fatal($"Failed to init report {reportJson}", ex);
                return;
            }

            var storeReport        = true;
            var applicationVersion = GetVersionFromReport(report);
            var isReOpened         = false;

            IncidentBeingAnalyzed incident = null;

            if (hashcodeResult.CompabilityHashSource != null)
            {
                incident = _repository.FindIncidentForReport(report.ApplicationId, hashcodeResult.CompabilityHashSource, hashcodeResult.CollisionIdentifier);
                if (incident != null)
                {
                    report.Init(hashcodeResult.CompabilityHashSource);
                }
            }
            if (incident == null)
            {
                incident = _repository.FindIncidentForReport(report.ApplicationId, report.ReportHashCode, hashcodeResult.CollisionIdentifier);
            }

            var isNewIncident = false;

            if (incident == null)
            {
                if (report.Exception == null)
                {
                    _logger.Debug("Got no exception");
                }

                isNewIncident = true;
                incident      = BuildIncident(report);
                _repository.CreateIncident(incident);
                await _repository.StoreReportStats(new ReportMapping()
                {
                    IncidentId    = incident.Id,
                    ErrorId       = report.ClientReportId,
                    ReceivedAtUtc = report.CreatedAtUtc
                });

                var evt = new IncidentCreated(incident.ApplicationId,
                                              incident.Id, incident.Description, incident.FullName)
                {
                    CreatedAtUtc       = incident.CreatedAtUtc,
                    ApplicationVersion = applicationVersion,
                };
                _logger.Info($"Storing IncidentCreated with {context.Principal.ToFriendlyString()}: {JsonConvert.SerializeObject(evt)}");
                await _domainQueue.PublishAsync(context.Principal, evt);

                await context.SendAsync(evt);
            }
            else
            {
                if (incident.IsIgnored)
                {
                    _logger.Info("Incident is ignored: " + JsonConvert.SerializeObject(report));
                    incident.WasJustIgnored();
                    _repository.UpdateIncident(incident);
                    return;
                }

                // Do this before checking closed
                // as we want to see if it still gets reports.
                var stat = new ReportMapping()
                {
                    IncidentId    = incident.Id,
                    ErrorId       = report.ClientReportId,
                    ReceivedAtUtc = report.CreatedAtUtc
                };
                await _repository.StoreReportStats(stat);

                _logger.Debug("Storing stats " + JsonConvert.SerializeObject(stat));

                if (incident.IsClosed)
                {
                    if (applicationVersion != null && incident.IsReportIgnored(applicationVersion))
                    {
                        _logger.Info("Ignored report since it's for a version less that the solution version: " + JsonConvert.SerializeObject(report));
                        incident.WasJustIgnored();
                        _repository.UpdateIncident(incident);
                        return;
                    }

                    isReOpened = true;
                    incident.ReOpen();
                    var evt = new IncidentReOpened(incident.ApplicationId, incident.Id,
                                                   incident.CreatedAtUtc)
                    {
                        ApplicationVersion = applicationVersion
                    };
                    await context.SendAsync(evt);

                    await _domainQueue.PublishAsync(context.Principal, evt);
                }

                incident.AddReport(report);

                // Let's continue to receive reports once a day when
                // limit is reached (to get more fresh data, and still not load the system unnecessary).
                var timesSinceLastReport = DateTime.UtcNow.Subtract(incident.LastStoredReportUtc);
                if (incident.ReportCount > _reportConfig.Value.MaxReportsPerIncident &&
                    timesSinceLastReport < TimeSpan.FromMinutes(10))
                {
                    _repository.UpdateIncident(incident);
                    _logger.Debug($"Report count is more than {_reportConfig.Value.MaxReportsPerIncident}. Ignoring reports for incident {incident.Id}. Minutes since last report: " + timesSinceLastReport.TotalMinutes);
                    storeReport = false;
                    //don't exit here, since we want to be able to process reports
                }
            }

            if (!string.IsNullOrWhiteSpace(report.EnvironmentName))
            {
                _repository.SaveEnvironmentName(incident.Id, report.EnvironmentName);
            }

            report.IncidentId = incident.Id;

            if (storeReport)
            {
                incident.LastStoredReportUtc = DateTime.UtcNow;
                _repository.UpdateIncident(incident);
                _repository.CreateReport(report);
                _logger.Debug($"saving report {report.Id} for incident {incident.Id}");
            }

            var appName = _repository.GetAppName(incident.ApplicationId);
            var summary = new IncidentSummaryDTO(incident.Id, incident.Description)
            {
                ApplicationId   = incident.ApplicationId,
                ApplicationName = appName,
                CreatedAtUtc    = incident.CreatedAtUtc,
                LastUpdateAtUtc = incident.UpdatedAtUtc,
                IsReOpened      = incident.IsReOpened,
                Name            = incident.Description,
                ReportCount     = incident.ReportCount
            };
            var sw = new Stopwatch();

            sw.Start();
            var e = new ReportAddedToIncident(summary, ConvertToCoreReport(report, applicationVersion), isReOpened)
            {
                IsNewIncident   = isNewIncident,
                IsStored        = storeReport,
                EnvironmentName = report.EnvironmentName
            };
            await context.SendAsync(e);

            if (storeReport)
            {
                await context.SendAsync(new ProcessInboundContextCollections());
            }

            if (sw.ElapsedMilliseconds > 200)
            {
                _logger.Debug($"PublishAsync took {sw.ElapsedMilliseconds}");
            }
            sw.Stop();
        }