require 'ddtrace/contrib/patcher' require 'ddtrace/contrib/redis/ext' module Datadog module Contrib module Redis # Patcher enables patching of 'redis' module. module Patcher include Contrib::Patcher module_function def patched? done?(:redis) end # patch applies our patch if needed def patch do_once(:redis) do begin # do not require these by default, but only when actually patching require 'redis' require 'ddtrace/ext/app_types' require 'ddtrace/contrib/redis/tags' require 'ddtrace/contrib/redis/quantize' patch_redis_client RailsCachePatcher.reload_cache_store if Datadog.registry[:rails].patcher.patched? rescue StandardError => e Datadog::Tracer.log.error("Unable to apply Redis integration: #{e}") end end end # rubocop:disable Metrics/MethodLength # rubocop:disable Metrics/BlockLength def patch_redis_client ::Redis::Client.class_eval do alias_method :initialize_without_datadog, :initialize Datadog::Patcher.without_warnings do remove_method :initialize end def initialize(*args) service = Datadog.configuration[:redis][:service_name] tracer = Datadog.configuration[:redis][:tracer] pin = Datadog::Pin.new( service, app: Ext::APP, app_type: Datadog::Ext::AppTypes::DB, tracer: tracer ) pin.onto(self) initialize_without_datadog(*args) end alias_method :call_without_datadog, :call remove_method :call def call(*args, &block) pin = Datadog::Pin.get_from(self) return call_without_datadog(*args, &block) unless pin && pin.tracer response = nil pin.tracer.trace(Datadog::Contrib::Redis::Ext::SPAN_COMMAND) do |span| span.service = pin.service span.span_type = Datadog::Contrib::Redis::Ext::TYPE span.resource = Datadog::Contrib::Redis::Quantize.format_command_args(*args) Datadog::Contrib::Redis::Tags.set_common_tags(self, span) response = call_without_datadog(*args, &block) end response end alias_method :call_pipeline_without_datadog, :call_pipeline remove_method :call_pipeline def call_pipeline(*args, &block) pin = Datadog::Pin.get_from(self) return call_pipeline_without_datadog(*args, &block) unless pin && pin.tracer response = nil pin.tracer.trace(Datadog::Contrib::Redis::Ext::SPAN_COMMAND) do |span| span.service = pin.service span.span_type = Datadog::Contrib::Redis::Ext::TYPE commands = args[0].commands.map { |c| Datadog::Contrib::Redis::Quantize.format_command_args(c) } span.resource = commands.join("\n") Datadog::Contrib::Redis::Tags.set_common_tags(self, span) span.set_metric Datadog::Contrib::Redis::Ext::METRIC_PIPELINE_LEN, commands.length response = call_pipeline_without_datadog(*args, &block) end response end end end end end end end