Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Next Next commit
Added SimpleStackTraceFactory
Resolves #3439
- #3439
  • Loading branch information
jamescrosswell committed Jul 17, 2025
commit 2dff37fcf12df3d9af7f8171b859321fb1e3fdd2
2 changes: 1 addition & 1 deletion src/Sentry/Extensibility/ISentryStackTraceFactory.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
namespace Sentry.Extensibility;

/// <summary>
/// Factory to <see cref="SentryStackTrace" /> from an <see cref="Exception" />.
/// Factory to create a <see cref="SentryStackTrace" /> from an <see cref="Exception" />.
/// </summary>
public interface ISentryStackTraceFactory
{
Expand Down
73 changes: 73 additions & 0 deletions src/Sentry/Extensibility/SimpleStackTraceFactory.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
using System;
using System.Collections.Generic;

namespace Sentry.Extensibility;

/// <summary>
/// A rudimentary implementation of <see cref="ISentryStackTraceFactory"/> that simply parses the
/// string representation of the stack trace from an exception. This lacks many of the features
/// off the full <see cref="SentryStackTraceFactory"/>, however it may be useful in AOT compiled
/// applications where the full factory is not returning a useful stack trace.
/// <remarks>SimpleStackTraceFactory is currently EXPERIMENTAL.</remarks>
/// </summary>
public partial class SimpleStackTraceFactory : ISentryStackTraceFactory
{
private readonly SentryOptions _options;
private const string StackTraceLinePattern = @"at (.+)\.(.+) \+";

#if NET9_0_OR_GREATER
[GeneratedRegex(StackTraceLinePattern)]
private static partial Regex StackTraceLine { get; }
#elif NET8_0
private static readonly Regex StackTraceLine = StackTraceLineRegex();

[GeneratedRegex(StackTraceLinePattern)]
private static partial Regex StackTraceLineRegex();
#else
private static readonly Regex StackTraceLine = new (StackTraceLinePattern, RegexOptions.Compiled);
#endif

/// <summary>
/// Creates a new instance of <see cref="SimpleStackTraceFactory"/>.
/// </summary>
/// <param name="options">The sentry options</param>
public SimpleStackTraceFactory(SentryOptions options)
{
_options = options;
}

/// <inheritdoc cref="ISentryStackTraceFactory.Create"/>
public SentryStackTrace? Create(Exception? exception = null)
{
_options.LogDebug("Source Stack Trace: {0}", exception?.StackTrace);

var trace = new SentryStackTrace();
var frames = new List<SentryStackFrame>();

var newlines = new[] { Environment.NewLine };
var lines = exception?.StackTrace?.Split(newlines, StringSplitOptions.RemoveEmptyEntries) ?? [];
foreach (var line in lines)
{
var match = StackTraceLine.Match(line);
if (match.Success)
{
frames.Add(new SentryStackFrame()
{
Module = match.Groups[1].Value,
Function = match.Groups[2].Value
});
}
else
{
_options.LogDebug("Regex match failed for: {0}", line);
frames.Add(new SentryStackFrame()
{
Function = line
});
}
}

trace.Frames = frames;
return trace;
}
}
9 changes: 9 additions & 0 deletions src/Sentry/SentryOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1631,7 +1631,16 @@ public IEnumerable<ISentryEventExceptionProcessor> GetAllExceptionProcessors()
=> ExceptionProcessorsProviders.SelectMany(p => p());

/// <summary>
/// <para>
/// Use custom <see cref="ISentryStackTraceFactory" />.
/// </para>
/// <para>
/// By default, Sentry uses the <see cref="SentryStackTraceFactory"/> to create stack traces and this implementation
/// offers the most comprehensive functionality. However, full stack traces are not available in AOT compiled
/// applications. If you are compiling your applications AOT and the stack traces that you see in Sentry are not
/// informative enough, you could consider using the <see cref="SimpleStackTraceFactory" /> instead. This is not as
/// functional but is guaranteed to provide at least _something_ useful in AOT compiled applications.
/// </para>
/// </summary>
/// <param name="sentryStackTraceFactory">The stack trace factory.</param>
public SentryOptions UseStackTraceFactory(ISentryStackTraceFactory sentryStackTraceFactory)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1516,6 +1516,11 @@ namespace Sentry.Extensibility
public SentryStackTraceFactory(Sentry.SentryOptions options) { }
public Sentry.SentryStackTrace? Create(System.Exception? exception = null) { }
}
public class SimpleStackTraceFactory : Sentry.Extensibility.ISentryStackTraceFactory
{
public SimpleStackTraceFactory(Sentry.SentryOptions options) { }
public Sentry.SentryStackTrace? Create(System.Exception? exception = null) { }
}
}
namespace Sentry.Http
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1516,6 +1516,11 @@ namespace Sentry.Extensibility
public SentryStackTraceFactory(Sentry.SentryOptions options) { }
public Sentry.SentryStackTrace? Create(System.Exception? exception = null) { }
}
public class SimpleStackTraceFactory : Sentry.Extensibility.ISentryStackTraceFactory
{
public SimpleStackTraceFactory(Sentry.SentryOptions options) { }
public Sentry.SentryStackTrace? Create(System.Exception? exception = null) { }
}
}
namespace Sentry.Http
{
Expand Down
Loading