Пример #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();
            }
        }
Пример #2
0
        /// <summary>
        ///     Execute on a set of report mastery.
        /// </summary>
        /// <returns><c>false</c> if there are no more reports to analyze.</returns>
        public bool Execute()
        {
            using (var transaction = _queue.BeginTransaction())
            {
                var dto = _queue.TryReceive <ReceivedReportDTO>(transaction, TimeSpan.FromMilliseconds(500));
                if (dto == null)
                {
                    return(false);
                }

                try
                {
                    ErrorReportException ex = null;
                    if (dto.Exception != null)
                    {
                        ex = ConvertException(dto.Exception);
                    }
                    var contexts = dto.ContextCollections.Select(ConvertContext).ToArray();
                    var entity   = new ErrorReportEntity(dto.ApplicationId, dto.ReportId, dto.CreatedAtUtc, ex, contexts)
                    {
                        RemoteAddress = dto.RemoteAddress
                    };
                    _analyzer.Analyze(entity);
                }
                catch (Exception ex)
                {
                    _logger.Error("Failed to analyze report ", ex);
                }

                transaction.Commit();
            }
            return(true);
        }
Пример #3
0
        /// <summary>
        ///     Generate a new hash code
        /// </summary>
        /// <param name="entity">entity</param>
        /// <returns>hashcode</returns>
        /// <exception cref="ArgumentNullException">entity</exception>
        public string GenerateHashCode(ErrorReportEntity entity)
        {
            string requestUrl = null;
            var    httpCode   = 0;

            foreach (var collection in entity.ContextCollections)
            {
                if (collection.Properties.TryGetValue("HttpCode", out var value))
                {
                    int.TryParse(value, out httpCode);
                }

                if (!collection.Properties.TryGetValue("RequestUrl", out requestUrl))
                {
                    collection.Properties.TryGetValue("Url", out requestUrl);
                }
            }

            if (httpCode == 0 || string.IsNullOrWhiteSpace(requestUrl))
            {
                return(null);
            }

            var pos = requestUrl.IndexOf("?");

            if (pos != -1)
            {
                requestUrl = requestUrl.Remove(pos);
            }

            return(HashCodeUtility.GetPersistentHashCode(httpCode + "-" + requestUrl).ToString("X"));
        }
        /// <summary>
        ///     Creates a new instance of <see cref="IncidentBeingAnalyzed" />.
        /// </summary>
        /// <param name="entity">entity</param>
        /// <param name="exception">exception to analyze</param>
        /// <exception cref="ArgumentNullException">entity; exception</exception>
        /// <exception cref="ArgumentException">entity.hashcode is null</exception>
        public IncidentBeingAnalyzed(ErrorReportEntity entity, ErrorReportException exception)
        {
            if (entity == null)
            {
                throw new ArgumentNullException("entity");
            }
            if (exception == null)
            {
                throw new ArgumentNullException("exception");
            }
            if (string.IsNullOrEmpty(entity.ReportHashCode))
            {
                throw new ArgumentException("ReportHashCode must be specified to be able to identify duplicates.");
            }

            Description = exception.Message;
            FullName    = exception.FullName;
            StackTrace  = HashCodeGenerator.CleanStackTrace(exception.StackTrace);

            AddReport(entity);
            ReportHashCode     = entity.ReportHashCode;
            HashCodeIdentifier = entity.GenerateHashCodeIdentifier();
            ApplicationId      = entity.ApplicationId;
            UpdatedAtUtc       = entity.CreatedAtUtc;
            CreatedAtUtc       = entity.CreatedAtUtc;
        }
Пример #5
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();
            }
        }
Пример #6
0
        public void Should_remove_AT_from_stacktrace_to_avoid_multi_language_issues()
        {
            var exceptionWithAt = new ErrorReportException()
            {
                StackTrace =
                    @"at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
   at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose)
   at System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady)
   at System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString)
   at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async, Int32 timeout, Task& task, Boolean asyncWrite, SqlDataReader ds)
   at System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(TaskCompletionSource`1 completion, Boolean sendToPipe, Int32 timeout, Boolean asyncWrite, String methodName)
   at System.Data.SqlClient.SqlCommand.ExecuteNonQuery()
   at Coderr.Server.Infrastructure.Configuration.Database.DatabaseStore.Store(IConfigurationSection section)
   at Coderr.Server.Premise.App.LicenseWrapper.IncreaseReportCount()
   at Coderr.Server.Web.Controllers.ReportReceiverController.PremiseLicenseCheck()
   at Coderr.Server.Web.Controllers.ReportReceiverController.Post(String appKey, String sig)
   at Microsoft.AspNetCore.Mvc.Internal.ActionMethodExecutor.TaskOfIActionResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
   at System.Threading.Tasks.ValueTask`1.get_Result()
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeActionMethodAsync():55
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeNextActionFilterAsync()
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Rethrow(ActionExecutedContext context)
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeInnerFilterAsync()
   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeNextExceptionFilterAsync():33"
            };
            var entityWithAt       = new ErrorReportEntity(1, "flldfd", DateTime.UtcNow, exceptionWithAt, new ErrorReportContextCollection[0]);
            var exceptionWithoutAt = new ErrorReportException()
            {
                StackTrace =
                    @"System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
   System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose)
   System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady)
   System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString)
   System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async, Int32 timeout, Task& task, Boolean asyncWrite, SqlDataReader ds)
   System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(TaskCompletionSource`1 completion, Boolean sendToPipe, Int32 timeout, Boolean asyncWrite, String methodName)
   System.Data.SqlClient.SqlCommand.ExecuteNonQuery()
   Coderr.Server.Infrastructure.Configuration.Database.DatabaseStore.Store(IConfigurationSection section)
   Coderr.Server.Premise.App.LicenseWrapper.IncreaseReportCount()
   Coderr.Server.Web.Controllers.ReportReceiverController.PremiseLicenseCheck()
   Coderr.Server.Web.Controllers.ReportReceiverController.Post(String appKey, String sig)
   Microsoft.AspNetCore.Mvc.Internal.ActionMethodExecutor.TaskOfIActionResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
   System.Threading.Tasks.ValueTask`1.get_Result()
   Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeActionMethodAsync():55
   Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeNextActionFilterAsync()
   Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Rethrow(ActionExecutedContext context)
   Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeInnerFilterAsync()
   Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeNextExceptionFilterAsync():33"
            };
            var entityWithoutAt = new ErrorReportEntity(1, "flldfd", DateTime.UtcNow, exceptionWithoutAt, new ErrorReportContextCollection[0]);
            var sut             = new HashCodeGenerator(new IHashCodeSubGenerator[0]);

            var result1 = sut.GenerateHashCode(entityWithAt);
            var result2 = sut.GenerateHashCode(entityWithAt);

            result1.HashCode.Should().Be(result2.HashCode);
        }
Пример #7
0
        /// <summary>
        ///     Method that will be invoked if no implementations of <see cref="IHashCodeSubGenerator" /> generates an hash code.
        /// </summary>
        /// <param name="report">received report</param>
        /// <returns>hash code</returns>
        /// <exception cref="ArgumentNullException">report</exception>
        protected virtual ErrorHashCode DefaultCreateHashCode(ErrorReportEntity report)
        {
            if (report == null)
            {
                throw new ArgumentNullException("report");
            }


            var hashSource      = $"{report.Exception.FullName ?? report.Exception.Name}\r\n";
            var foundHashSource = false;

            // the client libraries can by themselves specify how we should identify
            // unique incidents. We then use that identifier in combination with the exception name.
            var collection = report.ContextCollections.FirstOrDefault(x => x.Name == "CoderrData");

            if (collection != null)
            {
                if (collection.Properties.TryGetValue("HashSource", out var reportHashSource))
                {
                    foundHashSource = true;
                    hashSource     += reportHashSource;
                }
            }
            if (!foundHashSource)
            {
                // This identifier is determined by the developer when  the error is generated.
                foreach (var contextCollection in report.ContextCollections)
                {
                    if (!contextCollection.Properties.TryGetValue("ErrorHashSource", out var ourHashSource))
                    {
                        continue;
                    }

                    hashSource      = ourHashSource;
                    foundHashSource = true;
                    break;
                }
            }

            var hashSourceForCompability = "";

            if (!foundHashSource)
            {
                hashSourceForCompability = hashSource + CleanStackTrace(report.Exception.StackTrace ?? "");
                hashSource += CleanStackTrace(report.Exception.StackTrace ?? "");
            }

            var hash = HashTheSource(hashSource);

            return(new ErrorHashCode
            {
                CollisionIdentifier = report.GenerateHashCodeIdentifier(),
                HashCode = hash.ToString("X"),
                CompabilityHashSource = hashSourceForCompability == "" ? null : HashTheSource(hashSourceForCompability).ToString("X")
            });
        }
Пример #8
0
        /// <summary>
        ///     Generate a new hash code
        /// </summary>
        /// <param name="entity">entity</param>
        /// <returns>hashcode</returns>
        /// <exception cref="ArgumentNullException">entity</exception>
        public ErrorHashCode GenerateHashCode(ErrorReportEntity entity)
        {
            string requestUrl = null;
            var    httpCode   = 0;

            foreach (var collection in entity.ContextCollections)
            {
                if (collection.Properties.TryGetValue("HttpCode", out var value))
                {
                    int.TryParse(value, out httpCode);

                    // Server side errors are typically handled by other handlers.
                    if (httpCode == 500)
                    {
                        return(null);
                    }
                }

                if (!collection.Properties.TryGetValue("RequestUrl", out requestUrl))
                {
                    collection.Properties.TryGetValue("Url", out requestUrl);
                }
            }

            if (httpCode == 0 || string.IsNullOrWhiteSpace(requestUrl))
            {
                return(null);
            }

            // Since this is for a specific application, remove host to make sure that errors
            // for different environments/servers are treated as the same error.


            // Remove host or correct uris
            if (requestUrl.Contains("://"))
            {
                var pos2 = requestUrl.IndexOf("//");
                pos2       = requestUrl.IndexOf("/", pos2 + 2);
                requestUrl = requestUrl.Remove(0, pos2);
            }

            // and query string
            var pos = requestUrl.IndexOf("?");

            if (pos != -1)
            {
                requestUrl = requestUrl.Remove(pos);
            }

            return(new ErrorHashCode
            {
                HashCode = HashCodeUtility.GetPersistentHashCode($"{httpCode};{requestUrl}").ToString("X"),
                CollisionIdentifier = $"{httpCode};{requestUrl}"
            });
        }
        private string GetVersionFromReport(ErrorReportEntity report)
        {
            foreach (var contextCollection in report.ContextCollections)
            {
                if (contextCollection.Properties.TryGetValue(AppAssemblyVersion, out var version))
                {
                    return(version);
                }
            }

            return(null);
        }
Пример #10
0
        public void CreateReport(ErrorReportEntity report)
        {
            if (report == null)
            {
                throw new ArgumentNullException(nameof(report));
            }

            if (string.IsNullOrEmpty(report.Title) && report.Exception != null)
            {
                report.Title = report.Exception.Message;
                if (report.Title == null)
                {
                    report.Title = "[Exception message was not specified]";
                }
                else if (report.Title.Length > 100)
                {
                    report.Title = report.Title.Substring(0, 100);
                }
            }

            var collections = new List <string>();

            foreach (var context in report.ContextCollections)
            {
                var data = EntitySerializer.Serialize(context);
                if (data.Length > MaxCollectionSize)
                {
                    var tooLargeCtx = new ErrorReportContextCollection(context.Name,
                                                                       new Dictionary <string, string>()
                    {
                        {
                            "Error",
                            $"This collection was larger ({data.Length}bytes) than the threshold of {MaxCollectionSize}bytes"
                        }
                    });

                    data = EntitySerializer.Serialize(tooLargeCtx);
                }
                collections.Add(data);
            }

            _unitOfWork.Insert(report);

            var cols     = string.Join(", ", collections);
            var inboound = new InboundCollection
            {
                JsonData = $"[{cols}]",
                ReportId = report.Id
            };

            _unitOfWork.Insert(inboound);
        }
Пример #11
0
        /// <summary>
        ///     Method that will be invoked if no implementations of <see cref="IHashCodeSubGenerator" /> generates an hash code.
        /// </summary>
        /// <param name="report">received report</param>
        /// <returns>hash code</returns>
        /// <exception cref="ArgumentNullException">report</exception>
        protected virtual string DefaultCreateHashCode(ErrorReportEntity report)
        {
            if (report == null)
            {
                throw new ArgumentNullException("report");
            }


            var hashSource      = $"{report.Exception.FullName ?? report.Exception.Name}\r\n";
            var foundHashSource = false;

            // the client libraries can by themselves specify how we should identify
            // unqiue incidents. We then use that identifier in combination with the exception name.
            var collection = report.ContextCollections.FirstOrDefault(x => x.Name == "CoderrData");

            if (collection != null)
            {
                if (collection.Properties.TryGetValue("HashSource", out var reportHashSource))
                {
                    foundHashSource = true;
                    hashSource     += reportHashSource;
                }
                else
                {
                    hashSource += StripLineNumbers(report.Exception.StackTrace ?? "");
                }
            }
            if (!foundHashSource)
            {
                // This identifier is determined by the developer when  the error is generated.
                foreach (var contextCollection in report.ContextCollections)
                {
                    if (!contextCollection.Properties.TryGetValue("ErrorHashSource", out var ourHashSource))
                    {
                        continue;
                    }

                    hashSource = ourHashSource;
                    break;
                }
            }


            var hash = 23;

            foreach (var c in hashSource)
            {
                hash = hash * 31 + c;
            }
            return(hash.ToString("X"));
        }
Пример #12
0
        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));
        }
Пример #13
0
        /// <summary>
        ///     Convert received report to our internal format
        /// </summary>
        /// <param name="report">client report</param>
        /// <param name="applicationId">application that we identified that the report belongs to</param>
        /// <returns>internal format</returns>
        public ErrorReportEntity ConvertReport(ReceivedReportDTO report, int applicationId)
        {
            ErrorReportException ex = null;

            if (report.Exception != null)
            {
                ex = ConvertException(report.Exception);
            }

            //var id = _idGeneratorClient.GetNextId(ErrorReportEntity.SEQUENCE);
            var contexts = report.ContextCollections.Select(x => new ErrorReportContext(x.Name, x.Properties)).ToArray();
            var dto      = new ErrorReportEntity(applicationId, report.ReportId, report.CreatedAtUtc, ex, contexts);

            return(dto);
        }
Пример #14
0
        public static string FindCollectionProperty(this ErrorReportEntity instance, string collectionName, string propertyName)
        {
            var collection = instance.FindCollection(collectionName);

            if (collection == null)
            {
                return(null);
            }

            if (collection.Properties.TryGetValue(propertyName, out var value))
            {
                return(value);
            }
            else
            {
                return(null);
            }
        }
Пример #15
0
        public void CreateReport(ErrorReportEntity report)
        {
            if (report == null)
            {
                throw new ArgumentNullException("report");
            }

            if (string.IsNullOrEmpty(report.Title) && report.Exception != null)
            {
                report.Title = report.Exception.Message;
                if (report.Title.Length > 100)
                {
                    report.Title = report.Title.Substring(0, 100);
                }
            }


            _unitOfWork.Insert(report);
        }
        public void Should_generate_from_relative_uri()
        {
            var report = new ErrorReportEntity(1, "kffk", DateTime.UtcNow, new ErrorReportException(), new[]
            {
                new ErrorReportContextCollection("Yadayada",
                                                 new Dictionary <string, string>
                {
                    { "Url", "/some/path?hada=yada" },
                    { "HttpCode", "404" }
                })
            });

            var sut  = new HttpErrorGenerator();
            var code = sut.GenerateHashCode(report);

            var source = $"404;/some/path";

            code.HashCode.Should().Be(HashCodeUtility.GetPersistentHashCode(source).ToString("X"));
        }
        /// <summary>
        ///     Generate a new hash code
        /// </summary>
        /// <param name="entity">entity</param>
        /// <returns>hashcode</returns>
        /// <exception cref="ArgumentNullException">entity</exception>
        public ErrorHashCode GenerateHashCode(ErrorReportEntity entity)
        {
            string requestUrl = null;
            var    httpCode   = 0;

            foreach (var collection in entity.ContextCollections)
            {
                if (collection.Properties.TryGetValue("HttpCode", out var value))
                {
                    int.TryParse(value, out httpCode);

                    // Server side errors are typically handled by other handlers.
                    if (httpCode == 500)
                    {
                        return(null);
                    }
                }

                if (!collection.Properties.TryGetValue("RequestUrl", out requestUrl))
                {
                    collection.Properties.TryGetValue("Url", out requestUrl);
                }
            }

            if (httpCode == 0 || string.IsNullOrWhiteSpace(requestUrl))
            {
                return(null);
            }

            var pos = requestUrl.IndexOf("?");

            if (pos != -1)
            {
                requestUrl = requestUrl.Remove(pos);
            }

            return(new ErrorHashCode
            {
                HashCode = HashCodeUtility.GetPersistentHashCode($"{httpCode}-{requestUrl}").ToString("X"),
                CollisionIdentifier = $"{httpCode}-{requestUrl}"
            });
        }
        /// <summary>
        ///     Add another report.
        /// </summary>
        /// <param name="entity">entity</param>
        /// <exception cref="ArgumentNullException">entity</exception>
        public void AddReport(ErrorReportEntity entity)
        {
            if (entity == null)
            {
                throw new ArgumentNullException("entity");
            }

            if (string.IsNullOrWhiteSpace(StackTrace) && entity.Exception != null)
            {
                Description = entity.Exception.Message;
                FullName    = entity.Exception.FullName;
                StackTrace  = entity.Exception.StackTrace;
            }
            if (UpdatedAtUtc < entity.CreatedAtUtc)
            {
                UpdatedAtUtc = entity.CreatedAtUtc;
            }

            ReportCount++;
        }
Пример #19
0
        public void CreateUserAndApp()
        {
            using (var uow = CreateUnitOfWork())
            {
                var accountRepos = new AccountRepository(uow);
                var account      = new Account("arne", "123456")
                {
                    Email = "*****@*****.**"
                };
                accountRepos.Create(account);
                var userRepos = new UserRepository(uow);
                var user      = new User(account.Id, "arne")
                {
                    EmailAddress = "*****@*****.**"
                };
                userRepos.CreateAsync(user).GetAwaiter().GetResult();

                var appRepos = new ApplicationRepository(uow);
                var app      = new Application(account.Id, "MinApp");
                appRepos.CreateAsync(app).GetAwaiter().GetResult();
                var member = new ApplicationTeamMember(app.Id, account.Id, "Admin");
                appRepos.CreateAsync(member).GetAwaiter().GetResult();


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

                var incident = new ReportAnalyzer.Domain.Incidents.IncidentBeingAnalyzed(report);
                var incRepos = new AnalyticsRepository(new AnalysisDbContext(uow), ConfigStore);
                incRepos.CreateIncident(incident);
                report.IncidentId = incident.Id;
                incRepos.CreateReport(report);

                uow.SaveChanges();
            }
        }
Пример #20
0
        private ReportDTO ConvertToCoreReport(ErrorReportEntity report)
        {
            var dto = new ReportDTO
            {
                ApplicationId      = report.ApplicationId,
                ContextCollections =
                    report.ContextInfo.Select(x => new ContextCollectionDTO(x.Name, x.Properties)).ToArray(),
                CreatedAtUtc  = report.CreatedAtUtc,
                Id            = report.Id,
                IncidentId    = report.IncidentId,
                RemoteAddress = report.RemoteAddress,
                ReportId      = report.ClientReportId,
                ReportVersion = "1"
            };

            if (report.Exception != null)
            {
                dto.Exception = ConvertToCoreException(report.Exception);
            }
            return(dto);
        }
        /// <summary>
        ///     Generate a new hash code
        /// </summary>
        /// <param name="entity">entity</param>
        /// <returns>hash code</returns>
        /// <exception cref="ArgumentNullException">entity</exception>
        public ErrorHashCode GenerateHashCode(ErrorReportEntity entity)
        {
            if (entity == null)
            {
                throw new ArgumentNullException("entity");
            }
            foreach (var generator in _generators)
            {
                if (generator.CanGenerateFrom(entity))
                {
                    // forgiving ones so that we can get the report and process it with a default hash code instead.
                    var code = generator.GenerateHashCode(entity);
                    if (code != null)
                    {
                        return(code);
                    }
                }
            }

            return(DefaultCreateHashCode(entity));
        }
        public void should_match_line_numbers_and_without_line_numbers_to_reduce_the_number_of_incidents()
        {
            var ex1 = new ErrorReportException {
                StackTrace = @"at System.Web.Compilation.AssemblyBuilder.Compile():line 64
at System.Web.Compilation.BuildProvidersCompiler.PerformBuild():line 65
at System.Web.Compilation.BuildManager.CompileWebFile(VirtualPath virtualPath):line 67"
            };
            var ex2 = new ErrorReportException
            {
                StackTrace = @"at System.Web.Compilation.AssemblyBuilder.Compile()
at System.Web.Compilation.BuildProvidersCompiler.PerformBuild()
at System.Web.Compilation.BuildManager.CompileWebFile(VirtualPath virtualPath)"
            };
            var report1 = new ErrorReportEntity(1, "fjkkfjjkf", DateTime.UtcNow, ex1, new List <ErrorReportContextCollection>());
            var report2 = new ErrorReportEntity(1, "fjkkfjjkf", DateTime.UtcNow, ex2, new List <ErrorReportContextCollection>());

            var sut     = new HashCodeGenerator(new IHashCodeSubGenerator[0]);
            var actual1 = sut.GenerateHashCode(report1);
            var actual2 = sut.GenerateHashCode(report2);

            actual1.Should().Be(actual2);
        }
        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);
            }
        }
Пример #24
0
 public async Task HandleAsync(IMessageContext context, ProcessReport message)
 {
     try
     {
         ErrorReportException ex = null;
         if (message.Exception != null)
         {
             ex = ConvertException(message.Exception);
         }
         var contexts = message.ContextCollections.Select(ConvertContext).ToArray();
         var entity   = new ErrorReportEntity(message.ApplicationId, message.ReportId, message.CreatedAtUtc, ex,
                                              contexts)
         {
             RemoteAddress = message.RemoteAddress
         };
         await _analyzer.Analyze(context, entity);
     }
     catch (Exception ex)
     {
         _logger.Error("Failed to analyze report ", ex);
     }
 }
        public void should_strip_line_numbers_to_reduce_the_number_of_incidents()
        {
            var locator = Substitute.For <IServiceLocator>();
            var ex1     = new ErrorReportException {
                StackTrace = @"   at System.Web.Compilation.AssemblyBuilder.Compile():line 64
at System.Web.Compilation.BuildProvidersCompiler.PerformBuild():line 65
at System.Web.Compilation.BuildManager.CompileWebFile(VirtualPath virtualPath):line 67"
            };
            var ex2 = new ErrorReportException
            {
                StackTrace = @"   at System.Web.Compilation.AssemblyBuilder.Compile():line 12
at System.Web.Compilation.BuildProvidersCompiler.PerformBuild():line 23
at System.Web.Compilation.BuildManager.CompileWebFile(VirtualPath virtualPath):line 53"
            };
            var report1 = new ErrorReportEntity(1, "fjkkfjjkf", DateTime.UtcNow, ex1, new List <ErrorReportContext>());
            var report2 = new ErrorReportEntity(1, "fjkkfjjkf", DateTime.UtcNow, ex2, new List <ErrorReportContext>());

            var sut     = new HashCodeGenerator(locator);
            var actual1 = sut.GenerateHashCode(report1);
            var actual2 = sut.GenerateHashCode(report2);

            actual1.Should().Be(actual2);
        }
        /// <summary>
        ///     Generate a new hash code
        /// </summary>
        /// <param name="entity">entity</param>
        /// <returns>hashcode</returns>
        /// <exception cref="ArgumentNullException">entity</exception>
        public string GenerateHashCode(ErrorReportEntity entity)
        {
            var props = entity.ContextInfo.FirstOrDefault(x => x.Name == "ExceptionProperties")
                        ?? entity.ContextInfo.FirstOrDefault(x => x.Name == "Properties");

            if (props == null)
            {
                _logger.Error("Failed to find ExceptionProperties collection for entity " + entity.Id);
                return(null);
            }

            string value;

            if (!props.Properties.TryGetValue("HttpCode", out value))
            {
                return(null);
            }
            var statusCode = int.Parse(value);

            var headerProps = entity.ContextInfo.FirstOrDefault(x => x.Name == "HttpHeaders");

            if (headerProps == null)
            {
                _logger.Error("Failed to find HttpHeaders collection for entity " + entity.Id);
                return(null);
            }

            var url = headerProps.Properties["Url"].ToLower();
            var pos = url.IndexOf("?");

            if (pos != -1)
            {
                url = url.Remove(pos);
            }

            return(HashCodeUtility.GetPersistentHashCode(statusCode + "-" + url).ToString("X"));
        }
Пример #27
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();
        }
Пример #28
0
        /// <summary>
        ///     Analyze report
        /// </summary>
        /// <param name="report">report</param>
        /// <exception cref="ArgumentNullException">report</exception>
        public void Analyze(ErrorReportEntity report)
        {
            if (report == null)
            {
                throw new ArgumentNullException("report");
            }

            var exists = _repository.ExistsByClientId(report.ClientReportId);

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

            try
            {
                var hashCode = _hashCodeGenerator.GenerateHashCode(report);
                report.Init(hashCode);
            }
            catch (Exception ex)
            {
                _logger.Fatal("Failed to store report " + JsonConvert.SerializeObject(report), ex);
                return;
            }

            var isReOpened = false;
            var firstLine  = report.GenerateHashCodeIdentifier();
            var incident   = _repository.FindIncidentForReport(report.ApplicationId, report.ReportHashCode, firstLine);

            if (incident == null)
            {
                incident = BuildIncident(report);
                _repository.CreateIncident(incident);
            }
            else
            {
                if (incident.ReportCount > 10000)
                {
                    _logger.Debug("Reportcount is more than 10000. Ignoring report for incident " + incident.Id);
                    return;
                }

                if (incident.IsIgnored)
                {
                    _logger.Info("Incident is ignored: " + JsonConvert.SerializeObject(report));
                    incident.WasJustIgnored();
                    _repository.UpdateIncident(incident);
                    return;
                }
                if (incident.IsSolved)
                {
                    isReOpened = true;
                    incident.ReOpen();
                    _eventBus.PublishAsync(new IncidentReOpened(incident.ApplicationId, incident.Id,
                                                                incident.CreatedAtUtc));
                }

                incident.AddReport(report);
                _repository.UpdateIncident(incident);
            }

            report.IncidentId = incident.Id;
            _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();
            _logger.Debug("Publishing now: " + report.ClientReportId);
            var e = new ReportAddedToIncident(summary, ConvertToCoreReport(report), isReOpened);

            _eventBus.PublishAsync(e);
            if (sw.ElapsedMilliseconds > 200)
            {
                _logger.Debug("Publish took " + sw.ElapsedMilliseconds);
            }
            sw.Stop();
        }
 /// <summary>
 ///     Determines if this instance can generate a hashcode for the given entity.
 /// </summary>
 /// <param name="entity">entity to examine</param>
 /// <returns><c>true</c> for <c>HttpException</c>; otherwise <c>false</c>.</returns>
 /// <exception cref="ArgumentNullException">entity</exception>
 public bool CanGenerateFrom(ErrorReportEntity entity)
 {
     return(entity.Exception.Name == "HttpException" ||
            entity.Exception.BaseClasses.Any(x => x.EndsWith("HttpException")));
 }
Пример #30
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("report");
            }

            var countThisMonth = _repository.GetMonthReportCount();

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

            var exists = _repository.ExistsByClientId(report.ClientReportId);

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

            try
            {
                var hashCode = _hashCodeGenerator.GenerateHashCode(report);
                report.Init(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 applicationVersion = GetVersionFromReport(report);
            var isReOpened         = false;
            var firstLine          = report.GenerateHashCodeIdentifier();
            var incident           = _repository.FindIncidentForReport(report.ApplicationId, report.ReportHashCode, firstLine);

            if (incident == null)
            {
                incident = BuildIncident(report);
                _repository.CreateIncident(incident);

                var evt = new IncidentCreated(incident.ApplicationId,
                                              incident.Id, incident.Description, incident.FullName)
                {
                    CreatedAtUtc       = incident.CreatedAtUtc,
                    ApplicationVersion = applicationVersion,
                };

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

                await context.SendAsync(evt);
            }
            else
            {
                await _repository.StoreReportStats(new ReportMapping()
                {
                    IncidentId    = incident.Id,
                    ErrorId       = report.ClientReportId,
                    ReceivedAtUtc = report.CreatedAtUtc
                });

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

                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);
                _repository.UpdateIncident(incident);
                if (incident.ReportCount > 25)
                {
                    _logger.Debug("Report count is more than 25. Storing only report stats for incident " + incident.Id);
                    return;
                }
            }

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

            report.IncidentId = incident.Id;
            _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();
            _logger.Debug("Publishing now: " + report.ClientReportId);
            var e = new ReportAddedToIncident(summary, ConvertToCoreReport(report, applicationVersion), isReOpened);
            await context.SendAsync(e);

            await context.SendAsync(new ProcessInboundContextCollections());

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