lib/instana/instrumentation/redis.rb in instana-1.213.3 vs lib/instana/instrumentation/redis.rb in instana-1.214.0

- old
+ new

@@ -1,59 +1,86 @@ -# (c) Copyright IBM Corp. 2021 +# (c) Copyright IBM Corp. 2024 # (c) Copyright Instana Inc. 2017 module Instana module RedisInstrumentation - def call(*args, &block) - kv_payload = { redis: {} } - dnt_spans = [:redis, :'resque-client', :'sidekiq-client'] + if Gem::Specification.find_by_name('redis').version >= Gem::Version.new('5.0') && defined?(::RedisClient) + ORIGINAL_METHODS = { + :call_v => ::RedisClient.instance_method(:call_v), + :pipelined => ::RedisClient.instance_method(:pipelined), + :multi => ::RedisClient.instance_method(:multi) + }.freeze - if !Instana.tracer.tracing? || dnt_spans.include?(::Instana.tracer.current_span.name) || !Instana.config[:redis][:enabled] - return super(*args, &block) + def call_v(*args, &block) + if skip_instrumentation? + super(*args, &block) + else + call_with_instana(args[0][0].to_s.upcase, ORIGINAL_METHODS[:call_v], *args, &block) + end end - begin - ::Instana.tracer.log_entry(:redis) + def pipelined(*args, &block) + if skip_instrumentation? + super(*args, &block) + else + call_with_instana('PIPELINE', ORIGINAL_METHODS[:pipelined], *args, &block) + end + end - begin - kv_payload[:redis][:connection] = "#{self.host}:#{self.port}" - kv_payload[:redis][:db] = db.to_s - kv_payload[:redis][:command] = args[0][0].to_s.upcase - rescue - nil + # Since, starting with 5.1 redis/client.rb:114:multi takes an unused default argument `watch: nil` + # but calls redis_client.rb:442:multi, which doesn't take any argument, + # here we have to take arguments but we should not use it. + def multi(*_, &block) + if skip_instrumentation? + super(&block) + else + call_with_instana('MULTI', ORIGINAL_METHODS[:multi], &block) end + end - super(*args, &block) - rescue => e - ::Instana.tracer.log_info({ redis: {error: true} }) - ::Instana.tracer.log_error(e) - raise - ensure - ::Instana.tracer.log_exit(:redis, kv_payload) + else + ORIGINAL_METHODS = { + :call => ::Redis::Client.instance_method(:call), + :call_pipeline => ::Redis::Client.instance_method(:call_pipeline) + }.freeze + + def call(*args, &block) + if skip_instrumentation? + super(*args, &block) + else + call_with_instana(args[0][0].to_s.upcase, ORIGINAL_METHODS[:call], *args, &block) + end end + + def call_pipeline(*args, &block) + if skip_instrumentation? + super(*args, &block) + else + call_with_instana(args.first.is_a?(::Redis::Pipeline::Multi) ? 'MULTI' : 'PIPELINE', ORIGINAL_METHODS[:call_pipeline], *args, &block) + end + end end - def call_pipeline(*args, &block) - kv_payload = { redis: {} } + def skip_instrumentation? dnt_spans = [:redis, :'resque-client', :'sidekiq-client'] + !Instana.tracer.tracing? || dnt_spans.include?(::Instana.tracer.current_span.name) || !Instana.config[:redis][:enabled] + end - if !Instana.tracer.tracing? || dnt_spans.include?(::Instana.tracer.current_span.name) || !Instana.config[:redis][:enabled] - return super(*args, &block) - end + def call_with_instana(*args, &block) + command, original_super, *original_args = *args + kv_payload = { redis: {} } begin ::Instana.tracer.log_entry(:redis) - pipeline = args.first begin kv_payload[:redis][:connection] = "#{self.host}:#{self.port}" kv_payload[:redis][:db] = db.to_s - kv_payload[:redis][:command] = pipeline.is_a?(::Redis::Pipeline::Multi) ? 'MULTI' : 'PIPELINE' + kv_payload[:redis][:command] = command rescue nil end - - super(*args, &block) + original_super.bind(self).call(*original_args, &block) rescue => e ::Instana.tracer.log_info({ redis: {error: true} }) ::Instana.tracer.log_error(e) raise ensure