lib/new_relic/agent/instrumentation/memcache/dalli.rb in newrelic_rpm-6.15.0 vs lib/new_relic/agent/instrumentation/memcache/dalli.rb in newrelic_rpm-7.0.0

- old
+ new

@@ -1,166 +1,83 @@ # encoding: utf-8 # This file is distributed under New Relic's license terms. # See https://github.com/newrelic/newrelic-ruby-agent/blob/main/LICENSE for complete details. +# frozen_string_literal: true module NewRelic module Agent module Instrumentation module Memcache module Dalli - extend self + extend Helper + module_function - MEMCACHED = "Memcached".freeze - METHODS = [:get, :set, :add, :incr, :decr, :delete, :replace, :append, :prepend, :cas] - SEND_MULTIGET_METRIC_NAME = "get_multi_request".freeze - DATASTORE_INSTANCES_SUPPORTED_VERSION = Gem::Version.new '2.6.4' - SLASH = '/'.freeze - UNKNOWN = 'unknown'.freeze - LOCALHOST = 'localhost'.freeze - - def supports_datastore_instances? - DATASTORE_INSTANCES_SUPPORTED_VERSION <= Gem::Version.new(::Dalli::VERSION) - end - - def instrument_methods + def instrument! if supports_datastore_instances? - ::NewRelic::Agent::Instrumentation::Memcache.instrument_methods(::Dalli::Client, METHODS) + instrument_methods(::Dalli::Client, dalli_methods) instrument_multi_method :get_multi instrument_send_multiget instrument_server_for_key else - ::NewRelic::Agent::Instrumentation::Memcache.instrument_methods(::Dalli::Client, - ::NewRelic::Agent::Instrumentation::Memcache::METHODS) + instrument_methods(::Dalli::Client, client_methods) end end + def instrument_multi_method method_name + visibility = NewRelic::Helper.instance_method_visibility ::Dalli::Client, method_name + method_name_without = :"#{method_name}_without_newrelic_trace" + + ::Dalli::Client.class_eval do + alias_method method_name_without, method_name + + define_method method_name do |*args, &block| + get_multi_with_newrelic_tracing(method_name) { __send__ method_name_without, *args, &block } + end + + __send__ visibility, method_name + __send__ visibility, method_name_without + end + end + def instrument_server_for_key ::Dalli::Ring.class_eval do + include NewRelic::Agent::Instrumentation::Memcache::Tracer + alias_method :server_for_key_without_newrelic_trace, :server_for_key def server_for_key key - server = server_for_key_without_newrelic_trace key - begin - if txn = ::NewRelic::Agent::Tracer.current_transaction - segment = txn.current_segment - if ::NewRelic::Agent::Transaction::DatastoreSegment === segment - ::NewRelic::Agent::Instrumentation::Memcache::Dalli.assign_instance_to(segment, server) - end - end - rescue => e - ::NewRelic::Agent.logger.warn "Unable to set instance info on datastore segment: #{e.message}" - end - server + server_for_key_with_newrelic_tracing { server_for_key_without_newrelic_trace key } end end end def instrument_send_multiget ::Dalli::Server.class_eval do + include NewRelic::Agent::Instrumentation::Memcache::Tracer alias_method :send_multiget_without_newrelic_trace, :send_multiget - def send_multiget(keys) - segment = ::NewRelic::Agent::Tracer.start_datastore_segment( - product: MEMCACHED, - operation: SEND_MULTIGET_METRIC_NAME - ) - ::NewRelic::Agent::Instrumentation::Memcache::Dalli.assign_instance_to(segment, self) - - begin - NewRelic::Agent::Tracer.capture_segment_error segment do - send_multiget_without_newrelic_trace(keys) - end - ensure - if ::NewRelic::Agent.config[:capture_memcache_keys] - segment.notice_nosql_statement "#{SEND_MULTIGET_METRIC_NAME} #{keys.inspect}" - end - segment.finish if segment - end + def send_multiget keys + send_multiget_with_newrelic_tracing(keys) { send_multiget_without_newrelic_trace keys } end end end + end - def instrument_multi_method method_name - visibility = NewRelic::Helper.instance_method_visibility ::Dalli::Client, method_name - method_name_without = :"#{method_name}_without_newrelic_trace" + module DalliCAS + extend Dalli + extend Helper + module_function - ::Dalli::Client.class_eval do - alias_method method_name_without, method_name - - define_method method_name do |*args, &block| - segment = NewRelic::Agent::Tracer.start_segment name: "Ruby/Memcached/Dalli/#{method_name}" - begin - NewRelic::Agent::Tracer.capture_segment_error segment do - __send__ method_name_without, *args, &block - end - ensure - segment.finish if segment - end - end - - __send__ visibility, method_name - __send__ visibility, method_name_without - end + def should_instrument? + supported_methods_for(::Dalli::Client, dalli_cas_methods).any? end - def assign_instance_to segment, server - host = port_path_or_id = nil - if server.hostname.start_with? SLASH - host = LOCALHOST - port_path_or_id = server.hostname - else - host = server.hostname - port_path_or_id = server.port - end - segment.set_instance_info host, port_path_or_id - rescue => e - ::NewRelic::Agent.logger.debug "Failed to retrieve memcached instance info: #{e.message}" - segment.set_instance_info UNKNOWN, UNKNOWN + def instrument! + instrument_methods ::Dalli::Client, dalli_cas_methods + instrument_multi_method :get_multi_cas end - end end end end end -DependencyDetection.defer do - named :dalli - - depends_on do - NewRelic::Agent::Instrumentation::Memcache.enabled? - end - - depends_on do - defined?(::Dalli::Client) - end - - executes do - ::NewRelic::Agent.logger.info 'Installing Memcache instrumentation for dalli gem' - ::NewRelic::Agent::Instrumentation::Memcache::Dalli.instrument_methods - end -end - -DependencyDetection.defer do - named :dalli_cas_client - - depends_on do - NewRelic::Agent::Instrumentation::Memcache.enabled? - end - - depends_on do - # These CAS client methods are only optionally defined if users require - # dalli/cas/client. Use a separate dependency block so it can potentially - # re-evaluate after they've done that require. - defined?(::Dalli::Client) && - ::NewRelic::Agent::Instrumentation::Memcache.supported_methods_for(::Dalli::Client, - CAS_CLIENT_METHODS).any? - end - - CAS_CLIENT_METHODS = [:get_cas, :set_cas, :replace_cas, :delete_cas] - - executes do - ::NewRelic::Agent.logger.info 'Installing Dalli CAS Client Memcache instrumentation' - ::NewRelic::Agent::Instrumentation::Memcache.instrument_methods(::Dalli::Client, CAS_CLIENT_METHODS) - ::NewRelic::Agent::Instrumentation::Memcache::Dalli.instrument_multi_method(:get_multi_cas) - end -end