From 3a3ce127c1279f901bd90e05fa87aaa333f85fee Mon Sep 17 00:00:00 2001 From: Pawel Szczodruch Date: Wed, 16 Jun 2021 15:04:50 -0700 Subject: [PATCH 1/7] added support for setting items per minute --- async_transport.go | 61 +++++++++++++++++++++++++++++++--------------- base_transport.go | 11 +++++++++ client.go | 5 ++++ client_test.go | 1 + rollbar.go | 5 ++++ sync_transport.go | 40 ++++++++++++++++++++++++------ transport.go | 2 ++ 7 files changed, 99 insertions(+), 26 deletions(-) diff --git a/async_transport.go b/async_transport.go index 61c055a..29ae3db 100644 --- a/async_transport.go +++ b/async_transport.go @@ -1,7 +1,9 @@ package rollbar import ( + "fmt" "sync" + "time" ) // AsyncTransport is a concrete implementation of the Transport type which communicates with the @@ -10,9 +12,11 @@ type AsyncTransport struct { baseTransport // Buffer is the size of the channel used for queueing asynchronous payloads for sending to // Rollbar. - Buffer int - bodyChannel chan payload - waitGroup sync.WaitGroup + Buffer int + bodyChannel chan payload + waitGroup sync.WaitGroup + startTime time.Time + perMinCounter int } type payload struct { @@ -30,6 +34,7 @@ func NewAsyncTransport(token string, endpoint string, buffer int) *AsyncTranspor Endpoint: endpoint, RetryAttempts: DefaultRetryAttempts, PrintPayloadOnError: true, + ItemsPerMinute: 0, }, bodyChannel: make(chan payload, buffer), Buffer: buffer, @@ -37,36 +42,54 @@ func NewAsyncTransport(token string, endpoint string, buffer int) *AsyncTranspor go func() { for p := range transport.bodyChannel { - canRetry, err := transport.post(p.body) - if err != nil { - if canRetry && p.retriesLeft > 0 { - p.retriesLeft -= 1 - select { - case transport.bodyChannel <- p: - default: - // This can happen if the bodyChannel had an item added to it from another - // thread while we are processing such that the channel is now full. If we try - // to send the payload back to the channel without this select statement we - // could deadlock. Instead we consider this a retry failure. + elapsedTime := time.Now().Sub(transport.startTime).Seconds() + if elapsedTime < 0 || elapsedTime >= 6 { + transport.startTime = time.Now() + transport.perMinCounter = 0 + } + if transport.shouldSend() { + canRetry, err := transport.post(p.body) + if err != nil { + if canRetry && p.retriesLeft > 0 { + p.retriesLeft -= 1 + select { + case transport.bodyChannel <- p: + default: + // This can happen if the bodyChannel had an item added to it from another + // thread while we are processing such that the channel is now full. If we try + // to send the payload back to the channel without this select statement we + // could deadlock. Instead we consider this a retry failure. + if transport.PrintPayloadOnError { + writePayloadToStderr(transport.Logger, p.body) + } + transport.waitGroup.Done() + } + } else { if transport.PrintPayloadOnError { writePayloadToStderr(transport.Logger, p.body) } transport.waitGroup.Done() } } else { - if transport.PrintPayloadOnError { - writePayloadToStderr(transport.Logger, p.body) - } transport.waitGroup.Done() + transport.perMinCounter++ } - } else { - transport.waitGroup.Done() } } }() return transport } +func (t *AsyncTransport) shouldSend() bool { + if t.ItemsPerMinute > 0 && t.perMinCounter >= t.ItemsPerMinute { + rollbarError(t.Logger, fmt.Sprintf("item per minute limit reached: %d occurences,"+ + "ignoring errors until timeout", t.perMinCounter)) + t.waitGroup.Done() + return false + } + return true +} + // Send the body to Rollbar if the channel is not currently full. // Returns ErrBufferFull if the underlying channel is full. func (t *AsyncTransport) Send(body map[string]interface{}) error { diff --git a/base_transport.go b/base_transport.go index 0b16ef4..77f5c3a 100644 --- a/base_transport.go +++ b/base_transport.go @@ -6,6 +6,7 @@ import ( "io" "io/ioutil" "net/http" + "time" ) type baseTransport struct { @@ -24,8 +25,13 @@ type baseTransport struct { // PrintPayloadOnError is whether or not to output the payload to the set logger or to stderr if // an error occurs during transport to the Rollbar API. PrintPayloadOnError bool + // ItemsPerMinute has the max number of items to send in a given minute + ItemsPerMinute int // custom http client (http.DefaultClient used by default) httpClient *http.Client + + perMinCounter int + startTime time.Time } // SetToken updates the token to use for future API requests. @@ -38,6 +44,11 @@ func (t *baseTransport) SetEndpoint(endpoint string) { t.Endpoint = endpoint } +// SetItemsPerMinute sets the max number of items to send in a given minute +func (t *baseTransport) SetItemsPerMinute(itemsPerMinute int) { + t.ItemsPerMinute = itemsPerMinute +} + // SetLogger updates the logger that this transport uses for reporting errors that occur while // processing items. func (t *baseTransport) SetLogger(logger ClientLogger) { diff --git a/client.go b/client.go index 6793c41..b7a5c53 100644 --- a/client.go +++ b/client.go @@ -240,6 +240,11 @@ func (c *Client) SetRetryAttempts(retryAttempts int) { c.Transport.SetRetryAttempts(retryAttempts) } +// SetItemsPerMinute sets the max number of items to send in a given minute +func (c *Client) SetItemsPerMinute(itemsPerMinute int) { + c.Transport.SetItemsPerMinute(itemsPerMinute) +} + // SetPrintPayloadOnError sets whether or not to output the payload to the set logger or to // stderr if an error occurs during transport to the Rollbar API. For example, if you hit // your rate limit and we run out of retry attempts, then if this is true we will output the diff --git a/client_test.go b/client_test.go index e213bdd..c99f865 100644 --- a/client_test.go +++ b/client_test.go @@ -32,6 +32,7 @@ func (t *TestTransport) SetLogger(_l rollbar.ClientLogger) {} func (t *TestTransport) SetRetryAttempts(_r int) {} func (t *TestTransport) SetPrintPayloadOnError(_p bool) {} func (t *TestTransport) SetHTTPClient(_c *http.Client) {} +func (t *TestTransport) SetItemsPerMinute(_r int) {} func (t *TestTransport) Send(body map[string]interface{}) error { t.Body = body return nil diff --git a/rollbar.go b/rollbar.go index 33776be..f6bda08 100644 --- a/rollbar.go +++ b/rollbar.go @@ -128,6 +128,11 @@ func SetEndpoint(endpoint string) { std.SetEndpoint(endpoint) } +// SetItemsPerMinute sets the max number of items to send in a given minute +func SetItemsPerMinute(itemsPerMinute int) { + std.SetItemsPerMinute(itemsPerMinute) +} + // SetPlatform sets the platform on the managed Client instance. // The platform is reported for all Rollbar items. The default is // the running operating system (darwin, freebsd, linux, etc.) but it can diff --git a/sync_transport.go b/sync_transport.go index e56c2fe..f01a336 100644 --- a/sync_transport.go +++ b/sync_transport.go @@ -1,5 +1,10 @@ package rollbar +import ( + "fmt" + "time" +) + // SyncTransport is a concrete implementation of the Transport type which communicates with the // Rollbar API synchronously. type SyncTransport struct { @@ -15,6 +20,9 @@ func NewSyncTransport(token, endpoint string) *SyncTransport { Endpoint: endpoint, RetryAttempts: DefaultRetryAttempts, PrintPayloadOnError: true, + ItemsPerMinute: 0, + perMinCounter: 0, + startTime: time.Now(), }, } } @@ -28,19 +36,37 @@ func (t *SyncTransport) Send(body map[string]interface{}) error { } func (t *SyncTransport) doSend(body map[string]interface{}, retriesLeft int) error { - canRetry, err := t.post(body) - if err != nil { - if !canRetry || retriesLeft <= 0 { - if t.PrintPayloadOnError { - writePayloadToStderr(t.Logger, body) + elapsedTime := time.Now().Sub(t.startTime).Seconds() + if elapsedTime < 0 || elapsedTime >= 6 { + t.startTime = time.Now() + t.perMinCounter = 0 + } + if t.shouldSend() { + canRetry, err := t.post(body) + if err != nil { + if !canRetry || retriesLeft <= 0 { + if t.PrintPayloadOnError { + writePayloadToStderr(t.Logger, body) + } + return err } - return err + return t.doSend(body, retriesLeft-1) + } else { + t.perMinCounter++ } - return t.doSend(body, retriesLeft-1) } return nil } +func (t *SyncTransport) shouldSend() bool { + if t.ItemsPerMinute > 0 && t.perMinCounter >= t.ItemsPerMinute { + rollbarError(t.Logger, fmt.Sprintf("item per minute limit reached: %d occurences,"+ + "ignoring errors until timeout", t.perMinCounter)) + return false + } + return true +} + // Wait is a no-op for the synchronous transport. func (t *SyncTransport) Wait() {} diff --git a/transport.go b/transport.go index 12faf31..ccbc986 100644 --- a/transport.go +++ b/transport.go @@ -40,6 +40,8 @@ type Transport interface { SetPrintPayloadOnError(printPayloadOnError bool) // Sets custom http client. http.DefaultClient is used by default SetHTTPClient(httpClient *http.Client) + // SetItemsPerMinute sets the max number of items to send in a given minute + SetItemsPerMinute(itemsPerMinute int) } // ClientLogger is the interface used by the rollbar Client/Transport to report problems. From 90df42f4c8044c78e6567a72fef4c5624adbac7a Mon Sep 17 00:00:00 2001 From: Pawel Szczodruch Date: Wed, 16 Jun 2021 15:20:23 -0700 Subject: [PATCH 2/7] fixed the message --- async_transport.go | 2 +- sync_transport.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/async_transport.go b/async_transport.go index 29ae3db..0ed3e29 100644 --- a/async_transport.go +++ b/async_transport.go @@ -82,7 +82,7 @@ func NewAsyncTransport(token string, endpoint string, buffer int) *AsyncTranspor func (t *AsyncTransport) shouldSend() bool { if t.ItemsPerMinute > 0 && t.perMinCounter >= t.ItemsPerMinute { - rollbarError(t.Logger, fmt.Sprintf("item per minute limit reached: %d occurences,"+ + rollbarError(t.Logger, fmt.Sprintf("item per minute limit reached: %d occurences, "+ "ignoring errors until timeout", t.perMinCounter)) t.waitGroup.Done() return false diff --git a/sync_transport.go b/sync_transport.go index f01a336..b8b2463 100644 --- a/sync_transport.go +++ b/sync_transport.go @@ -60,7 +60,7 @@ func (t *SyncTransport) doSend(body map[string]interface{}, retriesLeft int) err func (t *SyncTransport) shouldSend() bool { if t.ItemsPerMinute > 0 && t.perMinCounter >= t.ItemsPerMinute { - rollbarError(t.Logger, fmt.Sprintf("item per minute limit reached: %d occurences,"+ + rollbarError(t.Logger, fmt.Sprintf("item per minute limit reached: %d occurences, "+ "ignoring errors until timeout", t.perMinCounter)) return false } From 4a4f280c80d607eaa0b6bc816e2052b411bc15c7 Mon Sep 17 00:00:00 2001 From: Pawel Szczodruch Date: Wed, 16 Jun 2021 15:31:36 -0700 Subject: [PATCH 3/7] correcting resetting the time --- async_transport.go | 2 +- sync_transport.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/async_transport.go b/async_transport.go index 0ed3e29..3489712 100644 --- a/async_transport.go +++ b/async_transport.go @@ -43,7 +43,7 @@ func NewAsyncTransport(token string, endpoint string, buffer int) *AsyncTranspor go func() { for p := range transport.bodyChannel { elapsedTime := time.Now().Sub(transport.startTime).Seconds() - if elapsedTime < 0 || elapsedTime >= 6 { + if elapsedTime < 0 || elapsedTime >= 60 { transport.startTime = time.Now() transport.perMinCounter = 0 } diff --git a/sync_transport.go b/sync_transport.go index b8b2463..350b610 100644 --- a/sync_transport.go +++ b/sync_transport.go @@ -37,7 +37,7 @@ func (t *SyncTransport) Send(body map[string]interface{}) error { func (t *SyncTransport) doSend(body map[string]interface{}, retriesLeft int) error { elapsedTime := time.Now().Sub(t.startTime).Seconds() - if elapsedTime < 0 || elapsedTime >= 6 { + if elapsedTime < 0 || elapsedTime >= 60 { t.startTime = time.Now() t.perMinCounter = 0 } From f0b8147aefe3b50742e926816ccbc5e15e4882a0 Mon Sep 17 00:00:00 2001 From: Pawel Szczodruch Date: Wed, 16 Jun 2021 15:54:29 -0700 Subject: [PATCH 4/7] moved shouldSend to baseTransport --- async_transport.go | 13 ++----------- base_transport.go | 10 ++++++++++ sync_transport.go | 10 ---------- 3 files changed, 12 insertions(+), 21 deletions(-) diff --git a/async_transport.go b/async_transport.go index 3489712..4f56926 100644 --- a/async_transport.go +++ b/async_transport.go @@ -1,7 +1,6 @@ package rollbar import ( - "fmt" "sync" "time" ) @@ -74,22 +73,14 @@ func NewAsyncTransport(token string, endpoint string, buffer int) *AsyncTranspor transport.waitGroup.Done() transport.perMinCounter++ } + } else { + transport.waitGroup.Done() } } }() return transport } -func (t *AsyncTransport) shouldSend() bool { - if t.ItemsPerMinute > 0 && t.perMinCounter >= t.ItemsPerMinute { - rollbarError(t.Logger, fmt.Sprintf("item per minute limit reached: %d occurences, "+ - "ignoring errors until timeout", t.perMinCounter)) - t.waitGroup.Done() - return false - } - return true -} - // Send the body to Rollbar if the channel is not currently full. // Returns ErrBufferFull if the underlying channel is full. func (t *AsyncTransport) Send(body map[string]interface{}) error { diff --git a/base_transport.go b/base_transport.go index 77f5c3a..e205de6 100644 --- a/base_transport.go +++ b/base_transport.go @@ -3,6 +3,7 @@ package rollbar import ( "bytes" "encoding/json" + "fmt" "io" "io/ioutil" "net/http" @@ -117,3 +118,12 @@ func (t *baseTransport) post(body map[string]interface{}) (bool, error) { return false, nil } + +func (t *baseTransport) shouldSend() bool { + if t.ItemsPerMinute > 0 && t.perMinCounter >= t.ItemsPerMinute { + rollbarError(t.Logger, fmt.Sprintf("item per minute limit reached: %d occurences, "+ + "ignoring errors until timeout", t.perMinCounter)) + return false + } + return true +} diff --git a/sync_transport.go b/sync_transport.go index 350b610..db54ad8 100644 --- a/sync_transport.go +++ b/sync_transport.go @@ -1,7 +1,6 @@ package rollbar import ( - "fmt" "time" ) @@ -58,15 +57,6 @@ func (t *SyncTransport) doSend(body map[string]interface{}, retriesLeft int) err return nil } -func (t *SyncTransport) shouldSend() bool { - if t.ItemsPerMinute > 0 && t.perMinCounter >= t.ItemsPerMinute { - rollbarError(t.Logger, fmt.Sprintf("item per minute limit reached: %d occurences, "+ - "ignoring errors until timeout", t.perMinCounter)) - return false - } - return true -} - // Wait is a no-op for the synchronous transport. func (t *SyncTransport) Wait() {} From 45ec3c996bc5c2bafb0e036c06a429ff4d2112cb Mon Sep 17 00:00:00 2001 From: Pawel Szczodruch Date: Thu, 17 Jun 2021 16:22:09 -0700 Subject: [PATCH 5/7] added unit tests --- async_transport.go | 8 ++--- async_transport_test.go | 49 +++++++++++++++++++------- client.go | 78 +++++++++++++++++++++++------------------ client_test.go | 5 +++ sync_transport_test.go | 49 +++++++++++++++++++------- 5 files changed, 125 insertions(+), 64 deletions(-) diff --git a/async_transport.go b/async_transport.go index 4f56926..10fb109 100644 --- a/async_transport.go +++ b/async_transport.go @@ -11,11 +11,9 @@ type AsyncTransport struct { baseTransport // Buffer is the size of the channel used for queueing asynchronous payloads for sending to // Rollbar. - Buffer int - bodyChannel chan payload - waitGroup sync.WaitGroup - startTime time.Time - perMinCounter int + Buffer int + bodyChannel chan payload + waitGroup sync.WaitGroup } type payload struct { diff --git a/async_transport_test.go b/async_transport_test.go index 470e485..192372a 100644 --- a/async_transport_test.go +++ b/async_transport_test.go @@ -1,13 +1,12 @@ -package rollbar_test +package rollbar import ( - "github.com/rollbar/rollbar-go" "testing" ) func TestAsyncTransportSend(t *testing.T) { - transport := rollbar.NewAsyncTransport("", "", 1) - transport.SetLogger(&rollbar.SilentClientLogger{}) + transport := NewAsyncTransport("", "", 1) + transport.SetLogger(&SilentClientLogger{}) body := map[string]interface{}{ "hello": "world", } @@ -19,8 +18,8 @@ func TestAsyncTransportSend(t *testing.T) { } func TestAsyncTransportSendFull(t *testing.T) { - transport := rollbar.NewAsyncTransport("", "", 1) - transport.SetLogger(&rollbar.SilentClientLogger{}) + transport := NewAsyncTransport("", "", 1) + transport.SetLogger(&SilentClientLogger{}) body := map[string]interface{}{ "hello": "world", } @@ -31,11 +30,14 @@ func TestAsyncTransportSendFull(t *testing.T) { t.Error("Expected to receive ErrBufferFull") } transport.Wait() + if transport.perMinCounter != 1 { + t.Error("shouldSend check failed") + } } func TestAsyncTransportClose(t *testing.T) { - transport := rollbar.NewAsyncTransport("", "", 1) - transport.SetLogger(&rollbar.SilentClientLogger{}) + transport := NewAsyncTransport("", "", 1) + transport.SetLogger(&SilentClientLogger{}) result := transport.Close() if result != nil { t.Error("Close returned an unexpected error:", result) @@ -43,8 +45,8 @@ func TestAsyncTransportClose(t *testing.T) { } func TestAsyncTransportSetToken(t *testing.T) { - transport := rollbar.NewAsyncTransport("", "", 1) - transport.SetLogger(&rollbar.SilentClientLogger{}) + transport := NewAsyncTransport("", "", 1) + transport.SetLogger(&SilentClientLogger{}) token := "abc" transport.SetToken(token) if transport.Token != token { @@ -53,11 +55,34 @@ func TestAsyncTransportSetToken(t *testing.T) { } func TestAsyncTransportSetEndpoint(t *testing.T) { - transport := rollbar.NewAsyncTransport("", "", 1) - transport.SetLogger(&rollbar.SilentClientLogger{}) + transport := NewAsyncTransport("", "", 1) + transport.SetLogger(&SilentClientLogger{}) endpoint := "https://fake.com" transport.SetEndpoint(endpoint) if transport.Endpoint != endpoint { t.Error("SetEndpoint failed") } } + +func TestAsyncTransportNotSend(t *testing.T) { + transport := NewAsyncTransport("", "", 2) + transport.SetLogger(&SilentClientLogger{}) + transport.SetItemsPerMinute(1) + if transport.ItemsPerMinute != 1 { + t.Error("SetItemsPerMinute failed") + } + + body := map[string]interface{}{ + "hello": "world", + } + + transport.Send(body) + result := transport.Send(body) + if result != nil { + t.Error("Send returned an unexpected error:", result) + } + transport.Wait() + if transport.perMinCounter != 1 { + t.Error("shouldSend check failed") + } +} diff --git a/client.go b/client.go index b7a5c53..b4381e4 100644 --- a/client.go +++ b/client.go @@ -242,6 +242,7 @@ func (c *Client) SetRetryAttempts(retryAttempts int) { // SetItemsPerMinute sets the max number of items to send in a given minute func (c *Client) SetItemsPerMinute(itemsPerMinute int) { + c.configuration.itemsPerMinute = itemsPerMinute c.Transport.SetItemsPerMinute(itemsPerMinute) } @@ -263,6 +264,11 @@ func (c *Client) Token() string { return c.configuration.token } +// ItemsPerMinute is the currently set Rollbar items per minute +func (c *Client) ItemsPerMinute() int { + return c.configuration.itemsPerMinute +} + // Environment is the currently set environment underwhich all errors and // messages will be submitted. func (c *Client) Environment() string { @@ -657,24 +663,25 @@ const ( ) type configuration struct { - enabled bool - token string - environment string - platform string - codeVersion string - serverHost string - serverRoot string - endpoint string - custom map[string]interface{} - fingerprint bool - scrubHeaders *regexp.Regexp - scrubFields *regexp.Regexp - checkIgnore func(string) bool - transform func(map[string]interface{}) - unwrapper UnwrapperFunc - stackTracer StackTracerFunc - person Person - captureIp captureIp + enabled bool + token string + environment string + platform string + codeVersion string + serverHost string + serverRoot string + endpoint string + custom map[string]interface{} + fingerprint bool + scrubHeaders *regexp.Regexp + scrubFields *regexp.Regexp + checkIgnore func(string) bool + transform func(map[string]interface{}) + unwrapper UnwrapperFunc + stackTracer StackTracerFunc + person Person + captureIp captureIp + itemsPerMinute int } func createConfiguration(token, environment, codeVersion, serverHost, serverRoot string) configuration { @@ -683,23 +690,24 @@ func createConfiguration(token, environment, codeVersion, serverHost, serverRoot hostname, _ = os.Hostname() } return configuration{ - enabled: true, - token: token, - environment: environment, - platform: runtime.GOOS, - endpoint: "https://api.rollbar.com/api/1/item/", - scrubHeaders: regexp.MustCompile("Authorization"), - scrubFields: regexp.MustCompile("password|secret|token"), - codeVersion: codeVersion, - serverHost: hostname, - serverRoot: serverRoot, - fingerprint: false, - checkIgnore: func(_s string) bool { return false }, - transform: func(_d map[string]interface{}) {}, - unwrapper: DefaultUnwrapper, - stackTracer: DefaultStackTracer, - person: Person{}, - captureIp: CaptureIpFull, + enabled: true, + token: token, + environment: environment, + platform: runtime.GOOS, + endpoint: "https://api.rollbar.com/api/1/item/", + scrubHeaders: regexp.MustCompile("Authorization"), + scrubFields: regexp.MustCompile("password|secret|token"), + codeVersion: codeVersion, + serverHost: hostname, + serverRoot: serverRoot, + fingerprint: false, + checkIgnore: func(_s string) bool { return false }, + transform: func(_d map[string]interface{}) {}, + unwrapper: DefaultUnwrapper, + stackTracer: DefaultStackTracer, + person: Person{}, + captureIp: CaptureIpFull, + itemsPerMinute: 0, } } diff --git a/client_test.go b/client_test.go index c99f865..b4235ed 100644 --- a/client_test.go +++ b/client_test.go @@ -426,6 +426,7 @@ func testGettersAndSetters(client *rollbar.Client, t *testing.T) { scrubHeaders := regexp.MustCompile("Foo") scrubFields := regexp.MustCompile("squirrel|doggo") captureIP := rollbar.CaptureIpNone + itemsPerMinute := 10 errorIfEqual(token, client.Token(), t) errorIfEqual(environment, client.Environment(), t) @@ -439,6 +440,7 @@ func testGettersAndSetters(client *rollbar.Client, t *testing.T) { errorIfEqual(scrubHeaders, client.ScrubHeaders(), t) errorIfEqual(scrubHeaders, client.Telemetry.Network.ScrubHeaders, t) errorIfEqual(scrubFields, client.ScrubFields(), t) + errorIfEqual(itemsPerMinute, client.ItemsPerMinute(), t) if client.Fingerprint() { t.Error("expected fingerprint to default to false") @@ -469,6 +471,7 @@ func testGettersAndSetters(client *rollbar.Client, t *testing.T) { client.SetTelemetry() client.SetEnabled(true) + client.SetItemsPerMinute(itemsPerMinute) errorIfNotEqual(token, client.Token(), t) errorIfNotEqual(environment, client.Environment(), t) @@ -482,6 +485,7 @@ func testGettersAndSetters(client *rollbar.Client, t *testing.T) { errorIfNotEqual(scrubHeaders, client.ScrubHeaders(), t) errorIfNotEqual(scrubHeaders, client.Telemetry.Network.ScrubHeaders, t) errorIfNotEqual(scrubFields, client.ScrubFields(), t) + errorIfNotEqual(itemsPerMinute, client.ItemsPerMinute(), t) if !client.Fingerprint() { t.Error("expected fingerprint to default to false") @@ -514,6 +518,7 @@ func testGettersAndSetters(client *rollbar.Client, t *testing.T) { errorIfNotEqual(fingerprint, configuredOptions["fingerprint"].(bool), t) errorIfNotEqual(scrubHeaders, configuredOptions["scrubHeaders"].(*regexp.Regexp), t) errorIfNotEqual(scrubFields, configuredOptions["scrubFields"].(*regexp.Regexp), t) + errorIfNotEqual(scrubFields, configuredOptions["itemsPerMinute"].(int), t) } else { t.Fail() diff --git a/sync_transport_test.go b/sync_transport_test.go index afc6bdb..4a8db37 100644 --- a/sync_transport_test.go +++ b/sync_transport_test.go @@ -1,13 +1,12 @@ -package rollbar_test +package rollbar import ( - "github.com/rollbar/rollbar-go" "testing" ) func TestSyncTransportSend(t *testing.T) { - transport := rollbar.NewSyncTransport("", "") - transport.SetLogger(&rollbar.SilentClientLogger{}) + transport := NewSyncTransport("", "") + transport.SetLogger(&SilentClientLogger{}) body := map[string]interface{}{ "hello": "world", } @@ -18,8 +17,8 @@ func TestSyncTransportSend(t *testing.T) { } func TestSyncTransportSendTwice(t *testing.T) { - transport := rollbar.NewSyncTransport("", "") - transport.SetLogger(&rollbar.SilentClientLogger{}) + transport := NewSyncTransport("", "") + transport.SetLogger(&SilentClientLogger{}) body := map[string]interface{}{ "hello": "world", } @@ -29,11 +28,15 @@ func TestSyncTransportSendTwice(t *testing.T) { if result != nil { t.Error("Send returned an unexpected error:", result) } + + if transport.perMinCounter != 2 { + t.Error("shouldSend check failed") + } } func TestSyncTransportClose(t *testing.T) { - transport := rollbar.NewSyncTransport("", "") - transport.SetLogger(&rollbar.SilentClientLogger{}) + transport := NewSyncTransport("", "") + transport.SetLogger(&SilentClientLogger{}) result := transport.Close() if result != nil { t.Error("Close returned an unexpected error:", result) @@ -41,8 +44,8 @@ func TestSyncTransportClose(t *testing.T) { } func TestSyncTransportSetToken(t *testing.T) { - transport := rollbar.NewSyncTransport("", "") - transport.SetLogger(&rollbar.SilentClientLogger{}) + transport := NewSyncTransport("", "") + transport.SetLogger(&SilentClientLogger{}) token := "abc" transport.SetToken(token) if transport.Token != token { @@ -51,11 +54,33 @@ func TestSyncTransportSetToken(t *testing.T) { } func TestSyncTransportSetEndpoint(t *testing.T) { - transport := rollbar.NewSyncTransport("", "") - transport.SetLogger(&rollbar.SilentClientLogger{}) + transport := NewSyncTransport("", "") + transport.SetLogger(&SilentClientLogger{}) endpoint := "https://fake.com" transport.SetEndpoint(endpoint) if transport.Endpoint != endpoint { t.Error("SetEndpoint failed") } } + +func TestSyncTransportNotSend(t *testing.T) { + transport := NewSyncTransport("", "") + transport.SetLogger(&SilentClientLogger{}) + transport.SetItemsPerMinute(1) + if transport.ItemsPerMinute != 1 { + t.Error("SetItemsPerMinute failed") + } + + body := map[string]interface{}{ + "hello": "world", + } + + transport.Send(body) + result := transport.Send(body) + if result != nil { + t.Error("Send returned an unexpected error:", result) + } + if transport.perMinCounter != 1 { + t.Error("shouldSend check failed") + } +} From d69a6f99d2e8203d6cc3fdc3e1e9f2c8a2c36264 Mon Sep 17 00:00:00 2001 From: Pawel Szczodruch Date: Thu, 17 Jun 2021 16:28:17 -0700 Subject: [PATCH 6/7] fix unit tests --- client_test.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/client_test.go b/client_test.go index b4235ed..79be3f2 100644 --- a/client_test.go +++ b/client_test.go @@ -518,8 +518,6 @@ func testGettersAndSetters(client *rollbar.Client, t *testing.T) { errorIfNotEqual(fingerprint, configuredOptions["fingerprint"].(bool), t) errorIfNotEqual(scrubHeaders, configuredOptions["scrubHeaders"].(*regexp.Regexp), t) errorIfNotEqual(scrubFields, configuredOptions["scrubFields"].(*regexp.Regexp), t) - errorIfNotEqual(scrubFields, configuredOptions["itemsPerMinute"].(int), t) - } else { t.Fail() } From 66c23597c4135fc0840743fc6b875e6943425723 Mon Sep 17 00:00:00 2001 From: Pawel Szczodruch Date: Fri, 18 Jun 2021 09:47:53 -0700 Subject: [PATCH 7/7] added itemsPerMinute to configuration --- client_test.go | 1 + transforms.go | 29 +++++++++++++++-------------- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/client_test.go b/client_test.go index 79be3f2..09c13b8 100644 --- a/client_test.go +++ b/client_test.go @@ -518,6 +518,7 @@ func testGettersAndSetters(client *rollbar.Client, t *testing.T) { errorIfNotEqual(fingerprint, configuredOptions["fingerprint"].(bool), t) errorIfNotEqual(scrubHeaders, configuredOptions["scrubHeaders"].(*regexp.Regexp), t) errorIfNotEqual(scrubFields, configuredOptions["scrubFields"].(*regexp.Regexp), t) + errorIfNotEqual(itemsPerMinute, configuredOptions["itemsPerMinute"].(int), t) } else { t.Fail() } diff --git a/transforms.go b/transforms.go index 11278e5..8dff133 100644 --- a/transforms.go +++ b/transforms.go @@ -79,20 +79,21 @@ func buildCustom(custom map[string]interface{}, extras map[string]interface{}) m func buildConfiguredOptions(configuration configuration) map[string]interface{} { return map[string]interface{}{ - "environment": configuration.environment, - "endpoint": configuration.endpoint, - "platform": configuration.platform, - "codeVersion": configuration.codeVersion, - "serverHost": configuration.serverHost, - "serverRoot": configuration.serverRoot, - "fingerprint": configuration.fingerprint, - "scrubHeaders": configuration.scrubHeaders, - "scrubFields": configuration.scrubFields, - "transform": functionToString(configuration.transform), - "unwrapper": functionToString(configuration.unwrapper), - "stackTracer": functionToString(configuration.stackTracer), - "checkIgnore": functionToString(configuration.checkIgnore), - "captureIp": configuration.captureIp, + "environment": configuration.environment, + "endpoint": configuration.endpoint, + "platform": configuration.platform, + "codeVersion": configuration.codeVersion, + "serverHost": configuration.serverHost, + "serverRoot": configuration.serverRoot, + "fingerprint": configuration.fingerprint, + "scrubHeaders": configuration.scrubHeaders, + "scrubFields": configuration.scrubFields, + "transform": functionToString(configuration.transform), + "unwrapper": functionToString(configuration.unwrapper), + "stackTracer": functionToString(configuration.stackTracer), + "checkIgnore": functionToString(configuration.checkIgnore), + "captureIp": configuration.captureIp, + "itemsPerMinute": configuration.itemsPerMinute, "person": map[string]string{ "Id": configuration.person.Id, "Username": configuration.person.Username,