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

feat: Add BeforeSendTransaction hook #517

Merged
merged 7 commits into from Jan 11, 2023
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
10 changes: 8 additions & 2 deletions CHANGELOG.md
@@ -1,5 +1,11 @@
# Changelog

## Unreleased

### Features

* Add `beforeSendTransaction` hook ([#517](https://github.com/getsentry/sentry-go/pull/517))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mind adding a small snippet on how to use this?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess adding a link that point to the docs (when they're ready) should be enough?
This change doesn't seem to be too important or breaking enough to cover it in the changelog.

Copy link
Member

@cleptric cleptric Jan 9, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would like our changelogs to be a bit more telling, especially when it comes to new features. The Ruby SDK is a good benchmark we should aim for https://github.com/getsentry/sentry-ruby/releases

Maybe we could add the new hook to some example in the repo and point to it?
The docs are not very good at showing the actual use of this.


## 0.16.0

The Sentry SDK team is happy to announce the immediate availability of Sentry Go SDK v0.16.0.
Expand All @@ -18,10 +24,10 @@ Due to ongoing work towards a stable API for `v1.0.0`, we sadly had to include *
```
- Unify TracesSampler [#498](https://github.com/getsentry/sentry-go/pull/498)
- `TracesSampler` was changed to a callback that must return a `float64` between `0.0` and `1.0`.

For example, you can apply a sample rate of `1.0` (100%) to all `/api` transactions, and a sample rate of `0.5` (50%) to all other transactions.
You can read more about this in our [SDK docs](https://docs.sentry.io/platforms/go/configuration/filtering/#using-sampling-to-filter-transaction-events).

```go
sentry.Init(sentry.ClientOptions{
TracesSampler: sentry.TracesSampler(func(ctx sentry.SamplingContext) float64 {
Expand Down
19 changes: 14 additions & 5 deletions client.go
Expand Up @@ -140,8 +140,10 @@ type ClientOptions struct {
SendDefaultPII bool
// BeforeSend is called before error events are sent to Sentry.
// Use it to mutate the event or return nil to discard the event.
// See EventProcessor if you need to mutate transactions.
BeforeSend func(event *Event, hint *EventHint) *Event
// BeforeSendTransaction is called before transaction events are sent to Sentry.
// Use it to mutate the transaction or return nil to discard the transaction.
BeforeSendTransaction func(event *Event, hint *EventHint) *Event
// Before breadcrumb add callback.
BeforeBreadcrumb func(breadcrumb *Breadcrumb, hint *BreadcrumbHint) *Breadcrumb
// Integrations to be installed on the current Client, receives default
Expand Down Expand Up @@ -570,11 +572,18 @@ func (client *Client) processEvent(event *Event, hint *EventHint, scope EventMod
return nil
}

// As per spec, transactions do not go through BeforeSend.
if event.Type != transactionType && options.BeforeSend != nil {
if hint == nil {
hint = &EventHint{}
// Apply beforeSend* processors
if hint == nil {
hint = &EventHint{}
}
if event.Type == transactionType && options.BeforeSendTransaction != nil {
// Transaction events
if event = options.BeforeSendTransaction(event, hint); event == nil {
Logger.Println("Transaction dropped due to BeforeSendTransaction callback.")
return nil
}
} else if event.Type != transactionType && options.BeforeSend != nil {
// All other events
if event = options.BeforeSend(event, hint); event == nil {
Logger.Println("Event dropped due to BeforeSend callback.")
return nil
Expand Down
54 changes: 54 additions & 0 deletions client_test.go
Expand Up @@ -383,6 +383,60 @@ func TestBeforeSendGetAccessToEventHint(t *testing.T) {
assertEqual(t, transport.lastEvent.Message, "customComplexError: Foo 42")
}

func TestBeforeSendTransactionCanDropTransaction(t *testing.T) {
transport := &TransportMock{}
ctx := NewTestContext(ClientOptions{
EnableTracing: true,
TracesSampleRate: 1.0,
Transport: transport,
BeforeSend: func(event *Event, hint *EventHint) *Event {
t.Error("beforeSend should not be called")
return event
},
BeforeSendTransaction: func(event *Event, hint *EventHint) *Event {
assertEqual(t, event.Transaction, "Foo")
return nil
},
})

transaction := StartTransaction(ctx,
"Foo",
)
transaction.Finish()

if transport.lastEvent != nil {
t.Error("expected event to be dropped")
}
}

func TestBeforeSendTransactionIsCalled(t *testing.T) {
transport := &TransportMock{}
ctx := NewTestContext(ClientOptions{
EnableTracing: true,
TracesSampleRate: 1.0,
Transport: transport,
BeforeSend: func(event *Event, hint *EventHint) *Event {
t.Error("beforeSend should not be called")
return event
},
BeforeSendTransaction: func(event *Event, hint *EventHint) *Event {
assertEqual(t, event.Transaction, "Foo")
event.Transaction = "Bar"
return event
},
})

transaction := StartTransaction(ctx,
"Foo",
)
transaction.Finish()

lastEvent := transport.lastEvent
assertEqual(t, lastEvent.Transaction, "Bar")
// Make sure it's the same span
assertEqual(t, lastEvent.Contexts["trace"]["span_id"], transaction.SpanID)
}

func TestSampleRate(t *testing.T) {
tests := []struct {
SampleRate float64
Expand Down