Skip to content

Commit 33665ed

Browse files
fix: ExtraData not captured for Breadcrumbs in MauiEventsBinder (#4254)
Resolves #4252: - #4252
1 parent 54511b5 commit 33665ed

14 files changed

+205
-70
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
### Fixes
1212

1313
- The HTTP instrumentation uses the span created for the outgoing request in the sentry-trace header, fixing the parent-child relationship between client and server ([#4264](https://github.com/getsentry/sentry-dotnet/pull/4264))
14+
- ExtraData not captured for Breadcrumbs in MauiEventsBinder ([#4254](https://github.com/getsentry/sentry-dotnet/pull/4254))
15+
- NOTE: Required breaking changes to the public API of `Sentry.Maui.BreadcrumbEvent`, while keeping an _Obsolete_ constructor for backward compatibility.
1416
- InvalidOperationException sending attachments on Android with LLVM enabled ([#4276](https://github.com/getsentry/sentry-dotnet/pull/4276))
1517

1618
### Dependencies

src/Sentry.Maui/BreadcrumbEvent.cs

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
namespace Sentry.Maui;
2+
3+
/// <summary>
4+
/// Argument to the OnBreadcrumbCreateCallback
5+
/// </summary>
6+
public sealed class BreadcrumbEvent
7+
{
8+
/// <summary>
9+
/// The sender of the event, usually the control that triggered it.
10+
/// </summary>
11+
public object? Sender { get; }
12+
13+
/// <summary>
14+
/// The event name (e.g. "Tapped", "Swiped", etc.)
15+
/// </summary>
16+
public string EventName { get; }
17+
18+
/// <summary>
19+
/// Any extra data to be included in the breadcrumb. This would typically be event specific information (for example
20+
/// it could include the X, Y coordinates of a tap event).
21+
/// </summary>
22+
public IEnumerable<KeyValuePair<string, string>> ExtraData { get; }
23+
24+
/// <summary>
25+
/// Creates a new BreadcrumbEvent
26+
/// </summary>
27+
public BreadcrumbEvent(object? sender, string eventName)
28+
: this(sender, eventName, Array.Empty<KeyValuePair<string, string>>())
29+
{
30+
}
31+
32+
/// <summary>
33+
/// Creates a new BreadcrumbEvent
34+
/// </summary>
35+
public BreadcrumbEvent(
36+
object? sender,
37+
string eventName,
38+
params IEnumerable<KeyValuePair<string, string>> extraData)
39+
{
40+
Sender = sender;
41+
EventName = eventName;
42+
ExtraData = extraData;
43+
}
44+
45+
/// <summary>
46+
/// Creates a new BreadcrumbEvent
47+
/// </summary>
48+
public BreadcrumbEvent(
49+
object? sender,
50+
string eventName,
51+
params IEnumerable<(string key, string value)> extraData) : this(sender, eventName, extraData.Select(
52+
e => new KeyValuePair<string, string>(e.key, e.value)))
53+
{
54+
}
55+
56+
/// <summary>
57+
/// This constructor remains for backward compatibility.
58+
/// </summary>
59+
/// <param name="sender"></param>
60+
/// <param name="eventName"></param>
61+
/// <param name="extraData"></param>
62+
[Obsolete("Use one of the other simpler constructors instead.")]
63+
public BreadcrumbEvent(
64+
object? sender,
65+
string eventName,
66+
IEnumerable<(string Key, string Value)>[] extraData) : this(sender, eventName, extraData.SelectMany(
67+
x => x.Select(pair => new KeyValuePair<string, string>(pair.Key, pair.Value)))
68+
)
69+
{
70+
}
71+
}

src/Sentry.Maui/IMauiElementEventBinder.cs

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,3 @@ public interface IMauiElementEventBinder
2121
/// <param name="element"></param>
2222
public void UnBind(VisualElement element);
2323
}
24-
25-
/// <summary>
26-
/// Breadcrumb arguments
27-
/// </summary>
28-
/// <param name="Sender"></param>
29-
/// <param name="EventName"></param>
30-
/// <param name="ExtraData"></param>
31-
public record BreadcrumbEvent(
32-
object? Sender,
33-
string EventName,
34-
params IEnumerable<(string Key, string Value)>[] ExtraData
35-
);

src/Sentry.Maui/Internal/MauiButtonEventsBinder.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@ namespace Sentry.Maui.Internal;
33
/// <inheritdoc />
44
public class MauiButtonEventsBinder : IMauiElementEventBinder
55
{
6-
private Action<BreadcrumbEvent>? addBreadcrumbCallback;
6+
private Action<BreadcrumbEvent>? _addBreadcrumbCallback;
77

88
/// <inheritdoc />
99
public void Bind(VisualElement element, Action<BreadcrumbEvent> addBreadcrumb)
1010
{
11-
addBreadcrumbCallback = addBreadcrumb;
11+
_addBreadcrumbCallback = addBreadcrumb;
1212

1313
if (element is Button button)
1414
{
@@ -30,11 +30,11 @@ public void UnBind(VisualElement element)
3030
}
3131

3232
private void OnButtonOnClicked(object? sender, EventArgs _)
33-
=> addBreadcrumbCallback?.Invoke(new(sender, nameof(Button.Clicked)));
33+
=> _addBreadcrumbCallback?.Invoke(new(sender, nameof(Button.Clicked)));
3434

3535
private void OnButtonOnPressed(object? sender, EventArgs _)
36-
=> addBreadcrumbCallback?.Invoke(new(sender, nameof(Button.Pressed)));
36+
=> _addBreadcrumbCallback?.Invoke(new(sender, nameof(Button.Pressed)));
3737

3838
private void OnButtonOnReleased(object? sender, EventArgs _)
39-
=> addBreadcrumbCallback?.Invoke(new(sender, nameof(Button.Released)));
39+
=> _addBreadcrumbCallback?.Invoke(new(sender, nameof(Button.Released)));
4040
}

src/Sentry.Maui/Internal/MauiEventsBinder.cs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,14 @@ internal void OnBreadcrumbCreateCallback(BreadcrumbEvent breadcrumb)
132132
breadcrumb.Sender,
133133
breadcrumb.EventName,
134134
UserType,
135-
UserActionCategory
135+
UserActionCategory,
136+
extra =>
137+
{
138+
foreach (var (key, value) in breadcrumb.ExtraData)
139+
{
140+
extra[key] = value;
141+
}
142+
}
136143
);
137144
}
138145

src/Sentry.Maui/Internal/MauiGestureRecognizerEventsBinder.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ private static void OnPointerEnteredGesture(object? sender, PointerEventArgs e)
139139
ToPointerData(e)
140140
));
141141

142-
private static IEnumerable<(string Key, string Value)> ToPointerData(PointerEventArgs e) =>
142+
private static (string Key, string Value)[] ToPointerData(PointerEventArgs e) =>
143143
[
144144
#if ANDROID
145145
("MotionEventAction", e.PlatformArgs?.MotionEvent.Action.ToString() ?? string.Empty)

test/Sentry.Maui.Tests/ApiApprovalTests.Run.DotNet8_0.verified.txt

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,20 @@ namespace Microsoft.Maui.Hosting
1111
}
1212
namespace Sentry.Maui
1313
{
14-
public class BreadcrumbEvent : System.IEquatable<Sentry.Maui.BreadcrumbEvent>
14+
public sealed class BreadcrumbEvent
1515
{
16-
public BreadcrumbEvent(object? Sender, string EventName, [System.Runtime.CompilerServices.TupleElementNames(new string[] {
16+
public BreadcrumbEvent(object? sender, string eventName) { }
17+
public BreadcrumbEvent(object? sender, string eventName, System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<string, string>> extraData) { }
18+
public BreadcrumbEvent(object? sender, string eventName, [System.Runtime.CompilerServices.TupleElementNames(new string[] {
19+
"key",
20+
"value"})] System.Collections.Generic.IEnumerable<System.ValueTuple<string, string>> extraData) { }
21+
[System.Obsolete("Use one of the other simpler constructors instead.")]
22+
public BreadcrumbEvent(object? sender, string eventName, [System.Runtime.CompilerServices.TupleElementNames(new string[] {
1723
"Key",
18-
"Value"})] params System.Collections.Generic.IEnumerable<System.ValueTuple<string, string>>[] ExtraData) { }
19-
public string EventName { get; init; }
20-
[System.Runtime.CompilerServices.TupleElementNames(new string[] {
21-
"Key",
22-
"Value"})]
23-
public System.Collections.Generic.IEnumerable<System.ValueTuple<string, string>>[] ExtraData { get; init; }
24-
public object? Sender { get; init; }
24+
"Value"})] System.Collections.Generic.IEnumerable<System.ValueTuple<string, string>>[] extraData) { }
25+
public string EventName { get; }
26+
public System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<string, string>> ExtraData { get; }
27+
public object? Sender { get; }
2528
}
2629
public interface IMauiElementEventBinder
2730
{

test/Sentry.Maui.Tests/ApiApprovalTests.Run.DotNet9_0.verified.txt

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,20 @@ namespace Microsoft.Maui.Hosting
1111
}
1212
namespace Sentry.Maui
1313
{
14-
public class BreadcrumbEvent : System.IEquatable<Sentry.Maui.BreadcrumbEvent>
14+
public sealed class BreadcrumbEvent
1515
{
16-
public BreadcrumbEvent(object? Sender, string EventName, [System.Runtime.CompilerServices.TupleElementNames(new string[] {
16+
public BreadcrumbEvent(object? sender, string eventName) { }
17+
public BreadcrumbEvent(object? sender, string eventName, [System.Runtime.CompilerServices.ParamCollection] System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<string, string>> extraData) { }
18+
public BreadcrumbEvent(object? sender, string eventName, [System.Runtime.CompilerServices.ParamCollection] [System.Runtime.CompilerServices.TupleElementNames(new string[] {
19+
"key",
20+
"value"})] System.Collections.Generic.IEnumerable<System.ValueTuple<string, string>> extraData) { }
21+
[System.Obsolete("Use one of the other simpler constructors instead.")]
22+
public BreadcrumbEvent(object? sender, string eventName, [System.Runtime.CompilerServices.TupleElementNames(new string[] {
1723
"Key",
18-
"Value"})] params System.Collections.Generic.IEnumerable<System.ValueTuple<string, string>>[] ExtraData) { }
19-
public string EventName { get; init; }
20-
[System.Runtime.CompilerServices.TupleElementNames(new string[] {
21-
"Key",
22-
"Value"})]
23-
public System.Collections.Generic.IEnumerable<System.ValueTuple<string, string>>[] ExtraData { get; init; }
24-
public object? Sender { get; init; }
24+
"Value"})] System.Collections.Generic.IEnumerable<System.ValueTuple<string, string>>[] extraData) { }
25+
public string EventName { get; }
26+
public System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<string, string>> ExtraData { get; }
27+
public object? Sender { get; }
2528
}
2629
public interface IMauiElementEventBinder
2730
{
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
using System.Collections.Generic;
2+
using FluentAssertions;
3+
using Xunit;
4+
5+
namespace Sentry.Maui.Tests;
6+
7+
public class BreadcrumbEventTests
8+
{
9+
[Fact]
10+
public void BreadcrumbEvent_OldConstructor_EquivalentToNewConstructor()
11+
{
12+
// Arrange
13+
var sender = new object();
14+
var eventName = "TestEvent";
15+
16+
// Act
17+
IEnumerable<(string Key, string Value)>[] extraData = [[("key1", "value1")], [("key2", "value2")]];
18+
#pragma warning disable CS0618 // Type or member is obsolete
19+
var oldEvent = new BreadcrumbEvent(sender, eventName, extraData);
20+
#pragma warning restore CS0618 // Type or member is obsolete
21+
var newEvent = new BreadcrumbEvent(sender, eventName, ("key1", "value1"), ("key2", "value2"));
22+
23+
// Assert
24+
oldEvent.Sender.Should().Be(newEvent.Sender);
25+
oldEvent.EventName.Should().Be(newEvent.EventName);
26+
oldEvent.ExtraData.Should().BeEquivalentTo(newEvent.ExtraData);
27+
}
28+
}

test/Sentry.Maui.Tests/MauiEventsBinderTests.Button.cs renamed to test/Sentry.Maui.Tests/MauiButtonEventsBinderTests.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@
22

33
namespace Sentry.Maui.Tests;
44

5-
public partial class MauiEventsBinderTests
5+
public class MauiButtonEventsBinderTests
66
{
7+
private readonly MauiEventsBinderFixture _fixture = new(new MauiButtonEventsBinder());
8+
79
[Theory]
810
[InlineData(nameof(Button.Clicked))]
911
[InlineData(nameof(Button.Pressed))]

0 commit comments

Comments
 (0)