Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Hint support #2351

Merged
merged 29 commits into from
May 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
556ba4c
Added SentryOptions.SetBeforeSend
jamescrosswell May 2, 2023
a713108
Added tests for new CaptureHint overloads taking a Hint parameter
jamescrosswell May 2, 2023
36699e8
Failed requests add a Hint for the HttpResponseMessage
jamescrosswell May 2, 2023
baed55b
Added BeforeBreadcrumb Hint support (for breadcrumbs on the scope only)
jamescrosswell May 3, 2023
836ac09
- Fixed ScopeExtensionTests
jamescrosswell May 4, 2023
7b4efa1
Added stub of Android platform code to enable builds to complete
jamescrosswell May 4, 2023
52e5a33
Sentry.Samples.Console.Customized now demonstrates using hints with b…
jamescrosswell May 4, 2023
baee2ca
Added missing XML docs on Hint constructors
jamescrosswell May 4, 2023
d3dae05
Updated MiddlewareLoggerIntegration tests to account for modified imp…
jamescrosswell May 4, 2023
fb6e9cf
Updated verified tests for CaptureTransaction_BeforeSendTransactionTh…
jamescrosswell May 4, 2023
d211548
Tail chasing Verify test errors
jamescrosswell May 4, 2023
6c9be76
Merge branch 'main' into feat/hint-before-send
mattjohnsonpint May 6, 2023
c1c2777
Update CHANGELOG.md
mattjohnsonpint May 6, 2023
eded3b6
Fix iOS compilation issue
mattjohnsonpint May 6, 2023
6d78761
Moved hint data from base Hint class to Items property, for clarity
jamescrosswell May 7, 2023
9142abf
Added XML docs for Hint.Items property
jamescrosswell May 7, 2023
8868e47
Updated Customized console sample to use new Hint
jamescrosswell May 7, 2023
0f701eb
- Added Hints to BeforeSendTransaction
jamescrosswell May 8, 2023
25b61f4
Attachments from the Scope get included in Hints before adding Bookma…
jamescrosswell May 9, 2023
aa6d91e
Added hint support for Transaction/Event processors
jamescrosswell May 9, 2023
aa3750f
Merge remote-tracking branch 'getsentry/main' into feat/hint-before-send
jamescrosswell May 9, 2023
860af91
- Renamed Contextual processors to ProcessorWithHint (more specific)
jamescrosswell May 9, 2023
f27a650
Merge remote-tracking branch 'origin/main' into feat/hint-before-send
jamescrosswell May 10, 2023
afb18bd
Merge branch 'main' into feat/hint-before-send
mattjohnsonpint May 15, 2023
d02f33a
Add overloads without hints
mattjohnsonpint May 15, 2023
e382114
Cleanup Hint. Just expose Attachments, not AddAttachments.
mattjohnsonpint May 15, 2023
c3fdad4
Update API snapshots
mattjohnsonpint May 15, 2023
13c70d6
Ensure hint modifications to attachments are sent
mattjohnsonpint May 15, 2023
af95623
Update CHANGELOG.md
mattjohnsonpint May 15, 2023
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
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@

### Features

- Add `Hint` support ([#2351](https://github.com/getsentry/sentry-dotnet/pull/2351))
- Currently, this allows you to manipulate attachments in the various "before" event delegates.
- Hints can also be used in event and transaction processors by implementing `ISentryEventProcessorWithHint` or `ISentryTransactionProcessorWithHint`, instead of `ISentryEventProcessor` or `ISentryTransactionProcessor`.
- Note: Obsoletes the `BeforeSend`, `BeforeSendTransaction`, and `BeforeBreadcrumb` properties on the `SentryOptions` class. They have been replaced with `SetBeforeSend`, `SetBeforeSendTransaction`, and `SetBeforeBreadcrumb` respectively. Each one provides overloads both with and without a `Hint` object.

- Allow setting the active span on the scope ([#2364](https://github.com/getsentry/sentry-dotnet/pull/2364))
- Note: Obsoletes the `Scope.GetSpan` method in favor of a `Scope.Span` property (which now has a setter as well).

Expand Down
33 changes: 23 additions & 10 deletions samples/Sentry.Samples.Console.Customized/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,28 +42,36 @@ await SentrySdk.ConfigureScopeAsync(async scope =>
// o.SampleRate = 0.5f; // Randomly drop (don't send to Sentry) half of events

// Modifications to event before it goes out. Could replace the event altogether
o.BeforeSend = @event =>
{
// Drop an event altogether:
if (@event.Tags.ContainsKey("SomeTag"))
o.SetBeforeSend((@event, _) =>
{
return null;
}
// Drop an event altogether:
if (@event.Tags.ContainsKey("SomeTag"))
{
return null;
}

return @event;
};
return @event;
}
);

// Allows inspecting and modifying, returning a new or simply rejecting (returning null)
o.BeforeBreadcrumb = crumb =>
o.SetBeforeBreadcrumb((crumb, hint) =>
{
// Don't add breadcrumbs with message containing:
if (crumb.Message?.Contains("bad breadcrumb") == true)
{
return null;
}

// Replace breadcrumbs entirely incase of a drastic hint
const string replaceBreadcrumb = "don't trust this breadcrumb";
if (hint.Items.TryGetValue(replaceBreadcrumb, out var replacementMessage))
{
return new Breadcrumb((string)replacementMessage, null, null, null, BreadcrumbLevel.Critical);
}

return crumb;
};
});

// Ignore exception by its type:
o.AddExceptionFilterForType<XsltCompileException>();
Expand Down Expand Up @@ -102,6 +110,11 @@ await SentrySdk.ConfigureScopeAsync(async scope =>
SentrySdk.AddBreadcrumb(
"A 'bad breadcrumb' that will be rejected because of 'BeforeBreadcrumb callback above.'");

SentrySdk.AddBreadcrumb(
new Breadcrumb("A breadcrumb that will be replaced by the 'BeforeBreadcrumb callback because of the hint", null),
new Hint("don't trust this breadcrumb", "trust this instead")
);

// Data added to the root scope (no PushScope called up to this point)
// The modifications done here will affect all events sent and will propagate to child scopes.
await SentrySdk.ConfigureScopeAsync(async scope =>
Expand Down
21 changes: 11 additions & 10 deletions samples/Sentry.Samples.Console.Profiling/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,19 +43,20 @@ await SentrySdk.ConfigureScopeAsync(async scope =>
// o.SampleRate = 0.5f; // Randomly drop (don't send to Sentry) half of events

// Modifications to event before it goes out. Could replace the event altogether
o.BeforeSend = @event =>
{
// Drop an event altogether:
if (@event.Tags.ContainsKey("SomeTag"))
o.SetBeforeSend((@event, _) =>
{
return null;
}
// Drop an event altogether:
if (@event.Tags.ContainsKey("SomeTag"))
{
return null;
}

return @event;
};
return @event;
}
);

// Allows inspecting and modifying, returning a new or simply rejecting (returning null)
o.BeforeBreadcrumb = crumb =>
o.SetBeforeBreadcrumb((crumb, _) =>
{
// Don't add breadcrumbs with message containing:
if (crumb.Message?.Contains("bad breadcrumb") == true)
Expand All @@ -64,7 +65,7 @@ await SentrySdk.ConfigureScopeAsync(async scope =>
}

return crumb;
};
});

// Ignore exception by its type:
o.AddExceptionFilterForType<XsltCompileException>();
Expand Down
12 changes: 12 additions & 0 deletions src/Sentry/Extensibility/DisabledHub.cs
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,11 @@ public void BindClient(ISentryClient client)
/// </summary>
public SentryId CaptureEvent(SentryEvent evt, Scope? scope = null) => SentryId.Empty;

/// <summary>
/// No-Op.
/// </summary>
public SentryId CaptureEvent(SentryEvent evt, Hint? hint, Scope? scope = null) => SentryId.Empty;

/// <summary>
/// No-Op.
/// </summary>
Expand All @@ -126,6 +131,13 @@ public void CaptureTransaction(Transaction transaction)
{
}

/// <summary>
/// No-Op.
/// </summary>
public void CaptureTransaction(Transaction transaction, Hint? hint)
{
}

/// <summary>
/// No-Op.
/// </summary>
Expand Down
36 changes: 26 additions & 10 deletions src/Sentry/Extensibility/HubAdapter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -163,33 +163,34 @@ public void AddBreadcrumb(
data,
level);

/// <summary>
/// Forwards the call to <see cref="SentrySdk"/>
/// </summary>
SentryId IHubEx.CaptureEventInternal(SentryEvent evt, Hint? hint, Scope? scope)
=> SentrySdk.CaptureEventInternal(evt, hint, scope);

/// <summary>
/// Forwards the call to <see cref="SentrySdk"/>.
/// </summary>
[DebuggerStepThrough]
public SentryId CaptureEvent(SentryEvent evt)
=> SentrySdk.CaptureEvent(evt);

/// <summary>
/// Forwards the call to <see cref="SentrySdk"/>
/// </summary>
SentryId IHubEx.CaptureEventInternal(SentryEvent evt, Scope? scope)
=> SentrySdk.CaptureEventInternal(evt, scope);

/// <summary>
/// Forwards the call to <see cref="SentrySdk"/>.
/// </summary>
[DebuggerStepThrough]
public SentryId CaptureException(Exception exception)
=> SentrySdk.CaptureException(exception);
[EditorBrowsable(EditorBrowsableState.Never)]
public SentryId CaptureEvent(SentryEvent evt, Scope? scope)
=> SentrySdk.CaptureEvent(evt, scope);

/// <summary>
/// Forwards the call to <see cref="SentrySdk"/>.
/// </summary>
[DebuggerStepThrough]
[EditorBrowsable(EditorBrowsableState.Never)]
public SentryId CaptureEvent(SentryEvent evt, Scope? scope)
=> SentrySdk.CaptureEvent(evt, scope);
public SentryId CaptureEvent(SentryEvent evt, Hint? hint, Scope? scope)
=> SentrySdk.CaptureEvent(evt, hint, scope);

/// <summary>
/// Forwards the call to <see cref="SentrySdk"/>.
Expand All @@ -199,6 +200,13 @@ public SentryId CaptureEvent(SentryEvent evt, Scope? scope)
public SentryId CaptureEvent(SentryEvent evt, Action<Scope> configureScope)
=> SentrySdk.CaptureEvent(evt, configureScope);

/// <summary>
/// Forwards the call to <see cref="SentrySdk"/>.
/// </summary>
[DebuggerStepThrough]
public SentryId CaptureException(Exception exception)
=> SentrySdk.CaptureException(exception);

/// <summary>
/// Forwards the call to <see cref="SentrySdk"/>.
/// </summary>
Expand All @@ -207,6 +215,14 @@ public SentryId CaptureEvent(SentryEvent evt, Action<Scope> configureScope)
public void CaptureTransaction(Transaction transaction)
=> SentrySdk.CaptureTransaction(transaction);

/// <summary>
/// Forwards the call to <see cref="SentrySdk"/>.
/// </summary>
[DebuggerStepThrough]
[EditorBrowsable(EditorBrowsableState.Never)]
public void CaptureTransaction(Transaction transaction, Hint? hint)
=> SentrySdk.CaptureTransaction(transaction, hint);

/// <summary>
/// Forwards the call to <see cref="SentrySdk"/>.
/// </summary>
Expand Down
12 changes: 11 additions & 1 deletion src/Sentry/Extensibility/ISentryEventProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,14 @@ public interface ISentryEventProcessor
/// Meaning the event should no longer be processed nor send.
/// </remarks>
SentryEvent? Process(SentryEvent @event);
}
}

internal static class ISentryEventProcessorExtensions
{
internal static SentryEvent? DoProcessEvent(this ISentryEventProcessor processor, SentryEvent @event, Hint hint)
{
return (processor is ISentryEventProcessorWithHint contextualProcessor)
? contextualProcessor.Process(@event, hint)
: processor.Process(@event);
}
}
21 changes: 21 additions & 0 deletions src/Sentry/Extensibility/ISentryEventProcessorWithHint.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
namespace Sentry.Extensibility;

/// <summary>
/// Process a SentryEvent during the prepare phase.
/// </summary>
public interface ISentryEventProcessorWithHint: ISentryEventProcessor
{
/// <summary>
/// Process the <see cref="SentryEvent"/>
/// </summary>
/// <param name="event">The event to process</param>
/// <param name="hint">A <see cref="Hint"/> with context that may be useful prior to sending the event</param>
/// <return>The processed event or <c>null</c> if the event was dropped.</return>
/// <remarks>
/// The event returned can be the same instance received or a new one.
/// Returning null will stop the processing pipeline so that the event will neither be processed by
/// additional event processors or sent to Sentry.
/// </remarks>
SentryEvent? Process(SentryEvent @event, Hint hint);
}

12 changes: 11 additions & 1 deletion src/Sentry/Extensibility/ISentryTransactionProcessor.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace Sentry.Extensibility;
namespace Sentry.Extensibility;

/// <summary>
/// Process a <see cref="Transaction"/> during the prepare phase.
Expand All @@ -16,3 +16,13 @@ public interface ISentryTransactionProcessor
/// </remarks>
Transaction? Process(Transaction transaction);
}

internal static class ISentryTransactionProcessorExtensions
{
internal static Transaction? DoProcessTransaction(this ISentryTransactionProcessor processor, Transaction transaction, Hint hint)
{
return (processor is ISentryTransactionProcessorWithHint contextualProcessor)
? contextualProcessor.Process(transaction, hint)
: processor.Process(transaction);
}
}
19 changes: 19 additions & 0 deletions src/Sentry/Extensibility/ISentryTransactionProcessorWithHint.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
namespace Sentry.Extensibility;

/// <summary>
/// Process a <see cref="Transaction"/> during the prepare phase.
/// </summary>
public interface ISentryTransactionProcessorWithHint: ISentryTransactionProcessor
{
/// <summary>
/// Process the <see cref="Transaction"/>
/// </summary>
/// <param name="transaction">The Transaction to process</param>
/// <param name="hint">A <see cref="Hint"/> with context that may be useful prior to sending the transaction</param>
/// <remarks>
/// The transaction returned can be the same instance received or a new one.
/// Returning null will stop the processing pipeline.
/// Meaning the transaction should no longer be processed nor send.
/// </remarks>
Transaction? Process(Transaction transaction, Hint hint);
}
73 changes: 73 additions & 0 deletions src/Sentry/Hint.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
namespace Sentry;

/// <summary>
/// A hint that can be provided when capturing a <see cref="SentryEvent"/> or when adding a <see cref="Breadcrumb"/>.
/// Hints can be used to filter or modify events, transactions, or breadcrumbs before they are sent to Sentry.
/// </summary>
public class Hint
{
private readonly List<Attachment> _attachments = new();
private readonly Dictionary<string, object?> _items = new();

/// <summary>
/// Creates a new instance of <see cref="Hint"/>.
/// </summary>
public Hint()
{
}

/// <summary>
/// Creates a new hint containing a single item.
/// </summary>
/// <param name="key">The key of the hint item.</param>
/// <param name="value">The value of the hint item.</param>
public Hint(string key, object? value)
: this()
{
_items[key] = value;
}

/// <summary>
/// The Java SDK has some logic so that certain Hint types do not copy attachments from the Scope.
/// This provides a location that allows us to do the same in the .NET SDK in the future.
/// </summary>
/// <param name="scope">The <see cref="Scope"/> that the attachments should be copied from</param>
internal void AddAttachmentsFromScope(Scope scope) => _attachments.AddRange(scope.Attachments);

/// <summary>
/// Attachments added to the Hint.
/// </summary>
/// <remarks>
/// This collection represents all of the attachments that will be sent to Sentry with the corresponding event.
/// You can add or remove attachments from this collection as needed.
/// </remarks>
public ICollection<Attachment> Attachments => _attachments;

/// <summary>
/// A dictionary of arbitrary items provided with the Hint.
/// </summary>
/// <remarks>
/// These are not sent to Sentry, but rather they are available during processing, such as when using
/// BeforeSend and others.
/// </remarks>
public IDictionary<string, object?> Items => _items;

/// <summary>
/// Creates a new Hint with one or more attachments.
/// </summary>
/// <param name="attachments">The attachment(s) to add.</param>
/// <returns>A Hint having the attachment(s).</returns>
public static Hint WithAttachments(params Attachment[] attachments) => WithAttachments(attachments.AsEnumerable());

/// <summary>
/// Creates a new Hint with attachments.
/// </summary>
/// <param name="attachments">The attachments to add.</param>
/// <returns>A Hint having the attachments.</returns>
public static Hint WithAttachments(IEnumerable<Attachment> attachments)
{
var hint = new Hint();
hint._attachments.AddRange(attachments);
return hint;
}
}
12 changes: 12 additions & 0 deletions src/Sentry/HintTypes.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
namespace Sentry;

/// <summary>
/// Constants used to name Hints generated by the Sentry SDK
/// </summary>
public static class HintTypes
{
/// <summary>
/// Used for HttpResponseMessage hints
/// </summary>
public const string HttpResponseMessage = "http-response-message";
}
Loading