Skip to content

Commit 33d3b22

Browse files
authored
Expose EnumerateChainedExceptions (#1733)
1 parent 58c6500 commit 33d3b22

12 files changed

+62
-29
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
### Features
66

7+
- Expose EnumerateChainedExceptions ([#1733](https://github.com/getsentry/sentry-dotnet/pull/1733))
78
- Android Scope Sync ([#1737](https://github.com/getsentry/sentry-dotnet/pull/1737))
89
- Enable logging in MAUI ([#1738](https://github.com/getsentry/sentry-dotnet/pull/1738))
910

src/Sentry/Internal/MainExceptionProcessor.cs

Lines changed: 14 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -82,49 +82,34 @@ keyValue.Value is string tagValue &&
8282

8383
internal IEnumerable<SentryException> CreateSentryException(Exception exception)
8484
{
85-
if (exception is AggregateException ae)
86-
{
87-
foreach (var inner in ae.InnerExceptions.SelectMany(CreateSentryException))
88-
{
89-
yield return inner;
90-
}
91-
92-
if (!_options.KeepAggregateException)
93-
{
94-
yield break;
95-
}
96-
}
97-
else if (exception.InnerException != null)
98-
{
99-
foreach (var inner in CreateSentryException(exception.InnerException))
100-
{
101-
yield return inner;
102-
}
103-
}
85+
return exception.EnumerateChainedExceptions(_options)
86+
.Select(BuildSentryException);
87+
}
10488

89+
private SentryException BuildSentryException(Exception innerException)
90+
{
10591
var sentryEx = new SentryException
10692
{
107-
Type = exception.GetType()?.FullName,
108-
Module = exception.GetType()?.Assembly?.FullName,
109-
Value = exception.Message,
93+
Type = innerException.GetType()?.FullName,
94+
Module = innerException.GetType()?.Assembly?.FullName,
95+
Value = innerException.Message,
11096
ThreadId = Environment.CurrentManagedThreadId,
111-
Mechanism = GetMechanism(exception)
97+
Mechanism = GetMechanism(innerException)
11298
};
11399

114-
if (exception.Data.Count != 0)
100+
if (innerException.Data.Count != 0)
115101
{
116-
foreach (var key in exception.Data.Keys)
102+
foreach (var key in innerException.Data.Keys)
117103
{
118104
if (key is string keyString)
119105
{
120-
sentryEx.Data[keyString] = exception.Data[key];
106+
sentryEx.Data[keyString] = innerException.Data[key];
121107
}
122108
}
123109
}
124110

125-
sentryEx.Stacktrace = SentryStackTraceFactoryAccessor().Create(exception);
126-
127-
yield return sentryEx;
111+
sentryEx.Stacktrace = SentryStackTraceFactoryAccessor().Create(innerException);
112+
return sentryEx;
128113
}
129114

130115
internal static Mechanism GetMechanism(Exception exception)

src/Sentry/SentryExceptionExtensions.cs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
using System;
22
using System.Collections.Generic;
33
using System.ComponentModel;
4+
using System.Linq;
5+
using Sentry;
46
using Sentry.Internal;
57

68
/// <summary>
@@ -18,6 +20,42 @@ public static class SentryExceptionExtensions
1820
public static void AddSentryTag(this Exception ex, string name, string value)
1921
=> ex.Data.Add($"{MainExceptionProcessor.ExceptionDataTagKey}{name}", value);
2022

23+
/// <summary>
24+
/// Recursively enumerates all <see cref="AggregateException.InnerExceptions"/> and <see cref="Exception.InnerException"/>
25+
/// Not for public use.
26+
/// </summary>
27+
[EditorBrowsable(EditorBrowsableState.Never)]
28+
public static IEnumerable<Exception> EnumerateChainedExceptions(this Exception exception, SentryOptions options)
29+
{
30+
if (exception is AggregateException aggregateException)
31+
{
32+
foreach (var inner in EnumerateInner(options, aggregateException))
33+
{
34+
yield return inner;
35+
}
36+
37+
if (!options.KeepAggregateException)
38+
{
39+
yield break;
40+
}
41+
}
42+
else if (exception.InnerException != null)
43+
{
44+
foreach (var inner in exception.InnerException.EnumerateChainedExceptions(options))
45+
{
46+
yield return inner;
47+
}
48+
}
49+
50+
yield return exception;
51+
}
52+
53+
private static IEnumerable<Exception> EnumerateInner(SentryOptions options, AggregateException aggregateException)
54+
{
55+
return aggregateException.InnerExceptions
56+
.SelectMany(exception => exception.EnumerateChainedExceptions(options));
57+
}
58+
2159
/// <summary>
2260
/// Set a Sentry's structured Context to the Exception.
2361
/// </summary>

test/Sentry.DiagnosticSource.Tests/ApiApprovalTests.Run.Core3_1.verified.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1403,4 +1403,5 @@ public static class SentryExceptionExtensions
14031403
{
14041404
public static void AddSentryContext(this System.Exception ex, string name, System.Collections.Generic.IReadOnlyDictionary<string, object> data) { }
14051405
public static void AddSentryTag(this System.Exception ex, string name, string value) { }
1406+
public static System.Collections.Generic.IEnumerable<System.Exception> EnumerateChainedExceptions(this System.Exception exception, Sentry.SentryOptions options) { }
14061407
}

test/Sentry.DiagnosticSource.Tests/ApiApprovalTests.Run.DotNet5_0.verified.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1403,4 +1403,5 @@ public static class SentryExceptionExtensions
14031403
{
14041404
public static void AddSentryContext(this System.Exception ex, string name, System.Collections.Generic.IReadOnlyDictionary<string, object> data) { }
14051405
public static void AddSentryTag(this System.Exception ex, string name, string value) { }
1406+
public static System.Collections.Generic.IEnumerable<System.Exception> EnumerateChainedExceptions(this System.Exception exception, Sentry.SentryOptions options) { }
14061407
}

test/Sentry.DiagnosticSource.Tests/ApiApprovalTests.Run.DotNet6_0.verified.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1403,4 +1403,5 @@ public static class SentryExceptionExtensions
14031403
{
14041404
public static void AddSentryContext(this System.Exception ex, string name, System.Collections.Generic.IReadOnlyDictionary<string, object> data) { }
14051405
public static void AddSentryTag(this System.Exception ex, string name, string value) { }
1406+
public static System.Collections.Generic.IEnumerable<System.Exception> EnumerateChainedExceptions(this System.Exception exception, Sentry.SentryOptions options) { }
14061407
}

test/Sentry.Tests/ApiApprovalTests.Run.Core2_1.verified.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1402,4 +1402,5 @@ public static class SentryExceptionExtensions
14021402
{
14031403
public static void AddSentryContext(this System.Exception ex, string name, System.Collections.Generic.IReadOnlyDictionary<string, object> data) { }
14041404
public static void AddSentryTag(this System.Exception ex, string name, string value) { }
1405+
public static System.Collections.Generic.IEnumerable<System.Exception> EnumerateChainedExceptions(this System.Exception exception, Sentry.SentryOptions options) { }
14051406
}

test/Sentry.Tests/ApiApprovalTests.Run.Core3_0.verified.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1402,4 +1402,5 @@ public static class SentryExceptionExtensions
14021402
{
14031403
public static void AddSentryContext(this System.Exception ex, string name, System.Collections.Generic.IReadOnlyDictionary<string, object> data) { }
14041404
public static void AddSentryTag(this System.Exception ex, string name, string value) { }
1405+
public static System.Collections.Generic.IEnumerable<System.Exception> EnumerateChainedExceptions(this System.Exception exception, Sentry.SentryOptions options) { }
14051406
}

test/Sentry.Tests/ApiApprovalTests.Run.Core3_1.verified.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1403,4 +1403,5 @@ public static class SentryExceptionExtensions
14031403
{
14041404
public static void AddSentryContext(this System.Exception ex, string name, System.Collections.Generic.IReadOnlyDictionary<string, object> data) { }
14051405
public static void AddSentryTag(this System.Exception ex, string name, string value) { }
1406+
public static System.Collections.Generic.IEnumerable<System.Exception> EnumerateChainedExceptions(this System.Exception exception, Sentry.SentryOptions options) { }
14061407
}

test/Sentry.Tests/ApiApprovalTests.Run.DotNet4_6.verified.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1403,4 +1403,5 @@ public static class SentryExceptionExtensions
14031403
{
14041404
public static void AddSentryContext(this System.Exception ex, string name, System.Collections.Generic.IReadOnlyDictionary<string, object> data) { }
14051405
public static void AddSentryTag(this System.Exception ex, string name, string value) { }
1406+
public static System.Collections.Generic.IEnumerable<System.Exception> EnumerateChainedExceptions(this System.Exception exception, Sentry.SentryOptions options) { }
14061407
}

0 commit comments

Comments
 (0)