/// <summary> /// Uploads all log entries that contains an exception to codeRR. /// </summary> /// <param name="loggingEvent">The logging event.</param> protected override void Append(LoggingEvent loggingEvent) { LogsProvider.Instance.Add(new LogEntryDto(loggingEvent.TimeStampUtc, ConvertLevel(loggingEvent.Level), loggingEvent.RenderedMessage) { Exception = loggingEvent.ExceptionObject?.ToString(), Source = loggingEvent.LoggerName, }); if (loggingEvent.ExceptionObject == null) { return; } IErrorReporterContext context = new ErrorReporterContext(this, loggingEvent.ExceptionObject); var dataCollection = new LogEntryDetails { LogLevel = loggingEvent.Level.ToString(), Message = loggingEvent.RenderedMessage, ThreadName = loggingEvent.ThreadName, Timestamp = loggingEvent.TimeStamp, LoggerName = loggingEvent.LoggerName, UserName = loggingEvent.UserName }.ToContextCollection("LogEntry"); context.ContextCollections.Add(dataCollection); var coderrCollection = context.ContextCollections.GetCoderrCollection(); coderrCollection.Properties[CoderrCollectionProperties.HighlightCollection] = "LogEntry"; Err.Report(context); }
/// <summary> /// Build an report, but do not upload it /// </summary> /// <param name="context"> /// context passed to all context providers when collecting information. This context is typically /// implemented by one of the integration libraries to provide more context that can be used to process the /// environment. /// </param> /// <remarks> /// <para> /// Will collect context info and generate a report. /// </para> /// </remarks> /// <exception cref="ArgumentNullException">exception;contextData</exception> public ErrorReportDTO Build(IErrorReporterContext context) { if (context == null) { throw new ArgumentNullException(nameof(context)); } if (context.Exception is CoderrClientException) { return(null); } if (IsReported(context.Exception)) { return(null); } ErrorReporterContext.MoveCollectionsInException(context.Exception, context.ContextCollections); InvokePreProcessor(context); _configuration.ContextProviders.Collect(context); // Invoke partition collection AFTER other context info providers // since those other collections might provide the property that // we want to create partions on. InvokePartitionCollection(context); var reportId = ReportIdGenerator.Generate(context.Exception); AddAddemblyVersion(context.ContextCollections); var report = new ErrorReportDTO(reportId, new ExceptionDTO(context.Exception), context.ContextCollections.ToArray()); return(report); }
public void should_assign_the_exception_so_that_we_have_something_to_work_with() { var ex = new Exception(); var sut = new ErrorReporterContext(this, ex); sut.Exception.Should().Be(ex); }
/// <summary> /// Build an report, but do not upload it /// </summary> /// <param name="exception">caught exception</param> /// <remarks> /// <para> /// Will collect context info and generate a report. /// </para> /// </remarks> public ErrorReportDTO Build(Exception exception) { var context = new ErrorReporterContext(null, exception); var contextInfo = _configuration.ContextProviders.Collect(context); var reportId = ReportIdGenerator.Generate(exception); return(new ErrorReportDTO(reportId, new ExceptionDTO(exception), contextInfo.ToArray())); }
public void should_initialize_the_colleciton_to_avoid_confusion_and_nullreference() { var ex = new Exception(); var sut = new ErrorReporterContext(this, ex); sut.ContextCollections.Should().BeEmpty(); }
public void Should_remove_old_entries() { _sut.Add(new LogEntryDto(DateTime.UtcNow.AddMinutes(-5).AddSeconds(-1), 3, "Hello")); var context = new ErrorReporterContext(this, new Exception()); _sut.Collect(context); context.LogEntries.Should().BeNull(); }
public void Should_ignore_incorrect_codeRRContext() { var context = new ErrorReporterContext(this, new Exception()); var sut = new FormProvider(); var result = sut.Collect(context); result.Should().BeNull(); }
/// <summary> /// Generate an error report /// </summary> /// <param name="context">context</param> /// <returns>generated report</returns> /// <exception cref="ArgumentNullException"></exception> public static ErrorReportDTO GenerateReport(IErrorReporterContext context) { if (context == null) { throw new ArgumentNullException("context"); } ErrorReporterContext.MoveCollectionsInException(context.Exception, context.ContextCollections); return(_exceptionProcessor.Build(context)); }
public void Should_add_existing_entry() { _sut.Add(new LogEntryDto(DateTime.UtcNow.AddMinutes(-3), 3, "Hello")); var context = new ErrorReporterContext(this, new Exception()); _sut.Collect(context); context.LogEntries[0].Message.Should().Be("Hello"); }
public void Should_ignore_invalid_json_in_collection_alternative() { var ex = new Exception(); ex.Data["ErrCollection.MyName2"] = "MEX"; var sut = new ErrorReporterContext(this, ex); var actual = sut.GetCollectionProperty("MyName2", "JSON"); actual.Should().Be("MEX"); }
public void should_Be_able_to_add_a_contextcollection() { var collector = Substitute.For <IContextCollectionProvider>(); var ctx = new ErrorReporterContext(this, new Exception("errror")); var sut = new ContextProvidersRegistrar(); sut.Add(collector); sut.Collect(ctx); collector.Received().Collect(ctx); }
public void should_not_use_removed_collectors() { var collector = Substitute.For <IContextCollectionProvider>(); var ctx = new ErrorReporterContext(this, new Exception("errror")); var sut = new ContextProvidersRegistrar(); sut.Add(collector); sut.Remove(collector.Name); sut.Collect(ctx); collector.DidNotReceiveWithAnyArgs().Collect(null); }
/// <summary> /// Report an exception using a custom context /// </summary> /// <param name="reporterContext">Context used to be able to collect context information</param> /// <param name="errorContextModel">Extra context collection(s).</param> public static void Report(IErrorReporterContext reporterContext, object errorContextModel) { if (reporterContext == null) { throw new ArgumentNullException(nameof(reporterContext)); } ErrorReporterContext.MoveCollectionsInException(reporterContext.Exception, reporterContext.ContextCollections); var collection = errorContextModel.ToContextCollection(); reporterContext.ContextCollections.Add(collection); _exceptionProcessor.Process(reporterContext); }
public void failing_collector_should_generate_a_collection_with_an_Error_to_be_Able_To_See_failures_serverSide() { var collector = Substitute.For <IContextCollectionProvider>(); var ctx = new ErrorReporterContext(this, new Exception("errror")); collector.When(x => x.Collect(ctx)).Do(x => throw new InvalidOperationException()); var sut = new ContextProvidersRegistrar(); sut.Add(collector); sut.Collect(ctx); ctx.ContextCollections.Last().Properties.Should().NotBeEmpty(); }
/// <summary> /// Process exception. /// </summary> /// <param name="exception">caught exception</param> /// <remarks> /// <para> /// Will collect context info, generate a report, go through filters and finally upload it. /// </para> /// </remarks> public void Process(Exception exception) { var context = new ErrorReporterContext(null, exception); var contextInfo = _configuration.ContextProviders.Collect(context); var reportId = ReportIdGenerator.Generate(exception); var report = new ErrorReportDTO(reportId, new ExceptionDTO(exception), contextInfo.ToArray()); var canUpload = _configuration.FilterCollection.CanUploadReport(report); if (!canUpload) { return; } _configuration.Uploaders.Upload(report); }
/// <summary> /// Build an report, but do not upload it /// </summary> /// <param name="exception">caught exception</param> /// <remarks> /// <para> /// Will collect context info and generate a report. /// </para> /// </remarks> /// <exception cref="ArgumentNullException">exception</exception> public ErrorReportDTO Build(Exception exception) { if (exception == null) { throw new ArgumentNullException(nameof(exception)); } if (IsReported(exception)) { return(null); } var context = new ErrorReporterContext(null, exception); return(Build(context)); }
public static string GetCollectionProperty(this ErrorReporterContext dto, string collectionName, string propertyName) { var col = dto.ContextCollections.FirstOrDefault(x => x.Name == collectionName); if (col != null) { return(col.Property(propertyName)); } var collectionNames = string.Join(",", dto.ContextCollections.Select(x => x.Name)); throw new AssertActualExpectedException(collectionName, null, $"Failed to find collection \'{collectionName}\', existing collections: {collectionNames}." ); }
public void Should_merge_with_existing_entries() { _sut.Add(new LogEntryDto(DateTime.UtcNow.AddMinutes(-3), 3, "Hello1")); _sut.Add(new LogEntryDto(DateTime.UtcNow.AddMinutes(-1), 3, "Hello3")); var context = new ErrorReporterContext(this, new Exception()) { LogEntries = new[] { new LogEntryDto(DateTime.UtcNow.AddMinutes(-2), 3, "Hello2") } }; _sut.Collect(context); context.LogEntries[0].Message.Should().Be("Hello1"); context.LogEntries[1].Message.Should().Be("Hello2"); context.LogEntries[2].Message.Should().Be("Hello3"); }
public void should_add_log_entries_from_context() { var dispatcher = Substitute.For <IUploadDispatcher>(); var config = new CoderrConfiguration(dispatcher); var ex = new Exception("hello"); var context = new ErrorReporterContext(this, ex) { LogEntries = new LogEntryDto[] { new LogEntryDto(DateTime.UtcNow, 1, "Hello") } }; var sut = new ExceptionProcessor(config); var actual = sut.Build(context); actual.LogEntries[0].Message.Should().Be(context.LogEntries[0].Message); }
public void failing_collectors_should_not_abort_the_processing() { var collector = Substitute.For <IContextCollectionProvider>(); var collector2 = Substitute.For <IContextCollectionProvider>(); var ctx = new ErrorReporterContext(this, new Exception("errror")); collector.When(x => x.Collect(ctx)).Do(x => throw new InvalidOperationException()); var sut = new ContextProvidersRegistrar(); sut.Add(collector); sut.Add(collector2); sut.Collect(ctx); collector2.Received().Collect(ctx); }
public void Should_ignore_reports_that_have_already_been_reported_since_same_frameworks_have_multiple_injection_points_which_would_Report_the_same_exception() { var upl = new TestUploader(); var config = new CoderrConfiguration(); var ex = new Exception("hello"); var ctx = new ErrorReporterContext(this, ex); config.Uploaders.Register(upl); ex.Data[ExceptionProcessor.AlreadyReportedSetting] = 1; var processor = new ExceptionProcessor(config); processor.Process(ctx); upl.Report.Should().BeNull("because report should have been ignored"); }
public void Should_be_able_to_move_collection() { var ex = new Exception(); var col = new ContextCollectionDTO("MyName", new Dictionary <string, string>() { { "Key", "Value" } }); ex.Data["ErrCollection.MyName"] = JsonConvert.SerializeObject(col); var sut = new ErrorReporterContext(this, ex); var actual = sut.GetCollectionProperty("MyName", "Key"); actual.Should().Be("Value"); }
public void clear_should_remove_all_collectors() { var collector1 = Substitute.For <IContextCollectionProvider>(); var collector2 = Substitute.For <IContextCollectionProvider>(); var ctx = new ErrorReporterContext(this, new Exception("errror")); var sut = new ContextProvidersRegistrar(); sut.Add(collector1); sut.Add(collector2); sut.Clear(); sut.Collect(ctx); collector1.DidNotReceiveWithAnyArgs().Collect(null); collector2.DidNotReceiveWithAnyArgs().Collect(null); }
public void Filter_should_not_affect_non_filtered_reports() { var upl = new TestUploader(); var config = new CoderrConfiguration(); var filter = Substitute.For <IReportFilter>(); var ctx = new ErrorReporterContext(this, new Exception()); config.Uploaders.Register(upl); config.FilterCollection.Add(filter); var processor = new ExceptionProcessor(config); processor.Process(ctx); upl.Report.Should().NotBeNull("because the report is not affected by the filter"); filter.ReceivedWithAnyArgs().Invoke(null); }
public void Should_be_able_to_filter_Reports() { var upl = new TestUploader(); var config = new CoderrConfiguration(); var filter = Substitute.For <IReportFilter>(); var ctx = new ErrorReporterContext(this, new Exception()); config.Uploaders.Register(upl); config.FilterCollection.Add(filter); filter.Invoke(Arg.Do((ReportFilterContext context) => context.CanSubmitReport = false)); var processor = new ExceptionProcessor(config); processor.Process(ctx); upl.Report.Should().BeNull("because report should have been filtered away"); }
public void Should_include_partitions_in_reports() { var upl = new TestUploader(); var config = new CoderrConfiguration(); var ex = new Exception("hello"); var ctx = new ErrorReporterContext(this, ex); config.Uploaders.Register(upl); config.AddPartition(x => { x.AddPartition("Id", "42"); }); var processor = new ExceptionProcessor(config); processor.Process(ctx); upl.Report.GetCollectionProperty("CoderrData", "ErrPartition.Id").Should().Be("42"); }
public void Should_ignore_reports_that_have_already_been_reported_since_same_frameworks_have_multiple_injection_points_which_would_Report_the_same_exception() { var upl = new TestUploader(); var config = new CoderrConfiguration(); var ex = new Exception("hello"); var ctx = new ErrorReporterContext(this, ex); config.Uploaders.Register(upl); config.AddPartition(x => { x.AddPartition("Id", "42"); }); var processor = new ExceptionProcessor(config); processor.Process(ctx); upl.Report.GetCollectionProperty("ErrPartitions", "Id").Should().Be("42"); }
public void Should_unpack_collections_that_are_attached_to_the_exception() { var upl = new TestUploader(); var config = new CoderrConfiguration(); config.Uploaders.Register(upl); var json = @"{""$type"":""System.Collections.Generic.List`1[[codeRR.Client.Contracts.ContextCollectionDTO, Coderr.Client]], mscorlib"",""$values"":[{""Name"":""SqlCommand"",""Properties"":{""CommandText"":""WaitFor Delay '00:00:05'"",""CommandTimeout"":""3"",""ExecutionTime"":""00:00:03.0313327"",""OtherCommand[0]"":""select * from accounts where id=@id""}},{""Name"":""DbConnection"",""Properties"":{""ConnectionString"":""Data Source=.;Initial Catalog=OneTrueError;Integrated Security=True;Connect Timeout=30;multipleactiveresultsets=true"",""DataSource"":""."",""Database"":""OneTrueError"",""RunTime"":""00:00:03.0681702"",""State"":""Open"",""IsDisposed"":""False"",""ServerVersion"":""12.00.5207""}}]}"; var ex = new InvalidOperationException(); var ctx = new ErrorReporterContext(this, ex); ex.Data["ErrCollections"] = json; var processor = new ExceptionProcessor(config); processor.Process(ctx); upl.Report.ContextCollections.Should().Contain(x => x.Name == "SqlCommand"); }
/// <summary> /// Build an report, but do not upload it /// </summary> /// <param name="exception">caught exception</param> /// <param name="contextData">context data</param> /// <remarks> /// <para> /// Will collect context info and generate a report. /// </para> /// </remarks> public ErrorReportDTO Build(Exception exception, object contextData) { if (exception is CoderrClientException) { return(null); } if (exception.Data.Contains(AlreadyReportedSetting)) { return(null); } var context = new ErrorReporterContext(null, exception); if (contextData != null) { AppendCustomContextData(contextData, context.ContextCollections); } return(Build(context)); }
/// <summary> /// Build an report, but do not upload it /// </summary> /// <param name="exception">caught exception</param> /// <param name="contextData">context data</param> /// <remarks> /// <para> /// Will collect context info and generate a report. /// </para> /// </remarks> /// <exception cref="ArgumentNullException">exception;contextData</exception> public ErrorReportDTO Build(Exception exception, object contextData) { if (exception == null) { throw new ArgumentNullException(nameof(exception)); } if (contextData == null) { throw new ArgumentNullException(nameof(contextData)); } if (IsReported(exception)) { return(null); } var context = new ErrorReporterContext(null, exception); AppendCustomContextData(contextData, context.ContextCollections); return(Build(context)); }