Skip to content

Redis middleware adds 10% to micro-benchmarks #2080

Description

@jdelStrother

Issue Description

The Redis middleware (https://github.com/getsentry/sentry-ruby/blob/master/sentry-ruby/lib/sentry/redis.rb) seems to add about 10% overhead to each redis call 1, even though we don't have Sentry's redis breadcrumbs enabled.

Reproduction Steps

Comment out the GlobalRedisInstrumentation insertion at the bottom of https://github.com/getsentry/sentry-ruby/blob/master/sentry-ruby/lib/sentry/redis.rb so we can compare it on a per-instance basis:

redis = RedisClient.new
redis_with_sentry = RedisClient.new(middlewares: [Sentry::Redis::GlobalRedisInstrumentation])
Benchmark.ips {|x|
  x.report("base") { redis.call('set', 'x', 1) }
  x.report('with-sentry') { redis_with_sentry.call('set', 'y', 1) }
  x.compare!
}

Expected Behavior

Minimal overhead

Actual Behavior

11% overhead:

Warming up --------------------------------------
                base     3.329k i/100ms
         with-sentry     2.999k i/100ms
Calculating -------------------------------------
                base     32.804k (± 3.9%) i/s -    166.450k in   5.082409s
         with-sentry     29.596k (± 3.5%) i/s -    149.950k in   5.072707s

Comparison:
                base:    32804.3 i/s
         with-sentry:    29596.0 i/s - 1.11x  slower

If I disable spans & breadcrumbs (with the following change:)

diff --git a/sentry-ruby/lib/sentry/redis.rb b/sentry-ruby/lib/sentry/redis.rb
index 8646cf24..b9c3d985 100644
--- a/sentry-ruby/lib/sentry/redis.rb
+++ b/sentry-ruby/lib/sentry/redis.rb
@@ -11,7 +11,7 @@ module Sentry
     end
 
     def instrument
-      return yield unless Sentry.initialized?
+      return yield unless Sentry.initialized? && Sentry.configuration.breadcrumbs_logger.include?(LOGGER_NAME)
 
       Sentry.with_child_span(op: OP_NAME, start_timestamp: Sentry.utc_now.to_f) do |span|
         yield.tap do

it returns to negligible overhead:

Warming up --------------------------------------
                base     3.268k i/100ms
         with-sentry     3.132k i/100ms
Calculating -------------------------------------
                base     32.820k (± 3.3%) i/s -    166.668k in   5.084203s
         with-sentry     31.543k (± 2.8%) i/s -    159.732k in   5.068441s

Comparison:
                base:    32819.9 i/s
         with-sentry:    31543.2 i/s - same-ish: difference falls within error

We're only using the error-monitoring part of Sentry, and don't use the redis_logger breadcrumbs. Could we have a way of opting out?

Ruby Version

3.2.2

SDK Version

5.10.0

Integration and Its Version

Rails 7.0

Sentry Config

Sentry.init do |config|
  if Rails.env.is_production?
    config.dsn = "..."
  end
  config.excluded_exceptions += %w[
    AbstractController::ActionNotFound
    ActionController::BadRequest
    ActionController::InvalidAuthenticityToken
    ActionController::InvalidCrossOriginRequest
    ActionController::RoutingError
    ActionController::UnknownFormat
    ActionController::UnknownHttpMethod
    ActionDispatch::ParamsParser::ParseError
    ActiveRecord::RecordNotFound
    Mime::Type::InvalidMimeType
  ]

  config.include_local_variables = true

  # Sentry by default doesn't include params on error reports.
  # Which is probably reasonable, but can make it hard to determine error-causes.
  # I think we can assume that our query-strings don't contain anything too sensitive.
  config.rack_env_whitelist = [*config.rack_env_whitelist, "QUERY_STRING"] # rubocop:disable Naming/InclusiveLanguage

  # This will exclude exceptions that are triggered by one of the ignored
  # exceptions. For example, when any exception occurs in a template,
  # Rails will raise a ActionView::Template::Error, instead of the original error.
  config.inspect_exception_causes_for_exclusion = true
end

Footnotes

  1. in artificial micro-benchmarks

Metadata

Metadata

Assignees

Labels

No labels
No labels

Fields

No fields configured for issues without a type.

Projects

Status
No status

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions