Skip to content

Commit 50444e5

Browse files
authored
Merge pull request #184 from pengweiqhca/EnhancedStackTrace
Custom SentryStackTraceFactory support
2 parents 08d5d8a + db78710 commit 50444e5

File tree

7 files changed

+78
-20
lines changed

7 files changed

+78
-20
lines changed

src/Sentry.AspNetCore/ApplicationBuilderExtensions.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,12 @@ public static IApplicationBuilder UseSentry(this IApplicationBuilder app)
3838
o.DiagnosticLogger = new MelDiagnosticLogger(logger, o.DiagnosticsLevel);
3939
}
4040

41+
var stackTraceFactory = app.ApplicationServices.GetService<ISentryStackTraceFactory>();
42+
if (stackTraceFactory != null)
43+
{
44+
o.UseStackTraceFactory(stackTraceFactory);
45+
}
46+
4147
if (app.ApplicationServices.GetService<IEnumerable<ISentryEventProcessor>>().Any())
4248
{
4349
o.AddEventProcessorProvider(app.ApplicationServices.GetServices<ISentryEventProcessor>);
Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
using System;
1+
using System;
22
using Sentry.Protocol;
33

4-
namespace Sentry.Internal
4+
namespace Sentry.Extensibility
55
{
6-
internal interface ISentryStackTraceFactory
6+
public interface ISentryStackTraceFactory
77
{
88
SentryStackTrace Create(Exception exception = null);
99
}
10-
}
10+
}

src/Sentry/Internal/SentryStackTraceFactory.cs renamed to src/Sentry/Extensibility/SentryStackTraceFactory.cs

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,11 @@
44
using System.Linq;
55
using System.Reflection;
66
using System.Text.RegularExpressions;
7-
using Sentry.Extensibility;
87
using Sentry.Protocol;
98

10-
namespace Sentry.Internal
9+
namespace Sentry.Extensibility
1110
{
12-
internal class SentryStackTraceFactory : ISentryStackTraceFactory
11+
public class SentryStackTraceFactory : ISentryStackTraceFactory
1312
{
1413
private readonly SentryOptions _options;
1514

@@ -27,13 +26,12 @@ public SentryStackTrace Create(Exception exception = null)
2726

2827
_options.DiagnosticLogger?.LogDebug("Creating SentryStackTrace. isCurrentStackTrace: {0}.", isCurrentStackTrace);
2928

30-
var stackTrace = isCurrentStackTrace
31-
? new StackTrace(true)
32-
: new StackTrace(exception, true);
33-
34-
return Create(stackTrace, isCurrentStackTrace);
29+
return Create(CreateStackTrace(exception), isCurrentStackTrace);
3530
}
3631

32+
protected virtual StackTrace CreateStackTrace(Exception exception) =>
33+
exception == null ? new StackTrace(true) : new StackTrace(exception, true);
34+
3735
internal SentryStackTrace Create(StackTrace stackTrace, bool isCurrentStackTrace)
3836
{
3937
var frames = CreateFrames(stackTrace, isCurrentStackTrace)
@@ -77,19 +75,23 @@ internal IEnumerable<SentryStackFrame> CreateFrames(StackTrace stackTrace, bool
7775

7876
firstFrames = false;
7977

80-
var frame = CreateFrame(stackFrame);
78+
var frame = CreateFrame(stackFrame, isCurrentStackTrace);
8179
if (frame != null)
8280
{
8381
yield return frame;
8482
}
8583
}
8684
}
8785

88-
internal SentryStackFrame CreateFrame(StackFrame stackFrame)
86+
internal SentryStackFrame CreateFrame(StackFrame stackFrame) => InternalCreateFrame(stackFrame, true);
87+
88+
protected virtual SentryStackFrame CreateFrame(StackFrame stackFrame, bool isCurrentStackTrace) => InternalCreateFrame(stackFrame, true);
89+
90+
protected SentryStackFrame InternalCreateFrame(StackFrame stackFrame, bool demangle)
8991
{
9092
const string unknownRequiredField = "(unknown)";
9193
var frame = new SentryStackFrame();
92-
if (stackFrame.GetMethod() is MethodBase method)
94+
if (GetMethod(stackFrame) is MethodBase method)
9395
{
9496
// TODO: SentryStackFrame.TryParse and skip frame instead of these unknown values:
9597
frame.Module = method.DeclaringType?.FullName ?? unknownRequiredField;
@@ -120,13 +122,17 @@ internal SentryStackFrame CreateFrame(StackFrame stackFrame)
120122
frame.ColumnNumber = colNo;
121123
}
122124

123-
// TODO: Consider Ben.Demystifier
124-
DemangleAsyncFunctionName(frame);
125-
DemangleAnonymousFunction(frame);
125+
if (demangle)
126+
{
127+
DemangleAsyncFunctionName(frame);
128+
DemangleAnonymousFunction(frame);
129+
}
126130

127131
return frame;
128132
}
129133

134+
protected virtual MethodBase GetMethod(StackFrame stackFrame) => stackFrame.GetMethod();
135+
130136
private bool IsSystemModuleName(string moduleName)
131137
{
132138
if (string.IsNullOrEmpty(moduleName))

src/Sentry/SentryOptionsExtensions.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,24 @@ public static IEnumerable<ISentryEventProcessor> GetAllEventProcessors(this Sent
120120
public static IEnumerable<ISentryEventExceptionProcessor> GetAllExceptionProcessors(this SentryOptions options)
121121
=> options.ExceptionProcessorsProviders.SelectMany(p => p());
122122

123+
/// <summary>
124+
/// Use custom <see cref="ISentryStackTraceFactory" />
125+
/// </summary>
126+
/// <param name="options">The SentryOptions to hold the processor provider.</param>
127+
/// <param name="sentryStackTraceFactory">The stack trace factory.</param>
128+
public static SentryOptions UseStackTraceFactory(this SentryOptions options, ISentryStackTraceFactory sentryStackTraceFactory)
129+
{
130+
if (sentryStackTraceFactory == null) throw new ArgumentNullException(nameof(sentryStackTraceFactory));
131+
132+
options.EventProcessors = options.EventProcessors.RemoveAt(1)
133+
.Insert(1, new MainSentryEventProcessor(options, sentryStackTraceFactory));
134+
135+
options.ExceptionProcessors = options.ExceptionProcessors.RemoveAt(0)
136+
.Insert(0, new MainExceptionProcessor(options, sentryStackTraceFactory));
137+
138+
return options;
139+
}
140+
123141
internal static void SetupLogging(this SentryOptions options)
124142
{
125143
if (options.Debug)

test/Sentry.Tests/Internals/MainExceptionProcessorTests.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
using System;
22
using System.Linq;
33
using NSubstitute;
4+
using Sentry.Extensibility;
45
using Sentry.Internal;
56
using Xunit;
67

78
namespace Sentry.Tests.Internals
89
{
910
public class MainExceptionProcessorTests
10-
{
11+
{
1112
private class Fixture
1213
{
1314
public ISentryStackTraceFactory SentryStackTraceFactory { get; set; } = Substitute.For<ISentryStackTraceFactory>();

test/Sentry.Tests/Internals/SentryStackTraceFactoryTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
using System.Diagnostics;
33
using System.Linq;
44
using Sentry;
5-
using Sentry.Internal;
5+
using Sentry.Extensibility;
66
using Sentry.Protocol;
77
using Xunit;
88

test/Sentry.Tests/SentryOptionsExtensionsTests.cs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using System;
12
using System.Linq;
23
using NSubstitute;
34
using Sentry.Extensibility;
@@ -187,6 +188,32 @@ public void GetAllEventProcessors_NoAdding_SecondReturned_MainSentryEventProcess
187188
Assert.IsType<MainSentryEventProcessor>(Sut.GetAllEventProcessors().Skip(1).First());
188189
}
189190

191+
[Fact]
192+
public void UseStackTraceFactory()
193+
{
194+
var eventProcessor1 = Sut.GetAllEventProcessors().Skip(1).First();
195+
var exceptionProcessor1 = Sut.GetAllExceptionProcessors().First();
196+
197+
Sut.UseStackTraceFactory(Substitute.For<ISentryStackTraceFactory>());
198+
199+
var eventProcessor2 = Sut.GetAllEventProcessors().Skip(1).First();
200+
var exceptionProcessor2 = Sut.GetAllExceptionProcessors().First();
201+
202+
Assert.IsType<MainSentryEventProcessor>(eventProcessor1);
203+
Assert.IsType<MainExceptionProcessor>(exceptionProcessor1);
204+
Assert.IsType<MainSentryEventProcessor>(eventProcessor2);
205+
Assert.IsType<MainExceptionProcessor>(exceptionProcessor2);
206+
207+
Assert.NotEqual(eventProcessor1, eventProcessor2);
208+
Assert.NotEqual(exceptionProcessor1, exceptionProcessor2);
209+
}
210+
211+
[Fact]
212+
public void UseStackTraceFactory_NotNull()
213+
{
214+
Assert.Throws<ArgumentNullException>(() => Sut.UseStackTraceFactory(null));
215+
}
216+
190217
[Fact]
191218
public void GetAllEventProcessors_AddingMore_FirstReturned_DuplicateDetectionProcessor()
192219
{

0 commit comments

Comments
 (0)