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: support IgnoreTransactions client option #717

Merged
merged 3 commits into from Sep 18, 2023
Merged
Show file tree
Hide file tree
Changes from 2 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
70 changes: 56 additions & 14 deletions client.go
Expand Up @@ -9,6 +9,7 @@
"math/rand"
"net/http"
"os"
"regexp"
"sort"
"strings"
"sync"
Expand Down Expand Up @@ -136,10 +137,13 @@
// The sample rate for profiling traces in the range [0.0, 1.0].
// This is relative to TracesSampleRate - it is a ratio of profiled traces out of all sampled traces.
ProfilesSampleRate float64
// List of regexp strings that will be used to match against event's message
// and if applicable, caught errors type and value.
// If the match is found, then a whole event will be dropped.
// List of regexp strings that will be used to match against an event's
// message and if applicable, the caught error's type and value. If a match
// is found, then the 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 @@ -226,13 +230,15 @@
// Client is the underlying processor that is used by the main API and Hub
// instances. It must be created with NewClient.
type Client struct {
mu sync.RWMutex
options ClientOptions
dsn *Dsn
eventProcessors []EventProcessor
integrations []Integration
sdkIdentifier string
sdkVersion string
mu sync.RWMutex
options ClientOptions
dsn *Dsn
eventProcessors []EventProcessor
integrations []Integration
sdkIdentifier string
sdkVersion string
ignoreErrors []*regexp.Regexp
ignoreTransactions []*regexp.Regexp
// Transport is read-only. Replacing the transport of an existing client is
// not supported, create a new client instead.
Transport Transport
Expand Down Expand Up @@ -328,11 +334,31 @@
}
}

ignoreErrorsRegexes := make([]*regexp.Regexp, len(options.IgnoreErrors))
for i, re := range options.IgnoreErrors {
compiled, err := regexp.Compile(re)
if err != nil {
return nil, err
}

Check warning on line 342 in client.go

View check run for this annotation

Codecov / codecov/patch

client.go#L341-L342

Added lines #L341 - L342 were not covered by tests
ignoreErrorsRegexes[i] = compiled
}

ignoreTransactionsRegexes := make([]*regexp.Regexp, len(options.IgnoreTransactions))
for i, re := range options.IgnoreTransactions {
compiled, err := regexp.Compile(re)
if err != nil {
return nil, err
}

Check warning on line 351 in client.go

View check run for this annotation

Codecov / codecov/patch

client.go#L350-L351

Added lines #L350 - L351 were not covered by tests
ignoreTransactionsRegexes[i] = compiled
}

client := Client{
options: options,
dsn: dsn,
sdkIdentifier: sdkIdentifier,
sdkVersion: SDKVersion,
options: options,
dsn: dsn,
sdkIdentifier: sdkIdentifier,
sdkVersion: SDKVersion,
ignoreErrors: ignoreErrorsRegexes,
ignoreTransactions: ignoreTransactionsRegexes,
}

client.setupTransport()
Expand Down Expand Up @@ -627,6 +653,22 @@
}
}

if event.Type == transactionType {
for _, re := range client.ignoreTransactions {
if re.MatchString(event.Transaction) {
Logger.Println("Transaction dropped due to IgnoreTransactions match.")
return nil
}
}
} else {
for _, re := range client.ignoreErrors {
if re.MatchString(event.Message) {
Logger.Println("Event dropped due to IgnoreErrors match.")
return nil
}

Check warning on line 668 in client.go

View check run for this annotation

Codecov / codecov/patch

client.go#L666-L668

Added lines #L666 - L668 were not covered by tests
}
}

client.Transport.SendEvent(event)

return &event.EventID
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