lib/new_relic/agent/instrumentation/mongo.rb in newrelic_rpm-3.7.2.190.beta vs lib/new_relic/agent/instrumentation/mongo.rb in newrelic_rpm-3.7.2.192
- old
+ new
@@ -26,57 +26,81 @@
NewRelic::Agent.logger.info 'Installing Mongo instrumentation'
install_mongo_instrumentation
end
def install_mongo_instrumentation
+ setup_logging_for_instrumentation
instrument_mongo_logging
instrument_save
instrument_ensure_index
end
- def instrument_mongo_logging
+ def setup_logging_for_instrumentation
::Mongo::Logging.class_eval do
include NewRelic::Agent::MethodTracer
require 'new_relic/agent/datastores/mongo/metric_generator'
require 'new_relic/agent/datastores/mongo/statement_formatter'
- def instrument_with_new_relic_trace(name, payload = {}, &block)
- metrics = NewRelic::Agent::Datastores::Mongo::MetricGenerator.generate_metrics_for(name, payload)
-
- trace_execution_scoped(metrics) do
- t0 = Time.now
- result = instrument_without_new_relic_trace(name, payload, &block)
-
- payload[:operation] = name
- statement = NewRelic::Agent::Datastores::Mongo::StatementFormatter.format(payload)
- if statement
- NewRelic::Agent.instance.transaction_sampler.notice_nosql_statement(statement, (Time.now - t0).to_f)
+ def new_relic_instance_metric_builder
+ Proc.new do
+ if @pool
+ host, port = @pool.host, @pool.port
+ elsif @connection && (primary = @connection.primary)
+ host, port = primary[0], primary[1]
end
- result
+ database_name = @db.name if @db
+ NewRelic::Agent::Datastores::Mongo::MetricGenerator.generate_instance_metric_for(host, port, database_name)
end
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!
+ def new_relic_notice_statement(t0, payload, operation)
+ payload[:operation] = operation
+ statement = NewRelic::Agent::Datastores::Mongo::StatementFormatter.format(payload)
+ if statement
+ NewRelic::Agent.instance.transaction_sampler.notice_nosql_statement(statement, (Time.now - t0).to_f)
+ end
+ rescue => e
+ NewRelic::Agent.logger.debug("Exception during Mongo statement gathering", e)
+ end
+
+ def new_relic_generate_metrics(operation, payload = nil)
+ payload ||= { :collection => self.name, :database => self.db.name }
+ metrics = NewRelic::Agent::Datastores::Mongo::MetricGenerator.generate_metrics_for(operation, payload)
+ end
+
::Mongo::Collection.class_eval { include Mongo::Logging; }
::Mongo::Connection.class_eval { include Mongo::Logging; }
::Mongo::Cursor.class_eval { include Mongo::Logging; }
+ end
+ end
+ def instrument_mongo_logging
+ ::Mongo::Logging.class_eval do
+ def instrument_with_new_relic_trace(name, payload = {}, &block)
+ metrics = new_relic_generate_metrics(name, payload)
+
+ trace_execution_scoped(metrics, :additional_metrics_callback => new_relic_instance_metric_builder) do
+ t0 = Time.now
+ result = instrument_without_new_relic_trace(name, payload, &block)
+ new_relic_notice_statement(t0, payload, name)
+ result
+ end
+ end
+
alias_method :instrument_without_new_relic_trace, :instrument
alias_method :instrument, :instrument_with_new_relic_trace
end
end
def instrument_save
::Mongo::Collection.class_eval do
- include NewRelic::Agent::MethodTracer
- require 'new_relic/agent/datastores/mongo/metric_generator'
- require 'new_relic/agent/datastores/mongo/statement_formatter'
-
def save_with_new_relic_trace(doc, opts = {}, &block)
- metrics = NewRelic::Agent::Datastores::Mongo::MetricGenerator.generate_metrics_for(:save, { :collection => self.name })
-
- trace_execution_scoped(metrics) do
+ metrics = new_relic_generate_metrics(:save)
+ trace_execution_scoped(metrics, :additional_metrics_callback => new_relic_instance_metric_builder) do
t0 = Time.now
transaction_state = NewRelic::Agent::TransactionState.get
transaction_state.push_traced(false)
@@ -84,16 +108,11 @@
result = save_without_new_relic_trace(doc, opts, &block)
ensure
transaction_state.pop_traced
end
- doc[:operation] = :save
- statement = NewRelic::Agent::Datastores::Mongo::StatementFormatter.format(doc)
- if statement
- NewRelic::Agent.instance.transaction_sampler.notice_nosql_statement(statement, (Time.now - t0).to_f)
- end
-
+ new_relic_notice_statement(t0, doc, :save)
result
end
end
alias_method :save_without_new_relic_trace, :save
@@ -101,18 +120,13 @@
end
end
def instrument_ensure_index
::Mongo::Collection.class_eval do
- include NewRelic::Agent::MethodTracer
- require 'new_relic/agent/datastores/mongo/metric_generator'
- require 'new_relic/agent/datastores/mongo/statement_formatter'
-
def ensure_index_with_new_relic_trace(spec, opts = {}, &block)
- metrics = NewRelic::Agent::Datastores::Mongo::MetricGenerator.generate_metrics_for(:ensureIndex, { :collection => self.name })
-
- trace_execution_scoped(metrics) do
+ metrics = new_relic_generate_metrics(:ensureIndex)
+ trace_execution_scoped(metrics, :additional_metrics_callback => new_relic_instance_metric_builder) do
t0 = Time.now
transaction_state = NewRelic::Agent::TransactionState.get
transaction_state.push_traced(false)
@@ -120,17 +134,19 @@
result = ensure_index_without_new_relic_trace(spec, opts, &block)
ensure
transaction_state.pop_traced
end
- spec = spec.is_a?(Array) ? Hash[spec] : spec.dup
- spec[:operation] = :ensureIndex
+ spec = case spec
+ when Array
+ Hash[spec]
+ when String, Symbol
+ { spec => 1 }
+ else
+ spec.dup
+ end
- statement = NewRelic::Agent::Datastores::Mongo::StatementFormatter.format(spec)
- if statement
- NewRelic::Agent.instance.transaction_sampler.notice_nosql_statement(statement, (Time.now - t0).to_f)
- end
-
+ new_relic_notice_statement(t0, spec, :ensureIndex)
result
end
end
alias_method :ensure_index_without_new_relic_trace, :ensure_index