Skip to content

Commit 8bf9a15

Browse files
authored
feat: support IgnoreTransactions client option (#717)
1 parent a835907 commit 8bf9a15

File tree

4 files changed

+180
-0
lines changed

4 files changed

+180
-0
lines changed

client.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,9 @@ type ClientOptions struct {
140140
// and if applicable, caught errors type and value.
141141
// If the match is found, then a whole event will be dropped.
142142
IgnoreErrors []string
143+
// List of regexp strings that will be used to match against a transaction's
144+
// name. If a match is found, then the transaction will be dropped.
145+
IgnoreTransactions []string
143146
// If this flag is enabled, certain personally identifiable information (PII) is added by active integrations.
144147
// By default, no such data is sent.
145148
SendDefaultPII bool
@@ -371,6 +374,7 @@ func (client *Client) setupIntegrations() {
371374
new(environmentIntegration),
372375
new(modulesIntegration),
373376
new(ignoreErrorsIntegration),
377+
new(ignoreTransactionsIntegration),
374378
}
375379

376380
if client.options.Integrations != nil {

client_test.go

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -552,6 +552,115 @@ func TestBeforeSendTransactionIsCalled(t *testing.T) {
552552
assertEqual(t, lastEvent.Contexts["trace"]["span_id"], transaction.SpanID)
553553
}
554554

555+
func TestIgnoreErrors(t *testing.T) {
556+
tests := []struct {
557+
name string
558+
ignoreErrors []string
559+
message string
560+
expectDrop bool
561+
}{
562+
{
563+
name: "No Match",
564+
message: "Foo",
565+
ignoreErrors: []string{"Bar", "Baz"},
566+
expectDrop: false,
567+
},
568+
{
569+
name: "Partial Match",
570+
message: "FooBar",
571+
ignoreErrors: []string{"Foo", "Baz"},
572+
expectDrop: true,
573+
},
574+
{
575+
name: "Exact Match",
576+
message: "Foo Bar",
577+
ignoreErrors: []string{"\\bFoo\\b", "Baz"},
578+
expectDrop: true,
579+
},
580+
{
581+
name: "Wildcard Match",
582+
message: "Foo",
583+
ignoreErrors: []string{"F*", "Bar"},
584+
expectDrop: true,
585+
},
586+
}
587+
for _, tt := range tests {
588+
t.Run(tt.name, func(t *testing.T) {
589+
scope := &ScopeMock{}
590+
transport := &TransportMock{}
591+
client, err := NewClient(ClientOptions{
592+
Transport: transport,
593+
IgnoreErrors: tt.ignoreErrors,
594+
})
595+
if err != nil {
596+
t.Fatal(err)
597+
}
598+
599+
client.CaptureMessage(tt.message, nil, scope)
600+
601+
dropped := transport.lastEvent == nil
602+
if !(tt.expectDrop == dropped) {
603+
t.Error("expected event to be dropped")
604+
}
605+
})
606+
}
607+
}
608+
609+
func TestIgnoreTransactions(t *testing.T) {
610+
tests := []struct {
611+
name string
612+
ignoreTransactions []string
613+
transaction string
614+
expectDrop bool
615+
}{
616+
{
617+
name: "No Match",
618+
transaction: "Foo",
619+
ignoreTransactions: []string{"Bar", "Baz"},
620+
expectDrop: false,
621+
},
622+
{
623+
name: "Partial Match",
624+
transaction: "FooBar",
625+
ignoreTransactions: []string{"Foo", "Baz"},
626+
expectDrop: true,
627+
},
628+
{
629+
name: "Exact Match",
630+
transaction: "Foo Bar",
631+
ignoreTransactions: []string{"\\bFoo\\b", "Baz"},
632+
expectDrop: true,
633+
},
634+
{
635+
name: "Wildcard Match",
636+
transaction: "Foo",
637+
ignoreTransactions: []string{"F*", "Bar"},
638+
expectDrop: true,
639+
},
640+
}
641+
for _, tt := range tests {
642+
t.Run(tt.name, func(t *testing.T) {
643+
transport := &TransportMock{}
644+
ctx := NewTestContext(ClientOptions{
645+
EnableTracing: true,
646+
TracesSampleRate: 1.0,
647+
Transport: transport,
648+
IgnoreTransactions: tt.ignoreTransactions,
649+
})
650+
651+
transaction := StartTransaction(ctx,
652+
tt.transaction,
653+
)
654+
transaction.Finish()
655+
656+
dropped := transport.lastEvent == nil
657+
if !(tt.expectDrop == dropped) {
658+
t.Error("expected event to be dropped")
659+
}
660+
})
661+
}
662+
}
663+
555664
func TestSampleRate(t *testing.T) {
556665
tests := []struct {
557666
SampleRate float64

integrations.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,40 @@ func getIgnoreErrorsSuspects(event *Event) []string {
177177
return suspects
178178
}
179179

180+
// ================================
181+
// Ignore Transactions Integration
182+
// ================================
183+
184+
type ignoreTransactionsIntegration struct {
185+
ignoreTransactions []*regexp.Regexp
186+
}
187+
188+
func (iei *ignoreTransactionsIntegration) Name() string {
189+
return "IgnoreTransactions"
190+
}
191+
192+
func (iei *ignoreTransactionsIntegration) SetupOnce(client *Client) {
193+
iei.ignoreTransactions = transformStringsIntoRegexps(client.options.IgnoreTransactions)
194+
client.AddEventProcessor(iei.processor)
195+
}
196+
197+
func (iei *ignoreTransactionsIntegration) processor(event *Event, hint *EventHint) *Event {
198+
suspect := event.Transaction
199+
if suspect == "" {
200+
return event
201+
}
202+
203+
for _, pattern := range iei.ignoreTransactions {
204+
if pattern.Match([]byte(suspect)) {
205+
Logger.Printf("Transaction dropped due to being matched by `IgnoreTransactions` option."+
206+
"| Value matched: %s | Filter used: %s", suspect, pattern)
207+
return nil
208+
}
209+
}
210+
211+
return event
212+
}
213+
180214
// ================================
181215
// Contextify Frames Integration
182216
// ================================

integrations_test.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,39 @@ func TestIgnoreErrorsIntegration(t *testing.T) {
173173
}
174174
}
175175

176+
func TestIgnoreTransactionsIntegration(t *testing.T) {
177+
iei := ignoreTransactionsIntegration{
178+
ignoreTransactions: []*regexp.Regexp{
179+
regexp.MustCompile("foo"),
180+
regexp.MustCompile("(?i)bar"),
181+
},
182+
}
183+
184+
dropped := &Event{
185+
Transaction: "foo",
186+
}
187+
188+
alsoDropped := &Event{
189+
Transaction: "Bar",
190+
}
191+
192+
notDropped := &Event{
193+
Transaction: "dont",
194+
}
195+
196+
if iei.processor(dropped, &EventHint{}) != nil {
197+
t.Error("Transaction should be dropped")
198+
}
199+
200+
if iei.processor(alsoDropped, &EventHint{}) != nil {
201+
t.Error("Transaction should be dropped")
202+
}
203+
204+
if iei.processor(notDropped, &EventHint{}) == nil {
205+
t.Error("Transaction should not be dropped")
206+
}
207+
}
208+
176209
func TestContextifyFrames(t *testing.T) {
177210
cfi := contextifyFramesIntegration{
178211
sr: newSourceReader(),

0 commit comments

Comments
 (0)