Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

namespace Sentry.AspNet.Internal;

internal class SystemWebRequestEventProcessor : ISentryEventProcessor
internal class SystemWebRequestEventProcessor : ISentryEventProcessor, ISdkProcessor
{
private static readonly SdkVersion SdkVersion =
typeof(SystemWebRequestEventProcessor).Assembly.GetNameAndVersion();
Expand Down
3 changes: 2 additions & 1 deletion src/Sentry.AspNetCore.Grpc/SentryBuilderExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using Microsoft.Extensions.DependencyInjection;
using Sentry.Extensibility;
using Sentry.Internal;
using Sentry.Reflection;

namespace Sentry.AspNetCore.Grpc;
Expand Down Expand Up @@ -28,7 +29,7 @@ public static ISentryBuilder AddGrpc(this ISentryBuilder builder)
return builder;
}

private class SentryGrpcEventProcessor : ISentryEventProcessor
private class SentryGrpcEventProcessor : ISentryEventProcessor, ISdkProcessor
{
private static readonly SdkVersion NameAndVersion
= typeof(SentryGrpcInterceptor).Assembly.GetNameAndVersion();
Expand Down
3 changes: 2 additions & 1 deletion src/Sentry.AspNetCore/AspNetCoreEventProcessor.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
using Sentry.Extensibility;
using Sentry.Internal;

namespace Sentry.AspNetCore;

internal class AspNetCoreEventProcessor : ISentryEventProcessor
internal class AspNetCoreEventProcessor : ISentryEventProcessor, ISdkProcessor
{
public SentryEvent Process(SentryEvent @event)
{
Expand Down
3 changes: 2 additions & 1 deletion src/Sentry.AspNetCore/AspNetCoreExceptionProcessor.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
using Sentry.Extensibility;
using Sentry.Internal;
using Sentry.Protocol;

namespace Sentry.AspNetCore;

internal class AspNetCoreExceptionProcessor : ISentryEventExceptionProcessor
internal class AspNetCoreExceptionProcessor : ISentryEventExceptionProcessor, ISdkProcessor
{
public void Process(Exception exception, SentryEvent @event)
{
Expand Down
3 changes: 2 additions & 1 deletion src/Sentry.AspNetCore/ExceptionHandlerFeatureProcessor.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
using Microsoft.AspNetCore.Diagnostics;
using Microsoft.AspNetCore.Routing;
using Sentry.Extensibility;
using Sentry.Internal;

namespace Sentry.AspNetCore;

#if NET6_0_OR_GREATER
internal class ExceptionHandlerFeatureProcessor : ISentryEventExceptionProcessor
internal class ExceptionHandlerFeatureProcessor : ISentryEventExceptionProcessor, ISdkProcessor
{
private readonly string _originalMethod;
private readonly IExceptionHandlerFeature _exceptionHandlerFeature;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
using Sentry.Internal;

namespace Sentry.EntityFramework.ErrorProcessors;

/// <summary>
/// Exception processor for Entity Framework <see cref="DBConcurrencyException"/>.
/// </summary>
public class DbConcurrencyExceptionProcessor : SentryEventExceptionProcessor<DBConcurrencyException>
public class DbConcurrencyExceptionProcessor : SentryEventExceptionProcessor<DBConcurrencyException>, ISdkProcessor
{
/// <summary>
/// Extracts RowCount and RowError from <see cref="DBConcurrencyException"/>.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
using Sentry.Internal;

namespace Sentry.EntityFramework.ErrorProcessors;

/// <summary>
/// Exception processor for <see cref="DbEntityValidationException"/>.
/// </summary>
public class DbEntityValidationExceptionProcessor : SentryEventExceptionProcessor<DbEntityValidationException>
public class DbEntityValidationExceptionProcessor : SentryEventExceptionProcessor<DbEntityValidationException>, ISdkProcessor
{
/// <summary>
/// Extracts details from <see cref="DbEntityValidationException"/> into the <see cref="SentryEvent"/>.
Expand Down
3 changes: 2 additions & 1 deletion src/Sentry.Google.Cloud.Functions/SentryStartup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using Sentry;
using Sentry.AspNetCore;
using Sentry.Extensibility;
using Sentry.Internal;
using Sentry.Reflection;

namespace Google.Cloud.Functions.Framework;
Expand Down Expand Up @@ -94,7 +95,7 @@ public override void Configure(WebHostBuilderContext context, IApplicationBuilde
app.UseSentryTracing();
}

private class SentryGoogleCloudFunctionEventProcessor : ISentryEventProcessor
private class SentryGoogleCloudFunctionEventProcessor : ISentryEventProcessor, ISdkProcessor
{
private static readonly SdkVersion NameAndVersion
= typeof(SentryStartup).Assembly.GetNameAndVersion();
Expand Down
3 changes: 2 additions & 1 deletion src/Sentry.Maui/Internal/SentryMauiEventProcessor.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
using Sentry.Extensibility;
using Sentry.Internal;

namespace Sentry.Maui.Internal;

internal class SentryMauiEventProcessor : ISentryEventProcessor
internal class SentryMauiEventProcessor : ISentryEventProcessor, ISdkProcessor
{
public static bool? InForeground { get; set; }

Expand Down
3 changes: 2 additions & 1 deletion src/Sentry.Maui/Internal/SentryMauiScreenshotProcessor.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
using Sentry.Extensibility;
using Sentry.Internal;

namespace Sentry.Maui.Internal;

internal class SentryMauiScreenshotProcessor : ISentryEventProcessorWithHint
internal class SentryMauiScreenshotProcessor : ISentryEventProcessorWithHint, ISdkProcessor
{
private readonly SentryMauiOptions _options;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

namespace Sentry.OpenTelemetry;

internal class OpenTelemetryTransactionProcessor : ISentryTransactionProcessor
internal class OpenTelemetryTransactionProcessor : ISentryTransactionProcessor, ISdkProcessor
{
public SentryTransaction Process(SentryTransaction transaction)
{
Expand Down
2 changes: 1 addition & 1 deletion src/Sentry.Serilog/SerilogScopeEventProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ namespace Sentry.Serilog;
/// <summary>
/// Sentry event processor that applies properties from the Serilog scope to Sentry events.
/// </summary>
internal class SerilogScopeEventProcessor : ISentryEventProcessor
internal class SerilogScopeEventProcessor : ISentryEventProcessor, ISdkProcessor
{
private readonly SentryOptions _options;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

namespace Sentry.Internal;

internal class DuplicateEventDetectionEventProcessor : ISentryEventProcessor
internal class DuplicateEventDetectionEventProcessor : ISentryEventProcessor, ISdkProcessor
{
private readonly SentryOptions _options;
private readonly ConditionalWeakTable<object, object?> _capturedObjects = new();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using Sentry.Extensibility;

namespace Sentry.Internal.Extensions;

internal static class SentryStackTraceFactoryExtensions
{
public static SentryStackTrace? TryCreate(this ISentryStackTraceFactory factory, SentryOptions options, Exception? exception = null)
{
try
{
return factory.Create(exception);
}
catch (Exception e)
{
options.LogError(e, "Stack trace factory {0} threw an exception. The stack trace will be omitted.", factory.GetType().Name);
return null;
}
}
}
5 changes: 5 additions & 0 deletions src/Sentry/Internal/ISdkProcessor.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
namespace Sentry.Internal;

// Marker interface for SDK processors.
// Must not be applied to processors that run user code (e.g. DelegateEventProcessor)
internal interface ISdkProcessor;
4 changes: 2 additions & 2 deletions src/Sentry/Internal/MainExceptionProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

namespace Sentry.Internal;

internal class MainExceptionProcessor : ISentryEventExceptionProcessor
internal class MainExceptionProcessor : ISentryEventExceptionProcessor, ISdkProcessor
Comment thread
jamescrosswell marked this conversation as resolved.
{
private const string ExceptionDataKeyPrefix = "sentry:";
internal const string ExceptionDataTagKey = ExceptionDataKeyPrefix + "tag:";
Expand Down Expand Up @@ -155,7 +155,7 @@ private SentryException BuildSentryException(Exception exception, int id, int? p
sentryEx.Mechanism = mechanism;
}

sentryEx.Stacktrace ??= SentryStackTraceFactoryAccessor().Create(exception);
sentryEx.Stacktrace ??= SentryStackTraceFactoryAccessor().TryCreate(_options, exception);
return sentryEx;
}

Expand Down
5 changes: 3 additions & 2 deletions src/Sentry/Internal/MainSentryEventProcessor.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
using Sentry.Extensibility;
using Sentry.Internal.Extensions;
using Sentry.Reflection;

namespace Sentry.Internal;

internal class MainSentryEventProcessor : ISentryEventProcessor
internal class MainSentryEventProcessor : ISentryEventProcessor, ISdkProcessor
Comment thread
jamescrosswell marked this conversation as resolved.
{
internal const string CultureInfoKey = "Current Culture";
internal const string CurrentUiCultureKey = "Current UI Culture";
Expand Down Expand Up @@ -87,7 +88,7 @@ public SentryEvent Process(SentryEvent @event)
if (@event.Exception?.StackTrace is null && @event.SentryThreads?.Any(t => t.Current == true) != true)
{
var stackTrace = @event.SentryExceptions?.FirstOrDefault()?.Stacktrace
?? SentryStackTraceFactoryAccessor().Create();
?? SentryStackTraceFactoryAccessor().TryCreate(_options);
if (stackTrace != null)
{
var currentThread = Thread.CurrentThread;
Expand Down
4 changes: 4 additions & 0 deletions src/Sentry/Internal/SentryEventHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ internal static class SentryEventHelper
{
processedEvent = processor.DoProcessEvent(processedEvent, effectiveHint);
}
catch (Exception e) when (processor is ISdkProcessor)
{
options.LogError(e, "Event processor {0} threw an exception. Continuing with the remaining processors.", processor.GetType().Name);
}
catch (Exception e)
{
options.ClientReportRecorder.RecordDiscardedEvent(DiscardReason.CallbackError, dataCategory);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

namespace Sentry.Internal;

internal class TraceIgnoreStatusCodeTransactionProcessor : ISentryTransactionProcessor
internal class TraceIgnoreStatusCodeTransactionProcessor : ISentryTransactionProcessor, ISdkProcessor
{
private const string IncomingRequestOperation = "http.server";

Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
#if NETFRAMEWORK
using Sentry.Extensibility;
using Sentry.Internal;

namespace Sentry.PlatformAbstractions;

internal class NetFxInstallationsEventProcessor : ISentryEventProcessor
internal class NetFxInstallationsEventProcessor : ISentryEventProcessor, ISdkProcessor
{
internal static readonly string NetFxInstallationsKey = ".NET Framework";

Expand Down
3 changes: 2 additions & 1 deletion src/Sentry/Platforms/Android/AndroidEventProcessor.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
using Sentry.Android.Extensions;
using Sentry.Extensibility;
using Sentry.Internal;
using Sentry.JavaSdk.Android.Core;

namespace Sentry.Android;

internal class AndroidEventProcessor : ISentryEventProcessor, IDisposable
internal class AndroidEventProcessor : ISentryEventProcessor, IDisposable, ISdkProcessor
{
private readonly JavaSdk.IEventProcessor? _androidProcessor;
private readonly JavaSdk.Hint _hint = new();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
using Sentry.Extensibility;
using Sentry.Internal;
using Runtime = Java.Lang.Runtime;

namespace Sentry.Android;

internal class LogCatAttachmentEventProcessor : ISentryEventProcessorWithHint
internal class LogCatAttachmentEventProcessor : ISentryEventProcessorWithHint, ISdkProcessor
{
private static bool SendLogcatLogs = true;
private readonly LogCatIntegrationType _logCatIntegrationType;
Expand Down
3 changes: 2 additions & 1 deletion src/Sentry/Platforms/Cocoa/CocoaEventProcessor.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
using Sentry.Cocoa.Extensions;
using Sentry.Extensibility;
using Sentry.Internal;

namespace Sentry.Cocoa;

internal class CocoaEventProcessor : ISentryEventProcessor, IDisposable
internal class CocoaEventProcessor : ISentryEventProcessor, IDisposable, ISdkProcessor
{
public SentryEvent Process(SentryEvent @event)
{
Expand Down
61 changes: 50 additions & 11 deletions src/Sentry/SentryClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,10 @@ public void CaptureTransaction(SentryTransaction transaction, Scope? scope, Sent
{
processedTransaction = processor.DoProcessTransaction(processedTransaction, hint);
}
catch (Exception e) when (processor is ISdkProcessor)
{
_options.LogError(e, "Transaction processor {0} threw an exception. Continuing with the remaining processors.", processor.GetType().Name);
}
catch (Exception e)
{
_options.ClientReportRecorder.RecordDiscardedEvent(DiscardReason.CallbackError, DataCategory.Transaction);
Expand Down Expand Up @@ -331,7 +335,12 @@ public SentryId CaptureCheckIn(

private SentryId DoSendEvent(SentryEvent @event, SentryHint? hint, Scope? scope)
{
var filteredExceptions = ApplyExceptionFilters(@event.Exception);
var filteredExceptions = ApplyExceptionFilters(@event.Exception, out var filterThrew);
if (filterThrew)
{
return SentryId.Empty;
}

if (filteredExceptions?.Count > 0)
{
_options.ClientReportRecorder.RecordDiscardedEvent(DiscardReason.EventProcessor, DataCategory.Error);
Expand Down Expand Up @@ -363,9 +372,20 @@ private SentryId DoSendEvent(SentryEvent @event, SentryHint? hint, Scope? scope)
// after the SDK is initialized. Useful for example once a DI container is up
foreach (var processor in scope.GetAllExceptionProcessors())
{
processor.Process(@event.Exception, @event);

// NOTE: Exception processors can't drop events, but exception filters (above) can.
try
{
processor.Process(@event.Exception, @event);
}
catch (Exception e) when (processor is ISdkProcessor)
{
_options.LogError(e, "Exception processor {0} threw an exception. Continuing with the remaining processors.", processor.GetType().Name);
}
catch (Exception e)
{
_options.ClientReportRecorder.RecordDiscardedEvent(DiscardReason.CallbackError, DataCategory.Error);
_options.LogError(e, "Exception processor {0} threw an exception. The event will be dropped.", processor.GetType().Name);
return SentryId.Empty;
}
}
}

Expand Down Expand Up @@ -437,30 +457,49 @@ private SentryId DoSendEvent(SentryEvent @event, SentryHint? hint, Scope? scope)
return SentryId.Empty;
}

private IReadOnlyCollection<Exception>? ApplyExceptionFilters(Exception? exception)
private IReadOnlyCollection<Exception>? ApplyExceptionFilters(Exception? exception, out bool filterThrew)
{
filterThrew = false;
var filters = _options.ExceptionFilters;
if (exception == null || filters == null || filters.Count == 0)
{
// There was nothing to filter.
return null;
}

if (filters.Any(f => f.Filter(exception)))
foreach (var filter in filters)
{
// The event should be filtered based on the given exception
return new[] { exception };
try
{
if (filter.Filter(exception))
{
// The event should be filtered based on the given exception
return new[] { exception };
}
}
catch (Exception e)
{
_options.ClientReportRecorder.RecordDiscardedEvent(DiscardReason.CallbackError, DataCategory.Error);
_options.LogError(e, "Exception filter {0} threw an exception. The event will be dropped.", filter.GetType().Name);
filterThrew = true;
return null;
}
}

if (exception is AggregateException aggregate)
{
// Flatten the tree of aggregates such that all the inner exceptions are non-aggregates.
var innerExceptions = aggregate.Flatten().InnerExceptions;
if (innerExceptions.All(e => ApplyExceptionFilters(e) != null))
foreach (var innerException in innerExceptions)
{
// All inner exceptions matched a filter, so the event should be filtered.
return innerExceptions;
if (ApplyExceptionFilters(innerException, out filterThrew) == null)
{
return null;
}
}

// All inner exceptions matched a filter, so the event should be filtered.
return innerExceptions;
}

// The event should not be filtered.
Expand Down
Loading
Loading