class Object
Constants
- CAS_CLIENT_METHODS
- CURB_MIN_VERSION
- EXCON_MIDDLEWARE_MIN_VERSION
- EXCON_MIN_VERSION
We have two ways of instrumenting Excon:
-
For newer versions, use the middleware mechanism
Excon
exposes -
For older versions, monkey-patch Excon::Connection#request
EXCON_MIN_VERSION
is the minimum version we attempt to instrument at all.EXCON_MIDDLEWARE_MIN_VERSION
is the min version we use the newerinstrumentation for.
Note that middlewares were added to
Excon
prior to 0.19, but we don’t use middleware-based instrumentation prior to that version because it didn’t expose a way for middlewares to know about request failures.Why don’t we use Excon.defaults? While this might seem a perfect fit, it unfortunately isn’t suitable in current form. Someone might reasonably set the default instrumentor to something else after we install our instrumentation. Ideally, excon would itself conform to the subscribe interface of ActiveSupport::Notifications, so we could safely subscribe and not be clobbered by future subscribers, but alas, it does not yet.
-
- HTTPCLIENT_MIN_VERSION
Public Class Methods
# File lib/mmtrix/agent/instrumentation/resque.rb, line 67 def self.new(*args) super(*args).extend Mmtrix::Agent::Instrumentation::ResqueInstrumentationInstaller end
Public Instance Methods
# File lib/mmtrix/agent/instrumentation/merb/controller.rb, line 32 def _dispatch_with_mmtrix_trace(*args) options = {} options[:params] = params perform_action_with_mmtrix_trace(options) do _dispatch_without_mmtrix_trace(*args) end end
# File lib/mmtrix/agent/instrumentation/grape.rb, line 91 def call_with_mmtrix(env) begin response = call_without_mmtrix(env) ensure begin endpoint = env[::Mmtrix::Agent::Instrumentation::GrapeInstrumentation::API_ENDPOINT] ::Mmtrix::Agent::Instrumentation::GrapeInstrumentation.handle_transaction(endpoint, self.class.name) rescue => e ::Mmtrix::Agent.logger.warn("Error in Grape instrumentation", e) end end response end
# File lib/mmtrix/agent/instrumentation/mongo.rb, line 101 def ensure_index_with_mmtrix_trace(spec, opts = {}, &block) metrics = mmtrix_generate_metrics(:ensureIndex) trace_execution_scoped(metrics) do t0 = Time.now result = Mmtrix::Agent.disable_all_tracing do ensure_index_without_mmtrix_trace(spec, opts, &block) end spec = case spec when Array Hash[spec] when String, Symbol { spec => 1 } else spec.dup end mmtrix_notice_statement(t0, spec, :ensureIndex) result end end
# File lib/mmtrix/agent/instrumentation/mongo.rb, line 38 def hook_instrument_method(target_class) target_class.class_eval do include Mmtrix::Agent::MethodTracer # It's key that this method eats all exceptions, as it rests between the # Mongo operation the user called and us returning them the data. Be safe! def mmtrix_notice_statement(t0, payload, name) statement = Mmtrix::Agent::Datastores::Mongo::StatementFormatter.format(payload, name) if statement Mmtrix::Agent.instance.transaction_sampler.notice_nosql_statement(statement, (Time.now - t0).to_f) end rescue => e Mmtrix::Agent.logger.debug("Exception during Mongo statement gathering", e) end def mmtrix_generate_metrics(operation, payload = nil) payload ||= { :collection => self.name, :database => self.db.name } Mmtrix::Agent::Datastores::Mongo::MetricTranslator.metrics_for(operation, payload) end def instrument_with_mmtrix_trace(name, payload = {}, &block) metrics = mmtrix_generate_metrics(name, payload) trace_execution_scoped(metrics) do t0 = Time.now result = Mmtrix::Agent.disable_all_tracing do instrument_without_mmtrix_trace(name, payload, &block) end mmtrix_notice_statement(t0, payload, name) result end end alias_method :instrument_without_mmtrix_trace, :instrument alias_method :instrument, :instrument_with_mmtrix_trace end end
# File lib/mmtrix/agent/instrumentation/mongo.rb, line 31 def hook_instrument_methods hook_instrument_method(::Mongo::Collection) hook_instrument_method(::Mongo::Connection) hook_instrument_method(::Mongo::Cursor) hook_instrument_method(::Mongo::CollectionWriter) if defined?(::Mongo::CollectionWriter) end
# File lib/mmtrix/agent/instrumentation/delayed_job_instrumentation.rb, line 24 def initialize_with_mmtrix(*args) initialize_without_mmtrix(*args) worker_name = case when self.respond_to?(:name) then self.name when self.class.respond_to?(:default_name) then self.class.default_name end Mmtrix::DelayedJobInjection.worker_name = worker_name if defined?(::Delayed::Job) && ::Delayed::Job.method_defined?(:invoke_job) ::Mmtrix::Agent.logger.info 'Installing DelayedJob instrumentation [part 2/2]' install_mmtrix_job_tracer Mmtrix::Control.instance.init_plugin :dispatcher => :delayed_job else Mmtrix::Agent.logger.warn("Did not find a Delayed::Job class responding to invoke_job, aborting DJ instrumentation") end end
# File lib/mmtrix/agent/instrumentation/excon.rb, line 44 def install_excon_instrumentation(excon_version) require 'mmtrix/agent/cross_app_tracing' require 'mmtrix/agent/http_clients/excon_wrappers' if excon_version >= EXCON_MIDDLEWARE_MIN_VERSION install_middleware_excon_instrumentation else install_legacy_excon_instrumentation end end
# File lib/mmtrix/agent/instrumentation/excon.rb, line 67 def install_legacy_excon_instrumentation ::Mmtrix::Agent.logger.info 'Installing legacy Excon instrumentation' require 'mmtrix/agent/instrumentation/excon/connection' ::Excon::Connection.install_mmtrix_instrumentation end
# File lib/mmtrix/agent/instrumentation/excon.rb, line 55 def install_middleware_excon_instrumentation ::Mmtrix::Agent.logger.info 'Installing middleware-based Excon instrumentation' require 'mmtrix/agent/instrumentation/excon/middleware' defaults = Excon.defaults if defaults[:middlewares] defaults[:middlewares] << ::Excon::Middleware::MmtrixCrossAppTracing else ::Mmtrix::Agent.logger.warn("Did not find :middlewares key in Excon.defaults, skipping Excon instrumentation") end end
# File lib/mmtrix/agent/instrumentation/delayed_job_instrumentation.rb, line 44 def install_mmtrix_job_tracer Delayed::Job.class_eval do include Mmtrix::Agent::Instrumentation::ControllerInstrumentation if self.instance_methods.include?('name') || self.instance_methods.include?(:name) add_transaction_tracer "invoke_job", :category => 'OtherTransaction/DelayedJob', :path => '#{self.name}' else add_transaction_tracer "invoke_job", :category => 'OtherTransaction/DelayedJob' end end end
# File lib/mmtrix/agent/instrumentation/mongo.rb, line 22 def install_mongo_instrumentation require 'mmtrix/agent/datastores/mongo/metric_translator' require 'mmtrix/agent/datastores/mongo/statement_formatter' hook_instrument_methods instrument_save instrument_ensure_index end
# File lib/mmtrix/agent/instrumentation/grape.rb, line 89 def instrument_call ::Grape::API.class_eval do def call_with_mmtrix(env) begin response = call_without_mmtrix(env) ensure begin endpoint = env[::Mmtrix::Agent::Instrumentation::GrapeInstrumentation::API_ENDPOINT] ::Mmtrix::Agent::Instrumentation::GrapeInstrumentation.handle_transaction(endpoint, self.class.name) rescue => e ::Mmtrix::Agent.logger.warn("Error in Grape instrumentation", e) end end response end alias_method :call_without_mmtrix, :call alias_method :call, :call_with_mmtrix end end
# File lib/mmtrix/agent/instrumentation/mongo.rb, line 99 def instrument_ensure_index ::Mongo::Collection.class_eval do def ensure_index_with_mmtrix_trace(spec, opts = {}, &block) metrics = mmtrix_generate_metrics(:ensureIndex) trace_execution_scoped(metrics) do t0 = Time.now result = Mmtrix::Agent.disable_all_tracing do ensure_index_without_mmtrix_trace(spec, opts, &block) end spec = case spec when Array Hash[spec] when String, Symbol { spec => 1 } else spec.dup end mmtrix_notice_statement(t0, spec, :ensureIndex) result end end alias_method :ensure_index_without_mmtrix_trace, :ensure_index alias_method :ensure_index, :ensure_index_with_mmtrix_trace end end
# File lib/mmtrix/agent/instrumentation/mongo.rb, line 78 def instrument_save ::Mongo::Collection.class_eval do def save_with_mmtrix_trace(doc, opts = {}, &block) metrics = mmtrix_generate_metrics(:save) trace_execution_scoped(metrics) do t0 = Time.now result = Mmtrix::Agent.disable_all_tracing do save_without_mmtrix_trace(doc, opts, &block) end mmtrix_notice_statement(t0, doc, :save) result end end alias_method :save_without_mmtrix_trace, :save alias_method :save, :save_with_mmtrix_trace end end
# File lib/mmtrix/agent/instrumentation/rails3/action_controller.rb, line 161 def instrument_with_mmtrix(name, payload = {}, &block) identifier = payload[:identifier] scope_name = "View/#{Mmtrix::Agent::Instrumentation::Rails3::ActionView::Mmtrix.template_metric(identifier)}/Partial" trace_execution_scoped(scope_name) do instrument_without_mmtrix(name, payload, &block) end end
# File lib/mmtrix/agent/instrumentation/mongo.rb, line 58 def instrument_with_mmtrix_trace(name, payload = {}, &block) metrics = mmtrix_generate_metrics(name, payload) trace_execution_scoped(metrics) do t0 = Time.now result = Mmtrix::Agent.disable_all_tracing do instrument_without_mmtrix_trace(name, payload, &block) end mmtrix_notice_statement(t0, payload, name) result end end
# File lib/mmtrix/recipes/capistrano3.rb, line 55 def lookup_changelog debug "Retrieving changelog for Mmtrix Deployment details" previous_revision = fetch(:previous_revision) current_revision = fetch(:current_revision) if scm == :git log_command = "git log --no-color --pretty=format:' * %an: %s' " + "--abbrev-commit --no-merges #{previous_revision}..#{current_revision}" `#{log_command}` end end
# File lib/mmtrix/recipes/capistrano_legacy.rb, line 72 def lookup_rev(rev) if rev.nil? rev = source.query_revision(source.head()) do |cmd| logger.debug "executing locally: '#{cmd}'" `#{cmd}` end rev = rev[0..6] if scm == :git end rev end
# File lib/mmtrix/agent/instrumentation/mongo.rb, line 53 def mmtrix_generate_metrics(operation, payload = nil) payload ||= { :collection => self.name, :database => self.db.name } Mmtrix::Agent::Datastores::Mongo::MetricTranslator.metrics_for(operation, payload) end
determine the path that is used in the metric name for the called controller action
# File lib/mmtrix/agent/instrumentation/merb/controller.rb, line 26 def mmtrix_metric_path "#{controller_name}/#{action_name}" end
Make a note of an exception associated with the currently executing controller action. Note that this used to be available on Object
but we replaced that global method with Mmtrix::Agent#notice_error
. Use that one instead.
@api public @deprecated
# File lib/mmtrix/agent/instrumentation/rails/errors.rb, line 31 def mmtrix_notice_error(exception, custom_params = {}) Mmtrix::Agent::Deprecator.deprecate("ActionController#mmtrix_notice_error", "Mmtrix::Agent#notice_error") Mmtrix::Agent::Transaction.notice_error exception, :custom_params => custom_params end
It’s key that this method eats all exceptions, as it rests between the Mongo operation the user called and us returning them the data. Be safe!
# File lib/mmtrix/agent/instrumentation/mongo.rb, line 44 def mmtrix_notice_statement(t0, payload, name) statement = Mmtrix::Agent::Datastores::Mongo::StatementFormatter.format(payload, name) if statement Mmtrix::Agent.instance.transaction_sampler.notice_nosql_statement(statement, (Time.now - t0).to_f) end rescue => e Mmtrix::Agent.logger.debug("Exception during Mongo statement gathering", e) end
# File lib/mmtrix/agent/instrumentation/rails/action_controller.rb, line 98 def perform_action_with_mmtrix_trace_wrapper munged_params = (respond_to?(:filter_parameters)) ? filter_parameters(params) : params munged_params = Mmtrix::Agent::ParameterFiltering.filter_rails_request_parameters(munged_params) perform_action_with_mmtrix_trace(:params => munged_params) do perform_action_without_mmtrix_trace end end
# File lib/mmtrix/agent/instrumentation/rails3/action_controller.rb, line 103 def render_with_mmtrix(*args, &block) options = if @virtual_path && @virtual_path.starts_with?('/') # file render {:file => true } else {} end str = "View/#{Mmtrix::Agent::Instrumentation::Rails3::ActionView::Mmtrix.template_metric(@identifier, options)}/#{Mmtrix::Agent::Instrumentation::Rails3::ActionView::Mmtrix.render_type(@identifier)}" trace_execution_scoped str do render_without_mmtrix(*args, &block) end end
# File lib/mmtrix/agent/instrumentation/rails/errors.rb, line 38 def rescue_action_with_mmtrix_trace(exception) rescue_action_without_mmtrix_trace exception Mmtrix::Agent::Transaction.notice_error exception end
# File lib/mmtrix/agent/instrumentation/mongo.rb, line 80 def save_with_mmtrix_trace(doc, opts = {}, &block) metrics = mmtrix_generate_metrics(:save) trace_execution_scoped(metrics) do t0 = Time.now result = Mmtrix::Agent.disable_all_tracing do save_without_mmtrix_trace(doc, opts, &block) end mmtrix_notice_statement(t0, doc, :save) result end end
# File lib/mmtrix/agent/instrumentation/sequel.rb, line 17 def supported_sequel_version? Sequel.const_defined?( :MAJOR ) && ( Sequel::MAJOR > 3 || Sequel::MAJOR == 3 && Sequel::MINOR >= 37 ) end