Skip to content

Commit

Permalink
feat: support IgnoreTransactions client option (#717)
Browse files Browse the repository at this point in the history
  • Loading branch information
greywolve committed Sep 18, 2023
1 parent a835907 commit 8bf9a15
Show file tree
Hide file tree
Showing 4 changed files with 180 additions and 0 deletions.
4 changes: 4 additions & 0 deletions client.go
Expand Up @@ -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
Expand Down Expand Up @@ -371,6 +374,7 @@ func (client *Client) setupIntegrations() {
new(environmentIntegration),
new(modulesIntegration),
new(ignoreErrorsIntegration),
new(ignoreTransactionsIntegration),
}

if client.options.Integrations != nil {
Expand Down
109 changes: 109 additions & 0 deletions client_test.go
Expand Up @@ -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
Expand Down
34 changes: 34 additions & 0 deletions integrations.go
Expand Up @@ -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
// ================================
Expand Down
33 changes: 33 additions & 0 deletions integrations_test.go
Expand Up @@ -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(),
Expand Down

0 comments on commit 8bf9a15

Please sign in to comment.