Repository: getsentry/sentry-go

Issue:
Add ignoreTransactions and ignoreErrors
### Background:
To further simplfiy ignoring certain events from being sent to sentry, it is also suggested to provide `ignoreTransactions` and `ignoreErrors`

More info here develop docs updated: https://develop.sentry.dev/sdk/features/#event-sampling

- [ ] ignoreErrors
- [ ] ignoreTransactions
- [ ] SDK docs


Hints from issue comments:
@onewland: @cleptric I think I'm probably not the right assignee for this. Never worked on SDKs and I'm not a golang expert@cleptric: @onewland Yep, this was meant for @greywolve 😬

Solution patch:
diff --git a/client.go b/client.go
index 3804c8a..6f7b62f 100644
--- a/client.go
+++ b/client.go
@@ -140,6 +140,9 @@ type ClientOptions struct {
 	// and if applicable, caught errors type and value.
 	// If the match is found, then a whole event will be dropped.
 	IgnoreErrors []string
+	// List of regexp strings that will be used to match against a transaction's
+	// name.  If a match is found, then the transaction  will be dropped.
+	IgnoreTransactions []string
 	// If this flag is enabled, certain personally identifiable information (PII) is added by active integrations.
 	// By default, no such data is sent.
 	SendDefaultPII bool
@@ -371,6 +374,7 @@ func (client *Client) setupIntegrations() {
 		new(environmentIntegration),
 		new(modulesIntegration),
 		new(ignoreErrorsIntegration),
+		new(ignoreTransactionsIntegration),
 	}
 
 	if client.options.Integrations != nil {
diff --git a/integrations.go b/integrations.go
index 5d87f6b..f5ef3ef 100644
--- a/integrations.go
+++ b/integrations.go
@@ -177,6 +177,40 @@ func getIgnoreErrorsSuspects(event *Event) []string {
 	return suspects
 }
 
+// ================================
+// Ignore Transactions Integration
+// ================================
+
+type ignoreTransactionsIntegration struct {
+	ignoreTransactions []*regexp.Regexp
+}
+
+func (iei *ignoreTransactionsIntegration) Name() string {
+	return "IgnoreTransactions"
+}
+
+func (iei *ignoreTransactionsIntegration) SetupOnce(client *Client) {
+	iei.ignoreTransactions = transformStringsIntoRegexps(client.options.IgnoreTransactions)
+	client.AddEventProcessor(iei.processor)
+}
+
+func (iei *ignoreTransactionsIntegration) processor(event *Event, hint *EventHint) *Event {
+	suspect := event.Transaction
+	if suspect == "" {
+		return event
+	}
+
+	for _, pattern := range iei.ignoreTransactions {
+		if pattern.Match([]byte(suspect)) {
+			Logger.Printf("Transaction dropped due to being matched by `IgnoreTransactions` option."+
+				"| Value matched: %s | Filter used: %s", suspect, pattern)
+			return nil
+		}
+	}
+
+	return event
+}
+
 // ================================
 // Contextify Frames Integration
 // ================================



Test patch:
diff --git a/client_test.go b/client_test.go
index 5a4f29e..7f3f12d 100644
--- a/client_test.go
+++ b/client_test.go
@@ -552,6 +552,115 @@ func TestBeforeSendTransactionIsCalled(t *testing.T) {
 	assertEqual(t, lastEvent.Contexts["trace"]["span_id"], transaction.SpanID)
 }
 
+func TestIgnoreErrors(t *testing.T) {
+	tests := []struct {
+		name         string
+		ignoreErrors []string
+		message      string
+		expectDrop   bool
+	}{
+		{
+			name:         "No Match",
+			message:      "Foo",
+			ignoreErrors: []string{"Bar", "Baz"},
+			expectDrop:   false,
+		},
+		{
+			name:         "Partial Match",
+			message:      "FooBar",
+			ignoreErrors: []string{"Foo", "Baz"},
+			expectDrop:   true,
+		},
+		{
+			name:         "Exact Match",
+			message:      "Foo Bar",
+			ignoreErrors: []string{"\\bFoo\\b", "Baz"},
+			expectDrop:   true,
+		},
+		{
+			name:         "Wildcard Match",
+			message:      "Foo",
+			ignoreErrors: []string{"F*", "Bar"},
+			expectDrop:   true,
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			scope := &ScopeMock{}
+			transport := &TransportMock{}
+			client, err := NewClient(ClientOptions{
+				Transport:    transport,
+				IgnoreErrors: tt.ignoreErrors,
+			})
+			if err != nil {
+				t.Fatal(err)
+			}
+
+			client.CaptureMessage(tt.message, nil, scope)
+
+			dropped := transport.lastEvent == nil
+			if !(tt.expectDrop == dropped) {
+				t.Error("expected event to be dropped")
+			}
+		})
+	}
+}
+
+func TestIgnoreTransactions(t *testing.T) {
+	tests := []struct {
+		name               string
+		ignoreTransactions []string
+		transaction        string
+		expectDrop         bool
+	}{
+		{
+			name:               "No Match",
+			transaction:        "Foo",
+			ignoreTransactions: []string{"Bar", "Baz"},
+			expectDrop:         false,
+		},
+		{
+			name:               "Partial Match",
+			transaction:        "FooBar",
+			ignoreTransactions: []string{"Foo", "Baz"},
+			expectDrop:         true,
+		},
+		{
+			name:               "Exact Match",
+			transaction:        "Foo Bar",
+			ignoreTransactions: []string{"\\bFoo\\b", "Baz"},
+			expectDrop:         true,
+		},
+		{
+			name:               "Wildcard Match",
+			transaction:        "Foo",
+			ignoreTransactions: []string{"F*", "Bar"},
+			expectDrop:         true,
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			transport := &TransportMock{}
+			ctx := NewTestContext(ClientOptions{
+				EnableTracing:      true,
+				TracesSampleRate:   1.0,
+				Transport:          transport,
+				IgnoreTransactions: tt.ignoreTransactions,
+			})
+
+			transaction := StartTransaction(ctx,
+				tt.transaction,
+			)
+			transaction.Finish()
+
+			dropped := transport.lastEvent == nil
+			if !(tt.expectDrop == dropped) {
+				t.Error("expected event to be dropped")
+			}
+		})
+	}
+}
+
 func TestSampleRate(t *testing.T) {
 	tests := []struct {
 		SampleRate float64
diff --git a/integrations_test.go b/integrations_test.go
index 389fe30..0b97a9b 100644
--- a/integrations_test.go
+++ b/integrations_test.go
@@ -173,6 +173,39 @@ func TestIgnoreErrorsIntegration(t *testing.T) {
 	}
 }
 
+func TestIgnoreTransactionsIntegration(t *testing.T) {
+	iei := ignoreTransactionsIntegration{
+		ignoreTransactions: []*regexp.Regexp{
+			regexp.MustCompile("foo"),
+			regexp.MustCompile("(?i)bar"),
+		},
+	}
+
+	dropped := &Event{
+		Transaction: "foo",
+	}
+
+	alsoDropped := &Event{
+		Transaction: "Bar",
+	}
+
+	notDropped := &Event{
+		Transaction: "dont",
+	}
+
+	if iei.processor(dropped, &EventHint{}) != nil {
+		t.Error("Transaction should be dropped")
+	}
+
+	if iei.processor(alsoDropped, &EventHint{}) != nil {
+		t.Error("Transaction should be dropped")
+	}
+
+	if iei.processor(notDropped, &EventHint{}) == nil {
+		t.Error("Transaction should not be dropped")
+	}
+}
+
 func TestContextifyFrames(t *testing.T) {
 	cfi := contextifyFramesIntegration{
 		sr:           newSourceReader(),