From c2cfb80e174e435b59834587ff84a5a567c3cfd2 Mon Sep 17 00:00:00 2001 From: Anton Ovchinnikov Date: Mon, 19 Dec 2022 16:22:31 +0100 Subject: [PATCH 1/5] feat: Add beforeSendTransaction hook `beforeSendTransaction` works similarly to `beforeSend`, but it is applied only to transaction events. --- client.go | 19 ++++++++++++----- client_test.go | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+), 5 deletions(-) diff --git a/client.go b/client.go index 2c580b037..49e2cd5ff 100644 --- a/client.go +++ b/client.go @@ -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 @@ -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 diff --git a/client_test.go b/client_test.go index d7d54d3a7..4f49c04ee 100644 --- a/client_test.go +++ b/client_test.go @@ -383,6 +383,61 @@ 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() + + last_event := transport.lastEvent + + assertEqual(t, last_event.Transaction, "Bar") + // Make sure it's the same span + assertEqual(t, last_event.Contexts["trace"]["span_id"], transaction.SpanID) +} + func TestSampleRate(t *testing.T) { tests := []struct { SampleRate float64 From 8274b753e1d16576c0baa4d60c9985a993e75b61 Mon Sep 17 00:00:00 2001 From: Anton Ovchinnikov Date: Mon, 19 Dec 2022 16:29:28 +0100 Subject: [PATCH 2/5] fix linter errors --- client_test.go | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/client_test.go b/client_test.go index 4f49c04ee..52cd40169 100644 --- a/client_test.go +++ b/client_test.go @@ -431,11 +431,10 @@ func TestBeforeSendTransactionIsCalled(t *testing.T) { ) transaction.Finish() - last_event := transport.lastEvent - - assertEqual(t, last_event.Transaction, "Bar") + lastEvent := transport.lastEvent + assertEqual(t, lastEvent.Transaction, "Bar") // Make sure it's the same span - assertEqual(t, last_event.Contexts["trace"]["span_id"], transaction.SpanID) + assertEqual(t, lastEvent.Contexts["trace"]["span_id"], transaction.SpanID) } func TestSampleRate(t *testing.T) { From 249522b0c4d8fedec544a3c70830f7ae9ed3b458 Mon Sep 17 00:00:00 2001 From: Anton Ovchinnikov Date: Mon, 19 Dec 2022 16:56:03 +0100 Subject: [PATCH 3/5] Update changelog --- CHANGELOG.md | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ae9a6c29e..302822d2a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## Unreleased + +### Features + +* Add `beforeSendTransaction` hook ([#517](https://github.com/getsentry/sentry-go/pull/517)) + ## 0.16.0 The Sentry SDK team is happy to announce the immediate availability of Sentry Go SDK v0.16.0. @@ -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 { From 8850d33538c3c1ef1648e93262eae6a1337450d5 Mon Sep 17 00:00:00 2001 From: Anton Ovchinnikov Date: Mon, 9 Jan 2023 12:21:16 +0100 Subject: [PATCH 4/5] Add an example usage --- _examples/http/main.go | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/_examples/http/main.go b/_examples/http/main.go index 25c1bbbd9..5c0af03ce 100644 --- a/_examples/http/main.go +++ b/_examples/http/main.go @@ -48,11 +48,22 @@ func run() error { // Useful when getting started or trying to figure something out. Debug: true, BeforeSend: func(event *sentry.Event, hint *sentry.EventHint) *sentry.Event { - // Here you can inspect/modify events before they are sent. + // Here you can inspect/modify non-transaction events (for example, errors) before they are sent. // Returning nil drops the event. log.Printf("BeforeSend event [%s]", event.EventID) return event }, + BeforeSendTransaction: func(event *sentry.Event, hint *sentry.EventHint) *sentry.Event { + // Here you can inspect/modify transaction events before they are sent. + // Returning nil drops the event. + if strings.Contains(event.Message, "test-transaction") { + // Drop the transaction + return nil + } + event.Message += " [example]" + log.Printf("BeforeSendTransaction event [%s]", event.EventID) + return event + }, // Enable tracing EnableTracing: true, // Specify either a TracesSampleRate... From 5b5ff639cd7a496fbfa1507ff6c6d9821f7c3c7b Mon Sep 17 00:00:00 2001 From: Anton Ovchinnikov Date: Mon, 9 Jan 2023 18:30:57 +0100 Subject: [PATCH 5/5] Update changelog --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e7e438043..dafded894 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,8 @@ ### Features -* Add `beforeSendTransaction` hook ([#517](https://github.com/getsentry/sentry-go/pull/517)) +* Add `BeforeSendTransaction` hook to `ClientOptions` ([#517](https://github.com/getsentry/sentry-go/pull/517)) + * Here's [an example](https://github.com/getsentry/sentry-go/blob/master/_examples/http/main.go#L56-L66) of how BeforeSendTransaction can be used to modify or drop transaction events. ## 0.16.0