Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 8 additions & 7 deletions lib/sentry/transport/rate_limiter.ex
Original file line number Diff line number Diff line change
Expand Up @@ -98,13 +98,14 @@ defmodule Sentry.Transport.RateLimiter do
@doc """
Checks whether sending items of the given data category is currently limited.

Logs and metrics have a companion byte category (`log_byte` /
`trace_metric_byte`) that Sentry can limit independently of the count
category, so a limit on either one must suppress sending. Every other category
gates on itself alone.

So an active `log_byte` limit makes this return `true` for `"log_item"`, even
though `rate_limited?("log_item")` on its own is `false`.
Logs, metrics, and attachments have companion categories (`log_byte`,
`trace_metric_byte`, and `attachment_item`) that Sentry can limit
independently of the count category, so a limit on either one must suppress
sending. Every other category gates on itself alone.

So an active `log_byte` limit makes this return `true` for `"log_item"`, and
an active `attachment_item` limit does the same for `"attachment"`, even
though the corresponding `rate_limited?/1` call on its own is `false`.
"""
@spec rate_limited_for_category?(String.t()) :: boolean()
def rate_limited_for_category?("log_item"),
Expand Down
20 changes: 20 additions & 0 deletions test/sentry/telemetry_processor_integration_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -519,6 +519,26 @@ defmodule Sentry.TelemetryProcessorIntegrationTest do
}
end

test "sends an error without attachments when attachment items are rate limited", ctx do
put_test_config(telemetry_processor_categories: [:error, :log])

set_rate_limit("attachment_item", scope: :scheduler)

:ok =
Sentry.Context.add_attachment(%Sentry.Attachment{filename: "report.txt", data: "report"})

on_exit(&Sentry.Context.clear_attachments/0)

Sentry.capture_message("pre-buffer-attachment-item-limit", result: :none)

assert [[{%{"type" => "event"}, event}]] = collect_envelopes(ctx.ref, 1, timeout: 2000)
assert event["message"]["formatted"] == "pre-buffer-attachment-item-limit"

assert collect_discarded_outcomes(ctx.ref, "ratelimit_backoff") == %{
"attachment" => 1
}
end

test "sends an error while dropping all of its rate-limited attachments", ctx do
put_test_config(telemetry_processor_categories: [:error, :log])

Expand Down
21 changes: 21 additions & 0 deletions test/sentry/transport/rate_limiter_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,27 @@ defmodule Sentry.Transport.RateLimiterTest do
assert RateLimiter.rate_limited?("trace_metric") == false
end

test "gates attachments on the attachment limit" do
set_rate_limit("attachment")

assert RateLimiter.rate_limited_for_category?("attachment") == true
assert RateLimiter.rate_limited?("attachment") == true
end

test "gates attachments on the attachment_item limit" do
set_rate_limit("attachment_item")

assert RateLimiter.rate_limited_for_category?("attachment") == true
assert RateLimiter.rate_limited?("attachment") == false
end

test "does not gate errors on attachment limits" do
set_rate_limit("attachment")
set_rate_limit("attachment_item")

assert RateLimiter.rate_limited_for_category?("error") == false
end

test "gates a category on itself when it has no companion byte category" do
set_rate_limit("error")

Expand Down
Loading